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