component_cloud_policy_browsertest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/base64.h" 8#include "base/command_line.h" 9#include "base/file_util.h" 10#include "base/files/file_path.h" 11#include "base/memory/ref_counted.h" 12#include "base/path_service.h" 13#include "base/run_loop.h" 14#include "base/strings/string_util.h" 15#include "chrome/browser/browser_process.h" 16#include "chrome/browser/extensions/extension_browsertest.h" 17#include "chrome/browser/extensions/extension_test_message_listener.h" 18#include "chrome/browser/policy/profile_policy_connector.h" 19#include "chrome/browser/policy/profile_policy_connector_factory.h" 20#include "chrome/browser/policy/test/local_policy_test_server.h" 21#include "chrome/browser/profiles/profile.h" 22#include "chrome/browser/ui/browser.h" 23#include "chrome/common/chrome_paths.h" 24#include "components/policy/core/browser/browser_policy_connector.h" 25#include "components/policy/core/common/cloud/cloud_policy_constants.h" 26#include "components/policy/core/common/cloud/mock_cloud_policy_client.h" 27#include "components/policy/core/common/policy_service.h" 28#include "components/policy/core/common/policy_switches.h" 29#include "components/policy/core/common/policy_test_utils.h" 30#include "extensions/common/extension.h" 31#include "net/url_request/url_request_context_getter.h" 32#include "policy/proto/chrome_extension_policy.pb.h" 33#include "policy/proto/cloud_policy.pb.h" 34#include "testing/gmock/include/gmock/gmock.h" 35#include "testing/gtest/include/gtest/gtest.h" 36 37#if defined(OS_CHROMEOS) 38#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" 39#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" 40#include "chromeos/chromeos_switches.h" 41#else 42#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h" 43#include "chrome/browser/signin/signin_manager.h" 44#include "chrome/browser/signin/signin_manager_factory.h" 45#include "components/policy/core/common/cloud/user_cloud_policy_manager.h" 46#endif 47 48using testing::InvokeWithoutArgs; 49using testing::Mock; 50using testing::Return; 51using testing::_; 52 53namespace em = enterprise_management; 54 55namespace policy { 56 57const char kDMToken[] = "dmtoken"; 58const char kDeviceID[] = "deviceid"; 59 60const char kTestExtension[] = "kjmkgkdkpedkejedfhmfcenooemhbpbo"; 61 62const base::FilePath::CharType kTestExtensionPath[] = 63 FILE_PATH_LITERAL("extensions/managed_extension"); 64 65const char kTestPolicy[] = 66 "{" 67 " \"Name\": {" 68 " \"Value\": \"disable_all_the_things\"" 69 " }" 70 "}"; 71 72const char kTestExtension2[] = "behllobkkfkfnphdnhnkndlbkcpglgmj"; 73const base::FilePath::CharType kTestExtension2Path[] = 74 FILE_PATH_LITERAL("extensions/managed_extension2"); 75 76const char kTestPolicyJSON[] = "{\"Name\":\"disable_all_the_things\"}"; 77 78const char kTestPolicy2[] = 79 "{" 80 " \"Another\": {" 81 " \"Value\": \"turn_it_off\"" 82 " }" 83 "}"; 84 85const char kTestPolicy2JSON[] = "{\"Another\":\"turn_it_off\"}"; 86 87// Same encoding as ResourceCache does for its keys. 88bool Base64Encode(const std::string& value, std::string* encoded) { 89 if (value.empty()) 90 return false; 91 base::Base64Encode(value, encoded); 92 base::ReplaceChars(*encoded, "+", "-", encoded); 93 base::ReplaceChars(*encoded, "/", "_", encoded); 94 return true; 95} 96 97class ComponentCloudPolicyTest : public ExtensionBrowserTest { 98 protected: 99 ComponentCloudPolicyTest() {} 100 virtual ~ComponentCloudPolicyTest() {} 101 102 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 103 ExtensionBrowserTest::SetUpCommandLine(command_line); 104#if defined(OS_CHROMEOS) 105 // ExtensionBrowserTest sets the login users to a non-managed value; 106 // replace it. This is the default username sent in policy blobs from the 107 // testserver. 108 command_line->AppendSwitchASCII( 109 ::chromeos::switches::kLoginUser, "user@example.com"); 110#endif 111 } 112 113 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 114 test_server_.RegisterClient(kDMToken, kDeviceID); 115 EXPECT_TRUE(test_server_.UpdatePolicyData( 116 dm_protocol::kChromeExtensionPolicyType, kTestExtension, kTestPolicy)); 117 ASSERT_TRUE(test_server_.Start()); 118 119 std::string url = test_server_.GetServiceURL().spec(); 120 CommandLine* command_line = CommandLine::ForCurrentProcess(); 121 command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, url); 122 command_line->AppendSwitch(switches::kEnableComponentCloudPolicy); 123 command_line->AppendSwitch(switches::kEnablePolicyKeyVerification); 124 125 ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); 126 } 127 128 virtual void SetUpOnMainThread() OVERRIDE { 129 ASSERT_TRUE(PolicyServiceIsEmpty(g_browser_process->policy_service())) 130 << "Pre-existing policies in this machine will make this test fail."; 131 132 // Install the initial extension. 133 ExtensionTestMessageListener ready_listener("ready", true); 134 event_listener_.reset(new ExtensionTestMessageListener("event", true)); 135 extension_ = LoadExtension(kTestExtensionPath); 136 ASSERT_TRUE(extension_.get()); 137 ASSERT_EQ(kTestExtension, extension_->id()); 138 EXPECT_TRUE(ready_listener.WaitUntilSatisfied()); 139 140 // And start with a signed-in user. 141 SignInAndRegister(); 142 143 // The extension will receive an update event. 144 EXPECT_TRUE(event_listener_->WaitUntilSatisfied()); 145 146 ExtensionBrowserTest::SetUpOnMainThread(); 147 } 148 149 scoped_refptr<const extensions::Extension> LoadExtension( 150 const base::FilePath::CharType* path) { 151 base::FilePath full_path; 152 if (!PathService::Get(chrome::DIR_TEST_DATA, &full_path)) { 153 ADD_FAILURE(); 154 return NULL; 155 } 156 scoped_refptr<const extensions::Extension> extension( 157 ExtensionBrowserTest::LoadExtension(full_path.Append(path))); 158 if (!extension.get()) { 159 ADD_FAILURE(); 160 return NULL; 161 } 162 return extension; 163 } 164 165 void SignInAndRegister() { 166 BrowserPolicyConnector* connector = 167 g_browser_process->browser_policy_connector(); 168 connector->ScheduleServiceInitialization(0); 169 170#if defined(OS_CHROMEOS) 171 UserCloudPolicyManagerChromeOS* policy_manager = 172 UserCloudPolicyManagerFactoryChromeOS::GetForProfile( 173 browser()->profile()); 174 ASSERT_TRUE(policy_manager); 175#else 176 // Mock a signed-in user. This is used by the UserCloudPolicyStore to pass 177 // the username to the UserCloudPolicyValidator. 178 SigninManager* signin_manager = 179 SigninManagerFactory::GetForProfile(browser()->profile()); 180 ASSERT_TRUE(signin_manager); 181 signin_manager->SetAuthenticatedUsername("user@example.com"); 182 183 UserCloudPolicyManager* policy_manager = 184 UserCloudPolicyManagerFactory::GetForBrowserContext( 185 browser()->profile()); 186 ASSERT_TRUE(policy_manager); 187 policy_manager->Connect( 188 g_browser_process->local_state(), 189 g_browser_process->system_request_context(), 190 UserCloudPolicyManager::CreateCloudPolicyClient( 191 connector->device_management_service(), 192 g_browser_process->system_request_context()).Pass()); 193#endif // defined(OS_CHROMEOS) 194 195 // Register the cloud policy client. 196 ASSERT_TRUE(policy_manager->core()->client()); 197 base::RunLoop run_loop; 198 MockCloudPolicyClientObserver observer; 199 EXPECT_CALL(observer, OnRegistrationStateChanged(_)) 200 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 201 policy_manager->core()->client()->AddObserver(&observer); 202 policy_manager->core()->client()->SetupRegistration(kDMToken, kDeviceID); 203 run_loop.Run(); 204 Mock::VerifyAndClearExpectations(&observer); 205 policy_manager->core()->client()->RemoveObserver(&observer); 206 } 207 208#if !defined(OS_CHROMEOS) 209 void SignOut() { 210 SigninManager* signin_manager = 211 SigninManagerFactory::GetForProfile(browser()->profile()); 212 ASSERT_TRUE(signin_manager); 213 signin_manager->SignOut(); 214 } 215#endif 216 217 void RefreshPolicies() { 218 ProfilePolicyConnector* profile_connector = 219 ProfilePolicyConnectorFactory::GetForProfile(browser()->profile()); 220 PolicyService* policy_service = profile_connector->policy_service(); 221 base::RunLoop run_loop; 222 policy_service->RefreshPolicies(run_loop.QuitClosure()); 223 run_loop.Run(); 224 } 225 226 LocalPolicyTestServer test_server_; 227 scoped_refptr<const extensions::Extension> extension_; 228 scoped_ptr<ExtensionTestMessageListener> event_listener_; 229}; 230 231IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, FetchExtensionPolicy) { 232 // Read the initial policy. 233 ExtensionTestMessageListener policy_listener(kTestPolicyJSON, true); 234 event_listener_->Reply("get-policy-Name"); 235 EXPECT_TRUE(policy_listener.WaitUntilSatisfied()); 236} 237 238IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, UpdateExtensionPolicy) { 239 // Read the initial policy. 240 ExtensionTestMessageListener policy_listener(kTestPolicyJSON, true); 241 event_listener_->Reply("get-policy-Name"); 242 EXPECT_TRUE(policy_listener.WaitUntilSatisfied()); 243 244 // Update the policy at the server and reload policy. 245 event_listener_.reset(new ExtensionTestMessageListener("event", true)); 246 policy_listener.Reply("idle"); 247 EXPECT_TRUE(test_server_.UpdatePolicyData( 248 dm_protocol::kChromeExtensionPolicyType, kTestExtension, kTestPolicy2)); 249 RefreshPolicies(); 250 251 // Check that the update event was received, and verify the new policy 252 // values. 253 EXPECT_TRUE(event_listener_->WaitUntilSatisfied()); 254 255 // This policy was removed. 256 ExtensionTestMessageListener policy_listener1("{}", true); 257 event_listener_->Reply("get-policy-Name"); 258 EXPECT_TRUE(policy_listener1.WaitUntilSatisfied()); 259 260 ExtensionTestMessageListener policy_listener2(kTestPolicy2JSON, true); 261 policy_listener1.Reply("get-policy-Another"); 262 EXPECT_TRUE(policy_listener2.WaitUntilSatisfied()); 263} 264 265IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, InstallNewExtension) { 266 EXPECT_TRUE(test_server_.UpdatePolicyData( 267 dm_protocol::kChromeExtensionPolicyType, kTestExtension2, kTestPolicy2)); 268 269 ExtensionTestMessageListener result_listener("ok", true); 270 result_listener.AlsoListenForFailureMessage("fail"); 271 scoped_refptr<const extensions::Extension> extension2 = 272 LoadExtension(kTestExtension2Path); 273 ASSERT_TRUE(extension2.get()); 274 ASSERT_EQ(kTestExtension2, extension2->id()); 275 276 // This extension only sends the 'policy' signal once it receives the policy, 277 // and after verifying it has the expected value. Otherwise it sends 'fail'. 278 EXPECT_TRUE(result_listener.WaitUntilSatisfied()); 279} 280 281// Signing out on Chrome OS is a different process from signing out on the 282// Desktop platforms. On Chrome OS the session is ended, and the user goes back 283// to the sign-in screen; the Profile data is not affected. On the Desktop the 284// session goes on though, and all the signed-in services are disconnected; 285// in particular, the policy caches are dropped if the user signs out. 286// This test verifies that when the user signs out then any existing component 287// policy caches are dropped, and that it's still possible to sign back in and 288// get policy for components working again. 289#if !defined(OS_CHROMEOS) 290IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, SignOutAndBackIn) { 291 // Read the initial policy. 292 ExtensionTestMessageListener initial_policy_listener(kTestPolicyJSON, true); 293 event_listener_->Reply("get-policy-Name"); 294 EXPECT_TRUE(initial_policy_listener.WaitUntilSatisfied()); 295 296 // Verify that the policy cache exists. 297 std::string cache_key; 298 ASSERT_TRUE(Base64Encode("extension-policy", &cache_key)); 299 std::string cache_subkey; 300 ASSERT_TRUE(Base64Encode(kTestExtension, &cache_subkey)); 301 base::FilePath cache_path = browser()->profile()->GetPath() 302 .Append(FILE_PATH_LITERAL("Policy")) 303 .Append(FILE_PATH_LITERAL("Components")) 304 .AppendASCII(cache_key) 305 .AppendASCII(cache_subkey); 306 EXPECT_TRUE(base::PathExists(cache_path)); 307 308 // Now sign-out. The policy cache should be removed, and the extension should 309 // get an empty policy update. 310 ExtensionTestMessageListener event_listener("event", true); 311 initial_policy_listener.Reply("idle"); 312 SignOut(); 313 EXPECT_TRUE(event_listener.WaitUntilSatisfied()); 314 315 // The extension got an update event; verify that the policy was empty. 316 ExtensionTestMessageListener signout_policy_listener("{}", true); 317 event_listener.Reply("get-policy-Name"); 318 EXPECT_TRUE(signout_policy_listener.WaitUntilSatisfied()); 319 320 // Verify that the cache is gone. 321 EXPECT_FALSE(base::PathExists(cache_path)); 322 323 // Verify that the policy is fetched again if the user signs back in. 324 ExtensionTestMessageListener event_listener2("event", true); 325 SignInAndRegister(); 326 EXPECT_TRUE(event_listener2.WaitUntilSatisfied()); 327 328 // The extension got updated policy; verify it. 329 ExtensionTestMessageListener signin_policy_listener(kTestPolicyJSON, true); 330 event_listener2.Reply("get-policy-Name"); 331 EXPECT_TRUE(signin_policy_listener.WaitUntilSatisfied()); 332 333 // And the cache is back. 334 EXPECT_TRUE(base::PathExists(cache_path)); 335} 336#endif 337 338} // namespace policy 339