1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/policy/cloud/user_policy_signin_service_base.h"
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/bind.h"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
11effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/profiles/profile.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/signin/signin_manager_factory.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/common/chrome_content_client.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/browser/browser_policy_connector.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/device_management_service.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/system_policy_request_context.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/user_policy_request_context.h"
19e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h"
2058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "content/public/browser/notification_source.h"
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace policy {
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochUserPolicySigninServiceBase::UserPolicySigninServiceBase(
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Profile* profile,
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    PrefService* local_state,
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DeviceManagementService* device_management_service,
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UserCloudPolicyManager* policy_manager,
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SigninManager* signin_manager,
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> system_request_context)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : policy_manager_(policy_manager),
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      signin_manager_(signin_manager),
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      local_state_(local_state),
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      device_management_service_(device_management_service),
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      system_request_context_(system_request_context),
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      weak_factory_(this) {
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Register a listener to be called back once the current profile has finished
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // initializing, so we can startup/shutdown the UserCloudPolicyManager.
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  registrar_.Add(this,
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 chrome::NOTIFICATION_PROFILE_ADDED,
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 content::Source<Profile>(profile));
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochUserPolicySigninServiceBase::~UserPolicySigninServiceBase() {}
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UserPolicySigninServiceBase::FetchPolicyForSignedInUser(
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& username,
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& dm_token,
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& client_id,
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> profile_request_context,
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const PolicyFetchCallback& callback) {
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<CloudPolicyClient> client(
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      UserCloudPolicyManager::CreateCloudPolicyClient(
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          device_management_service_,
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          CreateUserRequestContext(profile_request_context)).Pass());
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  client->SetupRegistration(dm_token, client_id);
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(client->is_registered());
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The user has just signed in, so the UserCloudPolicyManager should not yet
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // be initialized. This routine will initialize the UserCloudPolicyManager
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // with the passed client and will proactively ask the client to fetch
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // policy without waiting for the CloudPolicyService to finish initialization.
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UserCloudPolicyManager* manager = policy_manager();
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(manager);
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!manager->core()->client());
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  InitializeUserCloudPolicyManager(username, client.Pass());
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(manager->IsClientRegistered());
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Now initiate a policy fetch.
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  manager->core()->service()->RefreshPolicy(callback);
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid UserPolicySigninServiceBase::GoogleSignedOut(const std::string& account_id,
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                  const std::string& username) {
754ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  ShutdownUserCloudPolicyManager();
764ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch}
774ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UserPolicySigninServiceBase::Observe(
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int type,
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const content::NotificationSource& source,
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const content::NotificationDetails& details) {
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (type) {
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case chrome::NOTIFICATION_PROFILE_ADDED:
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // A new profile has been loaded - if it's signed in, then initialize the
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // UCPM, otherwise shut down the UCPM (which deletes any cached policy
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // data). This must be done here instead of at constructor time because
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // the Profile is not fully initialized when this object is constructed
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // (DoFinalInit() has not yet been called, so ProfileIOData and
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // SSLConfigServiceManager have not been created yet).
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // TODO(atwilson): Switch to using a timer instead, to avoid contention
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // with other services at startup (http://crbug.com/165468).
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      InitializeOnProfileReady(content::Source<Profile>(source).ptr());
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UserPolicySigninServiceBase::OnInitializationCompleted(
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CloudPolicyService* service) {
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This is meant to be overridden by subclasses. Starting and stopping to
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // observe the CloudPolicyService from this base class avoids the need for
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // more virtuals.
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UserPolicySigninServiceBase::OnPolicyFetched(CloudPolicyClient* client) {}
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UserPolicySigninServiceBase::OnRegistrationStateChanged(
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CloudPolicyClient* client) {}
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UserPolicySigninServiceBase::OnClientError(CloudPolicyClient* client) {
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (client->is_registered()) {
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // If the client is already registered, it means this error must have
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // come from a policy fetch.
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (client->status() == DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED) {
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // OK, policy fetch failed with MANAGEMENT_NOT_SUPPORTED - this is our
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // trigger to revert to "unmanaged" mode (we will check for management
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // being re-enabled on the next restart and/or login).
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      DVLOG(1) << "DMServer returned NOT_SUPPORTED error - removing policy";
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // Can't shutdown now because we're in the middle of a callback from
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // the CloudPolicyClient, so queue up a task to do the shutdown.
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::MessageLoop::current()->PostTask(
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          FROM_HERE,
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Bind(
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              &UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager,
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              weak_factory_.GetWeakPtr()));
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else {
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      DVLOG(1) << "Error fetching policy: " << client->status();
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UserPolicySigninServiceBase::Shutdown() {
1354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (signin_manager())
1364ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    signin_manager()->RemoveObserver(this);
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PrepareForUserCloudPolicyManagerShutdown();
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void UserPolicySigninServiceBase::PrepareForUserCloudPolicyManagerShutdown() {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UserCloudPolicyManager* manager = policy_manager();
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (manager && manager->core()->client())
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    manager->core()->client()->RemoveObserver(this);
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (manager && manager->core()->service())
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    manager->core()->service()->RemoveObserver(this);
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)scoped_ptr<CloudPolicyClient>
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)UserPolicySigninServiceBase::CreateClientForRegistrationOnly(
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& username) {
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!username.empty());
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We should not be called with a client already initialized.
1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if !defined(OS_IOS)
1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // On iOS we check if an account has policy while the profile is signed in
1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // to another account.
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!policy_manager() || !policy_manager()->core()->client());
1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // If the user should not get policy, just bail out.
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!policy_manager() || !ShouldLoadPolicyForUser(username)) {
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DVLOG(1) << "Signed in user is not in the whitelist";
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return scoped_ptr<CloudPolicyClient>();
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // If the DeviceManagementService is not yet initialized, start it up now.
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  device_management_service_->ScheduleInitialization(0);
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create a new CloudPolicyClient for fetching the DMToken.
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return UserCloudPolicyManager::CreateCloudPolicyClient(
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      device_management_service_, CreateSystemRequestContext());
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool UserPolicySigninServiceBase::ShouldLoadPolicyForUser(
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& username) {
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (username.empty())
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;  // Not signed in.
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return !BrowserPolicyConnector::IsNonEnterpriseUser(username);
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void UserPolicySigninServiceBase::InitializeOnProfileReady(Profile* profile) {
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If using a TestingProfile with no SigninManager or UserCloudPolicyManager,
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // skip initialization.
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!policy_manager() || !signin_manager()) {
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << "Skipping initialization for tests due to missing components.";
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1894ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Shutdown the UserCloudPolicyManager when the user signs out. We start
1904ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // observing the SigninManager here because we don't want to get signout
1914ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // notifications until after the profile has started initializing
1924ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // (http://crbug.com/316229).
1934ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  signin_manager()->AddObserver(this);
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string username = signin_manager()->GetAuthenticatedUsername();
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (username.empty())
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ShutdownUserCloudPolicyManager();
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  else
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    InitializeForSignedInUser(username, profile->GetRequestContext());
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UserPolicySigninServiceBase::InitializeForSignedInUser(
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& username,
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> profile_request_context) {
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!username.empty());
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!ShouldLoadPolicyForUser(username)) {
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DVLOG(1) << "Policy load not enabled for user: " << username;
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UserCloudPolicyManager* manager = policy_manager();
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Initialize the UCPM if it is not already initialized.
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!manager->core()->service()) {
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // If there is no cached DMToken then we can detect this when the
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // OnInitializationCompleted() callback is invoked and this will
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // initiate a policy fetch.
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    InitializeUserCloudPolicyManager(
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        username,
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        UserCloudPolicyManager::CreateCloudPolicyClient(
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            device_management_service_,
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            CreateUserRequestContext(profile_request_context)).Pass());
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    manager->SetSigninUsername(username);
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // If the CloudPolicyService is initialized, kick off registration.
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Otherwise OnInitializationCompleted is invoked as soon as the service
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // finishes its initialization.
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (manager->core()->service()->IsInitializationComplete())
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    OnInitializationCompleted(manager->core()->service());
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UserPolicySigninServiceBase::InitializeUserCloudPolicyManager(
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& username,
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<CloudPolicyClient> client) {
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(client);
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UserCloudPolicyManager* manager = policy_manager();
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  manager->SetSigninUsername(username);
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!manager->core()->client());
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> context =
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      client->GetRequestContext();
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  manager->Connect(local_state_, context, client.Pass());
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(manager->core()->service());
244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Observe the client to detect errors fetching policy.
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  manager->core()->client()->AddObserver(this);
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Observe the service to determine when it's initialized.
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  manager->core()->service()->AddObserver(this);
249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager() {
2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PrepareForUserCloudPolicyManagerShutdown();
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UserCloudPolicyManager* manager = policy_manager();
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (manager)
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    manager->DisconnectAndRemovePolicy();
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)scoped_refptr<net::URLRequestContextGetter>
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)UserPolicySigninServiceBase::CreateSystemRequestContext() {
260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return new SystemPolicyRequestContext(
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      system_request_context(), GetUserAgent());
262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)scoped_refptr<net::URLRequestContextGetter>
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)UserPolicySigninServiceBase::CreateUserRequestContext(
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> profile_request_context) {
267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return new UserPolicyRequestContext(
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      profile_request_context, system_request_context(), GetUserAgent());
269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace policy
272