• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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
47 
48 using testing::InvokeWithoutArgs;
49 using testing::Mock;
50 using testing::Return;
51 using testing::_;
52 
53 namespace em = enterprise_management;
54 
55 namespace policy {
56 
57 namespace {
58 
59 const char kDMToken[] = "dmtoken";
60 const char kDeviceID[] = "deviceid";
61 
62 const char kTestExtension[] = "kjmkgkdkpedkejedfhmfcenooemhbpbo";
63 
64 const base::FilePath::CharType kTestExtensionPath[] =
65     FILE_PATH_LITERAL("extensions/managed_extension");
66 
67 const char kTestPolicy[] =
68     "{"
69     "  \"Name\": {"
70     "    \"Value\": \"disable_all_the_things\""
71     "  }"
72     "}";
73 
74 const char kTestExtension2[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
75 const base::FilePath::CharType kTestExtension2Path[] =
76     FILE_PATH_LITERAL("extensions/managed_extension2");
77 
78 const char kTestPolicyJSON[] = "{\"Name\":\"disable_all_the_things\"}";
79 
80 const char kTestPolicy2[] =
81     "{"
82     "  \"Another\": {"
83     "    \"Value\": \"turn_it_off\""
84     "  }"
85     "}";
86 
87 const char kTestPolicy2JSON[] = "{\"Another\":\"turn_it_off\"}";
88 
89 #if !defined(OS_CHROMEOS)
90 // Same encoding as ResourceCache does for its keys.
Base64UrlEncode(const std::string & value,std::string * encoded)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;
98 }
99 #endif
100 
101 }  // namespace
102 
103 class ComponentCloudPolicyTest : public ExtensionBrowserTest {
104  protected:
ComponentCloudPolicyTest()105   ComponentCloudPolicyTest() {}
~ComponentCloudPolicyTest()106   virtual ~ComponentCloudPolicyTest() {}
107 
SetUpCommandLine(CommandLine * command_line)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
113     // testserver.
114     command_line->AppendSwitchASCII(
115         ::chromeos::switches::kLoginUser, "user@example.com");
116 #endif
117   }
118 
SetUpInProcessBrowserTestFixture()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());
124 
125     std::string url = test_server_.GetServiceURL().spec();
126     CommandLine* command_line = CommandLine::ForCurrentProcess();
127     command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, url);
128 
129     ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
130   }
131 
SetUpOnMainThread()132   virtual void SetUpOnMainThread() OVERRIDE {
133     ASSERT_TRUE(PolicyServiceIsEmpty(g_browser_process->policy_service()))
134         << "Pre-existing policies in this machine will make this test fail.";
135 
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());
143 
144     // And start with a signed-in user.
145     SignInAndRegister();
146 
147     // The extension will receive an update event.
148     EXPECT_TRUE(event_listener_->WaitUntilSatisfied());
149 
150     ExtensionBrowserTest::SetUpOnMainThread();
151   }
152 
LoadExtension(const base::FilePath::CharType * path)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;
159     }
160     scoped_refptr<const extensions::Extension> extension(
161         ExtensionBrowserTest::LoadExtension(full_path.Append(path)));
162     if (!extension.get()) {
163       ADD_FAILURE();
164       return NULL;
165     }
166     return extension;
167   }
168 
SignInAndRegister()169   void SignInAndRegister() {
170     BrowserPolicyConnector* connector =
171         g_browser_process->browser_policy_connector();
172     connector->ScheduleServiceInitialization(0);
173 
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->SetAuthenticatedUsername("user@example.com");
186 
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)
198 
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);
210   }
211 
212 #if !defined(OS_CHROMEOS)
SignOut()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);
218   }
219 #endif
220 
RefreshPolicies()221   void RefreshPolicies() {
222     ProfilePolicyConnector* profile_connector =
223         ProfilePolicyConnectorFactory::GetForProfile(browser()->profile());
224     PolicyService* policy_service = profile_connector->policy_service();
225     base::RunLoop run_loop;
226     policy_service->RefreshPolicies(run_loop.QuitClosure());
227     run_loop.Run();
228   }
229 
230   LocalPolicyTestServer test_server_;
231   scoped_refptr<const extensions::Extension> extension_;
232   scoped_ptr<ExtensionTestMessageListener> event_listener_;
233 };
234 
IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest,FetchExtensionPolicy)235 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, FetchExtensionPolicy) {
236   // Read the initial policy.
237   ExtensionTestMessageListener policy_listener(kTestPolicyJSON, true);
238   event_listener_->Reply("get-policy-Name");
239   EXPECT_TRUE(policy_listener.WaitUntilSatisfied());
240 }
241 
IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest,UpdateExtensionPolicy)242 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, UpdateExtensionPolicy) {
243   // Read the initial policy.
244   ExtensionTestMessageListener policy_listener(kTestPolicyJSON, true);
245   event_listener_->Reply("get-policy-Name");
246   EXPECT_TRUE(policy_listener.WaitUntilSatisfied());
247 
248   // Update the policy at the server and reload policy.
249   event_listener_.reset(new ExtensionTestMessageListener("event", true));
250   policy_listener.Reply("idle");
251   EXPECT_TRUE(test_server_.UpdatePolicyData(
252       dm_protocol::kChromeExtensionPolicyType, kTestExtension, kTestPolicy2));
253   RefreshPolicies();
254 
255   // Check that the update event was received, and verify the new policy
256   // values.
257   EXPECT_TRUE(event_listener_->WaitUntilSatisfied());
258 
259   // This policy was removed.
260   ExtensionTestMessageListener policy_listener1("{}", true);
261   event_listener_->Reply("get-policy-Name");
262   EXPECT_TRUE(policy_listener1.WaitUntilSatisfied());
263 
264   ExtensionTestMessageListener policy_listener2(kTestPolicy2JSON, true);
265   policy_listener1.Reply("get-policy-Another");
266   EXPECT_TRUE(policy_listener2.WaitUntilSatisfied());
267 }
268 
IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest,InstallNewExtension)269 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, InstallNewExtension) {
270   EXPECT_TRUE(test_server_.UpdatePolicyData(
271       dm_protocol::kChromeExtensionPolicyType, kTestExtension2, kTestPolicy2));
272   // Installing a new extension doesn't trigger another policy fetch because
273   // the server always sends down the list of all extensions that have policy.
274   // Fetch now that the configuration has been updated and before installing
275   // the extension.
276   RefreshPolicies();
277 
278   ExtensionTestMessageListener result_listener("ok", true);
279   result_listener.set_failure_message("fail");
280   scoped_refptr<const extensions::Extension> extension2 =
281       LoadExtension(kTestExtension2Path);
282   ASSERT_TRUE(extension2.get());
283   ASSERT_EQ(kTestExtension2, extension2->id());
284 
285   // This extension only sends the 'policy' signal once it receives the policy,
286   // and after verifying it has the expected value. Otherwise it sends 'fail'.
287   EXPECT_TRUE(result_listener.WaitUntilSatisfied());
288 }
289 
290 // Signing out on Chrome OS is a different process from signing out on the
291 // Desktop platforms. On Chrome OS the session is ended, and the user goes back
292 // to the sign-in screen; the Profile data is not affected. On the Desktop the
293 // session goes on though, and all the signed-in services are disconnected;
294 // in particular, the policy caches are dropped if the user signs out.
295 // This test verifies that when the user signs out then any existing component
296 // policy caches are dropped, and that it's still possible to sign back in and
297 // get policy for components working again.
298 #if !defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest,SignOutAndBackIn)299 IN_PROC_BROWSER_TEST_F(ComponentCloudPolicyTest, SignOutAndBackIn) {
300   // Read the initial policy.
301   ExtensionTestMessageListener initial_policy_listener(kTestPolicyJSON, true);
302   event_listener_->Reply("get-policy-Name");
303   EXPECT_TRUE(initial_policy_listener.WaitUntilSatisfied());
304 
305   // Verify that the policy cache exists.
306   std::string cache_key;
307   ASSERT_TRUE(Base64UrlEncode("extension-policy", &cache_key));
308   std::string cache_subkey;
309   ASSERT_TRUE(Base64UrlEncode(kTestExtension, &cache_subkey));
310   base::FilePath cache_path = browser()->profile()->GetPath()
311       .Append(FILE_PATH_LITERAL("Policy"))
312       .Append(FILE_PATH_LITERAL("Components"))
313       .AppendASCII(cache_key)
314       .AppendASCII(cache_subkey);
315   EXPECT_TRUE(base::PathExists(cache_path));
316 
317   // Now sign-out. The policy cache should be removed, and the extension should
318   // get an empty policy update.
319   ExtensionTestMessageListener event_listener("event", true);
320   initial_policy_listener.Reply("idle");
321   SignOut();
322   EXPECT_TRUE(event_listener.WaitUntilSatisfied());
323 
324   // The extension got an update event; verify that the policy was empty.
325   ExtensionTestMessageListener signout_policy_listener("{}", true);
326   event_listener.Reply("get-policy-Name");
327   EXPECT_TRUE(signout_policy_listener.WaitUntilSatisfied());
328 
329   // Verify that the cache is gone.
330   EXPECT_FALSE(base::PathExists(cache_path));
331 
332   // Verify that the policy is fetched again if the user signs back in.
333   ExtensionTestMessageListener event_listener2("event", true);
334   SignInAndRegister();
335   EXPECT_TRUE(event_listener2.WaitUntilSatisfied());
336 
337   // The extension got updated policy; verify it.
338   ExtensionTestMessageListener signin_policy_listener(kTestPolicyJSON, true);
339   event_listener2.Reply("get-policy-Name");
340   EXPECT_TRUE(signin_policy_listener.WaitUntilSatisfied());
341 
342   // And the cache is back.
343   EXPECT_TRUE(base::PathExists(cache_path));
344 }
345 #endif
346 
347 }  // namespace policy
348