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 "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
6
7#include "base/bind.h"
8#include "base/command_line.h"
9#include "base/files/file_path.h"
10#include "base/logging.h"
11#include "base/memory/ref_counted.h"
12#include "base/message_loop/message_loop_proxy.h"
13#include "base/path_service.h"
14#include "base/sequenced_task_runner.h"
15#include "base/threading/sequenced_worker_pool.h"
16#include "base/time/time.h"
17#include "chrome/browser/browser_process.h"
18#include "chrome/browser/chromeos/login/login_utils.h"
19#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
20#include "chrome/browser/chromeos/policy/user_cloud_external_data_manager.h"
21#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
22#include "chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.h"
23#include "chrome/browser/chromeos/profiles/profile_helper.h"
24#include "chrome/browser/policy/schema_registry_service.h"
25#include "chrome/browser/policy/schema_registry_service_factory.h"
26#include "chrome/browser/profiles/profile.h"
27#include "chromeos/chromeos_paths.h"
28#include "chromeos/chromeos_switches.h"
29#include "chromeos/dbus/dbus_thread_manager.h"
30#include "components/keyed_service/content/browser_context_dependency_manager.h"
31#include "components/policy/core/browser/browser_policy_connector.h"
32#include "components/policy/core/common/cloud/cloud_external_data_manager.h"
33#include "components/policy/core/common/cloud/device_management_service.h"
34#include "components/user_manager/user.h"
35#include "components/user_manager/user_manager.h"
36#include "components/user_manager/user_type.h"
37#include "content/public/browser/browser_thread.h"
38#include "net/url_request/url_request_context_getter.h"
39#include "policy/policy_constants.h"
40
41namespace policy {
42
43namespace {
44
45// Subdirectory in the user's profile for storing legacy user policies.
46const base::FilePath::CharType kDeviceManagementDir[] =
47    FILE_PATH_LITERAL("Device Management");
48
49// File in the above directory for storing legacy user policy dmtokens.
50const base::FilePath::CharType kToken[] = FILE_PATH_LITERAL("Token");
51
52// This constant is used to build two different paths. It can be a file inside
53// kDeviceManagementDir where legacy user policy data is stored, and it can be
54// a directory inside the profile directory where other resources are stored.
55const base::FilePath::CharType kPolicy[] = FILE_PATH_LITERAL("Policy");
56
57// Directory under kPolicy, in the user's profile dir, where policy for
58// components is cached.
59const base::FilePath::CharType kComponentsDir[] =
60    FILE_PATH_LITERAL("Components");
61
62// Directory in which to store external policy data. This is specified relative
63// to kPolicy.
64const base::FilePath::CharType kPolicyExternalDataDir[] =
65    FILE_PATH_LITERAL("External Data");
66
67// Timeout in seconds after which to abandon the initial policy fetch and start
68// the session regardless.
69const int kInitialPolicyFetchTimeoutSeconds = 10;
70
71}  // namespace
72
73// static
74UserCloudPolicyManagerFactoryChromeOS*
75    UserCloudPolicyManagerFactoryChromeOS::GetInstance() {
76  return Singleton<UserCloudPolicyManagerFactoryChromeOS>::get();
77}
78
79// static
80UserCloudPolicyManagerChromeOS*
81    UserCloudPolicyManagerFactoryChromeOS::GetForProfile(
82        Profile* profile) {
83  return GetInstance()->GetManagerForProfile(profile);
84}
85
86// static
87scoped_ptr<UserCloudPolicyManagerChromeOS>
88    UserCloudPolicyManagerFactoryChromeOS::CreateForProfile(
89        Profile* profile,
90        bool force_immediate_load,
91        scoped_refptr<base::SequencedTaskRunner> background_task_runner) {
92  return GetInstance()->CreateManagerForProfile(
93      profile, force_immediate_load, background_task_runner);
94}
95
96UserCloudPolicyManagerFactoryChromeOS::UserCloudPolicyManagerFactoryChromeOS()
97    : BrowserContextKeyedBaseFactory(
98        "UserCloudPolicyManagerChromeOS",
99        BrowserContextDependencyManager::GetInstance()) {
100  DependsOn(SchemaRegistryServiceFactory::GetInstance());
101}
102
103UserCloudPolicyManagerFactoryChromeOS::
104    ~UserCloudPolicyManagerFactoryChromeOS() {}
105
106UserCloudPolicyManagerChromeOS*
107    UserCloudPolicyManagerFactoryChromeOS::GetManagerForProfile(
108        Profile* profile) {
109  // Get the manager for the original profile, since the PolicyService is
110  // also shared between the incognito Profile and the original Profile.
111  ManagerMap::const_iterator it = managers_.find(profile->GetOriginalProfile());
112  return it != managers_.end() ? it->second : NULL;
113}
114
115scoped_ptr<UserCloudPolicyManagerChromeOS>
116    UserCloudPolicyManagerFactoryChromeOS::CreateManagerForProfile(
117        Profile* profile,
118        bool force_immediate_load,
119        scoped_refptr<base::SequencedTaskRunner> background_task_runner) {
120  const CommandLine* command_line = CommandLine::ForCurrentProcess();
121  // Don't initialize cloud policy for the signin profile.
122  if (chromeos::ProfileHelper::IsSigninProfile(profile))
123    return scoped_ptr<UserCloudPolicyManagerChromeOS>();
124
125  // |user| should never be NULL except for the signin profile. This object is
126  // created as part of the Profile creation, which happens right after
127  // sign-in. The just-signed-in User is the active user during that time.
128  user_manager::User* user =
129      chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
130  CHECK(user);
131
132  // Only USER_TYPE_REGULAR users have user cloud policy.
133  // USER_TYPE_RETAIL_MODE, USER_TYPE_KIOSK_APP, USER_TYPE_GUEST and
134  // USER_TYPE_SUPERVISED are not signed in and can't authenticate the
135  // policy registration.
136  // USER_TYPE_PUBLIC_ACCOUNT gets its policy from the
137  // DeviceLocalAccountPolicyService.
138  // Non-managed domains will be skipped by the below check
139  const std::string& username = user->email();
140  if (user->GetType() != user_manager::USER_TYPE_REGULAR ||
141      BrowserPolicyConnector::IsNonEnterpriseUser(username)) {
142    return scoped_ptr<UserCloudPolicyManagerChromeOS>();
143  }
144
145  policy::BrowserPolicyConnectorChromeOS* connector =
146      g_browser_process->platform_part()->browser_policy_connector_chromeos();
147  UserAffiliation affiliation = connector->GetUserAffiliation(username);
148  const bool is_affiliated_user = affiliation == USER_AFFILIATION_MANAGED;
149  const bool is_browser_restart =
150      command_line->HasSwitch(chromeos::switches::kLoginUser);
151  const bool wait_for_initial_policy =
152      !is_browser_restart &&
153      (user_manager::UserManager::Get()->IsCurrentUserNew() ||
154       is_affiliated_user);
155
156  const base::TimeDelta initial_policy_fetch_timeout =
157      user_manager::UserManager::Get()->IsCurrentUserNew()
158          ? base::TimeDelta::Max()
159          : base::TimeDelta::FromSeconds(kInitialPolicyFetchTimeoutSeconds);
160
161  DeviceManagementService* device_management_service =
162      connector->device_management_service();
163  if (wait_for_initial_policy)
164    device_management_service->ScheduleInitialization(0);
165
166  base::FilePath profile_dir = profile->GetPath();
167  const base::FilePath legacy_dir = profile_dir.Append(kDeviceManagementDir);
168  const base::FilePath policy_cache_file = legacy_dir.Append(kPolicy);
169  const base::FilePath token_cache_file = legacy_dir.Append(kToken);
170  const base::FilePath component_policy_cache_dir =
171      profile_dir.Append(kPolicy).Append(kComponentsDir);
172  const base::FilePath external_data_dir =
173        profile_dir.Append(kPolicy).Append(kPolicyExternalDataDir);
174  base::FilePath policy_key_dir;
175  CHECK(PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &policy_key_dir));
176
177  scoped_ptr<UserCloudPolicyStoreChromeOS> store(
178      new UserCloudPolicyStoreChromeOS(
179          chromeos::DBusThreadManager::Get()->GetCryptohomeClient(),
180          chromeos::DBusThreadManager::Get()->GetSessionManagerClient(),
181          background_task_runner,
182          username, policy_key_dir, token_cache_file, policy_cache_file));
183
184  scoped_refptr<base::SequencedTaskRunner> backend_task_runner =
185      content::BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
186          content::BrowserThread::GetBlockingPool()->GetSequenceToken());
187  scoped_refptr<base::SequencedTaskRunner> io_task_runner =
188      content::BrowserThread::GetMessageLoopProxyForThread(
189          content::BrowserThread::IO);
190  scoped_ptr<CloudExternalDataManager> external_data_manager(
191      new UserCloudExternalDataManager(base::Bind(&GetChromePolicyDetails),
192                                       backend_task_runner,
193                                       io_task_runner,
194                                       external_data_dir,
195                                       store.get()));
196  if (force_immediate_load)
197    store->LoadImmediately();
198
199  scoped_refptr<base::SequencedTaskRunner> file_task_runner =
200      content::BrowserThread::GetMessageLoopProxyForThread(
201          content::BrowserThread::FILE);
202
203  scoped_ptr<UserCloudPolicyManagerChromeOS> manager(
204      new UserCloudPolicyManagerChromeOS(
205          store.PassAs<CloudPolicyStore>(),
206          external_data_manager.Pass(),
207          component_policy_cache_dir,
208          wait_for_initial_policy,
209          initial_policy_fetch_timeout,
210          base::MessageLoopProxy::current(),
211          file_task_runner,
212          io_task_runner));
213
214  bool wildcard_match = false;
215  if (connector->IsEnterpriseManaged() &&
216      chromeos::LoginUtils::IsWhitelisted(username, &wildcard_match) &&
217      wildcard_match &&
218      !connector->IsNonEnterpriseUser(username)) {
219    manager->EnableWildcardLoginCheck(username);
220  }
221
222  manager->Init(
223      SchemaRegistryServiceFactory::GetForContext(profile)->registry());
224  manager->Connect(g_browser_process->local_state(),
225                   device_management_service,
226                   g_browser_process->system_request_context(),
227                   affiliation);
228
229  DCHECK(managers_.find(profile) == managers_.end());
230  managers_[profile] = manager.get();
231  return manager.Pass();
232}
233
234void UserCloudPolicyManagerFactoryChromeOS::BrowserContextShutdown(
235    content::BrowserContext* context) {
236  Profile* profile = static_cast<Profile*>(context);
237  if (profile->IsOffTheRecord())
238    return;
239  UserCloudPolicyManagerChromeOS* manager = GetManagerForProfile(profile);
240  if (manager)
241    manager->Shutdown();
242}
243
244void UserCloudPolicyManagerFactoryChromeOS::BrowserContextDestroyed(
245    content::BrowserContext* context) {
246  Profile* profile = static_cast<Profile*>(context);
247  managers_.erase(profile);
248  BrowserContextKeyedBaseFactory::BrowserContextDestroyed(context);
249}
250
251void UserCloudPolicyManagerFactoryChromeOS::SetEmptyTestingFactory(
252    content::BrowserContext* context) {}
253
254bool UserCloudPolicyManagerFactoryChromeOS::HasTestingFactory(
255    content::BrowserContext* context) {
256  return false;
257}
258
259void UserCloudPolicyManagerFactoryChromeOS::CreateServiceNow(
260    content::BrowserContext* context) {}
261
262}  // namespace policy
263