blob: 6a46a33f81a83fa7c7863600f0308f1b6a068ab8 [file] [log] [blame]
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01001// 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/managed_mode/managed_user_registration_utility.h"
6
7#include "base/base64.h"
8#include "base/bind.h"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01009#include "base/memory/scoped_ptr.h"
10#include "base/prefs/pref_service.h"
11#include "base/rand_util.h"
12#include "base/strings/utf_string_conversions.h"
13#include "chrome/browser/managed_mode/managed_user_refresh_token_fetcher.h"
14#include "chrome/browser/managed_mode/managed_user_service.h"
15#include "chrome/browser/managed_mode/managed_user_service_factory.h"
16#include "chrome/browser/managed_mode/managed_user_sync_service.h"
17#include "chrome/browser/managed_mode/managed_user_sync_service_factory.h"
18#include "chrome/browser/prefs/scoped_user_pref_update.h"
19#include "chrome/browser/signin/profile_oauth2_token_service.h"
20#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
21#include "chrome/browser/sync/glue/device_info.h"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010022#include "chrome/common/pref_names.h"
23#include "google_apis/gaia/gaia_urls.h"
24#include "google_apis/gaia/google_service_auth_error.h"
25
26using base::DictionaryValue;
27
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010028const char kAcknowledged[] = "acknowledged";
29const char kName[] = "name";
30const char kMasterKey[] = "masterKey";
31
32ManagedUserRegistrationInfo::ManagedUserRegistrationInfo(const string16& name)
33 : name(name) {
34}
35
36ManagedUserRegistrationUtility::ManagedUserRegistrationUtility(
37 PrefService* prefs,
38 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,
39 ManagedUserSyncService* service)
40 : weak_ptr_factory_(this),
41 prefs_(prefs),
42 token_fetcher_(token_fetcher.Pass()),
43 managed_user_sync_service_(service),
Ben Murdoch2385ea32013-08-06 11:01:04 +010044 pending_managed_user_acknowledged_(false),
45 is_existing_managed_user_(false) {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010046 managed_user_sync_service_->AddObserver(this);
47}
48
49ManagedUserRegistrationUtility::~ManagedUserRegistrationUtility() {
50 managed_user_sync_service_->RemoveObserver(this);
51 CancelPendingRegistration();
52}
53
54// static
55scoped_ptr<ManagedUserRegistrationUtility>
56ManagedUserRegistrationUtility::Create(Profile* profile) {
57 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher =
58 ManagedUserRefreshTokenFetcher::Create(
59 ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
60 profile->GetRequestContext());
61 ManagedUserSyncService* managed_user_sync_service =
62 ManagedUserSyncServiceFactory::GetForProfile(profile);
63 return make_scoped_ptr(new ManagedUserRegistrationUtility(
64 profile->GetPrefs(), token_fetcher.Pass(), managed_user_sync_service));
65}
66
Ben Murdoch2385ea32013-08-06 11:01:04 +010067// static
68std::string ManagedUserRegistrationUtility::GenerateNewManagedUserId() {
69 std::string new_managed_user_id;
70 bool success = base::Base64Encode(base::RandBytesAsString(8),
71 &new_managed_user_id);
72 DCHECK(success);
73 return new_managed_user_id;
74}
75
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010076void ManagedUserRegistrationUtility::Register(
Ben Murdoch2385ea32013-08-06 11:01:04 +010077 const std::string& managed_user_id,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010078 const ManagedUserRegistrationInfo& info,
79 const RegistrationCallback& callback) {
80 DCHECK(pending_managed_user_id_.empty());
81 callback_ = callback;
Ben Murdoch2385ea32013-08-06 11:01:04 +010082 pending_managed_user_id_ = managed_user_id;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010083
Ben Murdoch2385ea32013-08-06 11:01:04 +010084 const DictionaryValue* dict = prefs_->GetDictionary(prefs::kManagedUsers);
85 is_existing_managed_user_ = dict->HasKey(managed_user_id);
86 if (!is_existing_managed_user_) {
87 managed_user_sync_service_->AddManagedUser(pending_managed_user_id_,
88 base::UTF16ToUTF8(info.name),
89 info.master_key);
90 } else {
91 // User already exists, don't wait for acknowledgment.
92 OnManagedUserAcknowledged(managed_user_id);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010093 }
94
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010095 browser_sync::DeviceInfo::GetClientName(
96 base::Bind(&ManagedUserRegistrationUtility::FetchToken,
Ben Murdochbb1529c2013-08-08 10:24:53 +010097 weak_ptr_factory_.GetWeakPtr()));
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010098}
99
100void ManagedUserRegistrationUtility::CancelPendingRegistration() {
101 AbortPendingRegistration(
102 false, // Don't run the callback. The error will be ignored.
103 GoogleServiceAuthError(GoogleServiceAuthError::NONE));
104}
105
106void ManagedUserRegistrationUtility::OnManagedUserAcknowledged(
107 const std::string& managed_user_id) {
108 DCHECK_EQ(pending_managed_user_id_, managed_user_id);
109 DCHECK(!pending_managed_user_acknowledged_);
110 pending_managed_user_acknowledged_ = true;
111 CompleteRegistrationIfReady();
112}
113
114void ManagedUserRegistrationUtility::OnManagedUsersSyncingStopped() {
115 AbortPendingRegistration(
116 true, // Run the callback.
117 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
118}
119
120void ManagedUserRegistrationUtility::FetchToken(
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100121 const std::string& client_name) {
122 token_fetcher_->Start(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100123 pending_managed_user_id_, client_name,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100124 base::Bind(&ManagedUserRegistrationUtility::OnReceivedToken,
125 weak_ptr_factory_.GetWeakPtr()));
126}
127
128void ManagedUserRegistrationUtility::OnReceivedToken(
129 const GoogleServiceAuthError& error,
130 const std::string& token) {
131 if (error.state() != GoogleServiceAuthError::NONE) {
132 CompleteRegistration(true, error);
133 return;
134 }
135
136 DCHECK(!token.empty());
137 pending_managed_user_token_ = token;
138 CompleteRegistrationIfReady();
139}
140
141void ManagedUserRegistrationUtility::CompleteRegistrationIfReady() {
142 if (!pending_managed_user_acknowledged_ ||
143 pending_managed_user_token_.empty()) {
144 return;
145 }
146
147 GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
148 CompleteRegistration(true, error);
149}
150
151void ManagedUserRegistrationUtility::AbortPendingRegistration(
152 bool run_callback,
153 const GoogleServiceAuthError& error) {
154 pending_managed_user_token_.clear();
155 CompleteRegistration(run_callback, error);
156}
157
158void ManagedUserRegistrationUtility::CompleteRegistration(
159 bool run_callback,
160 const GoogleServiceAuthError& error) {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100161 if (callback_.is_null())
162 return;
163
Ben Murdoch2385ea32013-08-06 11:01:04 +0100164 // We check that the user being registered is not an existing managed
165 // user before deleting it from sync to avoid accidental deletion of
166 // existing managed users by just canceling the registration for example.
167 if (pending_managed_user_token_.empty() && !is_existing_managed_user_) {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100168 DCHECK(!pending_managed_user_id_.empty());
169 // Remove the pending managed user if we weren't successful.
170 DictionaryPrefUpdate update(prefs_, prefs::kManagedUsers);
171 bool success =
172 update->RemoveWithoutPathExpansion(pending_managed_user_id_, NULL);
173 DCHECK(success);
174 managed_user_sync_service_->DeleteManagedUser(pending_managed_user_id_);
175 }
176
177 if (run_callback)
178 callback_.Run(error, pending_managed_user_token_);
179 callback_.Reset();
180}