// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/signin/oauth2_token_service_delegate_android.h"

#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "chrome/browser/profiles/profile_android.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/sync/profile_sync_service_android.h"
#include "components/signin/core/browser/account_info.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/oauth2_access_token_fetcher.h"
#include "jni/OAuth2TokenService_jni.h"

using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaParamRef;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
using content::BrowserThread;

namespace {

// Callback from FetchOAuth2TokenWithUsername().
// Arguments:
// - the error, or NONE if the token fetch was successful.
// - the OAuth2 access token.
// - the expiry time of the token (may be null, indicating that the expiry
//   time is unknown.
typedef base::Callback<void(const GoogleServiceAuthError&,
                            const std::string&,
                            const base::Time&)> FetchOAuth2TokenCallback;

class AndroidAccessTokenFetcher : public OAuth2AccessTokenFetcher {
 public:
  AndroidAccessTokenFetcher(OAuth2AccessTokenConsumer* consumer,
                            const std::string& account_id);
  ~AndroidAccessTokenFetcher() override;

  // Overrides from OAuth2AccessTokenFetcher:
  void Start(const std::string& client_id,
             const std::string& client_secret,
             const std::vector<std::string>& scopes) override;
  void CancelRequest() override;

  // Handles an access token response.
  void OnAccessTokenResponse(const GoogleServiceAuthError& error,
                             const std::string& access_token,
                             const base::Time& expiration_time);

 private:
  std::string CombineScopes(const std::vector<std::string>& scopes);

  std::string account_id_;
  bool request_was_cancelled_;
  base::WeakPtrFactory<AndroidAccessTokenFetcher> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(AndroidAccessTokenFetcher);
};

AndroidAccessTokenFetcher::AndroidAccessTokenFetcher(
    OAuth2AccessTokenConsumer* consumer,
    const std::string& account_id)
    : OAuth2AccessTokenFetcher(consumer),
      account_id_(account_id),
      request_was_cancelled_(false),
      weak_factory_(this) {
}

AndroidAccessTokenFetcher::~AndroidAccessTokenFetcher() {
}

void AndroidAccessTokenFetcher::Start(const std::string& client_id,
                                      const std::string& client_secret,
                                      const std::vector<std::string>& scopes) {
  JNIEnv* env = AttachCurrentThread();
  std::string scope = CombineScopes(scopes);
  ScopedJavaLocalRef<jstring> j_username =
      ConvertUTF8ToJavaString(env, account_id_);
  ScopedJavaLocalRef<jstring> j_scope = ConvertUTF8ToJavaString(env, scope);
  std::unique_ptr<FetchOAuth2TokenCallback> heap_callback(
      new FetchOAuth2TokenCallback(
          base::Bind(&AndroidAccessTokenFetcher::OnAccessTokenResponse,
                     weak_factory_.GetWeakPtr())));

  // Call into Java to get a new token.
  Java_OAuth2TokenService_getOAuth2AuthToken(
      env, j_username, j_scope,
      reinterpret_cast<intptr_t>(heap_callback.release()));
}

void AndroidAccessTokenFetcher::CancelRequest() {
  request_was_cancelled_ = true;
}

void AndroidAccessTokenFetcher::OnAccessTokenResponse(
    const GoogleServiceAuthError& error,
    const std::string& access_token,
    const base::Time& expiration_time) {
  if (request_was_cancelled_) {
    // Ignore the callback if the request was cancelled.
    return;
  }
  if (error.state() == GoogleServiceAuthError::NONE) {
    FireOnGetTokenSuccess(access_token, expiration_time);
  } else {
    FireOnGetTokenFailure(error);
  }
}

// static
std::string AndroidAccessTokenFetcher::CombineScopes(
    const std::vector<std::string>& scopes) {
  // The Android AccountManager supports multiple scopes separated by a space:
  // https://code.google.com/p/google-api-java-client/wiki/OAuth2#Android
  std::string scope;
  for (std::vector<std::string>::const_iterator it = scopes.begin();
       it != scopes.end(); ++it) {
    if (!scope.empty())
      scope += " ";
    scope += *it;
  }
  return scope;
}

}  // namespace

bool OAuth2TokenServiceDelegateAndroid::is_testing_profile_ = false;

