Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / policy / consumer_enrollment_handler.cc
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/chromeos/policy/consumer_enrollment_handler.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/browser_process_platform_part.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
18 #include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h"
19 #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
20 #include "chrome/browser/chromeos/profiles/profile_helper.h"
21 #include "chrome/browser/notifications/notification.h"
22 #include "chrome/browser/notifications/notification_delegate.h"
23 #include "chrome/browser/notifications/notification_ui_manager.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
26 #include "chrome/browser/signin/signin_manager_factory.h"
27 #include "chrome/browser/ui/browser_navigator.h"
28 #include "chrome/common/url_constants.h"
29 #include "components/policy/core/common/cloud/device_management_service.h"
30 #include "components/signin/core/browser/profile_oauth2_token_service.h"
31 #include "components/signin/core/browser/signin_manager_base.h"
32 #include "components/user_manager/user_manager.h"
33 #include "content/public/browser/notification_details.h"
34 #include "content/public/browser/notification_service.h"
35 #include "content/public/browser/notification_source.h"
36 #include "google_apis/gaia/gaia_constants.h"
37 #include "google_apis/gaia/google_service_auth_error.h"
38 #include "grit/generated_resources.h"
39 #include "grit/theme_resources.h"
40 #include "policy/proto/device_management_backend.pb.h"
41 #include "third_party/WebKit/public/web/WebTextDirection.h"
42 #include "ui/base/l10n/l10n_util.h"
43 #include "ui/base/page_transition_types.h"
44 #include "ui/base/resource/resource_bundle.h"
45 #include "ui/base/window_open_disposition.h"
46 #include "ui/message_center/notification.h"
47 #include "ui/message_center/notification_types.h"
48 #include "ui/message_center/notifier_settings.h"
49 #include "url/gurl.h"
50
51 namespace em = enterprise_management;
52
53 namespace {
54
55 // Desktop notification constants.
56 const char kEnrollmentNotificationId[] = "consumer_management.enroll";
57 const char kEnrollmentNotificationUrl[] = "chrome://consumer-management/enroll";
58
59 // The path to the consumer management enrollment/unenrollment confirmation
60 // overlay, relative to the settings page URL.
61 const char kConsumerManagementOverlay[] = "consumer-management-overlay";
62
63   // Returns the account ID signed in to |profile|.
64 const std::string& GetAccountIdFromProfile(Profile* profile) {
65   return SigninManagerFactory::GetForProfile(profile)->
66       GetAuthenticatedAccountId();
67 }
68
69 class DesktopNotificationDelegate : public NotificationDelegate {
70  public:
71   // |button_click_callback| is called when the button in the notification is
72   // clicked.
73   DesktopNotificationDelegate(const std::string& id,
74                               const base::Closure& button_click_callback);
75
76   // NotificationDelegate:
77   virtual std::string id() const override;
78   virtual void ButtonClick(int button_index) override;
79
80  private:
81   virtual ~DesktopNotificationDelegate();
82
83   std::string id_;
84   base::Closure button_click_callback_;
85
86   DISALLOW_COPY_AND_ASSIGN(DesktopNotificationDelegate);
87 };
88
89 DesktopNotificationDelegate::DesktopNotificationDelegate(
90     const std::string& id,
91     const base::Closure& button_click_callback)
92     : id_(id), button_click_callback_(button_click_callback) {
93 }
94
95 DesktopNotificationDelegate::~DesktopNotificationDelegate() {
96 }
97
98 std::string DesktopNotificationDelegate::id() const {
99   return id_;
100 }
101
102 void DesktopNotificationDelegate::ButtonClick(int button_index) {
103   button_click_callback_.Run();
104 }
105
106 }  // namespace
107
108 namespace policy {
109
110 ConsumerEnrollmentHandler::ConsumerEnrollmentHandler(
111     ConsumerManagementService* consumer_management_service,
112     DeviceManagementService* device_management_service)
113     : Consumer("consumer_enrollment_handler"),
114       consumer_management_service_(consumer_management_service),
115       device_management_service_(device_management_service),
116       enrolling_profile_(NULL),
117       weak_ptr_factory_(this) {
118   registrar_.Add(this,
119                  chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
120                  content::NotificationService::AllSources());
121 }
122
123 ConsumerEnrollmentHandler::~ConsumerEnrollmentHandler() {
124   if (enrolling_profile_) {
125     ProfileOAuth2TokenServiceFactory::GetForProfile(enrolling_profile_)->
126         RemoveObserver(this);
127   }
128   registrar_.Remove(this,
129                     chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
130                     content::NotificationService::AllSources());
131 }
132
133 void ConsumerEnrollmentHandler::Observe(
134     int type,
135     const content::NotificationSource& source,
136     const content::NotificationDetails& details) {
137   if (type != chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED) {
138     NOTREACHED() << "Unexpected notification " << type;
139     return;
140   }
141
142   Profile* profile = content::Details<Profile>(details).ptr();
143   if (chromeos::ProfileHelper::IsOwnerProfile(profile))
144     OnOwnerSignin(profile);
145 }
146
147 void ConsumerEnrollmentHandler::OnRefreshTokenAvailable(
148     const std::string& account_id) {
149   CHECK(enrolling_profile_);
150
151   if (account_id == GetAccountIdFromProfile(enrolling_profile_)) {
152     ProfileOAuth2TokenServiceFactory::GetForProfile(enrolling_profile_)->
153         RemoveObserver(this);
154     OnOwnerRefreshTokenAvailable();
155   }
156 }
157
158 void ConsumerEnrollmentHandler::OnGetTokenSuccess(
159       const OAuth2TokenService::Request* request,
160       const std::string& access_token,
161       const base::Time& expiration_time) {
162   DCHECK_EQ(token_request_, request);
163   base::MessageLoop::current()->DeleteSoon(FROM_HERE, token_request_.release());
164
165   OnOwnerAccessTokenAvailable(access_token);
166 }
167
168 void ConsumerEnrollmentHandler::OnGetTokenFailure(
169       const OAuth2TokenService::Request* request,
170       const GoogleServiceAuthError& error) {
171   DCHECK_EQ(token_request_, request);
172   base::MessageLoop::current()->DeleteSoon(FROM_HERE, token_request_.release());
173
174   LOG(ERROR) << "Failed to get the access token: " << error.ToString();
175   EndEnrollment(ConsumerManagementService::ENROLLMENT_STAGE_GET_TOKEN_FAILED);
176 }
177
178 void ConsumerEnrollmentHandler::OnOwnerSignin(Profile* profile) {
179   const ConsumerManagementService::EnrollmentStage stage =
180       consumer_management_service_->GetEnrollmentStage();
181   switch (stage) {
182     case ConsumerManagementService::ENROLLMENT_STAGE_NONE:
183       // Do nothing.
184       return;
185
186     case ConsumerManagementService::ENROLLMENT_STAGE_OWNER_STORED:
187       // Continue the enrollment process after the owner signs in.
188       ContinueEnrollmentProcess(profile);
189       return;
190
191     case ConsumerManagementService::ENROLLMENT_STAGE_SUCCESS:
192     case ConsumerManagementService::ENROLLMENT_STAGE_CANCELED:
193     case ConsumerManagementService::ENROLLMENT_STAGE_BOOT_LOCKBOX_FAILED:
194     case ConsumerManagementService::ENROLLMENT_STAGE_DM_SERVER_FAILED:
195     case ConsumerManagementService::ENROLLMENT_STAGE_GET_TOKEN_FAILED:
196       ShowDesktopNotificationAndResetStage(stage, profile);
197       return;
198
199     case ConsumerManagementService::ENROLLMENT_STAGE_REQUESTED:
200     case ConsumerManagementService::ENROLLMENT_STAGE_LAST:
201       NOTREACHED() << "Unexpected enrollment stage " << stage;
202       return;
203   }
204 }
205
206 void ConsumerEnrollmentHandler::ContinueEnrollmentProcess(Profile* profile) {
207   enrolling_profile_ = profile;
208
209   // First, we need to ensure that the refresh token is available.
210   const std::string& account_id = GetAccountIdFromProfile(profile);
211   ProfileOAuth2TokenService* token_service =
212       ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
213   if (token_service->RefreshTokenIsAvailable(account_id)) {
214     OnOwnerRefreshTokenAvailable();
215   } else {
216     token_service->AddObserver(this);
217   }
218 }
219
220 void ConsumerEnrollmentHandler::OnOwnerRefreshTokenAvailable() {
221   CHECK(enrolling_profile_);
222
223   // Now we can request the OAuth access token for device management to send the
224   // device registration request to the device management server.
225   OAuth2TokenService::ScopeSet oauth_scopes;
226   oauth_scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth);
227   const std::string& account_id = GetAccountIdFromProfile(enrolling_profile_);
228   token_request_ = ProfileOAuth2TokenServiceFactory::GetForProfile(
229       enrolling_profile_)->StartRequest(account_id, oauth_scopes, this);
230 }
231
232 void ConsumerEnrollmentHandler::OnOwnerAccessTokenAvailable(
233     const std::string& access_token) {
234   // Now that we have the access token, we got everything we need to send the
235   // device registration request to the device management server.
236   BrowserPolicyConnectorChromeOS* connector =
237       g_browser_process->platform_part()->browser_policy_connector_chromeos();
238   DeviceCloudPolicyInitializer* initializer =
239       connector->GetDeviceCloudPolicyInitializer();
240   CHECK(initializer);
241
242   policy::DeviceCloudPolicyInitializer::AllowedDeviceModes device_modes;
243   device_modes[policy::DEVICE_MODE_ENTERPRISE] = true;
244
245   initializer->StartEnrollment(
246       em::PolicyData::CONSUMER_MANAGED,
247       device_management_service_,
248       access_token,
249       false,  // is_auto_enrollment
250       device_modes,
251       base::Bind(&ConsumerEnrollmentHandler::OnEnrollmentCompleted,
252                  weak_ptr_factory_.GetWeakPtr()));
253 }
254
255 void ConsumerEnrollmentHandler::OnEnrollmentCompleted(EnrollmentStatus status) {
256   if (status.status() != EnrollmentStatus::STATUS_SUCCESS) {
257     LOG(ERROR) << "Failed to enroll the device."
258                << " status=" << status.status()
259                << " client_status=" << status.client_status()
260                << " http_status=" << status.http_status()
261                << " store_status=" << status.store_status()
262                << " validation_status=" << status.validation_status();
263     EndEnrollment(ConsumerManagementService::ENROLLMENT_STAGE_DM_SERVER_FAILED);
264     return;
265   }
266
267   EndEnrollment(ConsumerManagementService::ENROLLMENT_STAGE_SUCCESS);
268 }
269
270 void ConsumerEnrollmentHandler::EndEnrollment(
271     ConsumerManagementService::EnrollmentStage stage) {
272   Profile* profile = enrolling_profile_;
273   enrolling_profile_ = NULL;
274
275   consumer_management_service_->SetEnrollmentStage(stage);
276   if (user_manager::UserManager::Get()->IsCurrentUserOwner())
277     ShowDesktopNotificationAndResetStage(stage, profile);
278 }
279
280 void ConsumerEnrollmentHandler::ShowDesktopNotificationAndResetStage(
281     ConsumerManagementService::EnrollmentStage stage, Profile* profile) {
282   base::string16 title;
283   base::string16 body;
284   base::string16 button_label;
285   base::Closure button_click_callback;
286
287   if (stage == ConsumerManagementService::ENROLLMENT_STAGE_SUCCESS) {
288     title = l10n_util::GetStringUTF16(
289         IDS_CONSUMER_MANAGEMENT_ENROLLMENT_NOTIFICATION_TITLE);
290     body = l10n_util::GetStringUTF16(
291         IDS_CONSUMER_MANAGEMENT_ENROLLMENT_NOTIFICATION_BODY);
292     button_label = l10n_util::GetStringUTF16(
293         IDS_CONSUMER_MANAGEMENT_NOTIFICATION_MODIFY_SETTINGS_BUTTON);
294     button_click_callback = base::Bind(
295         &ConsumerEnrollmentHandler::OpenSettingsPage,
296         weak_ptr_factory_.GetWeakPtr(),
297         profile);
298   } else {
299     title = l10n_util::GetStringUTF16(
300         IDS_CONSUMER_MANAGEMENT_ENROLLMENT_FAILURE_NOTIFICATION_TITLE);
301     body = l10n_util::GetStringUTF16(
302         IDS_CONSUMER_MANAGEMENT_ENROLLMENT_FAILURE_NOTIFICATION_BODY);
303     button_label = l10n_util::GetStringUTF16(
304         IDS_CONSUMER_MANAGEMENT_NOTIFICATION_TRY_AGAIN_BUTTON);
305     button_click_callback = base::Bind(
306         &ConsumerEnrollmentHandler::TryEnrollmentAgain,
307         weak_ptr_factory_.GetWeakPtr(),
308         profile);
309   }
310
311   message_center::RichNotificationData optional_field;
312   optional_field.buttons.push_back(message_center::ButtonInfo(button_label));
313   Notification notification(
314       message_center::NOTIFICATION_TYPE_SIMPLE,
315       GURL(kEnrollmentNotificationUrl),
316       title,
317       body,
318       ui::ResourceBundle::GetSharedInstance().GetImageNamed(
319           IDR_CONSUMER_MANAGEMENT_NOTIFICATION_ICON),
320       blink::WebTextDirectionDefault,
321       message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT,
322                                  kEnrollmentNotificationId),
323       base::string16(),  // display_source
324       base::UTF8ToUTF16(kEnrollmentNotificationId),
325       optional_field,
326       new DesktopNotificationDelegate(kEnrollmentNotificationId,
327                                       button_click_callback));
328   notification.SetSystemPriority();
329   g_browser_process->notification_ui_manager()->Add(notification, profile);
330
331   consumer_management_service_->SetEnrollmentStage(
332       ConsumerManagementService::ENROLLMENT_STAGE_NONE);
333 }
334
335 void ConsumerEnrollmentHandler::OpenSettingsPage(Profile* profile) const {
336   const GURL url(chrome::kChromeUISettingsURL);
337   chrome::NavigateParams params(profile, url, ui::PAGE_TRANSITION_LINK);
338   params.disposition = NEW_FOREGROUND_TAB;
339   chrome::Navigate(&params);
340 }
341
342 void ConsumerEnrollmentHandler::TryEnrollmentAgain(Profile* profile) const {
343   const GURL base_url(chrome::kChromeUISettingsURL);
344   const GURL url = base_url.Resolve(kConsumerManagementOverlay);
345
346   chrome::NavigateParams params(profile, url, ui::PAGE_TRANSITION_LINK);
347   params.disposition = NEW_FOREGROUND_TAB;
348   chrome::Navigate(&params);
349 }
350
351 }  // namespace policy