signin_manager_android.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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/android/signin/signin_manager_android.h"
6
7#include "base/android/jni_android.h"
8#include "base/android/jni_string.h"
9#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/memory/ref_counted.h"
12#include "base/message_loop/message_loop_proxy.h"
13#include "base/prefs/pref_service.h"
14#include "chrome/browser/bookmarks/bookmark_model_factory.h"
15#include "chrome/browser/browser_process.h"
16#include "chrome/browser/browsing_data/browsing_data_helper.h"
17#include "chrome/browser/browsing_data/browsing_data_remover.h"
18#include "chrome/browser/profiles/profile_manager.h"
19#include "chrome/browser/signin/android_profile_oauth2_token_service.h"
20#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
21#include "chrome/browser/signin/signin_manager_factory.h"
22#include "chrome/common/pref_names.h"
23#include "components/bookmarks/browser/bookmark_model.h"
24#include "components/signin/core/browser/profile_oauth2_token_service.h"
25#include "components/signin/core/browser/signin_manager.h"
26#include "components/signin/core/common/profile_management_switches.h"
27#include "jni/SigninManager_jni.h"
28
29#if defined(ENABLE_CONFIGURATION_POLICY)
30#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
31#include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
32#include "chrome/browser/policy/cloud/user_policy_signin_service_mobile.h"
33#include "components/policy/core/browser/browser_policy_connector.h"
34#include "components/policy/core/common/cloud/cloud_policy_core.h"
35#include "components/policy/core/common/cloud/cloud_policy_store.h"
36#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
37#include "google_apis/gaia/gaia_auth_util.h"
38#include "net/url_request/url_request_context_getter.h"
39#endif
40
41namespace {
42
43// A BrowsingDataRemover::Observer that clears all Profile data and then
44// invokes a callback and deletes itself.
45class ProfileDataRemover : public BrowsingDataRemover::Observer {
46 public:
47  ProfileDataRemover(Profile* profile, const base::Closure& callback)
48      : callback_(callback),
49        origin_loop_(base::MessageLoopProxy::current()),
50        remover_(BrowsingDataRemover::CreateForUnboundedRange(profile)) {
51    remover_->AddObserver(this);
52    remover_->Remove(BrowsingDataRemover::REMOVE_ALL, BrowsingDataHelper::ALL);
53  }
54
55  virtual ~ProfileDataRemover() {}
56
57  virtual void OnBrowsingDataRemoverDone() OVERRIDE {
58    remover_->RemoveObserver(this);
59    origin_loop_->PostTask(FROM_HERE, callback_);
60    origin_loop_->DeleteSoon(FROM_HERE, this);
61  }
62
63 private:
64  base::Closure callback_;
65  scoped_refptr<base::MessageLoopProxy> origin_loop_;
66  BrowsingDataRemover* remover_;
67
68  DISALLOW_COPY_AND_ASSIGN(ProfileDataRemover);
69};
70
71}  // namespace
72
73SigninManagerAndroid::SigninManagerAndroid(JNIEnv* env, jobject obj)
74    : profile_(NULL),
75      weak_factory_(this) {
76  java_signin_manager_.Reset(env, obj);
77  profile_ = ProfileManager::GetActiveUserProfile();
78  DCHECK(profile_);
79}
80
81SigninManagerAndroid::~SigninManagerAndroid() {}
82
83void SigninManagerAndroid::CheckPolicyBeforeSignIn(JNIEnv* env,
84                                                   jobject obj,
85                                                   jstring username) {
86#if defined(ENABLE_CONFIGURATION_POLICY)
87  username_ = base::android::ConvertJavaStringToUTF8(env, username);
88  policy::UserPolicySigninService* service =
89      policy::UserPolicySigninServiceFactory::GetForProfile(profile_);
90  service->RegisterForPolicy(
91      base::android::ConvertJavaStringToUTF8(env, username),
92      base::Bind(&SigninManagerAndroid::OnPolicyRegisterDone,
93                 weak_factory_.GetWeakPtr()));
94#else
95  // This shouldn't be called when ShouldLoadPolicyForUser() is false.
96  NOTREACHED();
97  base::android::ScopedJavaLocalRef<jstring> domain;
98  Java_SigninManager_onPolicyCheckedBeforeSignIn(env,
99                                                 java_signin_manager_.obj(),
100                                                 domain.obj());
101#endif
102}
103
104void SigninManagerAndroid::FetchPolicyBeforeSignIn(JNIEnv* env, jobject obj) {
105#if defined(ENABLE_CONFIGURATION_POLICY)
106  if (!dm_token_.empty()) {
107    policy::UserPolicySigninService* service =
108        policy::UserPolicySigninServiceFactory::GetForProfile(profile_);
109    service->FetchPolicyForSignedInUser(
110        username_,
111        dm_token_,
112        client_id_,
113        profile_->GetRequestContext(),
114        base::Bind(&SigninManagerAndroid::OnPolicyFetchDone,
115                   weak_factory_.GetWeakPtr()));
116    dm_token_.clear();
117    client_id_.clear();
118    return;
119  }
120#endif
121  // This shouldn't be called when ShouldLoadPolicyForUser() is false, or when
122  // CheckPolicyBeforeSignIn() failed.
123  NOTREACHED();
124  Java_SigninManager_onPolicyFetchedBeforeSignIn(env,
125                                                 java_signin_manager_.obj());
126}
127
128void SigninManagerAndroid::OnSignInCompleted(JNIEnv* env,
129                                             jobject obj,
130                                             jstring username) {
131  SigninManagerFactory::GetForProfile(profile_)->OnExternalSigninCompleted(
132      base::android::ConvertJavaStringToUTF8(env, username));
133}
134
135void SigninManagerAndroid::SignOut(JNIEnv* env, jobject obj) {
136  SigninManagerFactory::GetForProfile(profile_)->SignOut();
137}
138
139base::android::ScopedJavaLocalRef<jstring>
140SigninManagerAndroid::GetManagementDomain(JNIEnv* env, jobject obj) {
141  base::android::ScopedJavaLocalRef<jstring> domain;
142
143#if defined(ENABLE_CONFIGURATION_POLICY)
144  policy::UserCloudPolicyManager* manager =
145      policy::UserCloudPolicyManagerFactory::GetForBrowserContext(profile_);
146  policy::CloudPolicyStore* store = manager->core()->store();
147
148  if (store && store->is_managed() && store->policy()->has_username()) {
149    domain.Reset(
150        base::android::ConvertUTF8ToJavaString(
151            env, gaia::ExtractDomainName(store->policy()->username())));
152  }
153#endif
154
155  return domain;
156}
157
158void SigninManagerAndroid::WipeProfileData(JNIEnv* env, jobject obj) {
159  // The ProfileDataRemover deletes itself once done.
160  new ProfileDataRemover(
161      profile_,
162      base::Bind(&SigninManagerAndroid::OnBrowsingDataRemoverDone,
163                 weak_factory_.GetWeakPtr()));
164}
165
166#if defined(ENABLE_CONFIGURATION_POLICY)
167
168void SigninManagerAndroid::OnPolicyRegisterDone(
169    const std::string& dm_token,
170    const std::string& client_id) {
171  dm_token_ = dm_token;
172  client_id_ = client_id;
173
174  JNIEnv* env = base::android::AttachCurrentThread();
175  base::android::ScopedJavaLocalRef<jstring> domain;
176  if (!dm_token_.empty()) {
177    DCHECK(!username_.empty());
178    domain.Reset(
179        base::android::ConvertUTF8ToJavaString(
180            env, gaia::ExtractDomainName(username_)));
181  } else {
182    username_.clear();
183  }
184
185  Java_SigninManager_onPolicyCheckedBeforeSignIn(env,
186                                                 java_signin_manager_.obj(),
187                                                 domain.obj());
188}
189
190void SigninManagerAndroid::OnPolicyFetchDone(bool success) {
191  Java_SigninManager_onPolicyFetchedBeforeSignIn(
192      base::android::AttachCurrentThread(),
193      java_signin_manager_.obj());
194}
195
196#endif
197
198void SigninManagerAndroid::OnBrowsingDataRemoverDone() {
199  BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile_);
200  model->RemoveAllUserBookmarks();
201
202  // All the Profile data has been wiped. Clear the last signed in username as
203  // well, so that the next signin doesn't trigger the acount change dialog.
204  ClearLastSignedInUser();
205
206  Java_SigninManager_onProfileDataWiped(base::android::AttachCurrentThread(),
207                                        java_signin_manager_.obj());
208}
209
210void SigninManagerAndroid::ClearLastSignedInUser(JNIEnv* env, jobject obj) {
211  ClearLastSignedInUser();
212}
213
214void SigninManagerAndroid::ClearLastSignedInUser() {
215  profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesLastUsername);
216}
217
218void SigninManagerAndroid::MergeSessionCompleted(
219    const std::string& account_id,
220    const GoogleServiceAuthError& error) {
221  merge_session_helper_->RemoveObserver(this);
222  merge_session_helper_.reset();
223}
224
225void SigninManagerAndroid::LogInSignedInUser(JNIEnv* env, jobject obj) {
226  SigninManagerBase* signin_manager =
227      SigninManagerFactory::GetForProfile(profile_);
228  if (switches::IsNewProfileManagement()) {
229    // New Mirror code path that just fires the events and let the
230    // Account Reconcilor handles everything.
231    AndroidProfileOAuth2TokenService* token_service =
232        ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile(
233            profile_);
234    const std::string& primary_acct =
235        signin_manager->GetAuthenticatedAccountId();
236    token_service->ValidateAccounts(primary_acct, true);
237
238  } else {
239    DVLOG(1) << "SigninManagerAndroid::LogInSignedInUser "
240        " Manually calling MergeSessionHelper";
241    // Old code path that doesn't depend on the new Account Reconcilor.
242    // We manually login.
243
244    ProfileOAuth2TokenService* token_service =
245        ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
246    merge_session_helper_.reset(new MergeSessionHelper(
247        token_service, profile_->GetRequestContext(), this));
248    merge_session_helper_->LogIn(signin_manager->GetAuthenticatedAccountId());
249  }
250}
251
252static jlong Init(JNIEnv* env, jobject obj) {
253  SigninManagerAndroid* signin_manager_android =
254      new SigninManagerAndroid(env, obj);
255  return reinterpret_cast<intptr_t>(signin_manager_android);
256}
257
258static jboolean ShouldLoadPolicyForUser(JNIEnv* env,
259                                        jobject obj,
260                                        jstring j_username) {
261#if defined(ENABLE_CONFIGURATION_POLICY)
262  std::string username =
263      base::android::ConvertJavaStringToUTF8(env, j_username);
264  return !policy::BrowserPolicyConnector::IsNonEnterpriseUser(username);
265#else
266  return false;
267#endif
268}
269
270static jboolean IsNewProfileManagementEnabled(JNIEnv* env, jclass clazz) {
271  return switches::IsNewProfileManagement();
272}
273
274// static
275bool SigninManagerAndroid::Register(JNIEnv* env) {
276  return RegisterNativesImpl(env);
277}
278