OAuth2TokenServiceDelegateAndroid::OAuth2TokenServiceDelegateAndroid(
    AccountTrackerService* account_tracker_service)
    : account_tracker_service_(account_tracker_service),
      fire_refresh_token_loaded_(RT_LOAD_NOT_START) {
  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ctor";
  DCHECK(account_tracker_service_);
  JNIEnv* env = AttachCurrentThread();
  base::android::ScopedJavaLocalRef<jobject> local_java_ref =
      Java_OAuth2TokenService_create(env, reinterpret_cast<intptr_t>(this));
  java_ref_.Reset(env, local_java_ref.obj());

  if (account_tracker_service_->GetMigrationState() ==
      AccountTrackerService::MIGRATION_IN_PROGRESS) {
    std::vector<std::string> accounts = GetAccounts();
    std::vector<std::string> accounts_id;
    for (auto account_name : accounts) {
      AccountInfo account_info =
          account_tracker_service_->FindAccountInfoByEmail(account_name);
      DCHECK(!account_info.gaia.empty());
      accounts_id.push_back(account_info.gaia);
    }
    ScopedJavaLocalRef<jobjectArray> java_accounts(
        base::android::ToJavaArrayOfStrings(env, accounts_id));
    Java_OAuth2TokenService_saveStoredAccounts(env, java_accounts);
  }

  if (!is_testing_profile_) {
    Java_OAuth2TokenService_validateAccounts(AttachCurrentThread(), java_ref_,
                                             JNI_TRUE);
  }
}

OAuth2TokenServiceDelegateAndroid::~OAuth2TokenServiceDelegateAndroid() {
}

// static
ScopedJavaLocalRef<jobject> OAuth2TokenServiceDelegateAndroid::GetForProfile(
    JNIEnv* env,
    const JavaRef<jobject>& j_profile_android) {
  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
  ProfileOAuth2TokenService* service =
      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
  OAuth2TokenServiceDelegate* delegate = service->GetDelegate();
  return ScopedJavaLocalRef<jobject>(
      static_cast<OAuth2TokenServiceDelegateAndroid*>(delegate)->java_ref_);
}

static ScopedJavaLocalRef<jobject> JNI_OAuth2TokenService_GetForProfile(
    JNIEnv* env,
    const JavaParamRef<jclass>& clazz,
    const JavaParamRef<jobject>& j_profile_android) {
  return OAuth2TokenServiceDelegateAndroid::GetForProfile(env,
                                                          j_profile_android);
}

bool OAuth2TokenServiceDelegateAndroid::RefreshTokenIsAvailable(
    const std::string& account_id) const {
  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::RefreshTokenIsAvailable"
           << " account= " << account_id;
  std::string account_name = MapAccountIdToAccountName(account_id);
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jstring> j_account_id =
      ConvertUTF8ToJavaString(env, account_name);
  jboolean refresh_token_is_available =
      Java_OAuth2TokenService_hasOAuth2RefreshToken(env, j_account_id);
  return refresh_token_is_available == JNI_TRUE;
}

GoogleServiceAuthError OAuth2TokenServiceDelegateAndroid::GetAuthError(
    const std::string& account_id) const {
  auto it = errors_.find(account_id);
  return (it == errors_.end()) ? GoogleServiceAuthError::AuthErrorNone()
                               : it->second;
}

void OAuth2TokenServiceDelegateAndroid::UpdateAuthError(
    const std::string& account_id,
    const GoogleServiceAuthError& error) {
  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAuthError"
           << " account=" << account_id
           << " error=" << error.ToString();

  if (error.IsTransientError())
    return;

  auto it = errors_.find(account_id);
  if (error.state() == GoogleServiceAuthError::NONE) {
    if (it == errors_.end())
      return;
    errors_.erase(it);
  } else {
    if (it != errors_.end() && it->second == error)
      return;
    errors_[account_id] = error;
  }
  FireAuthErrorChanged(account_id, error);
}

std::vector<std::string> OAuth2TokenServiceDelegateAndroid::GetAccounts() {
  std::vector<std::string> accounts;
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobjectArray> j_accounts =
      Java_OAuth2TokenService_getAccounts(env);
  // TODO(fgorski): We may decide to filter out some of the accounts.
  base::android::AppendJavaStringArrayToStringVector(env, j_accounts.obj(),
                                                     &accounts);
  return accounts;
}

