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