| 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 |