1 // Copyright 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.
5 #include "chrome/browser/policy/cloud/user_policy_signin_service_base.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/signin/signin_manager_factory.h"
15 #include "chrome/common/chrome_content_client.h"
16 #include "components/policy/core/browser/browser_policy_connector.h"
17 #include "components/policy/core/common/cloud/device_management_service.h"
18 #include "components/policy/core/common/cloud/system_policy_request_context.h"
19 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
20 #include "components/signin/core/browser/signin_manager.h"
21 #include "content/public/browser/notification_source.h"
22 #include "net/url_request/url_request_context_getter.h"
26 UserPolicySigninServiceBase::UserPolicySigninServiceBase(
28 PrefService
* local_state
,
29 DeviceManagementService
* device_management_service
,
30 UserCloudPolicyManager
* policy_manager
,
31 SigninManager
* signin_manager
,
32 scoped_refptr
<net::URLRequestContextGetter
> system_request_context
)
33 : policy_manager_(policy_manager
),
34 signin_manager_(signin_manager
),
35 local_state_(local_state
),
36 device_management_service_(device_management_service
),
37 system_request_context_(system_request_context
),
39 // Register a listener to be called back once the current profile has finished
40 // initializing, so we can startup/shutdown the UserCloudPolicyManager.
42 chrome::NOTIFICATION_PROFILE_ADDED
,
43 content::Source
<Profile
>(profile
));
46 UserPolicySigninServiceBase::~UserPolicySigninServiceBase() {}
48 void UserPolicySigninServiceBase::FetchPolicyForSignedInUser(
49 const std::string
& username
,
50 const std::string
& dm_token
,
51 const std::string
& client_id
,
52 scoped_refptr
<net::URLRequestContextGetter
> profile_request_context
,
53 const PolicyFetchCallback
& callback
) {
54 scoped_ptr
<CloudPolicyClient
> client
=
55 UserCloudPolicyManager::CreateCloudPolicyClient(
56 device_management_service_
, profile_request_context
);
57 client
->SetupRegistration(dm_token
, client_id
);
58 DCHECK(client
->is_registered());
59 // The user has just signed in, so the UserCloudPolicyManager should not yet
60 // be initialized. This routine will initialize the UserCloudPolicyManager
61 // with the passed client and will proactively ask the client to fetch
62 // policy without waiting for the CloudPolicyService to finish initialization.
63 UserCloudPolicyManager
* manager
= policy_manager();
65 DCHECK(!manager
->core()->client());
66 InitializeUserCloudPolicyManager(username
, client
.Pass());
67 DCHECK(manager
->IsClientRegistered());
69 // Now initiate a policy fetch.
70 manager
->core()->service()->RefreshPolicy(callback
);
73 void UserPolicySigninServiceBase::GoogleSignedOut(const std::string
& account_id
,
74 const std::string
& username
) {
75 ShutdownUserCloudPolicyManager();
78 void UserPolicySigninServiceBase::Observe(
80 const content::NotificationSource
& source
,
81 const content::NotificationDetails
& details
) {
83 case chrome::NOTIFICATION_PROFILE_ADDED
:
84 // A new profile has been loaded - if it's signed in, then initialize the
85 // UCPM, otherwise shut down the UCPM (which deletes any cached policy
86 // data). This must be done here instead of at constructor time because
87 // the Profile is not fully initialized when this object is constructed
88 // (DoFinalInit() has not yet been called, so ProfileIOData and
89 // SSLConfigServiceManager have not been created yet).
90 // TODO(atwilson): Switch to using a timer instead, to avoid contention
91 // with other services at startup (http://crbug.com/165468).
92 InitializeOnProfileReady(content::Source
<Profile
>(source
).ptr());
99 void UserPolicySigninServiceBase::OnInitializationCompleted(
100 CloudPolicyService
* service
) {
101 // This is meant to be overridden by subclasses. Starting and stopping to
102 // observe the CloudPolicyService from this base class avoids the need for
106 void UserPolicySigninServiceBase::OnPolicyFetched(CloudPolicyClient
* client
) {}
108 void UserPolicySigninServiceBase::OnRegistrationStateChanged(
109 CloudPolicyClient
* client
) {}
111 void UserPolicySigninServiceBase::OnClientError(CloudPolicyClient
* client
) {
112 if (client
->is_registered()) {
113 // If the client is already registered, it means this error must have
114 // come from a policy fetch.
115 if (client
->status() == DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED
) {
116 // OK, policy fetch failed with MANAGEMENT_NOT_SUPPORTED - this is our
117 // trigger to revert to "unmanaged" mode (we will check for management
118 // being re-enabled on the next restart and/or login).
119 DVLOG(1) << "DMServer returned NOT_SUPPORTED error - removing policy";
121 // Can't shutdown now because we're in the middle of a callback from
122 // the CloudPolicyClient, so queue up a task to do the shutdown.
123 base::ThreadTaskRunnerHandle::Get()->PostTask(
126 &UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager
,
127 weak_factory_
.GetWeakPtr()));
129 DVLOG(1) << "Error fetching policy: " << client
->status();
134 void UserPolicySigninServiceBase::Shutdown() {
135 if (signin_manager())
136 signin_manager()->RemoveObserver(this);
137 PrepareForUserCloudPolicyManagerShutdown();
140 void UserPolicySigninServiceBase::PrepareForUserCloudPolicyManagerShutdown() {
141 UserCloudPolicyManager
* manager
= policy_manager();
142 if (manager
&& manager
->core()->client())
143 manager
->core()->client()->RemoveObserver(this);
144 if (manager
&& manager
->core()->service())
145 manager
->core()->service()->RemoveObserver(this);
148 scoped_ptr
<CloudPolicyClient
>
149 UserPolicySigninServiceBase::CreateClientForRegistrationOnly(
150 const std::string
& username
) {
151 DCHECK(!username
.empty());
152 // We should not be called with a client already initialized.
154 // On iOS we check if an account has policy while the profile is signed in
155 // to another account.
156 DCHECK(!policy_manager() || !policy_manager()->core()->client());
159 // If the user should not get policy, just bail out.
160 if (!policy_manager() || !ShouldLoadPolicyForUser(username
)) {
161 DVLOG(1) << "Signed in user is not in the whitelist";
162 return scoped_ptr
<CloudPolicyClient
>();
165 // If the DeviceManagementService is not yet initialized, start it up now.
166 device_management_service_
->ScheduleInitialization(0);
168 // Create a new CloudPolicyClient for fetching the DMToken.
169 return UserCloudPolicyManager::CreateCloudPolicyClient(
170 device_management_service_
, CreateSystemRequestContext());
173 bool UserPolicySigninServiceBase::ShouldLoadPolicyForUser(
174 const std::string
& username
) {
175 if (username
.empty())
176 return false; // Not signed in.
178 return !BrowserPolicyConnector::IsNonEnterpriseUser(username
);
181 void UserPolicySigninServiceBase::InitializeOnProfileReady(Profile
* profile
) {
182 // If using a TestingProfile with no SigninManager or UserCloudPolicyManager,
183 // skip initialization.
184 if (!policy_manager() || !signin_manager()) {
185 DVLOG(1) << "Skipping initialization for tests due to missing components.";
189 // Shutdown the UserCloudPolicyManager when the user signs out. We start
190 // observing the SigninManager here because we don't want to get signout
191 // notifications until after the profile has started initializing
192 // (http://crbug.com/316229).
193 signin_manager()->AddObserver(this);
195 std::string username
= signin_manager()->GetAuthenticatedUsername();
196 if (username
.empty())
197 ShutdownUserCloudPolicyManager();
199 InitializeForSignedInUser(username
, profile
->GetRequestContext());
202 void UserPolicySigninServiceBase::InitializeForSignedInUser(
203 const std::string
& username
,
204 scoped_refptr
<net::URLRequestContextGetter
> profile_request_context
) {
205 DCHECK(!username
.empty());
206 if (!ShouldLoadPolicyForUser(username
)) {
207 DVLOG(1) << "Policy load not enabled for user: " << username
;
211 UserCloudPolicyManager
* manager
= policy_manager();
212 // Initialize the UCPM if it is not already initialized.
213 if (!manager
->core()->service()) {
214 // If there is no cached DMToken then we can detect this when the
215 // OnInitializationCompleted() callback is invoked and this will
216 // initiate a policy fetch.
217 InitializeUserCloudPolicyManager(
219 UserCloudPolicyManager::CreateCloudPolicyClient(
220 device_management_service_
,
221 profile_request_context
));
223 manager
->SetSigninUsername(username
);
226 // If the CloudPolicyService is initialized, kick off registration.
227 // Otherwise OnInitializationCompleted is invoked as soon as the service
228 // finishes its initialization.
229 if (manager
->core()->service()->IsInitializationComplete())
230 OnInitializationCompleted(manager
->core()->service());
233 void UserPolicySigninServiceBase::InitializeUserCloudPolicyManager(
234 const std::string
& username
,
235 scoped_ptr
<CloudPolicyClient
> client
) {
237 UserCloudPolicyManager
* manager
= policy_manager();
238 manager
->SetSigninUsername(username
);
239 DCHECK(!manager
->core()->client());
240 scoped_refptr
<net::URLRequestContextGetter
> context
=
241 client
->GetRequestContext();
242 manager
->Connect(local_state_
, context
, client
.Pass());
243 DCHECK(manager
->core()->service());
245 // Observe the client to detect errors fetching policy.
246 manager
->core()->client()->AddObserver(this);
247 // Observe the service to determine when it's initialized.
248 manager
->core()->service()->AddObserver(this);
251 void UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager() {
252 PrepareForUserCloudPolicyManagerShutdown();
253 UserCloudPolicyManager
* manager
= policy_manager();
255 manager
->DisconnectAndRemovePolicy();
258 scoped_refptr
<net::URLRequestContextGetter
>
259 UserPolicySigninServiceBase::CreateSystemRequestContext() {
260 return new SystemPolicyRequestContext(
261 system_request_context(), GetUserAgent());
264 } // namespace policy