OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
| 6 #include <map> |
6 #include <set> | 7 #include <set> |
| 8 #include <string> |
7 #include <vector> | 9 #include <vector> |
8 | 10 |
9 #include "base/at_exit.h" | 11 #include "base/at_exit.h" |
10 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
11 #include "base/bind.h" | 13 #include "base/bind.h" |
12 #include "base/command_line.h" | 14 #include "base/command_line.h" |
13 #include "base/files/file_enumerator.h" | 15 #include "base/files/file_enumerator.h" |
14 #include "base/files/file_util.h" | 16 #include "base/files/file_util.h" |
15 #include "base/files/scoped_temp_dir.h" | 17 #include "base/files/scoped_temp_dir.h" |
16 #include "base/json/json_file_value_serializer.h" | 18 #include "base/json/json_file_value_serializer.h" |
17 #include "base/json/json_reader.h" | 19 #include "base/json/json_reader.h" |
18 #include "base/json/json_string_value_serializer.h" | 20 #include "base/json/json_string_value_serializer.h" |
19 #include "base/location.h" | 21 #include "base/location.h" |
20 #include "base/memory/scoped_ptr.h" | 22 #include "base/memory/scoped_ptr.h" |
21 #include "base/memory/weak_ptr.h" | 23 #include "base/memory/weak_ptr.h" |
22 #include "base/metrics/field_trial.h" | |
23 #include "base/prefs/scoped_user_pref_update.h" | 24 #include "base/prefs/scoped_user_pref_update.h" |
24 #include "base/single_thread_task_runner.h" | 25 #include "base/single_thread_task_runner.h" |
25 #include "base/stl_util.h" | 26 #include "base/stl_util.h" |
26 #include "base/strings/pattern.h" | 27 #include "base/strings/pattern.h" |
27 #include "base/strings/string16.h" | 28 #include "base/strings/string16.h" |
28 #include "base/strings/string_number_conversions.h" | 29 #include "base/strings/string_number_conversions.h" |
29 #include "base/strings/string_util.h" | 30 #include "base/strings/string_util.h" |
30 #include "base/strings/utf_string_conversions.h" | 31 #include "base/strings/utf_string_conversions.h" |
31 #include "base/test/mock_entropy_provider.h" | |
32 #include "base/thread_task_runner_handle.h" | 32 #include "base/thread_task_runner_handle.h" |
33 #include "base/version.h" | 33 #include "base/version.h" |
34 #include "chrome/browser/browser_process.h" | 34 #include "chrome/browser/browser_process.h" |
35 #include "chrome/browser/chrome_notification_types.h" | 35 #include "chrome/browser/chrome_notification_types.h" |
36 #include "chrome/browser/extensions/blacklist.h" | 36 #include "chrome/browser/extensions/blacklist.h" |
37 #include "chrome/browser/extensions/chrome_app_sorting.h" | 37 #include "chrome/browser/extensions/chrome_app_sorting.h" |
38 #include "chrome/browser/extensions/component_loader.h" | 38 #include "chrome/browser/extensions/component_loader.h" |
39 #include "chrome/browser/extensions/crx_installer.h" | 39 #include "chrome/browser/extensions/crx_installer.h" |
40 #include "chrome/browser/extensions/default_apps.h" | 40 #include "chrome/browser/extensions/default_apps.h" |
41 #include "chrome/browser/extensions/extension_creator.h" | 41 #include "chrome/browser/extensions/extension_creator.h" |
42 #include "chrome/browser/extensions/extension_error_reporter.h" | 42 #include "chrome/browser/extensions/extension_error_reporter.h" |
43 #include "chrome/browser/extensions/extension_error_ui.h" | 43 #include "chrome/browser/extensions/extension_error_ui.h" |
44 #include "chrome/browser/extensions/extension_management_test_util.h" | 44 #include "chrome/browser/extensions/extension_management_test_util.h" |
45 #include "chrome/browser/extensions/extension_notification_observer.h" | 45 #include "chrome/browser/extensions/extension_notification_observer.h" |
46 #include "chrome/browser/extensions/extension_service.h" | 46 #include "chrome/browser/extensions/extension_service.h" |
47 #include "chrome/browser/extensions/extension_service_test_base.h" | 47 #include "chrome/browser/extensions/extension_service_test_base.h" |
| 48 #include "chrome/browser/extensions/extension_service_test_with_install.h" |
48 #include "chrome/browser/extensions/extension_special_storage_policy.h" | 49 #include "chrome/browser/extensions/extension_special_storage_policy.h" |
49 #include "chrome/browser/extensions/extension_sync_data.h" | |
50 #include "chrome/browser/extensions/extension_sync_service.h" | |
51 #include "chrome/browser/extensions/extension_util.h" | 50 #include "chrome/browser/extensions/extension_util.h" |
52 #include "chrome/browser/extensions/external_install_error.h" | 51 #include "chrome/browser/extensions/external_install_error.h" |
53 #include "chrome/browser/extensions/external_install_manager.h" | 52 #include "chrome/browser/extensions/external_install_manager.h" |
54 #include "chrome/browser/extensions/external_policy_loader.h" | 53 #include "chrome/browser/extensions/external_policy_loader.h" |
55 #include "chrome/browser/extensions/external_pref_loader.h" | 54 #include "chrome/browser/extensions/external_pref_loader.h" |
56 #include "chrome/browser/extensions/external_provider_impl.h" | 55 #include "chrome/browser/extensions/external_provider_impl.h" |
57 #include "chrome/browser/extensions/fake_safe_browsing_database_manager.h" | 56 #include "chrome/browser/extensions/fake_safe_browsing_database_manager.h" |
58 #include "chrome/browser/extensions/installed_loader.h" | 57 #include "chrome/browser/extensions/installed_loader.h" |
59 #include "chrome/browser/extensions/pack_extension_job.h" | 58 #include "chrome/browser/extensions/pack_extension_job.h" |
60 #include "chrome/browser/extensions/pending_extension_info.h" | 59 #include "chrome/browser/extensions/pending_extension_info.h" |
61 #include "chrome/browser/extensions/pending_extension_manager.h" | 60 #include "chrome/browser/extensions/pending_extension_manager.h" |
62 #include "chrome/browser/extensions/permissions_updater.h" | 61 #include "chrome/browser/extensions/permissions_updater.h" |
63 #include "chrome/browser/extensions/test_blacklist.h" | 62 #include "chrome/browser/extensions/test_blacklist.h" |
64 #include "chrome/browser/extensions/test_extension_system.h" | 63 #include "chrome/browser/extensions/test_extension_system.h" |
65 #include "chrome/browser/extensions/unpacked_installer.h" | 64 #include "chrome/browser/extensions/unpacked_installer.h" |
66 #include "chrome/browser/extensions/updater/extension_updater.h" | 65 #include "chrome/browser/extensions/updater/extension_updater.h" |
67 #include "chrome/browser/policy/profile_policy_connector.h" | 66 #include "chrome/browser/policy/profile_policy_connector.h" |
68 #include "chrome/browser/policy/profile_policy_connector_factory.h" | 67 #include "chrome/browser/policy/profile_policy_connector_factory.h" |
69 #include "chrome/browser/sync/profile_sync_service.h" | |
70 #include "chrome/browser/sync/profile_sync_service_factory.h" | |
71 #include "chrome/common/chrome_constants.h" | 68 #include "chrome/common/chrome_constants.h" |
72 #include "chrome/common/chrome_switches.h" | 69 #include "chrome/common/chrome_switches.h" |
73 #include "chrome/common/extensions/api/plugins/plugins_handler.h" | 70 #include "chrome/common/extensions/api/plugins/plugins_handler.h" |
74 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" | 71 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
75 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" | 72 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" |
76 #include "chrome/common/extensions/sync_helper.h" | |
77 #include "chrome/common/pref_names.h" | 73 #include "chrome/common/pref_names.h" |
78 #include "chrome/common/url_constants.h" | 74 #include "chrome/common/url_constants.h" |
79 #include "chrome/test/base/scoped_browser_locale.h" | 75 #include "chrome/test/base/scoped_browser_locale.h" |
80 #include "chrome/test/base/testing_profile.h" | 76 #include "chrome/test/base/testing_profile.h" |
81 #include "components/crx_file/id_util.h" | 77 #include "components/crx_file/id_util.h" |
82 #include "components/pref_registry/pref_registry_syncable.h" | 78 #include "components/pref_registry/pref_registry_syncable.h" |
83 #include "components/syncable_prefs/pref_service_syncable.h" | 79 #include "components/syncable_prefs/pref_service_syncable.h" |
84 #include "components/syncable_prefs/testing_pref_service_syncable.h" | 80 #include "components/syncable_prefs/testing_pref_service_syncable.h" |
85 #include "content/public/browser/dom_storage_context.h" | 81 #include "content/public/browser/dom_storage_context.h" |
86 #include "content/public/browser/gpu_data_manager.h" | 82 #include "content/public/browser/gpu_data_manager.h" |
87 #include "content/public/browser/indexed_db_context.h" | 83 #include "content/public/browser/indexed_db_context.h" |
88 #include "content/public/browser/notification_registrar.h" | |
89 #include "content/public/browser/notification_service.h" | 84 #include "content/public/browser/notification_service.h" |
90 #include "content/public/browser/plugin_service.h" | 85 #include "content/public/browser/plugin_service.h" |
91 #include "content/public/browser/render_process_host.h" | 86 #include "content/public/browser/render_process_host.h" |
92 #include "content/public/browser/storage_partition.h" | 87 #include "content/public/browser/storage_partition.h" |
93 #include "content/public/common/content_constants.h" | 88 #include "content/public/common/content_constants.h" |
94 #include "content/public/test/test_browser_thread_bundle.h" | 89 #include "content/public/test/test_browser_thread_bundle.h" |
95 #include "content/public/test/test_utils.h" | 90 #include "content/public/test/test_utils.h" |
96 #include "extensions/browser/extension_dialog_auto_confirm.h" | 91 #include "extensions/browser/extension_dialog_auto_confirm.h" |
97 #include "extensions/browser/extension_prefs.h" | 92 #include "extensions/browser/extension_prefs.h" |
98 #include "extensions/browser/extension_registry.h" | 93 #include "extensions/browser/extension_registry.h" |
(...skipping 22 matching lines...) Expand all Loading... |
121 #include "grit/browser_resources.h" | 116 #include "grit/browser_resources.h" |
122 #include "grit/generated_resources.h" | 117 #include "grit/generated_resources.h" |
123 #include "net/cookies/canonical_cookie.h" | 118 #include "net/cookies/canonical_cookie.h" |
124 #include "net/cookies/cookie_monster.h" | 119 #include "net/cookies/cookie_monster.h" |
125 #include "net/cookies/cookie_options.h" | 120 #include "net/cookies/cookie_options.h" |
126 #include "net/url_request/url_request_context.h" | 121 #include "net/url_request/url_request_context.h" |
127 #include "net/url_request/url_request_context_getter.h" | 122 #include "net/url_request/url_request_context_getter.h" |
128 #include "storage/browser/database/database_tracker.h" | 123 #include "storage/browser/database/database_tracker.h" |
129 #include "storage/browser/quota/quota_manager.h" | 124 #include "storage/browser/quota/quota_manager.h" |
130 #include "storage/common/database/database_identifier.h" | 125 #include "storage/common/database/database_identifier.h" |
131 #include "sync/api/fake_sync_change_processor.h" | |
132 #include "sync/api/string_ordinal.h" | 126 #include "sync/api/string_ordinal.h" |
133 #include "sync/api/sync_data.h" | 127 #include "testing/gmock/include/gmock/gmock.h" |
134 #include "sync/api/sync_error_factory.h" | |
135 #include "sync/api/sync_error_factory_mock.h" | |
136 #include "sync/api/syncable_service.h" | |
137 #include "sync/protocol/app_specifics.pb.h" | |
138 #include "sync/protocol/extension_specifics.pb.h" | |
139 #include "sync/protocol/sync.pb.h" | |
140 #include "testing/gtest/include/gtest/gtest.h" | 128 #include "testing/gtest/include/gtest/gtest.h" |
141 #include "testing/platform_test.h" | 129 #include "testing/platform_test.h" |
142 #include "ui/base/l10n/l10n_util.h" | 130 #include "ui/base/l10n/l10n_util.h" |
143 #include "ui/base/resource/material_design/material_design_controller.h" | 131 #include "ui/base/resource/material_design/material_design_controller.h" |
144 #include "url/gurl.h" | 132 #include "url/gurl.h" |
145 | 133 |
146 #if defined(ENABLE_SUPERVISED_USERS) | |
147 #include "chrome/browser/supervised_user/permission_request_creator.h" | |
148 #include "chrome/browser/supervised_user/supervised_user_constants.h" | |
149 #include "chrome/browser/supervised_user/supervised_user_service.h" | |
150 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" | |
151 #endif | |
152 | |
153 #if defined(OS_CHROMEOS) | 134 #if defined(OS_CHROMEOS) |
154 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h" | 135 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h" |
155 #include "chrome/browser/chromeos/settings/cros_settings.h" | 136 #include "chrome/browser/chromeos/settings/cros_settings.h" |
156 #include "chrome/browser/chromeos/settings/device_settings_service.h" | 137 #include "chrome/browser/chromeos/settings/device_settings_service.h" |
157 #endif | 138 #endif |
158 | 139 |
159 // The blacklist tests rely on the safe-browsing database. | 140 // The blacklist tests rely on the safe-browsing database. |
160 #if defined(SAFE_BROWSING_DB_LOCAL) | 141 #if defined(SAFE_BROWSING_DB_LOCAL) |
161 #define ENABLE_BLACKLIST_TESTS | 142 #define ENABLE_BLACKLIST_TESTS |
162 #endif | 143 #endif |
163 | 144 |
164 using base::DictionaryValue; | |
165 using base::ListValue; | |
166 using base::Value; | |
167 using content::BrowserContext; | 145 using content::BrowserContext; |
168 using content::BrowserThread; | 146 using content::BrowserThread; |
169 using content::DOMStorageContext; | 147 using content::DOMStorageContext; |
170 using content::IndexedDBContext; | 148 using content::IndexedDBContext; |
171 using content::PluginService; | 149 using content::PluginService; |
172 using extensions::APIPermission; | 150 using extensions::APIPermission; |
173 using extensions::APIPermissionSet; | 151 using extensions::APIPermissionSet; |
174 using extensions::AppSorting; | 152 using extensions::AppSorting; |
175 using extensions::Blacklist; | 153 using extensions::Blacklist; |
176 using extensions::CrxInstaller; | 154 using extensions::CrxInstaller; |
177 using extensions::Extension; | 155 using extensions::Extension; |
178 using extensions::ExtensionCreator; | 156 using extensions::ExtensionCreator; |
179 using extensions::ExtensionPrefs; | 157 using extensions::ExtensionPrefs; |
180 using extensions::ExtensionRegistry; | 158 using extensions::ExtensionRegistry; |
181 using extensions::ExtensionResource; | 159 using extensions::ExtensionResource; |
182 using extensions::ExtensionSyncData; | |
183 using extensions::ExtensionSystem; | 160 using extensions::ExtensionSystem; |
184 using extensions::FakeSafeBrowsingDatabaseManager; | 161 using extensions::FakeSafeBrowsingDatabaseManager; |
185 using extensions::FeatureSwitch; | 162 using extensions::FeatureSwitch; |
186 using extensions::Manifest; | 163 using extensions::Manifest; |
187 using extensions::PermissionSet; | 164 using extensions::PermissionSet; |
188 using extensions::TestExtensionSystem; | 165 using extensions::TestExtensionSystem; |
189 using extensions::UnloadedExtensionInfo; | 166 using extensions::UnloadedExtensionInfo; |
190 using extensions::URLPatternSet; | 167 using extensions::URLPatternSet; |
191 | 168 |
192 namespace keys = extensions::manifest_keys; | 169 namespace keys = extensions::manifest_keys; |
193 | 170 |
194 namespace { | 171 namespace { |
195 | 172 |
196 // Extension ids used during testing. | 173 // Extension ids used during testing. |
197 const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj"; | 174 const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj"; |
198 const char good1[] = "hpiknbiabeeppbpihjehijgoemciehgk"; | 175 const char good1[] = "hpiknbiabeeppbpihjehijgoemciehgk"; |
199 const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa"; | 176 const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa"; |
200 const char all_zero[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; | 177 const char all_zero[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; |
201 const char good2048[] = "nmgjhmhbleinmjpbdhgajfjkbijcmgbh"; | 178 const char good2048[] = "nmgjhmhbleinmjpbdhgajfjkbijcmgbh"; |
202 const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; | 179 const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; |
203 const char hosted_app[] = "kbmnembihfiondgfjekmnmcbddelicoi"; | 180 const char hosted_app[] = "kbmnembihfiondgfjekmnmcbddelicoi"; |
204 const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln"; | 181 const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln"; |
205 const char theme_crx[] = "iamefpfkojoapidjnbafmgkgncegbkad"; | 182 const char theme_crx[] = "iamefpfkojoapidjnbafmgkgncegbkad"; |
206 const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; | 183 const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; |
207 const char permissions_crx[] = "eagpmdpfmaekmmcejjbmjoecnejeiiin"; | 184 const char permissions_crx[] = "eagpmdpfmaekmmcejjbmjoecnejeiiin"; |
208 const char updates_from_webstore[] = "akjooamlhcgeopfifcmlggaebeocgokj"; | 185 const char updates_from_webstore[] = "akjooamlhcgeopfifcmlggaebeocgokj"; |
209 const char permissions_blocklist[] = "noffkehfcaggllbcojjbopcmlhcnhcdn"; | 186 const char permissions_blocklist[] = "noffkehfcaggllbcojjbopcmlhcnhcdn"; |
210 | 187 |
211 struct ExtensionsOrder { | |
212 bool operator()(const scoped_refptr<const Extension>& a, | |
213 const scoped_refptr<const Extension>& b) { | |
214 return a->name() < b->name(); | |
215 } | |
216 }; | |
217 | |
218 static std::vector<base::string16> GetErrors() { | |
219 const std::vector<base::string16>* errors = | |
220 ExtensionErrorReporter::GetInstance()->GetErrors(); | |
221 std::vector<base::string16> ret_val; | |
222 | |
223 for (std::vector<base::string16>::const_iterator iter = errors->begin(); | |
224 iter != errors->end(); ++iter) { | |
225 std::string utf8_error = base::UTF16ToUTF8(*iter); | |
226 if (utf8_error.find(".svn") == std::string::npos) { | |
227 ret_val.push_back(*iter); | |
228 } | |
229 } | |
230 | |
231 // The tests rely on the errors being in a certain order, which can vary | |
232 // depending on how filesystem iteration works. | |
233 std::stable_sort(ret_val.begin(), ret_val.end()); | |
234 | |
235 return ret_val; | |
236 } | |
237 | |
238 static void AddPattern(URLPatternSet* extent, const std::string& pattern) { | 188 static void AddPattern(URLPatternSet* extent, const std::string& pattern) { |
239 int schemes = URLPattern::SCHEME_ALL; | 189 int schemes = URLPattern::SCHEME_ALL; |
240 extent->AddPattern(URLPattern(schemes, pattern)); | 190 extent->AddPattern(URLPattern(schemes, pattern)); |
241 } | 191 } |
242 | 192 |
243 base::FilePath GetTemporaryFile() { | 193 base::FilePath GetTemporaryFile() { |
244 base::FilePath temp_file; | 194 base::FilePath temp_file; |
245 CHECK(base::CreateTemporaryFile(&temp_file)); | 195 CHECK(base::CreateTemporaryFile(&temp_file)); |
246 return temp_file; | 196 return temp_file; |
247 } | 197 } |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 int ids_found_; | 423 int ids_found_; |
474 base::FilePath fake_base_path_; | 424 base::FilePath fake_base_path_; |
475 int expected_creation_flags_; | 425 int expected_creation_flags_; |
476 scoped_ptr<extensions::ExternalProviderImpl> provider_; | 426 scoped_ptr<extensions::ExternalProviderImpl> provider_; |
477 scoped_ptr<base::DictionaryValue> prefs_; | 427 scoped_ptr<base::DictionaryValue> prefs_; |
478 scoped_ptr<TestingProfile> profile_; | 428 scoped_ptr<TestingProfile> profile_; |
479 | 429 |
480 DISALLOW_COPY_AND_ASSIGN(MockProviderVisitor); | 430 DISALLOW_COPY_AND_ASSIGN(MockProviderVisitor); |
481 }; | 431 }; |
482 | 432 |
483 class ExtensionServiceTest : public extensions::ExtensionServiceTestBase, | 433 class ExtensionServiceTest |
484 public content::NotificationObserver { | 434 : public extensions::ExtensionServiceTestWithInstall { |
485 public: | 435 public: |
486 ExtensionServiceTest() | 436 ExtensionServiceTest() |
487 : unloaded_reason_(UnloadedExtensionInfo::REASON_UNDEFINED), | 437 : override_external_install_prompt_( |
488 installed_(NULL), | |
489 was_update_(false), | |
490 override_external_install_prompt_( | |
491 FeatureSwitch::prompt_for_external_extensions(), | 438 FeatureSwitch::prompt_for_external_extensions(), |
492 false), | 439 false) {} |
493 expected_extensions_count_(0) { | |
494 registrar_.Add(this, | |
495 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, | |
496 content::NotificationService::AllSources()); | |
497 registrar_.Add(this, | |
498 extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, | |
499 content::NotificationService::AllSources()); | |
500 registrar_.Add( | |
501 this, | |
502 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED, | |
503 content::NotificationService::AllSources()); | |
504 } | |
505 | |
506 void Observe(int type, | |
507 const content::NotificationSource& source, | |
508 const content::NotificationDetails& details) override { | |
509 switch (type) { | |
510 case extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: { | |
511 const Extension* extension = | |
512 content::Details<const Extension>(details).ptr(); | |
513 loaded_.push_back(make_scoped_refptr(extension)); | |
514 // The tests rely on the errors being in a certain order, which can vary | |
515 // depending on how filesystem iteration works. | |
516 std::stable_sort(loaded_.begin(), loaded_.end(), ExtensionsOrder()); | |
517 break; | |
518 } | |
519 | |
520 case extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: { | |
521 UnloadedExtensionInfo* unloaded_info = | |
522 content::Details<UnloadedExtensionInfo>(details).ptr(); | |
523 const Extension* e = unloaded_info->extension; | |
524 unloaded_id_ = e->id(); | |
525 unloaded_reason_ = unloaded_info->reason; | |
526 extensions::ExtensionList::iterator i = | |
527 std::find(loaded_.begin(), loaded_.end(), e); | |
528 // TODO(erikkay) fix so this can be an assert. Right now the tests | |
529 // are manually calling clear() on loaded_, so this isn't doable. | |
530 if (i == loaded_.end()) | |
531 return; | |
532 loaded_.erase(i); | |
533 break; | |
534 } | |
535 case extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED: { | |
536 const extensions::InstalledExtensionInfo* installed_info = | |
537 content::Details<const extensions::InstalledExtensionInfo>(details) | |
538 .ptr(); | |
539 installed_ = installed_info->extension; | |
540 was_update_ = installed_info->is_update; | |
541 old_name_ = installed_info->old_name; | |
542 break; | |
543 } | |
544 | |
545 default: | |
546 DCHECK(false); | |
547 } | |
548 } | |
549 | 440 |
550 void AddMockExternalProvider( | 441 void AddMockExternalProvider( |
551 extensions::ExternalProviderInterface* provider) { | 442 extensions::ExternalProviderInterface* provider) { |
552 service()->AddProviderForTesting(provider); | 443 service()->AddProviderForTesting(provider); |
553 } | 444 } |
554 | 445 |
555 void MockSyncStartFlare(bool* was_called, | |
556 syncer::ModelType* model_type_passed_in, | |
557 syncer::ModelType model_type) { | |
558 *was_called = true; | |
559 *model_type_passed_in = model_type; | |
560 } | |
561 | |
562 protected: | 446 protected: |
563 // Paths to some of the fake extensions. | 447 // Paths to some of the fake extensions. |
564 base::FilePath good0_path() { | |
565 return data_dir() | |
566 .AppendASCII("good") | |
567 .AppendASCII("Extensions") | |
568 .AppendASCII(good0) | |
569 .AppendASCII("1.0.0.0"); | |
570 } | |
571 | |
572 base::FilePath good1_path() { | 448 base::FilePath good1_path() { |
573 return data_dir() | 449 return data_dir() |
574 .AppendASCII("good") | 450 .AppendASCII("good") |
575 .AppendASCII("Extensions") | 451 .AppendASCII("Extensions") |
576 .AppendASCII(good1) | 452 .AppendASCII(good1) |
577 .AppendASCII("2"); | 453 .AppendASCII("2"); |
578 } | 454 } |
579 | 455 |
580 base::FilePath good2_path() { | 456 base::FilePath good2_path() { |
581 return data_dir() | 457 return data_dir() |
582 .AppendASCII("good") | 458 .AppendASCII("good") |
583 .AppendASCII("Extensions") | 459 .AppendASCII("Extensions") |
584 .AppendASCII(good2) | 460 .AppendASCII(good2) |
585 .AppendASCII("1.0"); | 461 .AppendASCII("1.0"); |
586 } | 462 } |
587 | 463 |
588 void TestExternalProvider(MockExtensionProvider* provider, | 464 void TestExternalProvider(MockExtensionProvider* provider, |
589 Manifest::Location location); | 465 Manifest::Location location); |
590 | 466 |
591 void PackCRX(const base::FilePath& dir_path, | |
592 const base::FilePath& pem_path, | |
593 const base::FilePath& crx_path) { | |
594 // Use the existing pem key, if provided. | |
595 base::FilePath pem_output_path; | |
596 if (pem_path.value().empty()) { | |
597 pem_output_path = crx_path.DirName().AppendASCII("temp.pem"); | |
598 } else { | |
599 ASSERT_TRUE(base::PathExists(pem_path)); | |
600 } | |
601 | |
602 ASSERT_TRUE(base::DeleteFile(crx_path, false)); | |
603 | |
604 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator()); | |
605 ASSERT_TRUE(creator->Run(dir_path, | |
606 crx_path, | |
607 pem_path, | |
608 pem_output_path, | |
609 ExtensionCreator::kOverwriteCRX)); | |
610 | |
611 ASSERT_TRUE(base::PathExists(crx_path)); | |
612 } | |
613 | |
614 enum InstallState { | |
615 INSTALL_FAILED, | |
616 INSTALL_UPDATED, | |
617 INSTALL_NEW, | |
618 INSTALL_WITHOUT_LOAD, | |
619 }; | |
620 | |
621 const Extension* PackAndInstallCRX(const base::FilePath& dir_path, | |
622 const base::FilePath& pem_path, | |
623 InstallState install_state, | |
624 int creation_flags) { | |
625 base::FilePath crx_path; | |
626 base::ScopedTempDir temp_dir; | |
627 EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); | |
628 crx_path = temp_dir.path().AppendASCII("temp.crx"); | |
629 | |
630 PackCRX(dir_path, pem_path, crx_path); | |
631 return InstallCRX(crx_path, install_state, creation_flags); | |
632 } | |
633 | |
634 const Extension* PackAndInstallCRX(const base::FilePath& dir_path, | |
635 const base::FilePath& pem_path, | |
636 InstallState install_state) { | |
637 return PackAndInstallCRX(dir_path, pem_path, install_state, | |
638 Extension::NO_FLAGS); | |
639 } | |
640 | |
641 const Extension* PackAndInstallCRX(const base::FilePath& dir_path, | |
642 InstallState install_state) { | |
643 return PackAndInstallCRX(dir_path, base::FilePath(), install_state, | |
644 Extension::NO_FLAGS); | |
645 } | |
646 | |
647 // Attempts to install an extension. Use INSTALL_FAILED if the installation | |
648 // is expected to fail. | |
649 // If |install_state| is INSTALL_UPDATED, and |expected_old_name| is | |
650 // non-empty, expects that the existing extension's title was | |
651 // |expected_old_name|. | |
652 const Extension* InstallCRX(const base::FilePath& path, | |
653 InstallState install_state, | |
654 int creation_flags, | |
655 const std::string& expected_old_name) { | |
656 InstallCRXInternal(path, creation_flags); | |
657 return VerifyCrxInstall(path, install_state, expected_old_name); | |
658 } | |
659 | |
660 // Attempts to install an extension. Use INSTALL_FAILED if the installation | |
661 // is expected to fail. | |
662 const Extension* InstallCRX(const base::FilePath& path, | |
663 InstallState install_state, | |
664 int creation_flags) { | |
665 return InstallCRX(path, install_state, creation_flags, std::string()); | |
666 } | |
667 | |
668 // Attempts to install an extension. Use INSTALL_FAILED if the installation | |
669 // is expected to fail. | |
670 const Extension* InstallCRX(const base::FilePath& path, | |
671 InstallState install_state) { | |
672 return InstallCRX(path, install_state, Extension::NO_FLAGS); | |
673 } | |
674 | |
675 const Extension* InstallCRXFromWebStore(const base::FilePath& path, | |
676 InstallState install_state) { | |
677 InstallCRXInternal(path, Extension::FROM_WEBSTORE); | |
678 return VerifyCrxInstall(path, install_state); | |
679 } | |
680 | |
681 const Extension* InstallCRXWithLocation(const base::FilePath& crx_path, | |
682 Manifest::Location install_location, | |
683 InstallState install_state) { | |
684 EXPECT_TRUE(base::PathExists(crx_path)) | |
685 << "Path does not exist: "<< crx_path.value().c_str(); | |
686 // no client (silent install) | |
687 scoped_refptr<CrxInstaller> installer( | |
688 CrxInstaller::CreateSilent(service())); | |
689 installer->set_install_source(install_location); | |
690 | |
691 content::WindowedNotificationObserver observer( | |
692 extensions::NOTIFICATION_CRX_INSTALLER_DONE, | |
693 content::NotificationService::AllSources()); | |
694 installer->InstallCrx(crx_path); | |
695 observer.Wait(); | |
696 | |
697 return VerifyCrxInstall(crx_path, install_state); | |
698 } | |
699 | |
700 // Verifies the result of a CRX installation. Used by InstallCRX. Set the | |
701 // |install_state| to INSTALL_FAILED if the installation is expected to fail. | |
702 // Returns an Extension pointer if the install succeeded, NULL otherwise. | |
703 const Extension* VerifyCrxInstall(const base::FilePath& path, | |
704 InstallState install_state) { | |
705 return VerifyCrxInstall(path, install_state, std::string()); | |
706 } | |
707 | |
708 // Verifies the result of a CRX installation. Used by InstallCRX. Set the | |
709 // |install_state| to INSTALL_FAILED if the installation is expected to fail. | |
710 // If |install_state| is INSTALL_UPDATED, and |expected_old_name| is | |
711 // non-empty, expects that the existing extension's title was | |
712 // |expected_old_name|. | |
713 // Returns an Extension pointer if the install succeeded, NULL otherwise. | |
714 const Extension* VerifyCrxInstall(const base::FilePath& path, | |
715 InstallState install_state, | |
716 const std::string& expected_old_name) { | |
717 std::vector<base::string16> errors = GetErrors(); | |
718 const Extension* extension = NULL; | |
719 if (install_state != INSTALL_FAILED) { | |
720 if (install_state == INSTALL_NEW) | |
721 ++expected_extensions_count_; | |
722 | |
723 EXPECT_TRUE(installed_) << path.value(); | |
724 // If and only if INSTALL_UPDATED, it should have the is_update flag. | |
725 EXPECT_EQ(install_state == INSTALL_UPDATED, was_update_) | |
726 << path.value(); | |
727 // If INSTALL_UPDATED, old_name_ should match the given string. | |
728 if (install_state == INSTALL_UPDATED && !expected_old_name.empty()) | |
729 EXPECT_EQ(expected_old_name, old_name_); | |
730 EXPECT_EQ(0u, errors.size()) << path.value(); | |
731 | |
732 if (install_state == INSTALL_WITHOUT_LOAD) { | |
733 EXPECT_EQ(0u, loaded_.size()) << path.value(); | |
734 } else { | |
735 EXPECT_EQ(1u, loaded_.size()) << path.value(); | |
736 size_t actual_extension_count = | |
737 registry()->enabled_extensions().size() + | |
738 registry()->disabled_extensions().size(); | |
739 EXPECT_EQ(expected_extensions_count_, actual_extension_count) << | |
740 path.value(); | |
741 extension = loaded_[0].get(); | |
742 EXPECT_TRUE(service()->GetExtensionById(extension->id(), false)) | |
743 << path.value(); | |
744 } | |
745 | |
746 for (std::vector<base::string16>::iterator err = errors.begin(); | |
747 err != errors.end(); ++err) { | |
748 LOG(ERROR) << *err; | |
749 } | |
750 } else { | |
751 EXPECT_FALSE(installed_) << path.value(); | |
752 EXPECT_EQ(0u, loaded_.size()) << path.value(); | |
753 EXPECT_EQ(1u, errors.size()) << path.value(); | |
754 } | |
755 | |
756 installed_ = NULL; | |
757 was_update_ = false; | |
758 old_name_ = ""; | |
759 loaded_.clear(); | |
760 ExtensionErrorReporter::GetInstance()->ClearErrors(); | |
761 return extension; | |
762 } | |
763 | |
764 enum UpdateState { | |
765 FAILED_SILENTLY, | |
766 FAILED, | |
767 UPDATED, | |
768 INSTALLED, | |
769 DISABLED, | |
770 ENABLED | |
771 }; | |
772 | |
773 void BlackListWebGL() { | 467 void BlackListWebGL() { |
774 static const std::string json_blacklist = | 468 static const std::string json_blacklist = |
775 "{\n" | 469 "{\n" |
776 " \"name\": \"gpu blacklist\",\n" | 470 " \"name\": \"gpu blacklist\",\n" |
777 " \"version\": \"1.0\",\n" | 471 " \"version\": \"1.0\",\n" |
778 " \"entries\": [\n" | 472 " \"entries\": [\n" |
779 " {\n" | 473 " {\n" |
780 " \"id\": 1,\n" | 474 " \"id\": 1,\n" |
781 " \"features\": [\"webgl\"]\n" | 475 " \"features\": [\"webgl\"]\n" |
782 " }\n" | 476 " }\n" |
783 " ]\n" | 477 " ]\n" |
784 "}"; | 478 "}"; |
785 gpu::GPUInfo gpu_info; | 479 gpu::GPUInfo gpu_info; |
786 content::GpuDataManager::GetInstance()->InitializeForTesting( | 480 content::GpuDataManager::GetInstance()->InitializeForTesting( |
787 json_blacklist, gpu_info); | 481 json_blacklist, gpu_info); |
788 } | 482 } |
789 | 483 |
790 // Grants all optional permissions stated in manifest to active permission | 484 // Grants all optional permissions stated in manifest to active permission |
791 // set for extension |id|. | 485 // set for extension |id|. |
792 void GrantAllOptionalPermissions(const std::string& id) { | 486 void GrantAllOptionalPermissions(const std::string& id) { |
793 const Extension* extension = service()->GetInstalledExtension(id); | 487 const Extension* extension = service()->GetInstalledExtension(id); |
794 const PermissionSet& all_optional_permissions = | 488 const PermissionSet& all_optional_permissions = |
795 extensions::PermissionsParser::GetOptionalPermissions(extension); | 489 extensions::PermissionsParser::GetOptionalPermissions(extension); |
796 extensions::PermissionsUpdater perms_updater(profile()); | 490 extensions::PermissionsUpdater perms_updater(profile()); |
797 perms_updater.AddPermissions(extension, all_optional_permissions); | 491 perms_updater.AddPermissions(extension, all_optional_permissions); |
798 } | 492 } |
799 | 493 |
800 // Helper method to set up a WindowedNotificationObserver to wait for a | |
801 // specific CrxInstaller to finish if we don't know the value of the | |
802 // |installer| yet. | |
803 static bool IsCrxInstallerDone(extensions::CrxInstaller** installer, | |
804 const content::NotificationSource& source, | |
805 const content::NotificationDetails& details) { | |
806 return content::Source<extensions::CrxInstaller>(source).ptr() == | |
807 *installer; | |
808 } | |
809 | |
810 void PackCRXAndUpdateExtension(const std::string& id, | |
811 const base::FilePath& dir_path, | |
812 const base::FilePath& pem_path, | |
813 UpdateState expected_state) { | |
814 base::ScopedTempDir temp_dir; | |
815 EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); | |
816 base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx"); | |
817 | |
818 PackCRX(dir_path, pem_path, crx_path); | |
819 UpdateExtension(id, crx_path, expected_state); | |
820 } | |
821 | |
822 void UpdateExtension(const std::string& id, | |
823 const base::FilePath& in_path, | |
824 UpdateState expected_state) { | |
825 ASSERT_TRUE(base::PathExists(in_path)); | |
826 | |
827 // We need to copy this to a temporary location because Update() will delete | |
828 // it. | |
829 base::FilePath path = temp_dir().path(); | |
830 path = path.Append(in_path.BaseName()); | |
831 ASSERT_TRUE(base::CopyFile(in_path, path)); | |
832 | |
833 int previous_enabled_extension_count = | |
834 registry()->enabled_extensions().size(); | |
835 int previous_installed_extension_count = | |
836 previous_enabled_extension_count + | |
837 registry()->disabled_extensions().size(); | |
838 | |
839 extensions::CrxInstaller* installer = NULL; | |
840 content::WindowedNotificationObserver observer( | |
841 extensions::NOTIFICATION_CRX_INSTALLER_DONE, | |
842 base::Bind(&IsCrxInstallerDone, &installer)); | |
843 service()->UpdateExtension(extensions::CRXFileInfo(id, path), true, | |
844 &installer); | |
845 | |
846 if (installer) | |
847 observer.Wait(); | |
848 else | |
849 base::RunLoop().RunUntilIdle(); | |
850 | |
851 std::vector<base::string16> errors = GetErrors(); | |
852 int error_count = errors.size(); | |
853 int enabled_extension_count = registry()->enabled_extensions().size(); | |
854 int installed_extension_count = | |
855 enabled_extension_count + registry()->disabled_extensions().size(); | |
856 | |
857 int expected_error_count = (expected_state == FAILED) ? 1 : 0; | |
858 EXPECT_EQ(expected_error_count, error_count) << path.value(); | |
859 | |
860 if (expected_state <= FAILED) { | |
861 EXPECT_EQ(previous_enabled_extension_count, | |
862 enabled_extension_count); | |
863 EXPECT_EQ(previous_installed_extension_count, | |
864 installed_extension_count); | |
865 } else { | |
866 int expected_installed_extension_count = | |
867 (expected_state >= INSTALLED) ? 1 : 0; | |
868 int expected_enabled_extension_count = | |
869 (expected_state >= ENABLED) ? 1 : 0; | |
870 EXPECT_EQ(expected_installed_extension_count, | |
871 installed_extension_count); | |
872 EXPECT_EQ(expected_enabled_extension_count, | |
873 enabled_extension_count); | |
874 } | |
875 | |
876 // Update() should the temporary input file. | |
877 EXPECT_FALSE(base::PathExists(path)); | |
878 } | |
879 | |
880 void TerminateExtension(const std::string& id) { | |
881 const Extension* extension = service()->GetInstalledExtension(id); | |
882 if (!extension) { | |
883 ADD_FAILURE(); | |
884 return; | |
885 } | |
886 service()->TrackTerminatedExtensionForTest(extension); | |
887 } | |
888 | |
889 testing::AssertionResult IsBlocked(const std::string& id) { | 494 testing::AssertionResult IsBlocked(const std::string& id) { |
890 scoped_ptr<extensions::ExtensionSet> all_unblocked_extensions = | 495 scoped_ptr<extensions::ExtensionSet> all_unblocked_extensions = |
891 registry()->GenerateInstalledExtensionsSet( | 496 registry()->GenerateInstalledExtensionsSet( |
892 ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::BLOCKED); | 497 ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::BLOCKED); |
893 if (all_unblocked_extensions.get()->Contains(id)) | 498 if (all_unblocked_extensions.get()->Contains(id)) |
894 return testing::AssertionFailure() << id << " is still unblocked!"; | 499 return testing::AssertionFailure() << id << " is still unblocked!"; |
895 if (!registry()->blocked_extensions().Contains(id)) | 500 if (!registry()->blocked_extensions().Contains(id)) |
896 return testing::AssertionFailure() << id << " is not blocked!"; | 501 return testing::AssertionFailure() << id << " is not blocked!"; |
897 return testing::AssertionSuccess(); | 502 return testing::AssertionSuccess(); |
898 } | 503 } |
(...skipping 13 matching lines...) Expand all Loading... |
912 ASSERT_TRUE(IsBlocked(extension_id)); | 517 ASSERT_TRUE(IsBlocked(extension_id)); |
913 else | 518 else |
914 ASSERT_FALSE(IsBlocked(extension_id)); | 519 ASSERT_FALSE(IsBlocked(extension_id)); |
915 | 520 |
916 service()->UnblockAllExtensions(); | 521 service()->UnblockAllExtensions(); |
917 base::RunLoop().RunUntilIdle(); | 522 base::RunLoop().RunUntilIdle(); |
918 | 523 |
919 ASSERT_FALSE(IsBlocked(extension_id)); | 524 ASSERT_FALSE(IsBlocked(extension_id)); |
920 } | 525 } |
921 | 526 |
922 size_t GetPrefKeyCount() { | |
923 const base::DictionaryValue* dict = | |
924 profile()->GetPrefs()->GetDictionary("extensions.settings"); | |
925 if (!dict) { | |
926 ADD_FAILURE(); | |
927 return 0; | |
928 } | |
929 return dict->size(); | |
930 } | |
931 | |
932 void UninstallExtension(const std::string& id, bool use_helper) { | |
933 UninstallExtension(id, use_helper, Extension::ENABLED); | |
934 } | |
935 | |
936 void UninstallExtension(const std::string& id, bool use_helper, | |
937 Extension::State expected_state) { | |
938 // Verify that the extension is installed. | |
939 base::FilePath extension_path = extensions_install_dir().AppendASCII(id); | |
940 EXPECT_TRUE(base::PathExists(extension_path)); | |
941 size_t pref_key_count = GetPrefKeyCount(); | |
942 EXPECT_GT(pref_key_count, 0u); | |
943 ValidateIntegerPref(id, "state", expected_state); | |
944 | |
945 // Uninstall it. | |
946 if (use_helper) { | |
947 EXPECT_TRUE(ExtensionService::UninstallExtensionHelper( | |
948 service(), id, extensions::UNINSTALL_REASON_FOR_TESTING)); | |
949 } else { | |
950 EXPECT_TRUE(service()->UninstallExtension( | |
951 id, | |
952 extensions::UNINSTALL_REASON_FOR_TESTING, | |
953 base::Bind(&base::DoNothing), | |
954 NULL)); | |
955 } | |
956 --expected_extensions_count_; | |
957 | |
958 // We should get an unload notification. | |
959 EXPECT_FALSE(unloaded_id_.empty()); | |
960 EXPECT_EQ(id, unloaded_id_); | |
961 | |
962 // Verify uninstalled state. | |
963 size_t new_pref_key_count = GetPrefKeyCount(); | |
964 if (new_pref_key_count == pref_key_count) { | |
965 ValidateIntegerPref(id, "state", | |
966 Extension::EXTERNAL_EXTENSION_UNINSTALLED); | |
967 } else { | |
968 EXPECT_EQ(new_pref_key_count, pref_key_count - 1); | |
969 } | |
970 | |
971 // The extension should not be in the service anymore. | |
972 EXPECT_FALSE(service()->GetInstalledExtension(id)); | |
973 base::RunLoop().RunUntilIdle(); | |
974 | |
975 // The directory should be gone. | |
976 EXPECT_FALSE(base::PathExists(extension_path)); | |
977 } | |
978 | |
979 void ValidatePrefKeyCount(size_t count) { | |
980 EXPECT_EQ(count, GetPrefKeyCount()); | |
981 } | |
982 | |
983 testing::AssertionResult ValidateBooleanPref( | |
984 const std::string& extension_id, | |
985 const std::string& pref_path, | |
986 bool expected_val) { | |
987 std::string msg = "while checking: "; | |
988 msg += extension_id; | |
989 msg += " "; | |
990 msg += pref_path; | |
991 msg += " == "; | |
992 msg += expected_val ? "true" : "false"; | |
993 | |
994 PrefService* prefs = profile()->GetPrefs(); | |
995 const base::DictionaryValue* dict = | |
996 prefs->GetDictionary("extensions.settings"); | |
997 if (!dict) { | |
998 return testing::AssertionFailure() | |
999 << "extension.settings does not exist " << msg; | |
1000 } | |
1001 | |
1002 const base::DictionaryValue* pref = NULL; | |
1003 if (!dict->GetDictionary(extension_id, &pref)) { | |
1004 return testing::AssertionFailure() | |
1005 << "extension pref does not exist " << msg; | |
1006 } | |
1007 | |
1008 bool val; | |
1009 if (!pref->GetBoolean(pref_path, &val)) { | |
1010 return testing::AssertionFailure() | |
1011 << pref_path << " pref not found " << msg; | |
1012 } | |
1013 | |
1014 return expected_val == val | |
1015 ? testing::AssertionSuccess() | |
1016 : testing::AssertionFailure() << "base::Value is incorrect " << msg; | |
1017 } | |
1018 | |
1019 bool IsPrefExist(const std::string& extension_id, | 527 bool IsPrefExist(const std::string& extension_id, |
1020 const std::string& pref_path) { | 528 const std::string& pref_path) { |
1021 const base::DictionaryValue* dict = | 529 const base::DictionaryValue* dict = |
1022 profile()->GetPrefs()->GetDictionary("extensions.settings"); | 530 profile()->GetPrefs()->GetDictionary("extensions.settings"); |
1023 if (dict == NULL) return false; | 531 if (dict == NULL) return false; |
1024 const base::DictionaryValue* pref = NULL; | 532 const base::DictionaryValue* pref = NULL; |
1025 if (!dict->GetDictionary(extension_id, &pref)) { | 533 if (!dict->GetDictionary(extension_id, &pref)) { |
1026 return false; | 534 return false; |
1027 } | 535 } |
1028 if (pref == NULL) { | 536 if (pref == NULL) { |
1029 return false; | 537 return false; |
1030 } | 538 } |
1031 bool val; | 539 bool val; |
1032 if (!pref->GetBoolean(pref_path, &val)) { | 540 if (!pref->GetBoolean(pref_path, &val)) { |
1033 return false; | 541 return false; |
1034 } | 542 } |
1035 return true; | 543 return true; |
1036 } | 544 } |
1037 | 545 |
1038 void ValidateIntegerPref(const std::string& extension_id, | |
1039 const std::string& pref_path, | |
1040 int expected_val) { | |
1041 std::string msg = " while checking: "; | |
1042 msg += extension_id; | |
1043 msg += " "; | |
1044 msg += pref_path; | |
1045 msg += " == "; | |
1046 msg += base::IntToString(expected_val); | |
1047 | |
1048 PrefService* prefs = profile()->GetPrefs(); | |
1049 const base::DictionaryValue* dict = | |
1050 prefs->GetDictionary("extensions.settings"); | |
1051 ASSERT_TRUE(dict != NULL) << msg; | |
1052 const base::DictionaryValue* pref = NULL; | |
1053 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg; | |
1054 EXPECT_TRUE(pref != NULL) << msg; | |
1055 int val; | |
1056 ASSERT_TRUE(pref->GetInteger(pref_path, &val)) << msg; | |
1057 EXPECT_EQ(expected_val, val) << msg; | |
1058 } | |
1059 | |
1060 void ValidateStringPref(const std::string& extension_id, | |
1061 const std::string& pref_path, | |
1062 const std::string& expected_val) { | |
1063 std::string msg = " while checking: "; | |
1064 msg += extension_id; | |
1065 msg += ".manifest."; | |
1066 msg += pref_path; | |
1067 msg += " == "; | |
1068 msg += expected_val; | |
1069 | |
1070 const base::DictionaryValue* dict = | |
1071 profile()->GetPrefs()->GetDictionary("extensions.settings"); | |
1072 ASSERT_TRUE(dict != NULL) << msg; | |
1073 const base::DictionaryValue* pref = NULL; | |
1074 std::string manifest_path = extension_id + ".manifest"; | |
1075 ASSERT_TRUE(dict->GetDictionary(manifest_path, &pref)) << msg; | |
1076 EXPECT_TRUE(pref != NULL) << msg; | |
1077 std::string val; | |
1078 ASSERT_TRUE(pref->GetString(pref_path, &val)) << msg; | |
1079 EXPECT_EQ(expected_val, val) << msg; | |
1080 } | |
1081 | |
1082 void SetPref(const std::string& extension_id, | 546 void SetPref(const std::string& extension_id, |
1083 const std::string& pref_path, | 547 const std::string& pref_path, |
1084 base::Value* value, | 548 base::Value* value, |
1085 const std::string& msg) { | 549 const std::string& msg) { |
1086 DictionaryPrefUpdate update(profile()->GetPrefs(), "extensions.settings"); | 550 DictionaryPrefUpdate update(profile()->GetPrefs(), "extensions.settings"); |
1087 base::DictionaryValue* dict = update.Get(); | 551 base::DictionaryValue* dict = update.Get(); |
1088 ASSERT_TRUE(dict != NULL) << msg; | 552 ASSERT_TRUE(dict != NULL) << msg; |
1089 base::DictionaryValue* pref = NULL; | 553 base::DictionaryValue* pref = NULL; |
1090 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg; | 554 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg; |
1091 EXPECT_TRUE(pref != NULL) << msg; | 555 EXPECT_TRUE(pref != NULL) << msg; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1154 ExtensionServiceTestBase::ExtensionServiceInitParams params = | 618 ExtensionServiceTestBase::ExtensionServiceInitParams params = |
1155 CreateDefaultInitParams(); | 619 CreateDefaultInitParams(); |
1156 params.pref_file = base::FilePath(); | 620 params.pref_file = base::FilePath(); |
1157 InitializeExtensionService(params); | 621 InitializeExtensionService(params); |
1158 } | 622 } |
1159 | 623 |
1160 extensions::ManagementPolicy* GetManagementPolicy() { | 624 extensions::ManagementPolicy* GetManagementPolicy() { |
1161 return ExtensionSystem::Get(browser_context())->management_policy(); | 625 return ExtensionSystem::Get(browser_context())->management_policy(); |
1162 } | 626 } |
1163 | 627 |
1164 ExtensionSyncService* extension_sync_service() { | |
1165 return ExtensionSyncService::Get(profile()); | |
1166 } | |
1167 | |
1168 protected: | 628 protected: |
1169 typedef extensions::ExtensionManagementPrefUpdater< | 629 typedef extensions::ExtensionManagementPrefUpdater< |
1170 syncable_prefs::TestingPrefServiceSyncable> ManagementPrefUpdater; | 630 syncable_prefs::TestingPrefServiceSyncable> ManagementPrefUpdater; |
1171 extensions::ExtensionList loaded_; | |
1172 std::string unloaded_id_; | |
1173 UnloadedExtensionInfo::Reason unloaded_reason_; | |
1174 const Extension* installed_; | |
1175 bool was_update_; | |
1176 std::string old_name_; | |
1177 FeatureSwitch::ScopedOverride override_external_install_prompt_; | 631 FeatureSwitch::ScopedOverride override_external_install_prompt_; |
1178 | |
1179 private: | |
1180 // Create a CrxInstaller and install the CRX file. | |
1181 // Instead of calling this method yourself, use InstallCRX(), which does extra | |
1182 // error checking. | |
1183 void InstallCRXInternal(const base::FilePath& crx_path) { | |
1184 InstallCRXInternal(crx_path, Extension::NO_FLAGS); | |
1185 } | |
1186 | |
1187 void InstallCRXInternal(const base::FilePath& crx_path, int creation_flags) { | |
1188 ASSERT_TRUE(base::PathExists(crx_path)) | |
1189 << "Path does not exist: "<< crx_path.value().c_str(); | |
1190 scoped_refptr<CrxInstaller> installer( | |
1191 CrxInstaller::CreateSilent(service())); | |
1192 installer->set_creation_flags(creation_flags); | |
1193 if (!(creation_flags & Extension::WAS_INSTALLED_BY_DEFAULT)) | |
1194 installer->set_allow_silent_install(true); | |
1195 | |
1196 content::WindowedNotificationObserver observer( | |
1197 extensions::NOTIFICATION_CRX_INSTALLER_DONE, | |
1198 content::Source<extensions::CrxInstaller>(installer.get())); | |
1199 | |
1200 installer->InstallCrx(crx_path); | |
1201 | |
1202 observer.Wait(); | |
1203 } | |
1204 | |
1205 size_t expected_extensions_count_; | |
1206 content::NotificationRegistrar registrar_; | |
1207 }; | 632 }; |
1208 | 633 |
1209 // Receives notifications from a PackExtensionJob, indicating either that | 634 // Receives notifications from a PackExtensionJob, indicating either that |
1210 // packing succeeded or that there was some error. | 635 // packing succeeded or that there was some error. |
1211 class PackExtensionTestClient : public extensions::PackExtensionJob::Client { | 636 class PackExtensionTestClient : public extensions::PackExtensionJob::Client { |
1212 public: | 637 public: |
1213 PackExtensionTestClient(const base::FilePath& expected_crx_path, | 638 PackExtensionTestClient(const base::FilePath& expected_crx_path, |
1214 const base::FilePath& expected_private_key_path); | 639 const base::FilePath& expected_private_key_path); |
1215 void OnPackSuccess(const base::FilePath& crx_path, | 640 void OnPackSuccess(const base::FilePath& crx_path, |
1216 const base::FilePath& private_key_path) override; | 641 const base::FilePath& private_key_path) override; |
(...skipping 4605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5822 ValidatePrefKeyCount(1); | 5247 ValidatePrefKeyCount(1); |
5823 | 5248 |
5824 // Reload all extensions, and make sure it comes back. | 5249 // Reload all extensions, and make sure it comes back. |
5825 std::string extension_id = (*registry()->enabled_extensions().begin())->id(); | 5250 std::string extension_id = (*registry()->enabled_extensions().begin())->id(); |
5826 loaded_.clear(); | 5251 loaded_.clear(); |
5827 service()->ReloadExtensionsForTest(); | 5252 service()->ReloadExtensionsForTest(); |
5828 ASSERT_EQ(1u, registry()->enabled_extensions().size()); | 5253 ASSERT_EQ(1u, registry()->enabled_extensions().size()); |
5829 EXPECT_EQ(extension_id, (*registry()->enabled_extensions().begin())->id()); | 5254 EXPECT_EQ(extension_id, (*registry()->enabled_extensions().begin())->id()); |
5830 } | 5255 } |
5831 | 5256 |
5832 TEST_F(ExtensionServiceTest, DeferredSyncStartupPreInstalledComponent) { | |
5833 InitializeEmptyExtensionService(); | |
5834 | |
5835 bool flare_was_called = false; | |
5836 syncer::ModelType triggered_type(syncer::UNSPECIFIED); | |
5837 base::WeakPtrFactory<ExtensionServiceTest> factory(this); | |
5838 extension_sync_service()->SetSyncStartFlareForTesting( | |
5839 base::Bind(&ExtensionServiceTest::MockSyncStartFlare, | |
5840 factory.GetWeakPtr(), | |
5841 &flare_was_called, // Safe due to WeakPtrFactory scope. | |
5842 &triggered_type)); // Safe due to WeakPtrFactory scope. | |
5843 | |
5844 // Install a component extension. | |
5845 std::string manifest; | |
5846 ASSERT_TRUE(base::ReadFileToString( | |
5847 good0_path().Append(extensions::kManifestFilename), &manifest)); | |
5848 service()->component_loader()->Add(manifest, good0_path()); | |
5849 ASSERT_FALSE(service()->is_ready()); | |
5850 service()->Init(); | |
5851 ASSERT_TRUE(service()->is_ready()); | |
5852 | |
5853 // Extensions added before service is_ready() don't trigger sync startup. | |
5854 EXPECT_FALSE(flare_was_called); | |
5855 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type); | |
5856 } | |
5857 | |
5858 TEST_F(ExtensionServiceTest, DeferredSyncStartupPreInstalledNormal) { | |
5859 InitializeGoodInstalledExtensionService(); | |
5860 | |
5861 bool flare_was_called = false; | |
5862 syncer::ModelType triggered_type(syncer::UNSPECIFIED); | |
5863 base::WeakPtrFactory<ExtensionServiceTest> factory(this); | |
5864 extension_sync_service()->SetSyncStartFlareForTesting( | |
5865 base::Bind(&ExtensionServiceTest::MockSyncStartFlare, | |
5866 factory.GetWeakPtr(), | |
5867 &flare_was_called, // Safe due to WeakPtrFactory scope. | |
5868 &triggered_type)); // Safe due to WeakPtrFactory scope. | |
5869 | |
5870 ASSERT_FALSE(service()->is_ready()); | |
5871 service()->Init(); | |
5872 ASSERT_EQ(3u, loaded_.size()); | |
5873 ASSERT_TRUE(service()->is_ready()); | |
5874 | |
5875 // Extensions added before service is_ready() don't trigger sync startup. | |
5876 EXPECT_FALSE(flare_was_called); | |
5877 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type); | |
5878 } | |
5879 | |
5880 TEST_F(ExtensionServiceTest, DeferredSyncStartupOnInstall) { | |
5881 InitializeEmptyExtensionService(); | |
5882 service()->Init(); | |
5883 ASSERT_TRUE(service()->is_ready()); | |
5884 | |
5885 bool flare_was_called = false; | |
5886 syncer::ModelType triggered_type(syncer::UNSPECIFIED); | |
5887 base::WeakPtrFactory<ExtensionServiceTest> factory(this); | |
5888 extension_sync_service()->SetSyncStartFlareForTesting( | |
5889 base::Bind(&ExtensionServiceTest::MockSyncStartFlare, | |
5890 factory.GetWeakPtr(), | |
5891 &flare_was_called, // Safe due to WeakPtrFactory scope. | |
5892 &triggered_type)); // Safe due to WeakPtrFactory scope. | |
5893 | |
5894 base::FilePath path = data_dir().AppendASCII("good.crx"); | |
5895 InstallCRX(path, INSTALL_NEW); | |
5896 | |
5897 EXPECT_TRUE(flare_was_called); | |
5898 EXPECT_EQ(syncer::EXTENSIONS, triggered_type); | |
5899 | |
5900 // Reset. | |
5901 flare_was_called = false; | |
5902 triggered_type = syncer::UNSPECIFIED; | |
5903 | |
5904 // Once sync starts, flare should no longer be invoked. | |
5905 extension_sync_service()->MergeDataAndStartSyncing( | |
5906 syncer::EXTENSIONS, | |
5907 syncer::SyncDataList(), | |
5908 scoped_ptr<syncer::SyncChangeProcessor>( | |
5909 new syncer::FakeSyncChangeProcessor), | |
5910 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
5911 path = data_dir().AppendASCII("page_action.crx"); | |
5912 InstallCRX(path, INSTALL_NEW); | |
5913 EXPECT_FALSE(flare_was_called); | |
5914 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type); | |
5915 } | |
5916 | |
5917 TEST_F(ExtensionServiceTest, DisableExtensionFromSync) { | |
5918 // Start the extensions service with one external extension already installed. | |
5919 base::FilePath source_install_dir = | |
5920 data_dir().AppendASCII("good").AppendASCII("Extensions"); | |
5921 base::FilePath pref_path = | |
5922 source_install_dir.DirName().Append(chrome::kPreferencesFilename); | |
5923 | |
5924 InitializeInstalledExtensionService(pref_path, source_install_dir); | |
5925 | |
5926 // The user has enabled sync. | |
5927 ProfileSyncService* sync_service = | |
5928 ProfileSyncServiceFactory::GetForProfile(profile()); | |
5929 sync_service->SetSyncSetupCompleted(); | |
5930 | |
5931 service()->Init(); | |
5932 ASSERT_TRUE(service()->is_ready()); | |
5933 | |
5934 ASSERT_EQ(3u, loaded_.size()); | |
5935 | |
5936 // We start enabled. | |
5937 const Extension* extension = service()->GetExtensionById(good0, true); | |
5938 ASSERT_TRUE(extension); | |
5939 ASSERT_TRUE(service()->IsExtensionEnabled(good0)); | |
5940 | |
5941 // Sync starts up. | |
5942 extension_sync_service()->MergeDataAndStartSyncing( | |
5943 syncer::EXTENSIONS, | |
5944 syncer::SyncDataList(), | |
5945 make_scoped_ptr(new syncer::FakeSyncChangeProcessor), | |
5946 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
5947 | |
5948 // Then sync data arrives telling us to disable |good0|. | |
5949 ExtensionSyncData disable_good_crx(*extension, false, | |
5950 Extension::DISABLE_USER_ACTION, false, | |
5951 false, ExtensionSyncData::BOOLEAN_UNSET); | |
5952 syncer::SyncChange sync_change(FROM_HERE, | |
5953 syncer::SyncChange::ACTION_UPDATE, | |
5954 disable_good_crx.GetSyncData()); | |
5955 syncer::SyncChangeList list(1, sync_change); | |
5956 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
5957 | |
5958 ASSERT_FALSE(service()->IsExtensionEnabled(good0)); | |
5959 } | |
5960 | |
5961 TEST_F(ExtensionServiceTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) { | |
5962 // Start the extension service with three extensions already installed. | |
5963 base::FilePath source_install_dir = | |
5964 data_dir().AppendASCII("good").AppendASCII("Extensions"); | |
5965 base::FilePath pref_path = | |
5966 source_install_dir.DirName().Append(chrome::kPreferencesFilename); | |
5967 | |
5968 InitializeInstalledExtensionService(pref_path, source_install_dir); | |
5969 | |
5970 // The user has enabled sync. | |
5971 ProfileSyncService* sync_service = | |
5972 ProfileSyncServiceFactory::GetForProfile(profile()); | |
5973 sync_service->SetSyncSetupCompleted(); | |
5974 // Make sure ExtensionSyncService is created, so it'll be notified of changes. | |
5975 extension_sync_service(); | |
5976 | |
5977 service()->Init(); | |
5978 ASSERT_TRUE(service()->is_ready()); | |
5979 ASSERT_EQ(3u, loaded_.size()); | |
5980 | |
5981 ASSERT_TRUE(service()->IsExtensionEnabled(good0)); | |
5982 ASSERT_TRUE(service()->IsExtensionEnabled(good2)); | |
5983 | |
5984 // Disable and re-enable good0 before first sync data arrives. | |
5985 service()->DisableExtension(good0, Extension::DISABLE_USER_ACTION); | |
5986 ASSERT_FALSE(service()->IsExtensionEnabled(good0)); | |
5987 service()->EnableExtension(good0); | |
5988 ASSERT_TRUE(service()->IsExtensionEnabled(good0)); | |
5989 // Disable good2 before first sync data arrives (good1 is considered | |
5990 // non-syncable because it has plugin permission). | |
5991 service()->DisableExtension(good2, Extension::DISABLE_USER_ACTION); | |
5992 ASSERT_FALSE(service()->IsExtensionEnabled(good2)); | |
5993 | |
5994 const Extension* extension0 = service()->GetExtensionById(good0, true); | |
5995 const Extension* extension2 = service()->GetExtensionById(good2, true); | |
5996 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0)); | |
5997 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2)); | |
5998 | |
5999 // Now sync data comes in that says to disable good0 and enable good2. | |
6000 ExtensionSyncData disable_good0(*extension0, false, | |
6001 Extension::DISABLE_USER_ACTION, false, false, | |
6002 ExtensionSyncData::BOOLEAN_UNSET); | |
6003 ExtensionSyncData enable_good2(*extension2, true, Extension::DISABLE_NONE, | |
6004 false, false, | |
6005 ExtensionSyncData::BOOLEAN_UNSET); | |
6006 syncer::SyncDataList sync_data; | |
6007 sync_data.push_back(disable_good0.GetSyncData()); | |
6008 sync_data.push_back(enable_good2.GetSyncData()); | |
6009 extension_sync_service()->MergeDataAndStartSyncing( | |
6010 syncer::EXTENSIONS, | |
6011 sync_data, | |
6012 make_scoped_ptr(new syncer::FakeSyncChangeProcessor), | |
6013 make_scoped_ptr(new syncer::SyncErrorFactoryMock)); | |
6014 | |
6015 // Both sync changes should be ignored, since the local state was changed | |
6016 // before sync started, and so the local state is considered more recent. | |
6017 EXPECT_TRUE(service()->IsExtensionEnabled(good0)); | |
6018 EXPECT_FALSE(service()->IsExtensionEnabled(good2)); | |
6019 } | |
6020 | |
6021 TEST_F(ExtensionServiceTest, GetSyncData) { | |
6022 InitializeEmptyExtensionService(); | |
6023 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW); | |
6024 const Extension* extension = service()->GetInstalledExtension(good_crx); | |
6025 ASSERT_TRUE(extension); | |
6026 | |
6027 extension_sync_service()->MergeDataAndStartSyncing( | |
6028 syncer::EXTENSIONS, | |
6029 syncer::SyncDataList(), | |
6030 scoped_ptr<syncer::SyncChangeProcessor>( | |
6031 new syncer::FakeSyncChangeProcessor), | |
6032 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6033 | |
6034 syncer::SyncDataList list = | |
6035 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS); | |
6036 ASSERT_EQ(list.size(), 1U); | |
6037 scoped_ptr<ExtensionSyncData> data = | |
6038 ExtensionSyncData::CreateFromSyncData(list[0]); | |
6039 ASSERT_TRUE(data.get()); | |
6040 EXPECT_EQ(extension->id(), data->id()); | |
6041 EXPECT_FALSE(data->uninstalled()); | |
6042 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled()); | |
6043 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()), | |
6044 data->incognito_enabled()); | |
6045 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled()); | |
6046 EXPECT_TRUE(data->version().Equals(*extension->version())); | |
6047 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension), | |
6048 data->update_url()); | |
6049 EXPECT_EQ(extension->name(), data->name()); | |
6050 } | |
6051 | |
6052 TEST_F(ExtensionServiceTest, GetSyncDataTerminated) { | |
6053 InitializeEmptyExtensionService(); | |
6054 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW); | |
6055 TerminateExtension(good_crx); | |
6056 const Extension* extension = service()->GetInstalledExtension(good_crx); | |
6057 ASSERT_TRUE(extension); | |
6058 | |
6059 syncer::FakeSyncChangeProcessor processor; | |
6060 extension_sync_service()->MergeDataAndStartSyncing( | |
6061 syncer::EXTENSIONS, | |
6062 syncer::SyncDataList(), | |
6063 scoped_ptr<syncer::SyncChangeProcessor>( | |
6064 new syncer::FakeSyncChangeProcessor), | |
6065 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6066 | |
6067 syncer::SyncDataList list = | |
6068 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS); | |
6069 ASSERT_EQ(list.size(), 1U); | |
6070 scoped_ptr<ExtensionSyncData> data = | |
6071 ExtensionSyncData::CreateFromSyncData(list[0]); | |
6072 ASSERT_TRUE(data.get()); | |
6073 EXPECT_EQ(extension->id(), data->id()); | |
6074 EXPECT_FALSE(data->uninstalled()); | |
6075 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled()); | |
6076 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()), | |
6077 data->incognito_enabled()); | |
6078 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled()); | |
6079 EXPECT_TRUE(data->version().Equals(*extension->version())); | |
6080 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension), | |
6081 data->update_url()); | |
6082 EXPECT_EQ(extension->name(), data->name()); | |
6083 } | |
6084 | |
6085 TEST_F(ExtensionServiceTest, GetSyncDataFilter) { | |
6086 InitializeEmptyExtensionService(); | |
6087 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW); | |
6088 const Extension* extension = service()->GetInstalledExtension(good_crx); | |
6089 ASSERT_TRUE(extension); | |
6090 | |
6091 syncer::FakeSyncChangeProcessor processor; | |
6092 extension_sync_service()->MergeDataAndStartSyncing( | |
6093 syncer::APPS, | |
6094 syncer::SyncDataList(), | |
6095 scoped_ptr<syncer::SyncChangeProcessor>( | |
6096 new syncer::FakeSyncChangeProcessor), | |
6097 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6098 | |
6099 syncer::SyncDataList list = | |
6100 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS); | |
6101 ASSERT_EQ(list.size(), 0U); | |
6102 } | |
6103 | |
6104 TEST_F(ExtensionServiceTest, GetSyncExtensionDataUserSettings) { | |
6105 InitializeEmptyExtensionService(); | |
6106 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW); | |
6107 const Extension* extension = service()->GetInstalledExtension(good_crx); | |
6108 ASSERT_TRUE(extension); | |
6109 | |
6110 syncer::FakeSyncChangeProcessor processor; | |
6111 extension_sync_service()->MergeDataAndStartSyncing( | |
6112 syncer::EXTENSIONS, | |
6113 syncer::SyncDataList(), | |
6114 scoped_ptr<syncer::SyncChangeProcessor>( | |
6115 new syncer::FakeSyncChangeProcessor), | |
6116 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6117 | |
6118 { | |
6119 syncer::SyncDataList list = | |
6120 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS); | |
6121 ASSERT_EQ(list.size(), 1U); | |
6122 scoped_ptr<ExtensionSyncData> data = | |
6123 ExtensionSyncData::CreateFromSyncData(list[0]); | |
6124 ASSERT_TRUE(data.get()); | |
6125 EXPECT_TRUE(data->enabled()); | |
6126 EXPECT_FALSE(data->incognito_enabled()); | |
6127 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled()); | |
6128 } | |
6129 | |
6130 service()->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION); | |
6131 { | |
6132 syncer::SyncDataList list = | |
6133 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS); | |
6134 ASSERT_EQ(list.size(), 1U); | |
6135 scoped_ptr<ExtensionSyncData> data = | |
6136 ExtensionSyncData::CreateFromSyncData(list[0]); | |
6137 ASSERT_TRUE(data.get()); | |
6138 EXPECT_FALSE(data->enabled()); | |
6139 EXPECT_FALSE(data->incognito_enabled()); | |
6140 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled()); | |
6141 } | |
6142 | |
6143 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true); | |
6144 extensions::util::SetAllowedScriptingOnAllUrls( | |
6145 good_crx, profile(), false); | |
6146 { | |
6147 syncer::SyncDataList list = | |
6148 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS); | |
6149 ASSERT_EQ(list.size(), 1U); | |
6150 scoped_ptr<ExtensionSyncData> data = | |
6151 ExtensionSyncData::CreateFromSyncData(list[0]); | |
6152 ASSERT_TRUE(data.get()); | |
6153 EXPECT_FALSE(data->enabled()); | |
6154 EXPECT_TRUE(data->incognito_enabled()); | |
6155 EXPECT_EQ(ExtensionSyncData::BOOLEAN_FALSE, data->all_urls_enabled()); | |
6156 } | |
6157 | |
6158 service()->EnableExtension(good_crx); | |
6159 extensions::util::SetAllowedScriptingOnAllUrls( | |
6160 good_crx, profile(), true); | |
6161 { | |
6162 syncer::SyncDataList list = | |
6163 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS); | |
6164 ASSERT_EQ(list.size(), 1U); | |
6165 scoped_ptr<ExtensionSyncData> data = | |
6166 ExtensionSyncData::CreateFromSyncData(list[0]); | |
6167 ASSERT_TRUE(data.get()); | |
6168 EXPECT_TRUE(data->enabled()); | |
6169 EXPECT_TRUE(data->incognito_enabled()); | |
6170 EXPECT_EQ(ExtensionSyncData::BOOLEAN_TRUE, data->all_urls_enabled()); | |
6171 } | |
6172 } | |
6173 | |
6174 TEST_F(ExtensionServiceTest, SyncForUninstalledExternalExtension) { | |
6175 InitializeEmptyExtensionService(); | |
6176 InstallCRXWithLocation( | |
6177 data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF, INSTALL_NEW); | |
6178 const Extension* extension = service()->GetInstalledExtension(good_crx); | |
6179 ASSERT_TRUE(extension); | |
6180 | |
6181 syncer::FakeSyncChangeProcessor processor; | |
6182 extension_sync_service()->MergeDataAndStartSyncing( | |
6183 syncer::EXTENSIONS, | |
6184 syncer::SyncDataList(), | |
6185 scoped_ptr<syncer::SyncChangeProcessor>( | |
6186 new syncer::FakeSyncChangeProcessor), | |
6187 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6188 | |
6189 UninstallExtension(good_crx, false); | |
6190 EXPECT_TRUE( | |
6191 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx)); | |
6192 | |
6193 sync_pb::EntitySpecifics specifics; | |
6194 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app(); | |
6195 sync_pb::ExtensionSpecifics* extension_specifics = | |
6196 app_specifics->mutable_extension(); | |
6197 extension_specifics->set_id(good_crx); | |
6198 extension_specifics->set_version("1.0"); | |
6199 extension_specifics->set_enabled(true); | |
6200 | |
6201 syncer::SyncData sync_data = | |
6202 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6203 syncer::SyncChange sync_change(FROM_HERE, | |
6204 syncer::SyncChange::ACTION_UPDATE, | |
6205 sync_data); | |
6206 syncer::SyncChangeList list(1); | |
6207 list[0] = sync_change; | |
6208 | |
6209 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6210 EXPECT_TRUE( | |
6211 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx)); | |
6212 } | |
6213 | |
6214 TEST_F(ExtensionServiceTest, GetSyncAppDataUserSettings) { | |
6215 InitializeEmptyExtensionService(); | |
6216 const Extension* app = | |
6217 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW); | |
6218 ASSERT_TRUE(app); | |
6219 ASSERT_TRUE(app->is_app()); | |
6220 | |
6221 syncer::FakeSyncChangeProcessor processor; | |
6222 extension_sync_service()->MergeDataAndStartSyncing( | |
6223 syncer::APPS, | |
6224 syncer::SyncDataList(), | |
6225 scoped_ptr<syncer::SyncChangeProcessor>( | |
6226 new syncer::FakeSyncChangeProcessor), | |
6227 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6228 | |
6229 syncer::StringOrdinal initial_ordinal = | |
6230 syncer::StringOrdinal::CreateInitialOrdinal(); | |
6231 { | |
6232 syncer::SyncDataList list = | |
6233 extension_sync_service()->GetAllSyncData(syncer::APPS); | |
6234 ASSERT_EQ(list.size(), 1U); | |
6235 | |
6236 scoped_ptr<ExtensionSyncData> app_sync_data = | |
6237 ExtensionSyncData::CreateFromSyncData(list[0]); | |
6238 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal())); | |
6239 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal())); | |
6240 } | |
6241 | |
6242 AppSorting* sorting = ExtensionPrefs::Get(profile())->app_sorting(); | |
6243 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter()); | |
6244 { | |
6245 syncer::SyncDataList list = | |
6246 extension_sync_service()->GetAllSyncData(syncer::APPS); | |
6247 ASSERT_EQ(list.size(), 1U); | |
6248 | |
6249 scoped_ptr<ExtensionSyncData> app_sync_data = | |
6250 ExtensionSyncData::CreateFromSyncData(list[0]); | |
6251 ASSERT_TRUE(app_sync_data.get()); | |
6252 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal())); | |
6253 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal())); | |
6254 } | |
6255 | |
6256 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter()); | |
6257 { | |
6258 syncer::SyncDataList list = | |
6259 extension_sync_service()->GetAllSyncData(syncer::APPS); | |
6260 ASSERT_EQ(list.size(), 1U); | |
6261 | |
6262 scoped_ptr<ExtensionSyncData> app_sync_data = | |
6263 ExtensionSyncData::CreateFromSyncData(list[0]); | |
6264 ASSERT_TRUE(app_sync_data.get()); | |
6265 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal())); | |
6266 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal())); | |
6267 } | |
6268 } | |
6269 | |
6270 // TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from | |
6271 // ExtensionService, so this test probably needs a new home. Unfortunately, it | |
6272 // relies pretty heavily on things like InitializeExtension[Sync]Service() and | |
6273 // PackAndInstallCRX(). When we clean up a bit more, this should move out. | |
6274 TEST_F(ExtensionServiceTest, GetSyncAppDataUserSettingsOnExtensionMoved) { | |
6275 InitializeEmptyExtensionService(); | |
6276 const size_t kAppCount = 3; | |
6277 const Extension* apps[kAppCount]; | |
6278 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW); | |
6279 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW); | |
6280 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW); | |
6281 for (size_t i = 0; i < kAppCount; ++i) { | |
6282 ASSERT_TRUE(apps[i]); | |
6283 ASSERT_TRUE(apps[i]->is_app()); | |
6284 } | |
6285 | |
6286 syncer::FakeSyncChangeProcessor processor; | |
6287 extension_sync_service()->MergeDataAndStartSyncing( | |
6288 syncer::APPS, | |
6289 syncer::SyncDataList(), | |
6290 scoped_ptr<syncer::SyncChangeProcessor>( | |
6291 new syncer::FakeSyncChangeProcessor), | |
6292 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6293 | |
6294 ExtensionPrefs::Get(service()->GetBrowserContext()) | |
6295 ->app_sorting() | |
6296 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id()); | |
6297 { | |
6298 syncer::SyncDataList list = | |
6299 extension_sync_service()->GetAllSyncData(syncer::APPS); | |
6300 ASSERT_EQ(list.size(), 3U); | |
6301 | |
6302 scoped_ptr<ExtensionSyncData> data[kAppCount]; | |
6303 for (size_t i = 0; i < kAppCount; ++i) { | |
6304 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]); | |
6305 ASSERT_TRUE(data[i].get()); | |
6306 } | |
6307 | |
6308 // The sync data is not always in the same order our apps were installed in, | |
6309 // so we do that sorting here so we can make sure the values are changed as | |
6310 // expected. | |
6311 syncer::StringOrdinal app_launch_ordinals[kAppCount]; | |
6312 for (size_t i = 0; i < kAppCount; ++i) { | |
6313 for (size_t j = 0; j < kAppCount; ++j) { | |
6314 if (apps[i]->id() == data[j]->id()) | |
6315 app_launch_ordinals[i] = data[j]->app_launch_ordinal(); | |
6316 } | |
6317 } | |
6318 | |
6319 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0])); | |
6320 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2])); | |
6321 } | |
6322 } | |
6323 | |
6324 TEST_F(ExtensionServiceTest, GetSyncDataList) { | |
6325 InitializeEmptyExtensionService(); | |
6326 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW); | |
6327 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW); | |
6328 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW); | |
6329 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW); | |
6330 | |
6331 syncer::FakeSyncChangeProcessor processor; | |
6332 extension_sync_service()->MergeDataAndStartSyncing( | |
6333 syncer::APPS, | |
6334 syncer::SyncDataList(), | |
6335 scoped_ptr<syncer::SyncChangeProcessor>( | |
6336 new syncer::FakeSyncChangeProcessor), | |
6337 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6338 extension_sync_service()->MergeDataAndStartSyncing( | |
6339 syncer::EXTENSIONS, | |
6340 syncer::SyncDataList(), | |
6341 scoped_ptr<syncer::SyncChangeProcessor>( | |
6342 new syncer::FakeSyncChangeProcessor), | |
6343 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6344 | |
6345 service()->DisableExtension(page_action, Extension::DISABLE_USER_ACTION); | |
6346 TerminateExtension(theme2_crx); | |
6347 | |
6348 EXPECT_EQ(0u, extension_sync_service()->GetAllSyncData(syncer::APPS).size()); | |
6349 EXPECT_EQ( | |
6350 2u, extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS).size()); | |
6351 } | |
6352 | |
6353 TEST_F(ExtensionServiceTest, ProcessSyncDataUninstall) { | |
6354 InitializeEmptyExtensionService(); | |
6355 syncer::FakeSyncChangeProcessor processor; | |
6356 extension_sync_service()->MergeDataAndStartSyncing( | |
6357 syncer::EXTENSIONS, | |
6358 syncer::SyncDataList(), | |
6359 scoped_ptr<syncer::SyncChangeProcessor>( | |
6360 new syncer::FakeSyncChangeProcessor), | |
6361 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6362 | |
6363 sync_pb::EntitySpecifics specifics; | |
6364 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
6365 ext_specifics->set_id(good_crx); | |
6366 ext_specifics->set_version("1.0"); | |
6367 syncer::SyncData sync_data = | |
6368 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6369 syncer::SyncChange sync_change(FROM_HERE, | |
6370 syncer::SyncChange::ACTION_DELETE, | |
6371 sync_data); | |
6372 syncer::SyncChangeList list(1); | |
6373 list[0] = sync_change; | |
6374 | |
6375 // Should do nothing. | |
6376 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6377 EXPECT_FALSE(service()->GetExtensionById(good_crx, true)); | |
6378 | |
6379 // Install the extension. | |
6380 base::FilePath extension_path = data_dir().AppendASCII("good.crx"); | |
6381 InstallCRX(extension_path, INSTALL_NEW); | |
6382 EXPECT_TRUE(service()->GetExtensionById(good_crx, true)); | |
6383 | |
6384 // Should uninstall the extension. | |
6385 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6386 EXPECT_FALSE(service()->GetExtensionById(good_crx, true)); | |
6387 | |
6388 // Should again do nothing. | |
6389 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6390 EXPECT_FALSE(service()->GetExtensionById(good_crx, true)); | |
6391 } | |
6392 | |
6393 TEST_F(ExtensionServiceTest, ProcessSyncDataWrongType) { | |
6394 InitializeEmptyExtensionService(); | |
6395 | |
6396 // Install the extension. | |
6397 base::FilePath extension_path = data_dir().AppendASCII("good.crx"); | |
6398 InstallCRX(extension_path, INSTALL_NEW); | |
6399 EXPECT_TRUE(service()->GetExtensionById(good_crx, true)); | |
6400 | |
6401 sync_pb::EntitySpecifics specifics; | |
6402 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app(); | |
6403 sync_pb::ExtensionSpecifics* extension_specifics = | |
6404 app_specifics->mutable_extension(); | |
6405 extension_specifics->set_id(good_crx); | |
6406 extension_specifics->set_version( | |
6407 service()->GetInstalledExtension(good_crx)->version()->GetString()); | |
6408 | |
6409 { | |
6410 extension_specifics->set_enabled(true); | |
6411 syncer::SyncData sync_data = | |
6412 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6413 syncer::SyncChange sync_change(FROM_HERE, | |
6414 syncer::SyncChange::ACTION_DELETE, | |
6415 sync_data); | |
6416 syncer::SyncChangeList list(1); | |
6417 list[0] = sync_change; | |
6418 | |
6419 // Should do nothing | |
6420 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6421 EXPECT_TRUE(service()->GetExtensionById(good_crx, true)); | |
6422 } | |
6423 | |
6424 { | |
6425 extension_specifics->set_enabled(false); | |
6426 syncer::SyncData sync_data = | |
6427 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6428 syncer::SyncChange sync_change(FROM_HERE, | |
6429 syncer::SyncChange::ACTION_UPDATE, | |
6430 sync_data); | |
6431 syncer::SyncChangeList list(1); | |
6432 list[0] = sync_change; | |
6433 | |
6434 // Should again do nothing. | |
6435 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6436 EXPECT_TRUE(service()->GetExtensionById(good_crx, false)); | |
6437 } | |
6438 } | |
6439 | |
6440 TEST_F(ExtensionServiceTest, ProcessSyncDataSettings) { | |
6441 InitializeEmptyExtensionService(); | |
6442 syncer::FakeSyncChangeProcessor processor; | |
6443 extension_sync_service()->MergeDataAndStartSyncing( | |
6444 syncer::EXTENSIONS, | |
6445 syncer::SyncDataList(), | |
6446 scoped_ptr<syncer::SyncChangeProcessor>( | |
6447 new syncer::FakeSyncChangeProcessor), | |
6448 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6449 | |
6450 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW); | |
6451 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx)); | |
6452 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile())); | |
6453 EXPECT_FALSE(extensions::util::HasSetAllowedScriptingOnAllUrls( | |
6454 good_crx, profile())); | |
6455 const bool kDefaultAllowedScripting = | |
6456 extensions::util::DefaultAllowedScriptingOnAllUrls(); | |
6457 EXPECT_EQ(kDefaultAllowedScripting, | |
6458 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile())); | |
6459 | |
6460 sync_pb::EntitySpecifics specifics; | |
6461 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
6462 ext_specifics->set_id(good_crx); | |
6463 ext_specifics->set_version( | |
6464 service()->GetInstalledExtension(good_crx)->version()->GetString()); | |
6465 ext_specifics->set_enabled(false); | |
6466 | |
6467 { | |
6468 syncer::SyncData sync_data = | |
6469 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6470 syncer::SyncChange sync_change(FROM_HERE, | |
6471 syncer::SyncChange::ACTION_UPDATE, | |
6472 sync_data); | |
6473 syncer::SyncChangeList list(1); | |
6474 list[0] = sync_change; | |
6475 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6476 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx)); | |
6477 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile())); | |
6478 EXPECT_FALSE(extensions::util::HasSetAllowedScriptingOnAllUrls( | |
6479 good_crx, profile())); | |
6480 EXPECT_EQ(kDefaultAllowedScripting, | |
6481 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile())); | |
6482 } | |
6483 | |
6484 { | |
6485 ext_specifics->set_enabled(true); | |
6486 ext_specifics->set_incognito_enabled(true); | |
6487 syncer::SyncData sync_data = | |
6488 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6489 syncer::SyncChange sync_change(FROM_HERE, | |
6490 syncer::SyncChange::ACTION_UPDATE, | |
6491 sync_data); | |
6492 syncer::SyncChangeList list(1); | |
6493 list[0] = sync_change; | |
6494 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6495 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx)); | |
6496 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile())); | |
6497 } | |
6498 | |
6499 { | |
6500 ext_specifics->set_enabled(false); | |
6501 ext_specifics->set_incognito_enabled(true); | |
6502 syncer::SyncData sync_data = | |
6503 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6504 syncer::SyncChange sync_change(FROM_HERE, | |
6505 syncer::SyncChange::ACTION_UPDATE, | |
6506 sync_data); | |
6507 syncer::SyncChangeList list(1); | |
6508 list[0] = sync_change; | |
6509 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6510 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx)); | |
6511 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile())); | |
6512 } | |
6513 | |
6514 { | |
6515 ext_specifics->set_enabled(true); | |
6516 ext_specifics->set_all_urls_enabled(!kDefaultAllowedScripting); | |
6517 syncer::SyncData sync_data = | |
6518 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6519 syncer::SyncChange sync_change(FROM_HERE, | |
6520 syncer::SyncChange::ACTION_UPDATE, | |
6521 sync_data); | |
6522 syncer::SyncChangeList list(1); | |
6523 list[0] = sync_change; | |
6524 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6525 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx)); | |
6526 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls( | |
6527 good_crx, profile())); | |
6528 EXPECT_EQ(!kDefaultAllowedScripting, | |
6529 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile())); | |
6530 } | |
6531 | |
6532 { | |
6533 ext_specifics->set_all_urls_enabled(kDefaultAllowedScripting); | |
6534 syncer::SyncData sync_data = | |
6535 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6536 syncer::SyncChange sync_change(FROM_HERE, | |
6537 syncer::SyncChange::ACTION_UPDATE, | |
6538 sync_data); | |
6539 syncer::SyncChangeList list(1); | |
6540 list[0] = sync_change; | |
6541 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6542 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx)); | |
6543 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls( | |
6544 good_crx, profile())); | |
6545 EXPECT_EQ(kDefaultAllowedScripting, | |
6546 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile())); | |
6547 } | |
6548 | |
6549 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx)); | |
6550 } | |
6551 | |
6552 TEST_F(ExtensionServiceTest, ProcessSyncDataNewExtension) { | |
6553 InitializeEmptyExtensionService(); | |
6554 syncer::FakeSyncChangeProcessor processor; | |
6555 extension_sync_service()->MergeDataAndStartSyncing( | |
6556 syncer::EXTENSIONS, | |
6557 syncer::SyncDataList(), | |
6558 scoped_ptr<syncer::SyncChangeProcessor>( | |
6559 new syncer::FakeSyncChangeProcessor), | |
6560 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6561 | |
6562 const base::FilePath path = data_dir().AppendASCII("good.crx"); | |
6563 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); | |
6564 | |
6565 struct TestCase { | |
6566 const char* name; // For failure output only. | |
6567 bool sync_enabled; // The "enabled" flag coming in from Sync. | |
6568 // The disable reason(s) coming in from Sync, or -1 for "not set". | |
6569 int sync_disable_reasons; | |
6570 // The disable reason(s) that should be set on the installed extension. | |
6571 // This will usually be the same as |sync_disable_reasons|, but see the | |
6572 // "Legacy" case. | |
6573 int expect_disable_reasons; | |
6574 // Whether the extension's permissions should be auto-granted during | |
6575 // installation. | |
6576 bool expect_permissions_granted; | |
6577 } test_cases[] = { | |
6578 // Standard case: Extension comes in enabled; permissions should be granted | |
6579 // during installation. | |
6580 { "Standard", true, 0, 0, true }, | |
6581 // If the extension comes in disabled, its permissions should still be | |
6582 // granted (the user already approved them on another machine). | |
6583 { "Disabled", false, Extension::DISABLE_USER_ACTION, | |
6584 Extension::DISABLE_USER_ACTION, true }, | |
6585 // Legacy case (<M45): No disable reasons come in from Sync (see | |
6586 // crbug.com/484214). After installation, the reason should be set to | |
6587 // DISABLE_UNKNOWN_FROM_SYNC. | |
6588 { "Legacy", false, -1, Extension::DISABLE_UNKNOWN_FROM_SYNC, true }, | |
6589 // If the extension came in disabled due to a permissions increase, then the | |
6590 // user has *not* approved the permissions, and they shouldn't be granted. | |
6591 // crbug.com/484214 | |
6592 { "PermissionsIncrease", false, Extension::DISABLE_PERMISSIONS_INCREASE, | |
6593 Extension::DISABLE_PERMISSIONS_INCREASE, false }, | |
6594 }; | |
6595 | |
6596 for (const TestCase& test_case : test_cases) { | |
6597 SCOPED_TRACE(test_case.name); | |
6598 | |
6599 sync_pb::EntitySpecifics specifics; | |
6600 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
6601 ext_specifics->set_id(good_crx); | |
6602 ext_specifics->set_version(base::Version("1").GetString()); | |
6603 ext_specifics->set_enabled(test_case.sync_enabled); | |
6604 if (test_case.sync_disable_reasons != -1) | |
6605 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons); | |
6606 | |
6607 syncer::SyncData sync_data = | |
6608 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6609 syncer::SyncChange sync_change(FROM_HERE, | |
6610 syncer::SyncChange::ACTION_UPDATE, | |
6611 sync_data); | |
6612 syncer::SyncChangeList list(1, sync_change); | |
6613 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6614 | |
6615 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx)); | |
6616 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED | |
6617 : DISABLED); | |
6618 EXPECT_EQ(test_case.expect_disable_reasons, | |
6619 prefs->GetDisableReasons(good_crx)); | |
6620 scoped_ptr<const PermissionSet> permissions = | |
6621 prefs->GetGrantedPermissions(good_crx); | |
6622 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty()); | |
6623 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx)); | |
6624 | |
6625 // Remove the extension again, so we can install it again for the next case. | |
6626 UninstallExtension(good_crx, false, | |
6627 test_case.sync_enabled ? Extension::ENABLED | |
6628 : Extension::DISABLED); | |
6629 } | |
6630 } | |
6631 | |
6632 TEST_F(ExtensionServiceTest, ProcessSyncDataTerminatedExtension) { | |
6633 InitializeExtensionServiceWithUpdater(); | |
6634 syncer::FakeSyncChangeProcessor processor; | |
6635 extension_sync_service()->MergeDataAndStartSyncing( | |
6636 syncer::EXTENSIONS, | |
6637 syncer::SyncDataList(), | |
6638 scoped_ptr<syncer::SyncChangeProcessor>( | |
6639 new syncer::FakeSyncChangeProcessor), | |
6640 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6641 | |
6642 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW); | |
6643 TerminateExtension(good_crx); | |
6644 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx)); | |
6645 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile())); | |
6646 | |
6647 sync_pb::EntitySpecifics specifics; | |
6648 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
6649 ext_specifics->set_id(good_crx); | |
6650 ext_specifics->set_version( | |
6651 service()->GetInstalledExtension(good_crx)->version()->GetString()); | |
6652 ext_specifics->set_enabled(false); | |
6653 ext_specifics->set_incognito_enabled(true); | |
6654 syncer::SyncData sync_data = | |
6655 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6656 syncer::SyncChange sync_change(FROM_HERE, | |
6657 syncer::SyncChange::ACTION_UPDATE, | |
6658 sync_data); | |
6659 syncer::SyncChangeList list(1); | |
6660 list[0] = sync_change; | |
6661 | |
6662 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6663 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx)); | |
6664 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile())); | |
6665 | |
6666 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx)); | |
6667 } | |
6668 | |
6669 TEST_F(ExtensionServiceTest, ProcessSyncDataVersionCheck) { | |
6670 InitializeExtensionServiceWithUpdater(); | |
6671 syncer::FakeSyncChangeProcessor processor; | |
6672 extension_sync_service()->MergeDataAndStartSyncing( | |
6673 syncer::EXTENSIONS, | |
6674 syncer::SyncDataList(), | |
6675 scoped_ptr<syncer::SyncChangeProcessor>( | |
6676 new syncer::FakeSyncChangeProcessor), | |
6677 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6678 | |
6679 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW); | |
6680 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx)); | |
6681 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile())); | |
6682 | |
6683 sync_pb::EntitySpecifics specifics; | |
6684 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
6685 ext_specifics->set_id(good_crx); | |
6686 ext_specifics->set_enabled(true); | |
6687 | |
6688 const base::Version installed_version = | |
6689 *service()->GetInstalledExtension(good_crx)->version(); | |
6690 | |
6691 { | |
6692 ext_specifics->set_version(installed_version.GetString()); | |
6693 syncer::SyncData sync_data = | |
6694 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6695 syncer::SyncChange sync_change(FROM_HERE, | |
6696 syncer::SyncChange::ACTION_UPDATE, | |
6697 sync_data); | |
6698 syncer::SyncChangeList list(1, sync_change); | |
6699 | |
6700 // Should do nothing if extension version == sync version. | |
6701 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6702 EXPECT_FALSE(service()->updater()->WillCheckSoon()); | |
6703 // Make sure the version we'll send back to sync didn't change. | |
6704 syncer::SyncDataList data = | |
6705 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS); | |
6706 ASSERT_EQ(1u, data.size()); | |
6707 scoped_ptr<ExtensionSyncData> extension_data = | |
6708 ExtensionSyncData::CreateFromSyncData(data[0]); | |
6709 ASSERT_TRUE(extension_data); | |
6710 EXPECT_TRUE(installed_version.Equals(extension_data->version())); | |
6711 } | |
6712 | |
6713 // Should do nothing if extension version > sync version. | |
6714 { | |
6715 ext_specifics->set_version("0.0.0.0"); | |
6716 syncer::SyncData sync_data = | |
6717 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6718 syncer::SyncChange sync_change(FROM_HERE, | |
6719 syncer::SyncChange::ACTION_UPDATE, | |
6720 sync_data); | |
6721 syncer::SyncChangeList list(1, sync_change); | |
6722 | |
6723 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6724 EXPECT_FALSE(service()->updater()->WillCheckSoon()); | |
6725 // Make sure the version we'll send back to sync didn't change. | |
6726 syncer::SyncDataList data = | |
6727 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS); | |
6728 ASSERT_EQ(1u, data.size()); | |
6729 scoped_ptr<ExtensionSyncData> extension_data = | |
6730 ExtensionSyncData::CreateFromSyncData(data[0]); | |
6731 ASSERT_TRUE(extension_data); | |
6732 EXPECT_TRUE(installed_version.Equals(extension_data->version())); | |
6733 } | |
6734 | |
6735 // Should kick off an update if extension version < sync version. | |
6736 { | |
6737 const base::Version new_version("9.9.9.9"); | |
6738 ext_specifics->set_version(new_version.GetString()); | |
6739 syncer::SyncData sync_data = | |
6740 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6741 syncer::SyncChange sync_change(FROM_HERE, | |
6742 syncer::SyncChange::ACTION_UPDATE, | |
6743 sync_data); | |
6744 syncer::SyncChangeList list(1, sync_change); | |
6745 | |
6746 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6747 EXPECT_TRUE(service()->updater()->WillCheckSoon()); | |
6748 // Make sure that we'll send the NEW version back to sync, even though we | |
6749 // haven't actually updated yet. This is to prevent the data in sync from | |
6750 // flip-flopping back and forth until all clients are up to date. | |
6751 syncer::SyncDataList data = | |
6752 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS); | |
6753 ASSERT_EQ(1u, data.size()); | |
6754 scoped_ptr<ExtensionSyncData> extension_data = | |
6755 ExtensionSyncData::CreateFromSyncData(data[0]); | |
6756 ASSERT_TRUE(extension_data); | |
6757 EXPECT_TRUE(new_version.Equals(extension_data->version())); | |
6758 } | |
6759 | |
6760 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx)); | |
6761 } | |
6762 | |
6763 TEST_F(ExtensionServiceTest, ProcessSyncDataNotInstalled) { | |
6764 InitializeExtensionServiceWithUpdater(); | |
6765 syncer::FakeSyncChangeProcessor processor; | |
6766 extension_sync_service()->MergeDataAndStartSyncing( | |
6767 syncer::EXTENSIONS, | |
6768 syncer::SyncDataList(), | |
6769 scoped_ptr<syncer::SyncChangeProcessor>( | |
6770 new syncer::FakeSyncChangeProcessor), | |
6771 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6772 | |
6773 sync_pb::EntitySpecifics specifics; | |
6774 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
6775 ext_specifics->set_id(good_crx); | |
6776 ext_specifics->set_enabled(false); | |
6777 ext_specifics->set_incognito_enabled(true); | |
6778 ext_specifics->set_update_url("http://www.google.com/"); | |
6779 ext_specifics->set_version("1.2.3.4"); | |
6780 syncer::SyncData sync_data = | |
6781 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6782 syncer::SyncChange sync_change(FROM_HERE, | |
6783 syncer::SyncChange::ACTION_UPDATE, | |
6784 sync_data); | |
6785 syncer::SyncChangeList list(1); | |
6786 list[0] = sync_change; | |
6787 | |
6788 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx)); | |
6789 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile())); | |
6790 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6791 EXPECT_TRUE(service()->updater()->WillCheckSoon()); | |
6792 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx)); | |
6793 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile())); | |
6794 | |
6795 const extensions::PendingExtensionInfo* info; | |
6796 EXPECT_TRUE( | |
6797 (info = service()->pending_extension_manager()->GetById(good_crx))); | |
6798 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec()); | |
6799 EXPECT_TRUE(info->is_from_sync()); | |
6800 EXPECT_EQ(Manifest::INTERNAL, info->install_source()); | |
6801 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|. | |
6802 } | |
6803 | |
6804 TEST_F(ExtensionServiceTest, ProcessSyncDataEnableDisable) { | |
6805 InitializeEmptyExtensionService(); | |
6806 extension_sync_service()->MergeDataAndStartSyncing( | |
6807 syncer::EXTENSIONS, | |
6808 syncer::SyncDataList(), | |
6809 scoped_ptr<syncer::SyncChangeProcessor>( | |
6810 new syncer::FakeSyncChangeProcessor), | |
6811 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6812 | |
6813 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); | |
6814 | |
6815 struct TestCase { | |
6816 const char* name; // For failure output only. | |
6817 // Set of disable reasons before any Sync data comes in. If this is != 0, | |
6818 // the extension is disabled. | |
6819 int previous_disable_reasons; | |
6820 bool sync_enable; // The enabled flag coming in from Sync. | |
6821 // The disable reason(s) coming in from Sync, or -1 for "not set". | |
6822 int sync_disable_reasons; | |
6823 // The expected set of disable reasons after processing the Sync update. The | |
6824 // extension should be disabled iff this is != 0. | |
6825 int expect_disable_reasons; | |
6826 } test_cases[] = { | |
6827 { "NopEnable", 0, true, 0, 0 }, | |
6828 { "NopDisable", Extension::DISABLE_USER_ACTION, false, | |
6829 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION }, | |
6830 { "Disable", 0, false, Extension::DISABLE_USER_ACTION, | |
6831 Extension::DISABLE_USER_ACTION }, | |
6832 { "DisableLegacy", 0, false, -1, Extension::DISABLE_UNKNOWN_FROM_SYNC }, | |
6833 { "AddDisableReason", Extension::DISABLE_REMOTE_INSTALL, false, | |
6834 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION, | |
6835 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION }, | |
6836 { "AddDisableReasonLegacy", Extension::DISABLE_USER_ACTION, false, -1, | |
6837 Extension::DISABLE_USER_ACTION | Extension::DISABLE_UNKNOWN_FROM_SYNC}, | |
6838 { "RemoveDisableReason", | |
6839 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION, false, | |
6840 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION }, | |
6841 { "Enable", Extension::DISABLE_USER_ACTION, true, 0, 0 }, | |
6842 { "EnableLegacy", Extension::DISABLE_USER_ACTION, true, -1, 0 }, | |
6843 }; | |
6844 | |
6845 for (const TestCase& test_case : test_cases) { | |
6846 SCOPED_TRACE(test_case.name); | |
6847 | |
6848 std::string id; | |
6849 std::string version; | |
6850 // Don't keep |extension| around longer than necessary. | |
6851 { | |
6852 const Extension* extension = | |
6853 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW); | |
6854 // The extension should now be installed and enabled. | |
6855 ASSERT_TRUE(extension); | |
6856 id = extension->id(); | |
6857 version = extension->VersionString(); | |
6858 } | |
6859 ASSERT_TRUE(registry()->enabled_extensions().Contains(id)); | |
6860 | |
6861 // Disable it if the test case says so. | |
6862 if (test_case.previous_disable_reasons) { | |
6863 service()->DisableExtension(id, test_case.previous_disable_reasons); | |
6864 ASSERT_TRUE(registry()->disabled_extensions().Contains(id)); | |
6865 } | |
6866 | |
6867 // Now a sync update comes in. | |
6868 sync_pb::EntitySpecifics specifics; | |
6869 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
6870 ext_specifics->set_id(id); | |
6871 ext_specifics->set_enabled(test_case.sync_enable); | |
6872 ext_specifics->set_version(version); | |
6873 if (test_case.sync_disable_reasons != -1) | |
6874 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons); | |
6875 | |
6876 syncer::SyncData sync_data = | |
6877 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6878 syncer::SyncChange sync_change(FROM_HERE, | |
6879 syncer::SyncChange::ACTION_UPDATE, | |
6880 sync_data); | |
6881 syncer::SyncChangeList list(1, sync_change); | |
6882 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6883 | |
6884 // Check expectations. | |
6885 const bool expect_enabled = !test_case.expect_disable_reasons; | |
6886 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id)); | |
6887 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id)); | |
6888 | |
6889 // Remove the extension again, so we can install it again for the next case. | |
6890 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED | |
6891 : Extension::DISABLED); | |
6892 } | |
6893 } | |
6894 | |
6895 TEST_F(ExtensionServiceTest, ProcessSyncDataDeferredEnable) { | |
6896 InitializeEmptyExtensionService(); | |
6897 extension_sync_service()->MergeDataAndStartSyncing( | |
6898 syncer::EXTENSIONS, | |
6899 syncer::SyncDataList(), | |
6900 scoped_ptr<syncer::SyncChangeProcessor>( | |
6901 new syncer::FakeSyncChangeProcessor), | |
6902 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6903 | |
6904 base::FilePath base_path = data_dir().AppendASCII("permissions_increase"); | |
6905 base::FilePath pem_path = base_path.AppendASCII("permissions.pem"); | |
6906 | |
6907 base::FilePath path = base_path.AppendASCII("v1"); | |
6908 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW); | |
6909 // The extension must now be installed and enabled. | |
6910 ASSERT_TRUE(extension); | |
6911 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id())); | |
6912 | |
6913 // Save the id, as the extension object will be destroyed during updating. | |
6914 std::string id = extension->id(); | |
6915 | |
6916 // Update to a new version with increased permissions. | |
6917 path = base_path.AppendASCII("v2"); | |
6918 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED); | |
6919 | |
6920 // Now a sync update comes in, telling us to re-enable a *newer* version. | |
6921 sync_pb::EntitySpecifics specifics; | |
6922 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
6923 ext_specifics->set_id(id); | |
6924 ext_specifics->set_version("3"); | |
6925 ext_specifics->set_enabled(true); | |
6926 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE); | |
6927 | |
6928 syncer::SyncData sync_data = | |
6929 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
6930 syncer::SyncChange sync_change(FROM_HERE, | |
6931 syncer::SyncChange::ACTION_UPDATE, | |
6932 sync_data); | |
6933 syncer::SyncChangeList list(1, sync_change); | |
6934 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
6935 | |
6936 // Since the version didn't match, the extension should still be disabled. | |
6937 EXPECT_TRUE(registry()->disabled_extensions().Contains(id)); | |
6938 | |
6939 // After we update to the matching version, the extension should get enabled. | |
6940 path = base_path.AppendASCII("v3"); | |
6941 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED); | |
6942 } | |
6943 | |
6944 TEST_F(ExtensionServiceTest, ProcessSyncDataPermissionApproval) { | |
6945 // This is the update URL specified in the test extension. Setting it here is | |
6946 // necessary to make it considered syncable. | |
6947 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( | |
6948 switches::kAppsGalleryUpdateURL, | |
6949 "http://localhost/autoupdate/updates.xml"); | |
6950 | |
6951 InitializeEmptyExtensionService(); | |
6952 extension_sync_service()->MergeDataAndStartSyncing( | |
6953 syncer::EXTENSIONS, | |
6954 syncer::SyncDataList(), | |
6955 scoped_ptr<syncer::SyncChangeProcessor>( | |
6956 new syncer::FakeSyncChangeProcessor), | |
6957 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
6958 | |
6959 const base::FilePath base_path = | |
6960 data_dir().AppendASCII("permissions_increase"); | |
6961 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem"); | |
6962 const base::FilePath path_v1 = base_path.AppendASCII("v1"); | |
6963 const base::FilePath path_v2 = base_path.AppendASCII("v2"); | |
6964 | |
6965 base::ScopedTempDir crx_dir; | |
6966 ASSERT_TRUE(crx_dir.CreateUniqueTempDir()); | |
6967 const base::FilePath crx_path_v1 = crx_dir.path().AppendASCII("temp1.crx"); | |
6968 PackCRX(path_v1, pem_path, crx_path_v1); | |
6969 const base::FilePath crx_path_v2 = crx_dir.path().AppendASCII("temp2.crx"); | |
6970 PackCRX(path_v2, pem_path, crx_path_v2); | |
6971 | |
6972 const std::string v1("1"); | |
6973 const std::string v2("2"); | |
6974 | |
6975 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); | |
6976 | |
6977 struct TestCase { | |
6978 const char* name; // For failure output only. | |
6979 const std::string& sync_version; // The version coming in from Sync. | |
6980 // The disable reason(s) coming in from Sync, or -1 for "not set". | |
6981 int sync_disable_reasons; | |
6982 // The expected set of disable reasons after processing the Sync update. The | |
6983 // extension should be enabled iff this is 0. | |
6984 int expect_disable_reasons; | |
6985 // Whether the extension's permissions should be auto-granted. | |
6986 bool expect_permissions_granted; | |
6987 } test_cases[] = { | |
6988 // Sync tells us to re-enable an older version. No permissions should be | |
6989 // granted, since we can't be sure if the user actually approved the right | |
6990 // set of permissions. | |
6991 { "OldVersion", v1, 0, Extension::DISABLE_PERMISSIONS_INCREASE, false }, | |
6992 // Legacy case: Sync tells us to re-enable the extension, but doesn't | |
6993 // specify disable reasons. No permissions should be granted. | |
6994 { "Legacy", v2, -1, Extension::DISABLE_PERMISSIONS_INCREASE, false }, | |
6995 // Sync tells us to re-enable the extension and explicitly removes the | |
6996 // disable reasons. Now the extension should have its permissions granted. | |
6997 { "GrantPermissions", v2, 0, Extension::DISABLE_NONE, true }, | |
6998 }; | |
6999 | |
7000 for (const TestCase& test_case : test_cases) { | |
7001 SCOPED_TRACE(test_case.name); | |
7002 | |
7003 std::string id; | |
7004 // Don't keep |extension| around longer than necessary (it'll be destroyed | |
7005 // during updating). | |
7006 { | |
7007 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW); | |
7008 // The extension should now be installed and enabled. | |
7009 ASSERT_TRUE(extension); | |
7010 ASSERT_EQ(v1, extension->VersionString()); | |
7011 id = extension->id(); | |
7012 } | |
7013 ASSERT_TRUE(registry()->enabled_extensions().Contains(id)); | |
7014 | |
7015 scoped_ptr<const PermissionSet> granted_permissions_v1 = | |
7016 prefs->GetGrantedPermissions(id); | |
7017 | |
7018 // Update to a new version with increased permissions. | |
7019 UpdateExtension(id, crx_path_v2, DISABLED); | |
7020 | |
7021 // Now the extension should be disabled due to a permissions increase. | |
7022 { | |
7023 const Extension* extension = | |
7024 registry()->disabled_extensions().GetByID(id); | |
7025 ASSERT_TRUE(extension); | |
7026 ASSERT_EQ(v2, extension->VersionString()); | |
7027 } | |
7028 ASSERT_TRUE(prefs->HasDisableReason( | |
7029 id, Extension::DISABLE_PERMISSIONS_INCREASE)); | |
7030 | |
7031 // No new permissions should have been granted. | |
7032 scoped_ptr<const PermissionSet> granted_permissions_v2 = | |
7033 prefs->GetGrantedPermissions(id); | |
7034 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2); | |
7035 | |
7036 // Now a sync update comes in. | |
7037 sync_pb::EntitySpecifics specifics; | |
7038 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
7039 ext_specifics->set_id(id); | |
7040 ext_specifics->set_enabled(true); | |
7041 ext_specifics->set_version(test_case.sync_version); | |
7042 if (test_case.sync_disable_reasons != -1) | |
7043 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons); | |
7044 | |
7045 syncer::SyncData sync_data = | |
7046 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics); | |
7047 syncer::SyncChange sync_change(FROM_HERE, | |
7048 syncer::SyncChange::ACTION_UPDATE, | |
7049 sync_data); | |
7050 syncer::SyncChangeList list(1, sync_change); | |
7051 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | |
7052 | |
7053 // Check expectations. | |
7054 const bool expect_enabled = !test_case.expect_disable_reasons; | |
7055 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id)); | |
7056 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id)); | |
7057 scoped_ptr<const PermissionSet> granted_permissions = | |
7058 prefs->GetGrantedPermissions(id); | |
7059 if (test_case.expect_permissions_granted) { | |
7060 scoped_ptr<const PermissionSet> active_permissions = | |
7061 prefs->GetActivePermissions(id); | |
7062 EXPECT_EQ(*granted_permissions, *active_permissions); | |
7063 } else { | |
7064 EXPECT_EQ(*granted_permissions, *granted_permissions_v1); | |
7065 } | |
7066 | |
7067 // Remove the extension again, so we can install it again for the next case. | |
7068 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED | |
7069 : Extension::DISABLED); | |
7070 } | |
7071 } | |
7072 | |
7073 #if defined(ENABLE_SUPERVISED_USERS) | |
7074 class ExtensionServiceTestSupervised : public ExtensionServiceTest, | |
7075 public SupervisedUserService::Delegate { | |
7076 public: | |
7077 void SetUp() override { | |
7078 ExtensionServiceTest::SetUp(); | |
7079 | |
7080 // This is the update URL specified in the permissions test extension. | |
7081 // Setting it here is necessary to make the extension considered syncable. | |
7082 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( | |
7083 switches::kAppsGalleryUpdateURL, | |
7084 "http://localhost/autoupdate/updates.xml"); | |
7085 } | |
7086 | |
7087 void TearDown() override { | |
7088 supervised_user_service()->SetDelegate(nullptr); | |
7089 | |
7090 ExtensionServiceTest::TearDown(); | |
7091 } | |
7092 | |
7093 protected: | |
7094 void InitServices(bool profile_is_supervised) { | |
7095 ExtensionServiceInitParams params = CreateDefaultInitParams(); | |
7096 params.profile_is_supervised = profile_is_supervised; | |
7097 InitializeExtensionService(params); | |
7098 | |
7099 supervised_user_service()->SetDelegate(this); | |
7100 supervised_user_service()->Init(); | |
7101 } | |
7102 | |
7103 std::string InstallPermissionsTestExtension() { | |
7104 const std::string version("1"); | |
7105 | |
7106 const Extension* extension = | |
7107 PackAndInstallCRX(dir_path(version), pem_path(), INSTALL_NEW, | |
7108 Extension::WAS_INSTALLED_BY_CUSTODIAN); | |
7109 // The extension must now be installed and enabled. | |
7110 EXPECT_TRUE(extension); | |
7111 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id())); | |
7112 EXPECT_EQ(version, extension->VersionString()); | |
7113 | |
7114 return extension->id(); | |
7115 } | |
7116 | |
7117 void UpdatePermissionsTestExtension(const std::string& id, | |
7118 const std::string& version, | |
7119 UpdateState expected_state) { | |
7120 PackCRXAndUpdateExtension(id, dir_path(version), pem_path(), | |
7121 expected_state); | |
7122 const Extension* extension = registry()->GetInstalledExtension(id); | |
7123 ASSERT_TRUE(extension); | |
7124 // The version should have been updated. | |
7125 EXPECT_EQ(version, extension->VersionString()); | |
7126 } | |
7127 | |
7128 SupervisedUserService* supervised_user_service() { | |
7129 return SupervisedUserServiceFactory::GetForProfile(profile()); | |
7130 } | |
7131 | |
7132 static std::string UpdateRequestId(const std::string& extension_id, | |
7133 const std::string& version) { | |
7134 return SupervisedUserService::GetExtensionUpdateRequestId( | |
7135 extension_id, base::Version(version)); | |
7136 } | |
7137 | |
7138 private: | |
7139 // This prevents the legacy supervised user init code from running. | |
7140 bool SetActive(bool active) override { return true; } | |
7141 | |
7142 base::FilePath base_path() const { | |
7143 return data_dir().AppendASCII("permissions_increase"); | |
7144 } | |
7145 base::FilePath dir_path(const std::string& version) const { | |
7146 return base_path().AppendASCII("v" + version); | |
7147 } | |
7148 base::FilePath pem_path() const { | |
7149 return base_path().AppendASCII("permissions.pem"); | |
7150 } | |
7151 }; | |
7152 | |
7153 class MockPermissionRequestCreator : public PermissionRequestCreator { | |
7154 public: | |
7155 MockPermissionRequestCreator() {} | |
7156 ~MockPermissionRequestCreator() override {} | |
7157 | |
7158 bool IsEnabled() const override { return true; } | |
7159 | |
7160 void CreateURLAccessRequest(const GURL& url_requested, | |
7161 const SuccessCallback& callback) override { | |
7162 FAIL(); | |
7163 } | |
7164 | |
7165 MOCK_METHOD2(CreateExtensionUpdateRequest, | |
7166 void(const std::string& id, | |
7167 const SupervisedUserService::SuccessCallback& callback)); | |
7168 | |
7169 private: | |
7170 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator); | |
7171 }; | |
7172 | |
7173 TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) { | |
7174 InitServices(true /* profile_is_supervised */); | |
7175 | |
7176 base::FilePath path1 = data_dir().AppendASCII("good.crx"); | |
7177 base::FilePath path2 = data_dir().AppendASCII("good2048.crx"); | |
7178 const Extension* extensions[] = { | |
7179 InstallCRX(path1, INSTALL_FAILED), | |
7180 InstallCRX(path2, INSTALL_NEW, Extension::WAS_INSTALLED_BY_CUSTODIAN) | |
7181 }; | |
7182 | |
7183 // Only the extension with the "installed by custodian" flag should have been | |
7184 // installed and enabled. | |
7185 EXPECT_FALSE(extensions[0]); | |
7186 ASSERT_TRUE(extensions[1]); | |
7187 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id())); | |
7188 } | |
7189 | |
7190 TEST_F(ExtensionServiceTestSupervised, PreinstalledExtension) { | |
7191 InitServices(false /* profile_is_supervised */); | |
7192 | |
7193 // Install an extension. | |
7194 base::FilePath path = data_dir().AppendASCII("good.crx"); | |
7195 const Extension* extension = InstallCRX(path, INSTALL_NEW); | |
7196 std::string id = extension->id(); | |
7197 | |
7198 // Now make the profile supervised. | |
7199 profile()->AsTestingProfile()->SetSupervisedUserId( | |
7200 supervised_users::kChildAccountSUID); | |
7201 | |
7202 // The extension should not be enabled anymore. | |
7203 EXPECT_FALSE(registry()->enabled_extensions().Contains(id)); | |
7204 } | |
7205 | |
7206 TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) { | |
7207 InitServices(true /* profile_is_supervised */); | |
7208 | |
7209 base::FilePath base_path = data_dir().AppendASCII("autoupdate"); | |
7210 base::FilePath pem_path = base_path.AppendASCII("key.pem"); | |
7211 | |
7212 const Extension* extension = | |
7213 PackAndInstallCRX(base_path.AppendASCII("v1"), pem_path, INSTALL_NEW, | |
7214 Extension::WAS_INSTALLED_BY_CUSTODIAN); | |
7215 // The extension must now be installed and enabled. | |
7216 ASSERT_TRUE(extension); | |
7217 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id())); | |
7218 | |
7219 // Save the id, as the extension object will be destroyed during updating. | |
7220 std::string id = extension->id(); | |
7221 | |
7222 std::string old_version = extension->VersionString(); | |
7223 | |
7224 // Update to a new version. | |
7225 PackCRXAndUpdateExtension(id, base_path.AppendASCII("v2"), pem_path, ENABLED); | |
7226 | |
7227 // The extension should still be there and enabled. | |
7228 extension = registry()->enabled_extensions().GetByID(id); | |
7229 ASSERT_TRUE(extension); | |
7230 // The version should have changed. | |
7231 EXPECT_NE(extension->VersionString(), old_version); | |
7232 } | |
7233 | |
7234 TEST_F(ExtensionServiceTestSupervised, UpdateWithPermissionIncreaseNoApproval) { | |
7235 // Explicitly disable the "need custodian approval" field trial. | |
7236 base::FieldTrialList field_trial_list(new base::MockEntropyProvider()); | |
7237 base::FieldTrialList::CreateFieldTrial( | |
7238 "SupervisedUserExtensionPermissionIncrease", ""); | |
7239 | |
7240 InitServices(true /* profile_is_supervised */); | |
7241 | |
7242 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator; | |
7243 supervised_user_service()->AddPermissionRequestCreator( | |
7244 make_scoped_ptr(creator)); | |
7245 | |
7246 std::string id = InstallPermissionsTestExtension(); | |
7247 | |
7248 // Update to a new version with increased permissions. | |
7249 // Since we don't require the custodian's approval, no permission request | |
7250 // should be created. | |
7251 const std::string version2("2"); | |
7252 EXPECT_CALL(*creator, CreateExtensionUpdateRequest( | |
7253 UpdateRequestId(id, version2), testing::_)) | |
7254 .Times(0); | |
7255 UpdatePermissionsTestExtension(id, version2, DISABLED); | |
7256 } | |
7257 | |
7258 TEST_F(ExtensionServiceTestSupervised, | |
7259 UpdateWithPermissionIncreaseApprovalOldVersion) { | |
7260 // Explicitly enable the "need custodian approval" field trial. | |
7261 base::FieldTrialList field_trial_list(new base::MockEntropyProvider()); | |
7262 base::FieldTrialList::CreateFieldTrial( | |
7263 "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval"); | |
7264 | |
7265 InitServices(true /* profile_is_supervised */); | |
7266 | |
7267 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator; | |
7268 supervised_user_service()->AddPermissionRequestCreator( | |
7269 make_scoped_ptr(creator)); | |
7270 | |
7271 const std::string version1("1"); | |
7272 const std::string version2("2"); | |
7273 | |
7274 std::string id = InstallPermissionsTestExtension(); | |
7275 | |
7276 // Update to a new version with increased permissions. | |
7277 EXPECT_CALL(*creator, CreateExtensionUpdateRequest( | |
7278 UpdateRequestId(id, version2), testing::_)); | |
7279 UpdatePermissionsTestExtension(id, version2, DISABLED); | |
7280 | |
7281 // Simulate a custodian approval for re-enabling the extension coming in | |
7282 // through Sync, but set the old version. This can happen when there already | |
7283 // was a pending request for an earlier version of the extension. | |
7284 sync_pb::EntitySpecifics specifics; | |
7285 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
7286 ext_specifics->set_id(id); | |
7287 ext_specifics->set_enabled(true); | |
7288 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE); | |
7289 ext_specifics->set_installed_by_custodian(true); | |
7290 ext_specifics->set_version(version1); | |
7291 | |
7292 // Attempting to re-enable an old version should result in a permission | |
7293 // request for the current version. | |
7294 EXPECT_CALL(*creator, CreateExtensionUpdateRequest( | |
7295 UpdateRequestId(id, version2), testing::_)); | |
7296 | |
7297 syncer::SyncData sync_data = | |
7298 syncer::SyncData::CreateLocalData(id, "Name", specifics); | |
7299 syncer::SyncChange sync_change(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, | |
7300 sync_data); | |
7301 syncer::SyncChangeList change_list(1, sync_change); | |
7302 extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list); | |
7303 // The re-enable should be ignored, since the version doesn't match. | |
7304 EXPECT_FALSE(registry()->enabled_extensions().Contains(id)); | |
7305 EXPECT_FALSE(extension_sync_service()->HasPendingReenable( | |
7306 id, base::Version(version1))); | |
7307 EXPECT_FALSE(extension_sync_service()->HasPendingReenable( | |
7308 id, base::Version(version2))); | |
7309 } | |
7310 | |
7311 TEST_F(ExtensionServiceTestSupervised, | |
7312 UpdateWithPermissionIncreaseApprovalMatchingVersion) { | |
7313 // Explicitly enable the "need custodian approval" field trial. | |
7314 base::FieldTrialList field_trial_list(new base::MockEntropyProvider()); | |
7315 base::FieldTrialList::CreateFieldTrial( | |
7316 "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval"); | |
7317 | |
7318 InitServices(true /* profile_is_supervised */); | |
7319 | |
7320 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator; | |
7321 supervised_user_service()->AddPermissionRequestCreator( | |
7322 make_scoped_ptr(creator)); | |
7323 | |
7324 std::string id = InstallPermissionsTestExtension(); | |
7325 | |
7326 // Update to a new version with increased permissions. | |
7327 const std::string version2("2"); | |
7328 EXPECT_CALL(*creator, CreateExtensionUpdateRequest( | |
7329 UpdateRequestId(id, version2), testing::_)); | |
7330 UpdatePermissionsTestExtension(id, version2, DISABLED); | |
7331 | |
7332 // Simulate a custodian approval for re-enabling the extension coming in | |
7333 // through Sync. | |
7334 sync_pb::EntitySpecifics specifics; | |
7335 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
7336 ext_specifics->set_id(id); | |
7337 ext_specifics->set_enabled(true); | |
7338 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE); | |
7339 ext_specifics->set_installed_by_custodian(true); | |
7340 ext_specifics->set_version(version2); | |
7341 | |
7342 syncer::SyncData sync_data = | |
7343 syncer::SyncData::CreateLocalData(id, "Name", specifics); | |
7344 syncer::SyncChange sync_change(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, | |
7345 sync_data); | |
7346 syncer::SyncChangeList change_list(1, sync_change); | |
7347 extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list); | |
7348 // The extension should have gotten re-enabled. | |
7349 EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); | |
7350 } | |
7351 | |
7352 TEST_F(ExtensionServiceTestSupervised, | |
7353 UpdateWithPermissionIncreaseApprovalNewVersion) { | |
7354 // Explicitly enable the "need custodian approval" field trial. | |
7355 base::FieldTrialList field_trial_list(new base::MockEntropyProvider()); | |
7356 base::FieldTrialList::CreateFieldTrial( | |
7357 "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval"); | |
7358 | |
7359 InitServices(true /* profile_is_supervised */); | |
7360 | |
7361 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator; | |
7362 supervised_user_service()->AddPermissionRequestCreator( | |
7363 make_scoped_ptr(creator)); | |
7364 | |
7365 std::string id = InstallPermissionsTestExtension(); | |
7366 | |
7367 // Update to a new version with increased permissions. | |
7368 const std::string version2("2"); | |
7369 EXPECT_CALL(*creator, CreateExtensionUpdateRequest( | |
7370 UpdateRequestId(id, version2), testing::_)); | |
7371 UpdatePermissionsTestExtension(id, version2, DISABLED); | |
7372 | |
7373 // Simulate a custodian approval for re-enabling the extension coming in | |
7374 // through Sync. Set a newer version than we have installed. | |
7375 const std::string version3("3"); | |
7376 sync_pb::EntitySpecifics specifics; | |
7377 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
7378 ext_specifics->set_id(id); | |
7379 ext_specifics->set_enabled(true); | |
7380 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE); | |
7381 ext_specifics->set_installed_by_custodian(true); | |
7382 ext_specifics->set_version(version3); | |
7383 | |
7384 // This should *not* result in a new permission request. | |
7385 EXPECT_CALL(*creator, CreateExtensionUpdateRequest( | |
7386 UpdateRequestId(id, version3), testing::_)) | |
7387 .Times(0); | |
7388 | |
7389 syncer::SyncData sync_data = | |
7390 syncer::SyncData::CreateLocalData(id, "Name", specifics); | |
7391 syncer::SyncChange sync_change(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, | |
7392 sync_data); | |
7393 syncer::SyncChangeList change_list(1, sync_change); | |
7394 extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list); | |
7395 // The re-enable should be delayed until the extension is updated to the | |
7396 // matching version. | |
7397 EXPECT_FALSE(registry()->enabled_extensions().Contains(id)); | |
7398 EXPECT_TRUE(extension_sync_service()->HasPendingReenable( | |
7399 id, base::Version(version3))); | |
7400 | |
7401 // Update to the matching version. Now the extension should get enabled. | |
7402 UpdatePermissionsTestExtension(id, version3, ENABLED); | |
7403 } | |
7404 | |
7405 TEST_F(ExtensionServiceTest, SyncUninstallByCustodianSkipsPolicy) { | |
7406 InitializeEmptyExtensionService(); | |
7407 extension_sync_service()->MergeDataAndStartSyncing( | |
7408 syncer::EXTENSIONS, | |
7409 syncer::SyncDataList(), | |
7410 scoped_ptr<syncer::SyncChangeProcessor>( | |
7411 new syncer::FakeSyncChangeProcessor), | |
7412 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock())); | |
7413 | |
7414 // Install two extensions. | |
7415 base::FilePath path1 = data_dir().AppendASCII("good.crx"); | |
7416 base::FilePath path2 = data_dir().AppendASCII("good2048.crx"); | |
7417 const Extension* extensions[] = { | |
7418 InstallCRX(path1, INSTALL_NEW), | |
7419 InstallCRX(path2, INSTALL_NEW, Extension::WAS_INSTALLED_BY_CUSTODIAN) | |
7420 }; | |
7421 | |
7422 // Add a policy provider that will disallow any changes. | |
7423 extensions::TestManagementPolicyProvider provider( | |
7424 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS); | |
7425 GetManagementPolicy()->RegisterProvider(&provider); | |
7426 | |
7427 // Create a sync deletion for each extension. | |
7428 syncer::SyncChangeList change_list; | |
7429 for (size_t i = 0; i < arraysize(extensions); i++) { | |
7430 const std::string& id = extensions[i]->id(); | |
7431 sync_pb::EntitySpecifics specifics; | |
7432 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); | |
7433 ext_specifics->set_id(id); | |
7434 ext_specifics->set_version("1.0"); | |
7435 ext_specifics->set_installed_by_custodian( | |
7436 extensions[i]->was_installed_by_custodian()); | |
7437 syncer::SyncData sync_data = | |
7438 syncer::SyncData::CreateLocalData(id, "Name", specifics); | |
7439 change_list.push_back(syncer::SyncChange(FROM_HERE, | |
7440 syncer::SyncChange::ACTION_DELETE, | |
7441 sync_data)); | |
7442 } | |
7443 | |
7444 // Save the extension ids, as uninstalling destroys the Extension instance. | |
7445 std::string extension_ids[] = { | |
7446 extensions[0]->id(), | |
7447 extensions[1]->id() | |
7448 }; | |
7449 | |
7450 // Now apply the uninstallations. | |
7451 extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list); | |
7452 | |
7453 // Uninstalling the extension without installed_by_custodian should have been | |
7454 // blocked by policy, so it should still be there. | |
7455 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0])); | |
7456 | |
7457 // But installed_by_custodian should result in bypassing the policy check. | |
7458 EXPECT_FALSE( | |
7459 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1])); | |
7460 } | |
7461 #endif // defined(ENABLE_SUPERVISED_USERS) | |
7462 | |
7463 TEST_F(ExtensionServiceTest, InstallPriorityExternalUpdateUrl) { | 5257 TEST_F(ExtensionServiceTest, InstallPriorityExternalUpdateUrl) { |
7464 InitializeEmptyExtensionService(); | 5258 InitializeEmptyExtensionService(); |
7465 | 5259 |
7466 base::FilePath path = data_dir().AppendASCII("good.crx"); | 5260 base::FilePath path = data_dir().AppendASCII("good.crx"); |
7467 InstallCRX(path, INSTALL_NEW); | 5261 InstallCRX(path, INSTALL_NEW); |
7468 ValidatePrefKeyCount(1u); | 5262 ValidatePrefKeyCount(1u); |
7469 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); | 5263 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); |
7470 ValidateIntegerPref(good_crx, "location", Manifest::INTERNAL); | 5264 ValidateIntegerPref(good_crx, "location", Manifest::INTERNAL); |
7471 | 5265 |
7472 extensions::PendingExtensionManager* pending = | 5266 extensions::PendingExtensionManager* pending = |
(...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8376 | 6170 |
8377 service()->Observe(chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED, | 6171 service()->Observe(chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED, |
8378 content::Source<Profile>(profile()), | 6172 content::Source<Profile>(profile()), |
8379 content::NotificationService::NoDetails()); | 6173 content::NotificationService::NoDetails()); |
8380 EXPECT_EQ(UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN, unloaded_reason_); | 6174 EXPECT_EQ(UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN, unloaded_reason_); |
8381 EXPECT_EQ(0u, registry()->enabled_extensions().size()); | 6175 EXPECT_EQ(0u, registry()->enabled_extensions().size()); |
8382 EXPECT_EQ(0u, registry()->disabled_extensions().size()); | 6176 EXPECT_EQ(0u, registry()->disabled_extensions().size()); |
8383 EXPECT_EQ(0u, registry()->terminated_extensions().size()); | 6177 EXPECT_EQ(0u, registry()->terminated_extensions().size()); |
8384 EXPECT_EQ(0u, registry()->blacklisted_extensions().size()); | 6178 EXPECT_EQ(0u, registry()->blacklisted_extensions().size()); |
8385 } | 6179 } |
OLD | NEW |