std::vector<std::string>
OAuth2TokenServiceDelegateAndroid::GetSystemAccountNames() {
  std::vector<std::string> account_names;
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobjectArray> j_accounts =
      Java_OAuth2TokenService_getSystemAccountNames(env);
  base::android::AppendJavaStringArrayToStringVector(env, j_accounts.obj(),
                                                     &account_names);
  return account_names;
}

OAuth2AccessTokenFetcher*
OAuth2TokenServiceDelegateAndroid::CreateAccessTokenFetcher(
    const std::string& account_id,
    net::URLRequestContextGetter* getter,
    OAuth2AccessTokenConsumer* consumer) {
  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::CreateAccessTokenFetcher"
           << " account= " << account_id;
  ValidateAccountId(account_id);
  return new AndroidAccessTokenFetcher(consumer,
                                       MapAccountIdToAccountName(account_id));
}

void OAuth2TokenServiceDelegateAndroid::InvalidateAccessToken(
    const std::string& account_id,
    const std::string& client_id,
    const OAuth2TokenService::ScopeSet& scopes,
    const std::string& access_token) {
  ValidateAccountId(account_id);
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jstring> j_access_token =
      ConvertUTF8ToJavaString(env, access_token);
  Java_OAuth2TokenService_invalidateOAuth2AuthToken(env, j_access_token);
}

void OAuth2TokenServiceDelegateAndroid::ValidateAccounts(
    JNIEnv* env,
    const JavaParamRef<jobject>& obj,
    const JavaParamRef<jstring>& j_current_acc,
    jboolean j_force_notifications) {
  std::string signed_in_account_name;
  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts from java";
  if (j_current_acc)
    signed_in_account_name = ConvertJavaStringToUTF8(env, j_current_acc);
  if (!signed_in_account_name.empty())
    signed_in_account_name = gaia::CanonicalizeEmail(signed_in_account_name);

  // Clear any auth errors so that client can retry to get access tokens.
  errors_.clear();

  ValidateAccounts(MapAccountNameToAccountId(signed_in_account_name),
                   j_force_notifications != JNI_FALSE);
}

void OAuth2TokenServiceDelegateAndroid::ValidateAccounts(
    const std::string& signed_in_account_id,
    bool force_notifications) {
  std::vector<std::string> curr_ids;
  for (const std::string& curr_name : GetSystemAccountNames()) {
    std::string curr_id(MapAccountNameToAccountId(curr_name));
    if (!curr_id.empty())
      curr_ids.push_back(curr_id);
  }

  std::vector<std::string> prev_ids;
  for (const std::string& prev_id : GetAccounts()) {
    if (ValidateAccountId(prev_id))
      prev_ids.push_back(prev_id);
  }

  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
           << " sigined_in_account_id=" << signed_in_account_id
           << " prev_ids=" << prev_ids.size() << " curr_ids=" << curr_ids.size()
           << " force=" << (force_notifications ? "true" : "false");

  std::vector<std::string> refreshed_ids;
  std::vector<std::string> revoked_ids;
  bool currently_signed_in =
      ValidateAccounts(signed_in_account_id, prev_ids, curr_ids, &refreshed_ids,
                       &revoked_ids, force_notifications);

  ScopedBatchChange batch(this);
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobjectArray> java_accounts;
  if (currently_signed_in) {
    java_accounts = base::android::ToJavaArrayOfStrings(env, curr_ids);
  } else {
    java_accounts =
        base::android::ToJavaArrayOfStrings(env, std::vector<std::string>());
  }

  // Save the current accounts in the token service before calling
  // FireRefreshToken* methods.
  Java_OAuth2TokenService_saveStoredAccounts(env, java_accounts);

  for (const std::string& refreshed_id : refreshed_ids)
    FireRefreshTokenAvailable(refreshed_id);
  for (const std::string& revoked_id : revoked_ids)
    FireRefreshTokenRevoked(revoked_id);
  if (fire_refresh_token_loaded_ == RT_WAIT_FOR_VALIDATION) {
    fire_refresh_token_loaded_ = RT_LOADED;
    FireRefreshTokensLoaded();
  } else if (fire_refresh_token_loaded_ == RT_LOAD_NOT_START) {
    fire_refresh_token_loaded_ = RT_HAS_BEEN_VALIDATED;
  }

  // Clear accounts no longer exist on device from AccountTrackerService.
  std::vector<AccountInfo> accounts_info =
      account_tracker_service_->GetAccounts();
  for (const AccountInfo& info : accounts_info) {
    if (!base::ContainsValue(curr_ids, info.account_id))
      account_tracker_service_->RemoveAccount(info.account_id);
  }

  // No need to wait for SigninManager to finish migration if not signed in.
  if (account_tracker_service_->GetMigrationState() ==
          AccountTrackerService::MIGRATION_IN_PROGRESS &&
      signed_in_account_id.empty()) {
    account_tracker_service_->SetMigrationDone();
  }
}

