Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "chrome/browser/extensions/api/developer_private/developer_private_api. h" | 5 #include "chrome/browser/extensions/api/developer_private/developer_private_api. h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "chrome/browser/chrome_notification_types.h" | |
| 14 #include "chrome/browser/extensions/error_console/error_console.h" | 15 #include "chrome/browser/extensions/error_console/error_console.h" |
| 15 #include "chrome/browser/extensions/extension_function_test_utils.h" | 16 #include "chrome/browser/extensions/extension_function_test_utils.h" |
| 16 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
| 17 #include "chrome/browser/extensions/extension_service_test_base.h" | 18 #include "chrome/browser/extensions/extension_service_test_with_install.h" |
| 18 #include "chrome/browser/extensions/extension_util.h" | 19 #include "chrome/browser/extensions/extension_util.h" |
| 19 #include "chrome/browser/extensions/scripting_permissions_modifier.h" | 20 #include "chrome/browser/extensions/scripting_permissions_modifier.h" |
| 20 #include "chrome/browser/extensions/test_extension_dir.h" | 21 #include "chrome/browser/extensions/test_extension_dir.h" |
| 21 #include "chrome/browser/extensions/test_extension_system.h" | 22 #include "chrome/browser/extensions/test_extension_system.h" |
| 22 #include "chrome/browser/extensions/unpacked_installer.h" | 23 #include "chrome/browser/extensions/unpacked_installer.h" |
| 23 #include "chrome/browser/ui/browser.h" | 24 #include "chrome/browser/ui/browser.h" |
| 24 #include "chrome/common/extensions/api/developer_private.h" | 25 #include "chrome/common/extensions/api/developer_private.h" |
| 25 #include "chrome/common/pref_names.h" | 26 #include "chrome/common/pref_names.h" |
| 26 #include "chrome/test/base/test_browser_window.h" | 27 #include "chrome/test/base/test_browser_window.h" |
| 27 #include "components/crx_file/id_util.h" | 28 #include "components/crx_file/id_util.h" |
| 28 #include "components/policy/core/browser/browser_policy_connector.h" | 29 #include "components/policy/core/browser/browser_policy_connector.h" |
| 29 #include "components/policy/core/common/mock_configuration_policy_provider.h" | 30 #include "components/policy/core/common/mock_configuration_policy_provider.h" |
| 30 #include "components/policy/core/common/policy_map.h" | 31 #include "components/policy/core/common/policy_map.h" |
| 31 #include "components/policy/core/common/policy_service_impl.h" | 32 #include "components/policy/core/common/policy_service_impl.h" |
| 32 #include "components/policy/core/common/policy_types.h" | 33 #include "components/policy/core/common/policy_types.h" |
| 33 #include "components/policy/policy_constants.h" | 34 #include "components/policy/policy_constants.h" |
| 34 #include "components/sync_preferences/testing_pref_service_syncable.h" | 35 #include "components/sync_preferences/testing_pref_service_syncable.h" |
| 36 #include "content/public/browser/notification_service.h" | |
| 35 #include "content/public/test/web_contents_tester.h" | 37 #include "content/public/test/web_contents_tester.h" |
| 36 #include "extensions/browser/api_test_utils.h" | 38 #include "extensions/browser/api_test_utils.h" |
| 37 #include "extensions/browser/event_router_factory.h" | 39 #include "extensions/browser/event_router_factory.h" |
| 38 #include "extensions/browser/extension_error_test_util.h" | 40 #include "extensions/browser/extension_error_test_util.h" |
| 39 #include "extensions/browser/extension_prefs.h" | 41 #include "extensions/browser/extension_prefs.h" |
| 40 #include "extensions/browser/extension_registry.h" | 42 #include "extensions/browser/extension_registry.h" |
| 41 #include "extensions/browser/extension_system.h" | 43 #include "extensions/browser/extension_system.h" |
| 42 #include "extensions/browser/extension_util.h" | 44 #include "extensions/browser/extension_util.h" |
| 45 #include "extensions/browser/external_install_info.h" | |
| 43 #include "extensions/browser/test_extension_registry_observer.h" | 46 #include "extensions/browser/test_extension_registry_observer.h" |
| 44 #include "extensions/common/extension.h" | 47 #include "extensions/common/extension.h" |
| 45 #include "extensions/common/extension_builder.h" | 48 #include "extensions/common/extension_builder.h" |
| 46 #include "extensions/common/extension_set.h" | 49 #include "extensions/common/extension_set.h" |
| 47 #include "extensions/common/feature_switch.h" | 50 #include "extensions/common/feature_switch.h" |
| 48 #include "extensions/common/manifest_constants.h" | 51 #include "extensions/common/manifest_constants.h" |
| 49 #include "extensions/common/test_util.h" | 52 #include "extensions/common/test_util.h" |
| 50 #include "extensions/common/value_builder.h" | 53 #include "extensions/common/value_builder.h" |
| 51 | 54 |
| 52 using testing::Return; | 55 using testing::Return; |
| 53 using testing::_; | 56 using testing::_; |
| 54 | 57 |
| 55 namespace extensions { | 58 namespace extensions { |
| 56 | 59 |
| 57 namespace { | 60 namespace { |
| 58 | 61 |
| 62 const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; | |
| 63 | |
| 59 std::unique_ptr<KeyedService> BuildAPI(content::BrowserContext* context) { | 64 std::unique_ptr<KeyedService> BuildAPI(content::BrowserContext* context) { |
| 60 return base::MakeUnique<DeveloperPrivateAPI>(context); | 65 return base::MakeUnique<DeveloperPrivateAPI>(context); |
| 61 } | 66 } |
| 62 | 67 |
| 63 std::unique_ptr<KeyedService> BuildEventRouter( | 68 std::unique_ptr<KeyedService> BuildEventRouter( |
| 64 content::BrowserContext* profile) { | 69 content::BrowserContext* profile) { |
| 65 return base::MakeUnique<EventRouter>(profile, ExtensionPrefs::Get(profile)); | 70 return base::MakeUnique<EventRouter>(profile, ExtensionPrefs::Get(profile)); |
| 66 } | 71 } |
| 67 | 72 |
| 68 bool HasAllUrlsPermission(const Extension* extension, | 73 bool HasAllUrlsPermission(const Extension* extension, |
| 69 content::BrowserContext* context) { | 74 content::BrowserContext* context) { |
| 70 return ScriptingPermissionsModifier(context, extension).IsAllowedOnAllUrls(); | 75 return ScriptingPermissionsModifier(context, extension).IsAllowedOnAllUrls(); |
| 71 } | 76 } |
| 72 | 77 |
| 73 bool HasPrefsPermission(bool (*has_pref)(const std::string&, | 78 bool HasPrefsPermission(bool (*has_pref)(const std::string&, |
| 74 content::BrowserContext*), | 79 content::BrowserContext*), |
| 75 content::BrowserContext* context, | 80 content::BrowserContext* context, |
| 76 const std::string& id) { | 81 const std::string& id) { |
| 77 return has_pref(id, context); | 82 return has_pref(id, context); |
| 78 } | 83 } |
| 79 | 84 |
| 85 // This class is almost entirely copied from extension_service_unittest.cc. | |
| 86 // TODO(lazyboy): ) Extract to a separate file. | |
| 87 class MockExtensionProvider : public extensions::ExternalProviderInterface { | |
| 88 public: | |
| 89 MockExtensionProvider(VisitorInterface* visitor, Manifest::Location location) | |
| 90 : location_(location), visitor_(visitor) {} | |
| 91 | |
| 92 ~MockExtensionProvider() override {} | |
| 93 | |
| 94 void AddExtension(const std::string& id, | |
| 95 const std::string& version, | |
| 96 const base::FilePath& path) { | |
| 97 extension_map_[id] = std::make_pair(version, path); | |
| 98 } | |
| 99 | |
| 100 void RemoveExtension(const std::string& id) { extension_map_.erase(id); } | |
| 101 | |
| 102 // ExternalProvider implementation: | |
| 103 void VisitRegisteredExtension() override { | |
| 104 for (DataMap::const_iterator i = extension_map_.begin(); | |
| 105 i != extension_map_.end(); ++i) { | |
| 106 std::unique_ptr<base::Version> version( | |
| 107 new base::Version(i->second.first)); | |
| 108 | |
| 109 std::unique_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile( | |
| 110 i->first, std::move(version), i->second.second, location_, | |
| 111 Extension::NO_FLAGS, false, false)); | |
| 112 visitor_->OnExternalExtensionFileFound(*info); | |
| 113 } | |
| 114 visitor_->OnExternalProviderReady(this); | |
| 115 } | |
| 116 | |
| 117 bool HasExtension(const std::string& id) const override { | |
| 118 return extension_map_.find(id) != extension_map_.end(); | |
| 119 } | |
| 120 | |
| 121 bool GetExtensionDetails( | |
| 122 const std::string& id, | |
| 123 Manifest::Location* location, | |
| 124 std::unique_ptr<base::Version>* version) const override { | |
| 125 DataMap::const_iterator it = extension_map_.find(id); | |
| 126 if (it == extension_map_.end()) | |
| 127 return false; | |
| 128 | |
| 129 if (version) | |
| 130 version->reset(new base::Version(it->second.first)); | |
| 131 | |
| 132 if (location) | |
| 133 *location = location_; | |
| 134 | |
| 135 return true; | |
| 136 } | |
| 137 | |
| 138 bool IsReady() const override { return true; } | |
| 139 | |
| 140 void ServiceShutdown() override {} | |
| 141 | |
| 142 private: | |
| 143 using DataMap = std::map<std::string, std::pair<std::string, base::FilePath>>; | |
| 144 DataMap extension_map_; | |
| 145 Manifest::Location location_; | |
| 146 VisitorInterface* visitor_; | |
| 147 | |
| 148 DISALLOW_COPY_AND_ASSIGN(MockExtensionProvider); | |
| 149 }; | |
| 150 | |
| 80 } // namespace | 151 } // namespace |
| 81 | 152 |
| 82 class DeveloperPrivateApiUnitTest : public ExtensionServiceTestBase { | 153 class DeveloperPrivateApiUnitTest : public ExtensionServiceTestWithInstall { |
| 83 protected: | 154 protected: |
| 84 DeveloperPrivateApiUnitTest() {} | 155 DeveloperPrivateApiUnitTest() {} |
| 85 ~DeveloperPrivateApiUnitTest() override {} | 156 ~DeveloperPrivateApiUnitTest() override {} |
| 86 | 157 |
| 158 void AddMockExternalProvider( | |
| 159 std::unique_ptr<ExternalProviderInterface> provider) { | |
| 160 service()->AddProviderForTesting(std::move(provider)); | |
| 161 } | |
| 162 | |
| 87 // A wrapper around extension_function_test_utils::RunFunction that runs with | 163 // A wrapper around extension_function_test_utils::RunFunction that runs with |
| 88 // the associated browser, no flags, and can take stack-allocated arguments. | 164 // the associated browser, no flags, and can take stack-allocated arguments. |
| 89 bool RunFunction(const scoped_refptr<UIThreadExtensionFunction>& function, | 165 bool RunFunction(const scoped_refptr<UIThreadExtensionFunction>& function, |
| 90 const base::ListValue& args); | 166 const base::ListValue& args); |
| 91 | 167 |
| 92 // Loads an unpacked extension that is backed by a real directory, allowing | 168 // Loads an unpacked extension that is backed by a real directory, allowing |
| 93 // it to be reloaded. | 169 // it to be reloaded. |
| 94 const Extension* LoadUnpackedExtension(); | 170 const Extension* LoadUnpackedExtension(); |
| 95 | 171 |
| 96 // Loads an extension with no real directory; this is faster, but means the | 172 // Loads an extension with no real directory; this is faster, but means the |
| (...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 847 ListBuilder() | 923 ListBuilder() |
| 848 .Append( | 924 .Append( |
| 849 DictionaryBuilder().Set("extensionId", extension->id()).Build()) | 925 DictionaryBuilder().Set("extensionId", extension->id()).Build()) |
| 850 .Build(); | 926 .Build(); |
| 851 function = new api::DeveloperPrivateDeleteExtensionErrorsFunction(); | 927 function = new api::DeveloperPrivateDeleteExtensionErrorsFunction(); |
| 852 EXPECT_TRUE(RunFunction(function, *args)) << function->GetError(); | 928 EXPECT_TRUE(RunFunction(function, *args)) << function->GetError(); |
| 853 // No more errors! | 929 // No more errors! |
| 854 EXPECT_TRUE(error_console->GetErrorsForExtension(extension->id()).empty()); | 930 EXPECT_TRUE(error_console->GetErrorsForExtension(extension->id()).empty()); |
| 855 } | 931 } |
| 856 | 932 |
| 933 // Tests that developerPrivate.repair does not succeed for a non-corrupted | |
| 934 // extension and any policy extension. | |
| 935 // Regression test for https://crbug.com/577959. | |
| 936 TEST_F(DeveloperPrivateApiUnitTest, RepairNotBrokenExtension) { | |
| 937 std::string extension_id(good_crx); | |
| 938 | |
| 939 // Set up a mock provider with a policy extension. | |
| 940 std::unique_ptr<MockExtensionProvider> mock_provider = | |
| 941 base::MakeUnique<MockExtensionProvider>( | |
| 942 service(), Manifest::EXTERNAL_POLICY_DOWNLOAD); | |
| 943 MockExtensionProvider* mock_provider_ptr = mock_provider.get(); | |
| 944 AddMockExternalProvider(std::move(mock_provider)); | |
| 945 mock_provider_ptr->AddExtension(extension_id, "1.0.0.0", | |
| 946 data_dir().AppendASCII("good.crx")); | |
| 947 // Reloading extensions should find our externally registered extension | |
| 948 // and install it. | |
| 949 content::WindowedNotificationObserver observer( | |
| 950 extensions::NOTIFICATION_CRX_INSTALLER_DONE, | |
| 951 content::NotificationService::AllSources()); | |
| 952 service()->CheckForExternalUpdates(); | |
| 953 observer.Wait(); | |
| 954 | |
| 955 // Attempt to repair the good extension, expect failure. | |
| 956 std::unique_ptr<base::ListValue> args = | |
| 957 ListBuilder().Append(extension_id).Build(); | |
| 958 scoped_refptr<UIThreadExtensionFunction> function = | |
| 959 new api::DeveloperPrivateRepairExtensionFunction(); | |
| 960 EXPECT_FALSE(RunFunction(function, *args)); | |
| 961 EXPECT_EQ("Cannot repair a not corrupted extension.", function->GetError()); | |
| 962 | |
| 963 // Corrupt the extension , still expect repair failure because this is a | |
| 964 // policy extension. | |
| 965 service()->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED); | |
| 966 args = ListBuilder().Append(extension_id).Build(); | |
| 967 function = new api::DeveloperPrivateRepairExtensionFunction(); | |
| 968 EXPECT_FALSE(RunFunction(function, *args)); | |
| 969 EXPECT_EQ("Cannot repair a policy extension.", function->GetError()); | |
|
Devlin
2017/04/06 21:01:32
I'd slightly prefer two separate tests - one for u
lazyboy
2017/04/06 22:32:56
Done.
| |
| 970 } | |
| 971 | |
| 857 // Test developerPrivate.updateProfileConfiguration: Try to turn on devMode | 972 // Test developerPrivate.updateProfileConfiguration: Try to turn on devMode |
| 858 // when DeveloperToolsDisabled policy is active. | 973 // when DeveloperToolsDisabled policy is active. |
| 859 TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateDevModeDisabledPolicy) { | 974 TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateDevModeDisabledPolicy) { |
| 860 testing_pref_service()->SetManagedPref(prefs::kExtensionsUIDeveloperMode, | 975 testing_pref_service()->SetManagedPref(prefs::kExtensionsUIDeveloperMode, |
| 861 base::MakeUnique<base::Value>(false)); | 976 base::MakeUnique<base::Value>(false)); |
| 862 | 977 |
| 863 UpdateProfileConfigurationDevMode(true); | 978 UpdateProfileConfigurationDevMode(true); |
| 864 | 979 |
| 865 EXPECT_FALSE( | 980 EXPECT_FALSE( |
| 866 profile()->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode)); | 981 profile()->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode)); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 882 EXPECT_TRUE( | 997 EXPECT_TRUE( |
| 883 profile()->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode)); | 998 profile()->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode)); |
| 884 | 999 |
| 885 std::unique_ptr<api::developer_private::ProfileInfo> profile_info; | 1000 std::unique_ptr<api::developer_private::ProfileInfo> profile_info; |
| 886 ASSERT_NO_FATAL_FAILURE(GetProfileConfiguration(&profile_info)); | 1001 ASSERT_NO_FATAL_FAILURE(GetProfileConfiguration(&profile_info)); |
| 887 EXPECT_TRUE(profile_info->in_developer_mode); | 1002 EXPECT_TRUE(profile_info->in_developer_mode); |
| 888 EXPECT_FALSE(profile_info->is_developer_mode_controlled_by_policy); | 1003 EXPECT_FALSE(profile_info->is_developer_mode_controlled_by_policy); |
| 889 } | 1004 } |
| 890 | 1005 |
| 891 } // namespace extensions | 1006 } // namespace extensions |
| OLD | NEW |