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.
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"
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"
42 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
43 #include "chrome/browser/signin/signin_manager_factory.h"
44 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
45 #include "components/signin/core/browser/signin_manager.h"
48 using testing::InvokeWithoutArgs
;
50 using testing::Return
;
53 namespace em
= enterprise_management
;
59 const char kDMToken
[] = "dmtoken";
60 const char kDeviceID
[] = "deviceid";
62 const char kTestExtension
[] = "kjmkgkdkpedkejedfhmfcenooemhbpbo";
64 const base::FilePath::CharType kTestExtensionPath
[] =
65 FILE_PATH_LITERAL("extensions/managed_extension");
67 const char kTestPolicy
[] =
70 " \"Value\": \"disable_all_the_things\""
74 const char kTestExtension2
[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
75 const base::FilePath::CharType kTestExtension2Path
[] =
76 FILE_PATH_LITERAL("extensions/managed_extension2");
78 const char kTestPolicyJSON
[] = "{\"Name\":\"disable_all_the_things\"}";
80 const char kTestPolicy2
[] =
83 " \"Value\": \"turn_it_off\""
87 const char kTestPolicy2JSON
[] = "{\"Another\":\"turn_it_off\"}";
89 #if !defined(OS_CHROMEOS)
90 // Same encoding as ResourceCache does for its keys.
91 bool Base64UrlEncode(const std::string
& value
, std::string
* encoded
) {
94 base::Base64Encode(value
, encoded
);
95 base::ReplaceChars(*encoded
, "+", "-", encoded
);
96 base::ReplaceChars(*encoded
, "/", "_", encoded
);
103 class ComponentCloudPolicyTest
: public ExtensionBrowserTest
{
105 ComponentCloudPolicyTest() {}
106 virtual ~ComponentCloudPolicyTest() {}
108 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
109 ExtensionBrowserTest::SetUpCommandLine(command_line
);
110 #if defined(OS_CHROMEOS)
111 // ExtensionBrowserTest sets the login users to a non-managed value;
112 // replace it. This is the default username sent in policy blobs from the
114 command_line
->AppendSwitchASCII(
115 ::chromeos::switches::kLoginUser
, "user@example.com");
119 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE
{
120 test_server_
.RegisterClient(kDMToken
, kDeviceID
);
121 EXPECT_TRUE(test_server_
.UpdatePolicyData(
122 dm_protocol::kChromeExtensionPolicyType
, kTestExtension
, kTestPolicy
));
123 ASSERT_TRUE(test_server_
.Start());
125 std::string url
= test_server_
.GetServiceURL().spec();
126 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
127 command_line
->AppendSwitchASCII(switches::kDeviceManagementUrl
, url
);
128 command_line
->AppendSwitch(switches::kEnableComponentCloudPolicy
);
130 ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
133 virtual void SetUpOnMainThread() OVERRIDE
{
134 ASSERT_TRUE(PolicyServiceIsEmpty(g_browser_process
->policy_service()))
135 << "Pre-existing policies in this machine will make this test fail.";
137 // Install the initial extension.
138 ExtensionTestMessageListener
ready_listener("ready", true);
139 event_listener_
.reset(new ExtensionTestMessageListener("event", true));
140 extension_
= LoadExtension(kTestExtensionPath
);
141 ASSERT_TRUE(extension_
.get());
142 ASSERT_EQ(kTestExtension
, extension_
->id());
143 EXPECT_TRUE(ready_listener
.WaitUntilSatisfied());
145 // And start with a signed-in user.
148 // The extension will receive an update event.
149 EXPECT_TRUE(event_listener_
->WaitUntilSatisfied());
151 ExtensionBrowserTest::SetUpOnMainThread();
154 scoped_refptr
<const extensions::Extension
> LoadExtension(
155 const base::FilePath::CharType
* path
) {
156 base::FilePath full_path
;
157 if (!PathService::Get(chrome::DIR_TEST_DATA
, &full_path
)) {
161 scoped_refptr
<const extensions::Extension
> extension(
162 ExtensionBrowserTest::LoadExtension(full_path
.Append(path
)));
163 if (!extension
.get()) {
170 void SignInAndRegister() {
171 BrowserPolicyConnector
* connector
=
172 g_browser_process
->browser_policy_connector();
173 connector
->ScheduleServiceInitialization(0);
175 #if defined(OS_CHROMEOS)
176 UserCloudPolicyManagerChromeOS
* policy_manager
=
177 UserCloudPolicyManagerFactoryChromeOS::GetForProfile(
178 browser()->profile());
179 ASSERT_TRUE(policy_manager
);
181 // Mock a signed-in user. This is used by the UserCloudPolicyStore to pass
182 // the username to the UserCloudPolicyValidator.
183 SigninManager
* signin_manager
=
184 SigninManagerFactory::GetForProfile(browser()->profile());
185 ASSERT_TRUE(signin_manager
);
186 signin_manager
->SetAuthenticatedUsername("user@example.com");
188 UserCloudPolicyManager
* policy_manager
=
189 UserCloudPolicyManagerFactory::GetForBrowserContext(
190 browser()->profile());
191 ASSERT_TRUE(policy_manager
);
192 policy_manager
->Connect(
193 g_browser_process
->local_state(),
194 g_browser_process
->system_request_context(),
195 UserCloudPolicyManager::CreateCloudPolicyClient(
196 connector
->device_management_service(),
197 g_browser_process
->system_request_context()).Pass());
198 #endif // defined(OS_CHROMEOS)
200 // Register the cloud policy client.
201 ASSERT_TRUE(policy_manager
->core()->client());
202 base::RunLoop run_loop
;
203 MockCloudPolicyClientObserver observer
;
204 EXPECT_CALL(observer
, OnRegistrationStateChanged(_
))
205 .WillOnce(InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
206 policy_manager
->core()->client()->AddObserver(&observer
);
207 policy_manager
->core()->client()->SetupRegistration(kDMToken
, kDeviceID
);
209 Mock::VerifyAndClearExpectations(&observer
);
210 policy_manager
->core()->client()->RemoveObserver(&observer
);
213 #if !defined(OS_CHROMEOS)
215 SigninManager
* signin_manager
=
216 SigninManagerFactory::GetForProfile(browser()->profile());
217 ASSERT_TRUE(signin_manager
);
218 signin_manager
->SignOut();
222 void RefreshPolicies() {
223 ProfilePolicyConnector
* profile_connector
=
224 ProfilePolicyConnectorFactory::GetForProfile(browser()->profile());
225 PolicyService
* policy_service
= profile_connector
->policy_service();
226 base::RunLoop run_loop
;
227 policy_service
->RefreshPolicies(run_loop
.QuitClosure());
231 LocalPolicyTestServer test_server_
;
232 scoped_refptr
<const extensions::Extension
> extension_
;
233 scoped_ptr
<ExtensionTestMessageListener
> event_listener_
;
236 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest
, FetchExtensionPolicy
) {
237 // Read the initial policy.
238 ExtensionTestMessageListener
policy_listener(kTestPolicyJSON
, true);
239 event_listener_
->Reply("get-policy-Name");
240 EXPECT_TRUE(policy_listener
.WaitUntilSatisfied());
243 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest
, UpdateExtensionPolicy
) {
244 // Read the initial policy.
245 ExtensionTestMessageListener
policy_listener(kTestPolicyJSON
, true);
246 event_listener_
->Reply("get-policy-Name");
247 EXPECT_TRUE(policy_listener
.WaitUntilSatisfied());
249 // Update the policy at the server and reload policy.
250 event_listener_
.reset(new ExtensionTestMessageListener("event", true));
251 policy_listener
.Reply("idle");
252 EXPECT_TRUE(test_server_
.UpdatePolicyData(
253 dm_protocol::kChromeExtensionPolicyType
, kTestExtension
, kTestPolicy2
));
256 // Check that the update event was received, and verify the new policy
258 EXPECT_TRUE(event_listener_
->WaitUntilSatisfied());
260 // This policy was removed.
261 ExtensionTestMessageListener
policy_listener1("{}", true);
262 event_listener_
->Reply("get-policy-Name");
263 EXPECT_TRUE(policy_listener1
.WaitUntilSatisfied());
265 ExtensionTestMessageListener
policy_listener2(kTestPolicy2JSON
, true);
266 policy_listener1
.Reply("get-policy-Another");
267 EXPECT_TRUE(policy_listener2
.WaitUntilSatisfied());
270 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest
, InstallNewExtension
) {
271 EXPECT_TRUE(test_server_
.UpdatePolicyData(
272 dm_protocol::kChromeExtensionPolicyType
, kTestExtension2
, kTestPolicy2
));
274 ExtensionTestMessageListener
result_listener("ok", true);
275 result_listener
.set_failure_message("fail");
276 scoped_refptr
<const extensions::Extension
> extension2
=
277 LoadExtension(kTestExtension2Path
);
278 ASSERT_TRUE(extension2
.get());
279 ASSERT_EQ(kTestExtension2
, extension2
->id());
281 // This extension only sends the 'policy' signal once it receives the policy,
282 // and after verifying it has the expected value. Otherwise it sends 'fail'.
283 EXPECT_TRUE(result_listener
.WaitUntilSatisfied());
286 // Signing out on Chrome OS is a different process from signing out on the
287 // Desktop platforms. On Chrome OS the session is ended, and the user goes back
288 // to the sign-in screen; the Profile data is not affected. On the Desktop the
289 // session goes on though, and all the signed-in services are disconnected;
290 // in particular, the policy caches are dropped if the user signs out.
291 // This test verifies that when the user signs out then any existing component
292 // policy caches are dropped, and that it's still possible to sign back in and
293 // get policy for components working again.
294 #if !defined(OS_CHROMEOS)
295 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest
, SignOutAndBackIn
) {
296 // Read the initial policy.
297 ExtensionTestMessageListener
initial_policy_listener(kTestPolicyJSON
, true);
298 event_listener_
->Reply("get-policy-Name");
299 EXPECT_TRUE(initial_policy_listener
.WaitUntilSatisfied());
301 // Verify that the policy cache exists.
302 std::string cache_key
;
303 ASSERT_TRUE(Base64UrlEncode("extension-policy", &cache_key
));
304 std::string cache_subkey
;
305 ASSERT_TRUE(Base64UrlEncode(kTestExtension
, &cache_subkey
));
306 base::FilePath cache_path
= browser()->profile()->GetPath()
307 .Append(FILE_PATH_LITERAL("Policy"))
308 .Append(FILE_PATH_LITERAL("Components"))
309 .AppendASCII(cache_key
)
310 .AppendASCII(cache_subkey
);
311 EXPECT_TRUE(base::PathExists(cache_path
));
313 // Now sign-out. The policy cache should be removed, and the extension should
314 // get an empty policy update.
315 ExtensionTestMessageListener
event_listener("event", true);
316 initial_policy_listener
.Reply("idle");
318 EXPECT_TRUE(event_listener
.WaitUntilSatisfied());
320 // The extension got an update event; verify that the policy was empty.
321 ExtensionTestMessageListener
signout_policy_listener("{}", true);
322 event_listener
.Reply("get-policy-Name");
323 EXPECT_TRUE(signout_policy_listener
.WaitUntilSatisfied());
325 // Verify that the cache is gone.
326 EXPECT_FALSE(base::PathExists(cache_path
));
328 // Verify that the policy is fetched again if the user signs back in.
329 ExtensionTestMessageListener
event_listener2("event", true);
331 EXPECT_TRUE(event_listener2
.WaitUntilSatisfied());
333 // The extension got updated policy; verify it.
334 ExtensionTestMessageListener
signin_policy_listener(kTestPolicyJSON
, true);
335 event_listener2
.Reply("get-policy-Name");
336 EXPECT_TRUE(signin_policy_listener
.WaitUntilSatisfied());
338 // And the cache is back.
339 EXPECT_TRUE(base::PathExists(cache_path
));
343 } // namespace policy