- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / policy / cloud / user_policy_signin_service_base.cc
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.
4
5 #include "chrome/browser/policy/cloud/user_policy_signin_service_base.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/policy/browser_policy_connector.h"
12 #include "chrome/browser/policy/cloud/device_management_service.h"
13 #include "chrome/browser/policy/cloud/user_cloud_policy_manager.h"
14 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
15 #include "chrome/browser/signin/signin_manager.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "content/public/browser/notification_source.h"
19 #include "net/url_request/url_request_context_getter.h"
20
21 namespace policy {
22
23 UserPolicySigninServiceBase::UserPolicySigninServiceBase(
24     Profile* profile,
25     PrefService* local_state,
26     scoped_refptr<net::URLRequestContextGetter> request_context,
27     DeviceManagementService* device_management_service)
28     : profile_(profile),
29       local_state_(local_state),
30       request_context_(request_context),
31       device_management_service_(device_management_service),
32       weak_factory_(this) {
33   // Initialize/shutdown the UserCloudPolicyManager when the user signs out.
34   registrar_.Add(this,
35                  chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
36                  content::Source<Profile>(profile));
37
38   // Register a listener to be called back once the current profile has finished
39   // initializing, so we can startup the UserCloudPolicyManager.
40   registrar_.Add(this,
41                  chrome::NOTIFICATION_PROFILE_ADDED,
42                  content::Source<Profile>(profile));
43 }
44
45 UserPolicySigninServiceBase::~UserPolicySigninServiceBase() {}
46
47 void UserPolicySigninServiceBase::FetchPolicyForSignedInUser(
48     scoped_ptr<CloudPolicyClient> client,
49     const PolicyFetchCallback& callback) {
50   DCHECK(client);
51   DCHECK(client->is_registered());
52   // The user has just signed in, so the UserCloudPolicyManager should not yet
53   // be initialized. This routine will initialize the UserCloudPolicyManager
54   // with the passed client and will proactively ask the client to fetch
55   // policy without waiting for the CloudPolicyService to finish initialization.
56   UserCloudPolicyManager* manager = GetManager();
57   DCHECK(manager);
58   DCHECK(!manager->core()->client());
59   InitializeUserCloudPolicyManager(client.Pass());
60   DCHECK(manager->IsClientRegistered());
61
62   // Now initiate a policy fetch.
63   manager->core()->service()->RefreshPolicy(callback);
64 }
65
66 void UserPolicySigninServiceBase::Observe(
67     int type,
68     const content::NotificationSource& source,
69     const content::NotificationDetails& details) {
70   // If using a TestingProfile with no SigninManager or UserCloudPolicyManager,
71   // skip initialization.
72   if (!GetManager() || !GetSigninManager()) {
73     DVLOG(1) << "Skipping initialization for tests due to missing components.";
74     return;
75   }
76
77   switch (type) {
78     case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
79       ShutdownUserCloudPolicyManager();
80       break;
81     case chrome::NOTIFICATION_PROFILE_ADDED:
82       // A new profile has been loaded - if it's signed in, then initialize the
83       // UCPM, otherwise shut down the UCPM (which deletes any cached policy
84       // data). This must be done here instead of at constructor time because
85       // the Profile is not fully initialized when this object is constructed
86       // (DoFinalInit() has not yet been called, so ProfileIOData and
87       // SSLConfigServiceManager have not been created yet).
88       // TODO(atwilson): Switch to using a timer instead, to avoid contention
89       // with other services at startup (http://crbug.com/165468).
90       InitializeOnProfileReady();
91       break;
92     default:
93       NOTREACHED();
94   }
95 }
96
97 void UserPolicySigninServiceBase::OnInitializationCompleted(
98     CloudPolicyService* service) {
99   // This is meant to be overridden by subclasses. Starting and stopping to
100   // observe the CloudPolicyService from this base class avoids the need for
101   // more virtuals.
102 }
103
104 void UserPolicySigninServiceBase::OnPolicyFetched(CloudPolicyClient* client) {}
105
106 void UserPolicySigninServiceBase::OnRegistrationStateChanged(
107     CloudPolicyClient* client) {}
108
109 void UserPolicySigninServiceBase::OnClientError(CloudPolicyClient* client) {
110   if (client->is_registered()) {
111     // If the client is already registered, it means this error must have
112     // come from a policy fetch.
113     if (client->status() == DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED) {
114       // OK, policy fetch failed with MANAGEMENT_NOT_SUPPORTED - this is our
115       // trigger to revert to "unmanaged" mode (we will check for management
116       // being re-enabled on the next restart and/or login).
117       DVLOG(1) << "DMServer returned NOT_SUPPORTED error - removing policy";
118
119       // Can't shutdown now because we're in the middle of a callback from
120       // the CloudPolicyClient, so queue up a task to do the shutdown.
121       base::MessageLoop::current()->PostTask(
122           FROM_HERE,
123           base::Bind(
124               &UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager,
125               weak_factory_.GetWeakPtr()));
126     } else {
127       DVLOG(1) << "Error fetching policy: " << client->status();
128     }
129   }
130 }
131
132 void UserPolicySigninServiceBase::Shutdown() {
133   PrepareForUserCloudPolicyManagerShutdown();
134 }
135
136 void UserPolicySigninServiceBase::PrepareForUserCloudPolicyManagerShutdown() {
137   UserCloudPolicyManager* manager = GetManager();
138   if (manager && manager->core()->client())
139     manager->core()->client()->RemoveObserver(this);
140   if (manager && manager->core()->service())
141     manager->core()->service()->RemoveObserver(this);
142 }
143
144 // static
145 bool UserPolicySigninServiceBase::ShouldForceLoadPolicy() {
146   return CommandLine::ForCurrentProcess()->HasSwitch(
147       switches::kForceLoadCloudPolicy);
148 }
149
150 scoped_ptr<CloudPolicyClient> UserPolicySigninServiceBase::PrepareToRegister(
151     const std::string& username) {
152   DCHECK(!username.empty());
153   // We should not be called with a client already initialized.
154   DCHECK(!GetManager() || !GetManager()->core()->client());
155
156   // If the user should not get policy, just bail out.
157   if (!GetManager() || !ShouldLoadPolicyForUser(username)) {
158     DVLOG(1) << "Signed in user is not in the whitelist";
159     return scoped_ptr<CloudPolicyClient>();
160   }
161
162   // If the DeviceManagementService is not yet initialized, start it up now.
163   device_management_service_->ScheduleInitialization(0);
164
165   // Create a new CloudPolicyClient for fetching the DMToken.
166   return UserCloudPolicyManager::CreateCloudPolicyClient(
167       device_management_service_);
168 }
169
170 bool UserPolicySigninServiceBase::ShouldLoadPolicyForUser(
171     const std::string& username) {
172   if (username.empty())
173     return false;  // Not signed in.
174
175   if (ShouldForceLoadPolicy())
176     return true;
177
178   return !BrowserPolicyConnector::IsNonEnterpriseUser(username);
179 }
180
181 void UserPolicySigninServiceBase::InitializeOnProfileReady() {
182   std::string username = GetSigninManager()->GetAuthenticatedUsername();
183   if (username.empty())
184     ShutdownUserCloudPolicyManager();
185   else
186     InitializeForSignedInUser(username);
187 }
188
189 void UserPolicySigninServiceBase::InitializeForSignedInUser(
190     const std::string& username) {
191   DCHECK(!username.empty());
192   if (!ShouldLoadPolicyForUser(username)) {
193     DVLOG(1) << "Policy load not enabled for user: " << username;
194     return;
195   }
196
197   UserCloudPolicyManager* manager = GetManager();
198   // Initialize the UCPM if it is not already initialized.
199   if (!manager->core()->service()) {
200     // If there is no cached DMToken then we can detect this when the
201     // OnInitializationCompleted() callback is invoked and this will
202     // initiate a policy fetch.
203     InitializeUserCloudPolicyManager(
204         UserCloudPolicyManager::CreateCloudPolicyClient(
205             device_management_service_).Pass());
206   }
207
208   // If the CloudPolicyService is initialized, kick off registration.
209   // Otherwise OnInitializationCompleted is invoked as soon as the service
210   // finishes its initialization.
211   if (manager->core()->service()->IsInitializationComplete())
212     OnInitializationCompleted(manager->core()->service());
213 }
214
215 void UserPolicySigninServiceBase::InitializeUserCloudPolicyManager(
216     scoped_ptr<CloudPolicyClient> client) {
217   UserCloudPolicyManager* manager = GetManager();
218   DCHECK(!manager->core()->client());
219   manager->Connect(local_state_, request_context_, client.Pass());
220   DCHECK(manager->core()->service());
221
222   // Observe the client to detect errors fetching policy.
223   manager->core()->client()->AddObserver(this);
224   // Observe the service to determine when it's initialized.
225   manager->core()->service()->AddObserver(this);
226 }
227
228 void UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager() {
229   PrepareForUserCloudPolicyManagerShutdown();
230   UserCloudPolicyManager* manager = GetManager();
231   if (manager)
232     manager->DisconnectAndRemovePolicy();
233 }
234
235 UserCloudPolicyManager* UserPolicySigninServiceBase::GetManager() {
236   return UserCloudPolicyManagerFactory::GetForProfile(profile_);
237 }
238
239 SigninManager* UserPolicySigninServiceBase::GetSigninManager() {
240   return SigninManagerFactory::GetForProfile(profile_);
241 }
242
243 }  // namespace policy