bool OAuth2TokenServiceDelegateAndroid::ValidateAccounts(
    const std::string& signed_in_id,
    const std::vector<std::string>& prev_ids,
    const std::vector<std::string>& curr_ids,
    std::vector<std::string>* refreshed_ids,
    std::vector<std::string>* revoked_ids,
    bool force_notifications) {
  bool currently_signed_in = base::ContainsValue(curr_ids, signed_in_id);
  if (currently_signed_in) {
    // Revoke token for ids that have been removed from the device.
    for (const std::string& prev_id : prev_ids) {
      if (prev_id == signed_in_id)
        continue;
      if (!base::ContainsValue(curr_ids, prev_id)) {
        DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
                 << "revoked=" << prev_id;
        revoked_ids->push_back(prev_id);
      }
    }

    // Refresh token for new ids or all ids if |force_notifications|.
    if (force_notifications || !base::ContainsValue(prev_ids, signed_in_id)) {
      // Always fire the primary signed in account first.
      DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
               << "refreshed=" << signed_in_id;
      refreshed_ids->push_back(signed_in_id);
    }
    for (const std::string& curr_id : curr_ids) {
      if (curr_id == signed_in_id)
        continue;
      if (force_notifications || !base::ContainsValue(prev_ids, curr_id)) {
        DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
                 << "refreshed=" << curr_id;
        refreshed_ids->push_back(curr_id);
      }
    }
  } else {
    if (base::ContainsValue(prev_ids, signed_in_id)) {
      DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
               << "revoked=" << signed_in_id;
      revoked_ids->push_back(signed_in_id);
    }
    for (const std::string& prev_id : prev_ids) {
      if (prev_id == signed_in_id)
        continue;
      DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
               << "revoked=" << prev_id;
      revoked_ids->push_back(prev_id);
    }
  }
  return currently_signed_in;
}

void OAuth2TokenServiceDelegateAndroid::FireRefreshTokenAvailableFromJava(
    JNIEnv* env,
    const JavaParamRef<jobject>& obj,
    const JavaParamRef<jstring>& account_name) {
  std::string account_id =
      MapAccountNameToAccountId(ConvertJavaStringToUTF8(env, account_name));
  // Notify native observers.
  FireRefreshTokenAvailable(account_id);
}

void OAuth2TokenServiceDelegateAndroid::FireRefreshTokenAvailable(
    const std::string& account_id) {
  DCHECK(!account_id.empty());
  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::FireRefreshTokenAvailable id="
           << account_id;
  std::string account_name = MapAccountIdToAccountName(account_id);
  DCHECK(!account_name.empty());
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jstring> j_account_name =
      ConvertUTF8ToJavaString(env, account_name);
  Java_OAuth2TokenService_notifyRefreshTokenAvailable(env, java_ref_,
                                                      j_account_name);
  OAuth2TokenServiceDelegate::FireRefreshTokenAvailable(account_id);
}

void OAuth2TokenServiceDelegateAndroid::FireRefreshTokenRevokedFromJava(
    JNIEnv* env,
    const JavaParamRef<jobject>& obj,
    const JavaParamRef<jstring>& account_name) {
  std::string account_id =
      MapAccountNameToAccountId(ConvertJavaStringToUTF8(env, account_name));
  // Notify native observers.
  FireRefreshTokenRevoked(account_id);
}

