1// Copyright 2014 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/policy/cloud/user_policy_signin_service_mobile.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/callback.h"
10#include "base/command_line.h"
11#include "base/logging.h"
12#include "base/message_loop/message_loop.h"
13#include "base/prefs/pref_service.h"
14#include "base/time/time.h"
15#include "chrome/browser/profiles/profile.h"
16#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
17#include "chrome/common/pref_names.h"
18#include "components/policy/core/common/cloud/cloud_policy_client_registration_helper.h"
19#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
20#include "components/policy/core/common/policy_switches.h"
21#include "components/signin/core/browser/profile_oauth2_token_service.h"
22#include "components/signin/core/browser/signin_manager.h"
23#include "net/base/network_change_notifier.h"
24#include "net/url_request/url_request_context_getter.h"
25#include "policy/proto/device_management_backend.pb.h"
26
27namespace policy {
28
29namespace {
30
31enterprise_management::DeviceRegisterRequest::Type GetRegistrationType() {
32  CommandLine* command_line = CommandLine::ForCurrentProcess();
33  if (command_line->HasSwitch(switches::kFakeCloudPolicyType))
34    return enterprise_management::DeviceRegisterRequest::BROWSER;
35#if defined(OS_IOS)
36  return enterprise_management::DeviceRegisterRequest::IOS_BROWSER;
37#elif defined(OS_ANDROID)
38  return enterprise_management::DeviceRegisterRequest::ANDROID_BROWSER;
39#else
40#error "This file can be built only on OS_IOS or OS_ANDROID."
41#endif
42}
43
44}  // namespace
45
46UserPolicySigninService::UserPolicySigninService(
47    Profile* profile,
48    PrefService* local_state,
49    DeviceManagementService* device_management_service,
50    UserCloudPolicyManager* policy_manager,
51    SigninManager* signin_manager,
52    scoped_refptr<net::URLRequestContextGetter> system_request_context,
53    ProfileOAuth2TokenService* token_service)
54    : UserPolicySigninServiceBase(profile,
55                                  local_state,
56                                  device_management_service,
57                                  policy_manager,
58                                  signin_manager,
59                                  system_request_context),
60      oauth2_token_service_(token_service),
61      profile_prefs_(profile->GetPrefs()),
62      weak_factory_(this) {
63#if defined(OS_IOS)
64  // iOS doesn't create this service with the Profile; instead it's created
65  // a little bit later. See UserPolicySigninServiceFactory.
66  InitializeOnProfileReady(profile);
67#endif
68}
69
70UserPolicySigninService::~UserPolicySigninService() {}
71
72void UserPolicySigninService::RegisterForPolicy(
73    const std::string& username,
74    const PolicyRegistrationCallback& callback) {
75  RegisterForPolicyInternal(username, "", callback);
76}
77
78#if !defined(OS_ANDROID)
79void UserPolicySigninService::RegisterForPolicyWithAccessToken(
80    const std::string& username,
81    const std::string& access_token,
82    const PolicyRegistrationCallback& callback) {
83  RegisterForPolicyInternal(username, access_token, callback);
84}
85
86// static
87std::vector<std::string> UserPolicySigninService::GetScopes() {
88  return CloudPolicyClientRegistrationHelper::GetScopes();
89}
90#endif
91
92void UserPolicySigninService::RegisterForPolicyInternal(
93    const std::string& username,
94    const std::string& access_token,
95    const PolicyRegistrationCallback& callback) {
96  // Create a new CloudPolicyClient for fetching the DMToken.
97  scoped_ptr<CloudPolicyClient> policy_client = CreateClientForRegistrationOnly(
98      username);
99  if (!policy_client) {
100    callback.Run(std::string(), std::string());
101    return;
102  }
103
104  CancelPendingRegistration();
105
106  // Fire off the registration process. Callback keeps the CloudPolicyClient
107  // alive for the length of the registration process.
108  registration_helper_.reset(new CloudPolicyClientRegistrationHelper(
109      policy_client.get(),
110      GetRegistrationType()));
111
112  if (access_token.empty()) {
113    registration_helper_->StartRegistration(
114        oauth2_token_service_,
115        username,
116        base::Bind(&UserPolicySigninService::CallPolicyRegistrationCallback,
117                   base::Unretained(this),
118                   base::Passed(&policy_client),
119                   callback));
120  } else {
121#if defined(OS_ANDROID)
122    NOTREACHED();
123#else
124    registration_helper_->StartRegistrationWithAccessToken(
125        access_token,
126        base::Bind(&UserPolicySigninService::CallPolicyRegistrationCallback,
127                   base::Unretained(this),
128                   base::Passed(&policy_client),
129                   callback));
130#endif
131  }
132}
133
134void UserPolicySigninService::CallPolicyRegistrationCallback(
135    scoped_ptr<CloudPolicyClient> client,
136    PolicyRegistrationCallback callback) {
137  registration_helper_.reset();
138  callback.Run(client->dm_token(), client->client_id());
139}
140
141void UserPolicySigninService::Shutdown() {
142  CancelPendingRegistration();
143  registration_helper_.reset();
144  UserPolicySigninServiceBase::Shutdown();
145}
146
147void UserPolicySigninService::OnInitializationCompleted(
148    CloudPolicyService* service) {
149  UserCloudPolicyManager* manager = policy_manager();
150  DCHECK_EQ(service, manager->core()->service());
151  DCHECK(service->IsInitializationComplete());
152  // The service is now initialized - if the client is not yet registered, then
153  // it means that there is no cached policy and so we need to initiate a new
154  // client registration.
155  if (manager->IsClientRegistered()) {
156    DVLOG(1) << "Client already registered - not fetching DMToken";
157    return;
158  }
159
160  net::NetworkChangeNotifier::ConnectionType connection_type =
161      net::NetworkChangeNotifier::GetConnectionType();
162  base::TimeDelta retry_delay = base::TimeDelta::FromDays(3);
163  if (connection_type == net::NetworkChangeNotifier::CONNECTION_ETHERNET ||
164      connection_type == net::NetworkChangeNotifier::CONNECTION_WIFI) {
165    retry_delay = base::TimeDelta::FromDays(1);
166  }
167
168  base::Time last_check_time = base::Time::FromInternalValue(
169      profile_prefs_->GetInt64(prefs::kLastPolicyCheckTime));
170  base::Time now = base::Time::Now();
171  base::Time next_check_time = last_check_time + retry_delay;
172
173  // Check immediately if no check was ever done before (last_check_time == 0),
174  // or if the last check was in the future (?), or if we're already past the
175  // next check time. Otherwise, delay checking until the next check time.
176  base::TimeDelta try_registration_delay = base::TimeDelta::FromSeconds(5);
177  if (now > last_check_time && now < next_check_time)
178    try_registration_delay = next_check_time - now;
179
180  base::MessageLoop::current()->PostDelayedTask(
181      FROM_HERE,
182      base::Bind(&UserPolicySigninService::RegisterCloudPolicyService,
183                 weak_factory_.GetWeakPtr()),
184      try_registration_delay);
185}
186
187void UserPolicySigninService::ShutdownUserCloudPolicyManager() {
188  CancelPendingRegistration();
189  UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager();
190}
191
192void UserPolicySigninService::RegisterCloudPolicyService() {
193  // If the user signed-out while this task was waiting then Shutdown() would
194  // have been called, which would have invalidated this task. Since we're here
195  // then the user must still be signed-in.
196  const std::string& username = signin_manager()->GetAuthenticatedUsername();
197  DCHECK(!username.empty());
198  DCHECK(!policy_manager()->IsClientRegistered());
199  DCHECK(policy_manager()->core()->client());
200
201  // Persist the current time as the last policy registration attempt time.
202  profile_prefs_->SetInt64(prefs::kLastPolicyCheckTime,
203                           base::Time::Now().ToInternalValue());
204
205  registration_helper_.reset(new CloudPolicyClientRegistrationHelper(
206      policy_manager()->core()->client(),
207      GetRegistrationType()));
208  registration_helper_->StartRegistration(
209      oauth2_token_service_,
210      username,
211      base::Bind(&UserPolicySigninService::OnRegistrationDone,
212                 base::Unretained(this)));
213}
214
215void UserPolicySigninService::CancelPendingRegistration() {
216  weak_factory_.InvalidateWeakPtrs();
217}
218
219void UserPolicySigninService::OnRegistrationDone() {
220  registration_helper_.reset();
221}
222
223}  // namespace policy
224