| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <string> | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/command_line.h" | |
| 9 #include "base/file_util.h" | |
| 10 #include "base/files/file_path.h" | |
| 11 #include "base/files/scoped_temp_dir.h" | |
| 12 #include "base/memory/ref_counted.h" | |
| 13 #include "base/message_loop.h" | |
| 14 #include "base/path_service.h" | |
| 15 #include "base/run_loop.h" | |
| 16 #include "chrome/browser/browser_process.h" | |
| 17 #include "chrome/browser/extensions/extension_browsertest.h" | |
| 18 #include "chrome/browser/extensions/extension_test_message_listener.h" | |
| 19 #include "chrome/browser/policy/browser_policy_connector.h" | |
| 20 #include "chrome/browser/policy/cloud_policy_constants.h" | |
| 21 #include "chrome/browser/policy/mock_cloud_policy_client.h" | |
| 22 #include "chrome/browser/policy/policy_service.h" | |
| 23 #include "chrome/browser/policy/proto/chrome_extension_policy.pb.h" | |
| 24 #include "chrome/browser/policy/proto/cloud_policy.pb.h" | |
| 25 #include "chrome/browser/policy/test/local_policy_test_server.h" | |
| 26 #include "chrome/browser/policy/test_utils.h" | |
| 27 #include "chrome/browser/profiles/profile.h" | |
| 28 #include "chrome/common/chrome_paths.h" | |
| 29 #include "chrome/common/chrome_switches.h" | |
| 30 #include "chrome/common/extensions/extension.h" | |
| 31 #include "testing/gmock/include/gmock/gmock.h" | |
| 32 #include "testing/gtest/include/gtest/gtest.h" | |
| 33 | |
| 34 #if defined(OS_CHROMEOS) | |
| 35 #include "chrome/browser/chromeos/login/user_manager.h" | |
| 36 #include "chrome/browser/policy/user_cloud_policy_manager_chromeos.h" | |
| 37 #include "chrome/common/chrome_paths.h" | |
| 38 #include "chromeos/dbus/mock_cryptohome_client.h" | |
| 39 #include "chromeos/dbus/mock_dbus_thread_manager.h" | |
| 40 #include "chromeos/dbus/mock_session_manager_client.h" | |
| 41 #else | |
| 42 #include "chrome/browser/policy/user_cloud_policy_manager.h" | |
| 43 #include "chrome/browser/policy/user_cloud_policy_manager_factory.h" | |
| 44 #include "chrome/browser/signin/signin_manager.h" | |
| 45 #include "chrome/browser/signin/signin_manager_factory.h" | |
| 46 #endif | |
| 47 | |
| 48 using testing::InvokeWithoutArgs; | |
| 49 using testing::Mock; | |
| 50 using testing::_; | |
| 51 | |
| 52 namespace em = enterprise_management; | |
| 53 | |
| 54 namespace policy { | |
| 55 | |
| 56 namespace { | |
| 57 | |
| 58 const char kDMToken[] = "dmtoken"; | |
| 59 const char kDeviceID[] = "deviceid"; | |
| 60 | |
| 61 const char kTestExtension[] = "kjmkgkdkpedkejedfhmfcenooemhbpbo"; | |
| 62 const char kTestExtension2[] = "behllobkkfkfnphdnhnkndlbkcpglgmj"; | |
| 63 | |
| 64 const base::FilePath::CharType kTestExtensionPath[] = | |
| 65 FILE_PATH_LITERAL("extensions/managed_extension"); | |
| 66 const base::FilePath::CharType kTestExtension2Path[] = | |
| 67 FILE_PATH_LITERAL("extensions/managed_extension2"); | |
| 68 | |
| 69 const char kTestPolicy[] = | |
| 70 "{" | |
| 71 " \"Name\": {" | |
| 72 " \"Value\": \"disable_all_the_things\"" | |
| 73 " }" | |
| 74 "}"; | |
| 75 | |
| 76 const char kTestPolicyJSON[] = "{\"Name\":\"disable_all_the_things\"}"; | |
| 77 | |
| 78 const char kTestPolicy2[] = | |
| 79 "{" | |
| 80 " \"Another\": {" | |
| 81 " \"Value\": \"turn_it_off\"" | |
| 82 " }" | |
| 83 "}"; | |
| 84 | |
| 85 const char kTestPolicy2JSON[] = "{\"Another\":\"turn_it_off\"}"; | |
| 86 | |
| 87 #if defined(OS_CHROMEOS) | |
| 88 | |
| 89 const char kSanitizedUsername[] = "0123456789ABCDEF0123456789ABCDEF01234567"; | |
| 90 | |
| 91 ACTION(GetSanitizedUsername) { | |
| 92 MessageLoop::current()->PostTask( | |
| 93 FROM_HERE, | |
| 94 base::Bind(arg1, chromeos::DBUS_METHOD_CALL_SUCCESS, kSanitizedUsername)); | |
| 95 } | |
| 96 | |
| 97 ACTION_P(RetrieveUserPolicy, storage) { | |
| 98 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(arg0, *storage)); | |
| 99 } | |
| 100 | |
| 101 ACTION_P2(StoreUserPolicy, storage, user_policy_key_file) { | |
| 102 // The session_manager stores a copy of the policy key at | |
| 103 // /var/run/user_policy/$hash/policy.pub. Simulate that behavior here, so | |
| 104 // that the policy signature can be validated. | |
| 105 em::PolicyFetchResponse policy; | |
| 106 ASSERT_TRUE(policy.ParseFromString(arg0)); | |
| 107 if (policy.has_new_public_key()) { | |
| 108 ASSERT_TRUE(file_util::CreateDirectory(user_policy_key_file.DirName())); | |
| 109 int result = file_util::WriteFile( | |
| 110 user_policy_key_file, | |
| 111 policy.new_public_key().data(), | |
| 112 policy.new_public_key().size()); | |
| 113 ASSERT_EQ(static_cast<int>(policy.new_public_key().size()), result); | |
| 114 } | |
| 115 | |
| 116 *storage = arg0; | |
| 117 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(arg1, true)); | |
| 118 } | |
| 119 | |
| 120 #else | |
| 121 | |
| 122 const char kTestUser[] = "user@example.com"; | |
| 123 | |
| 124 #endif // OS_CHROMEOS | |
| 125 | |
| 126 } // namespace | |
| 127 | |
| 128 class ComponentCloudPolicyTest : public ExtensionBrowserTest { | |
| 129 protected: | |
| 130 ComponentCloudPolicyTest() {} | |
| 131 virtual ~ComponentCloudPolicyTest() {} | |
| 132 | |
| 133 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
| 134 ExtensionBrowserTest::SetUpCommandLine(command_line); | |
| 135 #if defined(OS_CHROMEOS) | |
| 136 // ExtensionBrowserTest sets the login users to a non-managed value; | |
| 137 // replace it. This is the default username sent in policy blobs from the | |
| 138 // testserver. | |
| 139 command_line->AppendSwitchASCII(switches::kLoginUser, "user@example.com"); | |
| 140 #endif | |
| 141 } | |
| 142 | |
| 143 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { | |
| 144 test_server_.RegisterClient(kDMToken, kDeviceID); | |
| 145 EXPECT_TRUE(test_server_.UpdatePolicyData( | |
| 146 dm_protocol::kChromeExtensionPolicyType, kTestExtension, kTestPolicy)); | |
| 147 ASSERT_TRUE(test_server_.Start()); | |
| 148 | |
| 149 std::string url = test_server_.GetServiceURL().spec(); | |
| 150 CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
| 151 command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, url); | |
| 152 command_line->AppendSwitch(switches::kEnableComponentCloudPolicy); | |
| 153 | |
| 154 #if defined(OS_CHROMEOS) | |
| 155 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
| 156 base::FilePath user_key_path = | |
| 157 temp_dir_.path().AppendASCII(kSanitizedUsername) | |
| 158 .AppendASCII("policy.pub"); | |
| 159 PathService::Override(chrome::DIR_USER_POLICY_KEYS, temp_dir_.path()); | |
| 160 | |
| 161 mock_dbus_thread_manager_ = new chromeos::MockDBusThreadManager(); | |
| 162 chromeos::DBusThreadManager::InitializeForTesting( | |
| 163 mock_dbus_thread_manager_); | |
| 164 EXPECT_CALL(*mock_dbus_thread_manager_->mock_cryptohome_client(), | |
| 165 GetSanitizedUsername(_, _)) | |
| 166 .WillRepeatedly(GetSanitizedUsername()); | |
| 167 EXPECT_CALL(*mock_dbus_thread_manager_->mock_session_manager_client(), | |
| 168 StoreUserPolicy(_, _)) | |
| 169 .WillRepeatedly(StoreUserPolicy(&session_manager_user_policy_, | |
| 170 user_key_path)); | |
| 171 EXPECT_CALL(*mock_dbus_thread_manager_->mock_session_manager_client(), | |
| 172 RetrieveUserPolicy(_)) | |
| 173 .WillRepeatedly(RetrieveUserPolicy(&session_manager_user_policy_)); | |
| 174 #endif // OS_CHROMEOS | |
| 175 | |
| 176 ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); | |
| 177 } | |
| 178 | |
| 179 virtual void SetUpOnMainThread() OVERRIDE { | |
| 180 ASSERT_TRUE(PolicyServiceIsEmpty(g_browser_process->policy_service())) | |
| 181 << "Pre-existing policies in this machine will make this test fail."; | |
| 182 | |
| 183 // Install the initial extension. | |
| 184 ExtensionTestMessageListener ready_listener("ready", true); | |
| 185 event_listener_.reset(new ExtensionTestMessageListener("event", true)); | |
| 186 extension_ = LoadExtension(kTestExtensionPath); | |
| 187 ASSERT_TRUE(extension_); | |
| 188 ASSERT_EQ(kTestExtension, extension_->id()); | |
| 189 EXPECT_TRUE(ready_listener.WaitUntilSatisfied()); | |
| 190 | |
| 191 BrowserPolicyConnector* connector = | |
| 192 g_browser_process->browser_policy_connector(); | |
| 193 connector->ScheduleServiceInitialization(0); | |
| 194 | |
| 195 #if defined(OS_CHROMEOS) | |
| 196 UserCloudPolicyManagerChromeOS* policy_manager = | |
| 197 connector->GetUserCloudPolicyManager(); | |
| 198 ASSERT_TRUE(policy_manager); | |
| 199 #else | |
| 200 // Mock a signed-in user. This is used by the UserCloudPolicyStore to pass | |
| 201 // the username to the UserCloudPolicyValidator. | |
| 202 SigninManager* signin_manager = | |
| 203 SigninManagerFactory::GetForProfile(browser()->profile()); | |
| 204 ASSERT_TRUE(signin_manager); | |
| 205 signin_manager->SetAuthenticatedUsername(kTestUser); | |
| 206 | |
| 207 UserCloudPolicyManager* policy_manager = | |
| 208 UserCloudPolicyManagerFactory::GetForProfile(browser()->profile()); | |
| 209 ASSERT_TRUE(policy_manager); | |
| 210 policy_manager->Connect(g_browser_process->local_state(), | |
| 211 UserCloudPolicyManager::CreateCloudPolicyClient( | |
| 212 connector->device_management_service()).Pass()); | |
| 213 #endif // defined(OS_CHROMEOS) | |
| 214 | |
| 215 // Register the cloud policy client. | |
| 216 ASSERT_TRUE(policy_manager->core()->client()); | |
| 217 base::RunLoop run_loop; | |
| 218 MockCloudPolicyClientObserver observer; | |
| 219 EXPECT_CALL(observer, OnRegistrationStateChanged(_)) | |
| 220 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); | |
| 221 policy_manager->core()->client()->AddObserver(&observer); | |
| 222 policy_manager->core()->client()->SetupRegistration(kDMToken, kDeviceID); | |
| 223 run_loop.Run(); | |
| 224 Mock::VerifyAndClearExpectations(&observer); | |
| 225 policy_manager->core()->client()->RemoveObserver(&observer); | |
| 226 | |
| 227 // The extension will receive an update event. | |
| 228 EXPECT_TRUE(event_listener_->WaitUntilSatisfied()); | |
| 229 | |
| 230 ExtensionBrowserTest::SetUpOnMainThread(); | |
| 231 } | |
| 232 | |
| 233 scoped_refptr<const extensions::Extension> LoadExtension( | |
| 234 const base::FilePath::CharType* path) { | |
| 235 base::FilePath full_path; | |
| 236 if (!PathService::Get(chrome::DIR_TEST_DATA, &full_path)) { | |
| 237 ADD_FAILURE(); | |
| 238 return NULL; | |
| 239 } | |
| 240 scoped_refptr<const extensions::Extension> extension( | |
| 241 ExtensionBrowserTest::LoadExtension(full_path.Append(path))); | |
| 242 if (!extension) { | |
| 243 ADD_FAILURE(); | |
| 244 return NULL; | |
| 245 } | |
| 246 return extension; | |
| 247 } | |
| 248 | |
| 249 void RefreshPolicies() { | |
| 250 PolicyService* policy_service = browser()->profile()->GetPolicyService(); | |
| 251 base::RunLoop run_loop; | |
| 252 policy_service->RefreshPolicies(run_loop.QuitClosure()); | |
| 253 run_loop.Run(); | |
| 254 } | |
| 255 | |
| 256 LocalPolicyTestServer test_server_; | |
| 257 scoped_refptr<const extensions::Extension> extension_; | |
| 258 scoped_ptr<ExtensionTestMessageListener> event_listener_; | |
| 259 | |
| 260 #if defined(OS_CHROMEOS) | |
| 261 base::ScopedTempDir temp_dir_; | |
| 262 std::string session_manager_user_policy_; | |
| 263 chromeos::MockDBusThreadManager* mock_dbus_thread_manager_; | |
| 264 #endif | |
| 265 }; | |
| 266 | |
| 267 // TODO(joaodasilva): enable these for other platforms once ready. | |
| 268 #if defined(OS_CHROMEOS) | |
| 269 | |
| 270 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, FetchExtensionPolicy) { | |
| 271 // Read the initial policy. | |
| 272 ExtensionTestMessageListener policy_listener(kTestPolicyJSON, true); | |
| 273 event_listener_->Reply("get-policy-Name"); | |
| 274 EXPECT_TRUE(policy_listener.WaitUntilSatisfied()); | |
| 275 } | |
| 276 | |
| 277 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, UpdateExtensionPolicy) { | |
| 278 // Read the initial policy. | |
| 279 ExtensionTestMessageListener policy_listener(kTestPolicyJSON, true); | |
| 280 event_listener_->Reply("get-policy-Name"); | |
| 281 EXPECT_TRUE(policy_listener.WaitUntilSatisfied()); | |
| 282 | |
| 283 // Update the policy at the server and reload policy. | |
| 284 event_listener_.reset(new ExtensionTestMessageListener("event", true)); | |
| 285 policy_listener.Reply("idle"); | |
| 286 EXPECT_TRUE(test_server_.UpdatePolicyData( | |
| 287 dm_protocol::kChromeExtensionPolicyType, kTestExtension, kTestPolicy2)); | |
| 288 RefreshPolicies(); | |
| 289 | |
| 290 // Check that the update event was received, and verify the new policy | |
| 291 // values. | |
| 292 EXPECT_TRUE(event_listener_->WaitUntilSatisfied()); | |
| 293 | |
| 294 // This policy was removed. | |
| 295 ExtensionTestMessageListener policy_listener1("{}", true); | |
| 296 event_listener_->Reply("get-policy-Name"); | |
| 297 EXPECT_TRUE(policy_listener1.WaitUntilSatisfied()); | |
| 298 | |
| 299 ExtensionTestMessageListener policy_listener2(kTestPolicy2JSON, true); | |
| 300 policy_listener1.Reply("get-policy-Another"); | |
| 301 EXPECT_TRUE(policy_listener2.WaitUntilSatisfied()); | |
| 302 } | |
| 303 | |
| 304 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, InstallNewExtension) { | |
| 305 EXPECT_TRUE(test_server_.UpdatePolicyData( | |
| 306 dm_protocol::kChromeExtensionPolicyType, kTestExtension2, kTestPolicy2)); | |
| 307 | |
| 308 ExtensionTestMessageListener result_listener("ok", true); | |
| 309 result_listener.AlsoListenForFailureMessage("fail"); | |
| 310 scoped_refptr<const extensions::Extension> extension2 = | |
| 311 LoadExtension(kTestExtension2Path); | |
| 312 ASSERT_TRUE(extension2); | |
| 313 ASSERT_EQ(kTestExtension2, extension2->id()); | |
| 314 | |
| 315 // This extension only sends the 'policy' signal once it receives the policy, | |
| 316 // and after verifying it has the expected value. Otherwise it sends 'fail'. | |
| 317 EXPECT_TRUE(result_listener.WaitUntilSatisfied()); | |
| 318 } | |
| 319 | |
| 320 #endif // OS_CHROMEOS | |
| 321 | |
| 322 } // namespace policy | |
| OLD | NEW |