void OAuth2TokenServiceDelegateAndroid::FireRefreshTokenRevoked(
    const std::string& account_id) {
  DCHECK(!account_id.empty());
  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::FireRefreshTokenRevoked id="
           << account_id;
  std::string account_name = MapAccountIdToAccountName(account_id);
  if (!account_name.empty()) {
    JNIEnv* env = AttachCurrentThread();
    ScopedJavaLocalRef<jstring> j_account_name =
        ConvertUTF8ToJavaString(env, account_name);
    Java_OAuth2TokenService_notifyRefreshTokenRevoked(env, java_ref_,
                                                      j_account_name);
  } else {
    // Current prognosis is that we have an unmigrated account which is due for
    // deletion. Record a histogram to debug this.
    UMA_HISTOGRAM_ENUMERATION("OAuth2Login.AccountRevoked.MigrationState",
                              account_tracker_service_->GetMigrationState(),
                              AccountTrackerService::NUM_MIGRATION_STATES);
    bool is_email_id = account_id.find('@') != std::string::npos;
    UMA_HISTOGRAM_BOOLEAN("OAuth2Login.AccountRevoked.IsEmailId", is_email_id);
  }
  OAuth2TokenServiceDelegate::FireRefreshTokenRevoked(account_id);
}

void OAuth2TokenServiceDelegateAndroid::FireRefreshTokensLoadedFromJava(
    JNIEnv* env,
    const JavaParamRef<jobject>& obj) {
  // Notify native observers.
  FireRefreshTokensLoaded();
}

void OAuth2TokenServiceDelegateAndroid::FireRefreshTokensLoaded() {
  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::FireRefreshTokensLoaded";
  JNIEnv* env = AttachCurrentThread();
  Java_OAuth2TokenService_notifyRefreshTokensLoaded(env, java_ref_);
  OAuth2TokenServiceDelegate::FireRefreshTokensLoaded();
}

void OAuth2TokenServiceDelegateAndroid::RevokeAllCredentials() {
  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::RevokeAllCredentials";
  ScopedBatchChange batch(this);
  std::vector<std::string> accounts_to_revoke = GetAccounts();

  // Clear accounts in the token service before calling
  // |FireRefreshTokenRevoked|.
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobjectArray> java_accounts(
      base::android::ToJavaArrayOfStrings(env, std::vector<std::string>()));
  Java_OAuth2TokenService_saveStoredAccounts(env, java_accounts);

  for (const std::string& account : accounts_to_revoke)
    FireRefreshTokenRevoked(account);
}

void OAuth2TokenServiceDelegateAndroid::LoadCredentials(
    const std::string& primary_account_id) {
  if (primary_account_id.empty()) {
    FireRefreshTokensLoaded();
    return;
  }
  if (fire_refresh_token_loaded_ == RT_HAS_BEEN_VALIDATED) {
    fire_refresh_token_loaded_ = RT_LOADED;
    FireRefreshTokensLoaded();
  } else if (fire_refresh_token_loaded_ == RT_LOAD_NOT_START) {
    fire_refresh_token_loaded_ = RT_WAIT_FOR_VALIDATION;
  }
}

std::string OAuth2TokenServiceDelegateAndroid::MapAccountIdToAccountName(
    const std::string& account_id) const {
  std::string account_name =
      account_tracker_service_->GetAccountInfo(account_id).email;
  DCHECK(!account_name.empty() || account_id.empty())
      << "Can't find account name, account_id=" << account_id;
  return account_name;
}

std::string OAuth2TokenServiceDelegateAndroid::MapAccountNameToAccountId(
    const std::string& account_name) const {
  std::string account_id =
      account_tracker_service_->FindAccountInfoByEmail(account_name).account_id;
  DCHECK(!account_id.empty() || account_name.empty())
      << "Can't find account id, account_name=" << account_name;
  return account_id;
}

// Called from Java when fetching of an OAuth2 token is finished. The
// |authToken| param is only valid when |result| is true.
void JNI_OAuth2TokenService_OAuth2TokenFetched(
    JNIEnv* env,
    const JavaParamRef<jclass>& clazz,
    const JavaParamRef<jstring>& authToken,
    jboolean isTransientError,
    jlong nativeCallback) {
  std::string token;
  if (authToken)
    token = ConvertJavaStringToUTF8(env, authToken);
  std::unique_ptr<FetchOAuth2TokenCallback> heap_callback(
      reinterpret_cast<FetchOAuth2TokenCallback*>(nativeCallback));
  GoogleServiceAuthError err = GoogleServiceAuthError::AuthErrorNone();
  if (!authToken) {
    err =
        isTransientError
            ? GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED)
            : GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
                  GoogleServiceAuthError::InvalidGaiaCredentialsReason::
                      CREDENTIALS_REJECTED_BY_SERVER);
  }
  heap_callback->Run(err, token, base::Time());
}
