Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / policy / cloud / component_cloud_policy_browsertest.cc
blobd1adf4ed30f90fa5a7c19fd25102cdf7f12d7b88
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.
5 #include <string>
7 #include "base/base64.h"
8 #include "base/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.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/policy/profile_policy_connector.h"
18 #include "chrome/browser/policy/profile_policy_connector_factory.h"
19 #include "chrome/browser/policy/test/local_policy_test_server.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "components/policy/core/browser/browser_policy_connector.h"
24 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
25 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
26 #include "components/policy/core/common/policy_service.h"
27 #include "components/policy/core/common/policy_switches.h"
28 #include "components/policy/core/common/policy_test_utils.h"
29 #include "extensions/common/extension.h"
30 #include "extensions/test/extension_test_message_listener.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"
41 #else
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"
46 #endif
48 using testing::InvokeWithoutArgs;
49 using testing::Mock;
50 using testing::Return;
51 using testing::_;
53 namespace em = enterprise_management;
55 namespace policy {
57 namespace {
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[] =
68 "{"
69 " \"Name\": {"
70 " \"Value\": \"disable_all_the_things\""
71 " }"
72 "}";
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[] =
81 "{"
82 " \"Another\": {"
83 " \"Value\": \"turn_it_off\""
84 " }"
85 "}";
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) {
92 if (value.empty())
93 return false;
94 base::Base64Encode(value, encoded);
95 base::ReplaceChars(*encoded, "+", "-", encoded);
96 base::ReplaceChars(*encoded, "/", "_", encoded);
97 return true;
99 #endif
101 } // namespace
103 class ComponentCloudPolicyTest : public ExtensionBrowserTest {
104 protected:
105 ComponentCloudPolicyTest() {}
106 ~ComponentCloudPolicyTest() override {}
108 void SetUpCommandLine(base::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
113 // testserver.
114 command_line->AppendSwitchASCII(
115 ::chromeos::switches::kLoginUser, "user@example.com");
116 #endif
119 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 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
127 command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, url);
129 ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
132 void SetUpOnMainThread() override {
133 ASSERT_TRUE(PolicyServiceIsEmpty(g_browser_process->policy_service()))
134 << "Pre-existing policies in this machine will make this test fail.";
136 // Install the initial extension.
137 ExtensionTestMessageListener ready_listener("ready", true);
138 event_listener_.reset(new ExtensionTestMessageListener("event", true));
139 extension_ = LoadExtension(kTestExtensionPath);
140 ASSERT_TRUE(extension_.get());
141 ASSERT_EQ(kTestExtension, extension_->id());
142 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
144 // And start with a signed-in user.
145 SignInAndRegister();
147 // The extension will receive an update event.
148 EXPECT_TRUE(event_listener_->WaitUntilSatisfied());
150 ExtensionBrowserTest::SetUpOnMainThread();
153 scoped_refptr<const extensions::Extension> LoadExtension(
154 const base::FilePath::CharType* path) {
155 base::FilePath full_path;
156 if (!PathService::Get(chrome::DIR_TEST_DATA, &full_path)) {
157 ADD_FAILURE();
158 return NULL;
160 scoped_refptr<const extensions::Extension> extension(
161 ExtensionBrowserTest::LoadExtension(full_path.Append(path)));
162 if (!extension.get()) {
163 ADD_FAILURE();
164 return NULL;
166 return extension;
169 void SignInAndRegister() {
170 BrowserPolicyConnector* connector =
171 g_browser_process->browser_policy_connector();
172 connector->ScheduleServiceInitialization(0);
174 #if defined(OS_CHROMEOS)
175 UserCloudPolicyManagerChromeOS* policy_manager =
176 UserCloudPolicyManagerFactoryChromeOS::GetForProfile(
177 browser()->profile());
178 ASSERT_TRUE(policy_manager);
179 #else
180 // Mock a signed-in user. This is used by the UserCloudPolicyStore to pass
181 // the username to the UserCloudPolicyValidator.
182 SigninManager* signin_manager =
183 SigninManagerFactory::GetForProfile(browser()->profile());
184 ASSERT_TRUE(signin_manager);
185 signin_manager->SetAuthenticatedAccountInfo("12345", "user@example.com");
187 UserCloudPolicyManager* policy_manager =
188 UserCloudPolicyManagerFactory::GetForBrowserContext(
189 browser()->profile());
190 ASSERT_TRUE(policy_manager);
191 policy_manager->Connect(
192 g_browser_process->local_state(),
193 g_browser_process->system_request_context(),
194 UserCloudPolicyManager::CreateCloudPolicyClient(
195 connector->device_management_service(),
196 g_browser_process->system_request_context()).Pass());
197 #endif // defined(OS_CHROMEOS)
199 // Register the cloud policy client.
200 ASSERT_TRUE(policy_manager->core()->client());
201 base::RunLoop run_loop;
202 MockCloudPolicyClientObserver observer;
203 EXPECT_CALL(observer, OnRegistrationStateChanged(_))
204 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
205 policy_manager->core()->client()->AddObserver(&observer);
206 policy_manager->core()->client()->SetupRegistration(kDMToken, kDeviceID);
207 run_loop.Run();
208 Mock::VerifyAndClearExpectations(&observer);
209 policy_manager->core()->client()->RemoveObserver(&observer);
212 #if !defined(OS_CHROMEOS)
213 void SignOut() {
214 SigninManager* signin_manager =
215 SigninManagerFactory::GetForProfile(browser()->profile());
216 ASSERT_TRUE(signin_manager);
217 signin_manager->SignOut(signin_metrics::SIGNOUT_TEST);
219 #endif
221 void RefreshPolicies() {
222 ProfilePolicyConnector* profile_connector =
223 ProfilePolicyConnectorFactory::GetForBrowserContext(
224 browser()->profile());
225 PolicyService* policy_service = profile_connector->policy_service();
226 base::RunLoop run_loop;
227 policy_service->RefreshPolicies(run_loop.QuitClosure());
228 run_loop.Run();
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));
254 RefreshPolicies();
256 // Check that the update event was received, and verify the new policy
257 // values.
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));
273 // Installing a new extension doesn't trigger another policy fetch because
274 // the server always sends down the list of all extensions that have policy.
275 // Fetch now that the configuration has been updated and before installing
276 // the extension.
277 RefreshPolicies();
279 ExtensionTestMessageListener result_listener("ok", true);
280 result_listener.set_failure_message("fail");
281 scoped_refptr<const extensions::Extension> extension2 =
282 LoadExtension(kTestExtension2Path);
283 ASSERT_TRUE(extension2.get());
284 ASSERT_EQ(kTestExtension2, extension2->id());
286 // This extension only sends the 'policy' signal once it receives the policy,
287 // and after verifying it has the expected value. Otherwise it sends 'fail'.
288 EXPECT_TRUE(result_listener.WaitUntilSatisfied());
291 // Signing out on Chrome OS is a different process from signing out on the
292 // Desktop platforms. On Chrome OS the session is ended, and the user goes back
293 // to the sign-in screen; the Profile data is not affected. On the Desktop the
294 // session goes on though, and all the signed-in services are disconnected;
295 // in particular, the policy caches are dropped if the user signs out.
296 // This test verifies that when the user signs out then any existing component
297 // policy caches are dropped, and that it's still possible to sign back in and
298 // get policy for components working again.
299 #if !defined(OS_CHROMEOS)
300 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, SignOutAndBackIn) {
301 // Read the initial policy.
302 ExtensionTestMessageListener initial_policy_listener(kTestPolicyJSON, true);
303 event_listener_->Reply("get-policy-Name");
304 EXPECT_TRUE(initial_policy_listener.WaitUntilSatisfied());
306 // Verify that the policy cache exists.
307 std::string cache_key;
308 ASSERT_TRUE(Base64UrlEncode("extension-policy", &cache_key));
309 std::string cache_subkey;
310 ASSERT_TRUE(Base64UrlEncode(kTestExtension, &cache_subkey));
311 base::FilePath cache_path = browser()->profile()->GetPath()
312 .Append(FILE_PATH_LITERAL("Policy"))
313 .Append(FILE_PATH_LITERAL("Components"))
314 .AppendASCII(cache_key)
315 .AppendASCII(cache_subkey);
316 EXPECT_TRUE(base::PathExists(cache_path));
318 // Now sign-out. The policy cache should be removed, and the extension should
319 // get an empty policy update.
320 ExtensionTestMessageListener event_listener("event", true);
321 initial_policy_listener.Reply("idle");
322 SignOut();
323 EXPECT_TRUE(event_listener.WaitUntilSatisfied());
325 // The extension got an update event; verify that the policy was empty.
326 ExtensionTestMessageListener signout_policy_listener("{}", true);
327 event_listener.Reply("get-policy-Name");
328 EXPECT_TRUE(signout_policy_listener.WaitUntilSatisfied());
330 // Verify that the cache is gone.
331 EXPECT_FALSE(base::PathExists(cache_path));
333 // Verify that the policy is fetched again if the user signs back in.
334 ExtensionTestMessageListener event_listener2("event", true);
335 SignInAndRegister();
336 EXPECT_TRUE(event_listener2.WaitUntilSatisfied());
338 // The extension got updated policy; verify it.
339 ExtensionTestMessageListener signin_policy_listener(kTestPolicyJSON, true);
340 event_listener2.Reply("get-policy-Name");
341 EXPECT_TRUE(signin_policy_listener.WaitUntilSatisfied());
343 // And the cache is back.
344 EXPECT_TRUE(base::PathExists(cache_path));
346 #endif
348 } // namespace policy