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/command_line.h" 8#include "base/files/file_path.h" 9#include "base/memory/ref_counted.h" 10#include "base/path_service.h" 11#include "base/run_loop.h" 12#include "chrome/browser/browser_process.h" 13#include "chrome/browser/extensions/extension_browsertest.h" 14#include "chrome/browser/extensions/extension_test_message_listener.h" 15#include "chrome/browser/policy/browser_policy_connector.h" 16#include "chrome/browser/policy/cloud/cloud_policy_constants.h" 17#include "chrome/browser/policy/cloud/mock_cloud_policy_client.h" 18#include "chrome/browser/policy/policy_service.h" 19#include "chrome/browser/policy/profile_policy_connector.h" 20#include "chrome/browser/policy/profile_policy_connector_factory.h" 21#include "chrome/browser/policy/proto/cloud/chrome_extension_policy.pb.h" 22#include "chrome/browser/policy/test/local_policy_test_server.h" 23#include "chrome/browser/policy/test_utils.h" 24#include "chrome/browser/profiles/profile.h" 25#include "chrome/common/chrome_paths.h" 26#include "chrome/common/chrome_switches.h" 27#include "chrome/common/extensions/extension.h" 28#include "policy/proto/cloud_policy.pb.h" 29#include "testing/gmock/include/gmock/gmock.h" 30#include "testing/gtest/include/gtest/gtest.h" 31 32#if defined(OS_CHROMEOS) 33#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" 34#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" 35#include "chrome/common/chrome_paths.h" 36#include "chromeos/chromeos_switches.h" 37#else 38#include "chrome/browser/policy/cloud/user_cloud_policy_manager.h" 39#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h" 40#include "chrome/browser/signin/signin_manager.h" 41#include "chrome/browser/signin/signin_manager_factory.h" 42#endif 43 44using testing::InvokeWithoutArgs; 45using testing::Mock; 46using testing::Return; 47using testing::_; 48 49namespace em = enterprise_management; 50 51namespace policy { 52 53namespace { 54 55const char kDMToken[] = "dmtoken"; 56const char kDeviceID[] = "deviceid"; 57 58const char kTestExtension[] = "kjmkgkdkpedkejedfhmfcenooemhbpbo"; 59const char kTestExtension2[] = "behllobkkfkfnphdnhnkndlbkcpglgmj"; 60 61const base::FilePath::CharType kTestExtensionPath[] = 62 FILE_PATH_LITERAL("extensions/managed_extension"); 63const base::FilePath::CharType kTestExtension2Path[] = 64 FILE_PATH_LITERAL("extensions/managed_extension2"); 65 66const char kTestPolicy[] = 67 "{" 68 " \"Name\": {" 69 " \"Value\": \"disable_all_the_things\"" 70 " }" 71 "}"; 72 73const char kTestPolicyJSON[] = "{\"Name\":\"disable_all_the_things\"}"; 74 75const char kTestPolicy2[] = 76 "{" 77 " \"Another\": {" 78 " \"Value\": \"turn_it_off\"" 79 " }" 80 "}"; 81 82const char kTestPolicy2JSON[] = "{\"Another\":\"turn_it_off\"}"; 83 84} // namespace 85 86class ComponentCloudPolicyTest : public ExtensionBrowserTest { 87 protected: 88 ComponentCloudPolicyTest() {} 89 virtual ~ComponentCloudPolicyTest() {} 90 91 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 92 ExtensionBrowserTest::SetUpCommandLine(command_line); 93#if defined(OS_CHROMEOS) 94 // ExtensionBrowserTest sets the login users to a non-managed value; 95 // replace it. This is the default username sent in policy blobs from the 96 // testserver. 97 command_line->AppendSwitchASCII( 98 chromeos::switches::kLoginUser, "user@example.com"); 99#endif 100 } 101 102 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 103 test_server_.RegisterClient(kDMToken, kDeviceID); 104 EXPECT_TRUE(test_server_.UpdatePolicyData( 105 dm_protocol::kChromeExtensionPolicyType, kTestExtension, kTestPolicy)); 106 ASSERT_TRUE(test_server_.Start()); 107 108 std::string url = test_server_.GetServiceURL().spec(); 109 CommandLine* command_line = CommandLine::ForCurrentProcess(); 110 command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, url); 111 command_line->AppendSwitch(switches::kEnableComponentCloudPolicy); 112 113 ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); 114 } 115 116 virtual void SetUpOnMainThread() OVERRIDE { 117 ASSERT_TRUE(PolicyServiceIsEmpty(g_browser_process->policy_service())) 118 << "Pre-existing policies in this machine will make this test fail."; 119 120 // Install the initial extension. 121 ExtensionTestMessageListener ready_listener("ready", true); 122 event_listener_.reset(new ExtensionTestMessageListener("event", true)); 123 extension_ = LoadExtension(kTestExtensionPath); 124 ASSERT_TRUE(extension_.get()); 125 ASSERT_EQ(kTestExtension, extension_->id()); 126 EXPECT_TRUE(ready_listener.WaitUntilSatisfied()); 127 128 BrowserPolicyConnector* connector = 129 g_browser_process->browser_policy_connector(); 130 connector->ScheduleServiceInitialization(0); 131 132#if defined(OS_CHROMEOS) 133 UserCloudPolicyManagerChromeOS* policy_manager = 134 UserCloudPolicyManagerFactoryChromeOS::GetForProfile( 135 browser()->profile()); 136 ASSERT_TRUE(policy_manager); 137#else 138 // Mock a signed-in user. This is used by the UserCloudPolicyStore to pass 139 // the username to the UserCloudPolicyValidator. 140 SigninManager* signin_manager = 141 SigninManagerFactory::GetForProfile(browser()->profile()); 142 ASSERT_TRUE(signin_manager); 143 signin_manager->SetAuthenticatedUsername("user@example.com"); 144 145 UserCloudPolicyManager* policy_manager = 146 UserCloudPolicyManagerFactory::GetForProfile(browser()->profile()); 147 ASSERT_TRUE(policy_manager); 148 policy_manager->Connect(g_browser_process->local_state(), 149 UserCloudPolicyManager::CreateCloudPolicyClient( 150 connector->device_management_service()).Pass()); 151#endif // defined(OS_CHROMEOS) 152 153 // Register the cloud policy client. 154 ASSERT_TRUE(policy_manager->core()->client()); 155 base::RunLoop run_loop; 156 MockCloudPolicyClientObserver observer; 157 EXPECT_CALL(observer, OnRegistrationStateChanged(_)) 158 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 159 policy_manager->core()->client()->AddObserver(&observer); 160 policy_manager->core()->client()->SetupRegistration(kDMToken, kDeviceID); 161 run_loop.Run(); 162 Mock::VerifyAndClearExpectations(&observer); 163 policy_manager->core()->client()->RemoveObserver(&observer); 164 165 // The extension will receive an update event. 166 EXPECT_TRUE(event_listener_->WaitUntilSatisfied()); 167 168 ExtensionBrowserTest::SetUpOnMainThread(); 169 } 170 171 scoped_refptr<const extensions::Extension> LoadExtension( 172 const base::FilePath::CharType* path) { 173 base::FilePath full_path; 174 if (!PathService::Get(chrome::DIR_TEST_DATA, &full_path)) { 175 ADD_FAILURE(); 176 return NULL; 177 } 178 scoped_refptr<const extensions::Extension> extension( 179 ExtensionBrowserTest::LoadExtension(full_path.Append(path))); 180 if (!extension.get()) { 181 ADD_FAILURE(); 182 return NULL; 183 } 184 return extension; 185 } 186 187 void RefreshPolicies() { 188 ProfilePolicyConnector* profile_connector = 189 ProfilePolicyConnectorFactory::GetForProfile(browser()->profile()); 190 PolicyService* policy_service = profile_connector->policy_service(); 191 base::RunLoop run_loop; 192 policy_service->RefreshPolicies(run_loop.QuitClosure()); 193 run_loop.Run(); 194 } 195 196 LocalPolicyTestServer test_server_; 197 scoped_refptr<const extensions::Extension> extension_; 198 scoped_ptr<ExtensionTestMessageListener> event_listener_; 199}; 200 201// TODO(joaodasilva): enable these for other platforms once ready. 202#if defined(OS_CHROMEOS) 203 204IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, FetchExtensionPolicy) { 205 // Read the initial policy. 206 ExtensionTestMessageListener policy_listener(kTestPolicyJSON, true); 207 event_listener_->Reply("get-policy-Name"); 208 EXPECT_TRUE(policy_listener.WaitUntilSatisfied()); 209} 210 211IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, UpdateExtensionPolicy) { 212 // Read the initial policy. 213 ExtensionTestMessageListener policy_listener(kTestPolicyJSON, true); 214 event_listener_->Reply("get-policy-Name"); 215 EXPECT_TRUE(policy_listener.WaitUntilSatisfied()); 216 217 // Update the policy at the server and reload policy. 218 event_listener_.reset(new ExtensionTestMessageListener("event", true)); 219 policy_listener.Reply("idle"); 220 EXPECT_TRUE(test_server_.UpdatePolicyData( 221 dm_protocol::kChromeExtensionPolicyType, kTestExtension, kTestPolicy2)); 222 RefreshPolicies(); 223 224 // Check that the update event was received, and verify the new policy 225 // values. 226 EXPECT_TRUE(event_listener_->WaitUntilSatisfied()); 227 228 // This policy was removed. 229 ExtensionTestMessageListener policy_listener1("{}", true); 230 event_listener_->Reply("get-policy-Name"); 231 EXPECT_TRUE(policy_listener1.WaitUntilSatisfied()); 232 233 ExtensionTestMessageListener policy_listener2(kTestPolicy2JSON, true); 234 policy_listener1.Reply("get-policy-Another"); 235 EXPECT_TRUE(policy_listener2.WaitUntilSatisfied()); 236} 237 238IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, InstallNewExtension) { 239 EXPECT_TRUE(test_server_.UpdatePolicyData( 240 dm_protocol::kChromeExtensionPolicyType, kTestExtension2, kTestPolicy2)); 241 242 ExtensionTestMessageListener result_listener("ok", true); 243 result_listener.AlsoListenForFailureMessage("fail"); 244 scoped_refptr<const extensions::Extension> extension2 = 245 LoadExtension(kTestExtension2Path); 246 ASSERT_TRUE(extension2.get()); 247 ASSERT_EQ(kTestExtension2, extension2->id()); 248 249 // This extension only sends the 'policy' signal once it receives the policy, 250 // and after verifying it has the expected value. Otherwise it sends 'fail'. 251 EXPECT_TRUE(result_listener.WaitUntilSatisfied()); 252} 253 254#endif // OS_CHROMEOS 255 256} // namespace policy 257