// Copyright (c) 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/invalidation/ticl_invalidation_service.h"

#include "base/command_line.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/invalidation/invalidation_service_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/about_signin_internals.h"
#include "chrome/browser/signin/about_signin_internals_factory.h"
#include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager.h"
#include "content/public/browser/notification_service.h"
#include "google_apis/gaia/gaia_constants.h"
#include "sync/notifier/invalidator.h"
#include "sync/notifier/invalidator_state.h"
#include "sync/notifier/non_blocking_invalidator.h"

static const char* kOAuth2Scopes[] = {
  GaiaConstants::kGoogleTalkOAuth2Scope
};

static const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
  // Number of initial errors (in sequence) to ignore before applying
  // exponential back-off rules.
  0,

  // Initial delay for exponential back-off in ms.
  2000,

  // Factor by which the waiting time will be multiplied.
  2,

  // Fuzzing percentage. ex: 10% will spread requests randomly
  // between 90%-100% of the calculated time.
  0.2, // 20%

  // Maximum amount of time we are willing to delay our request in ms.
  // TODO(pavely): crbug.com/246686 ProfileSyncService should retry
  // RequestAccessToken on connection state change after backoff
  1000 * 3600 * 4, // 4 hours.

  // Time to keep an entry from being discarded even when it
  // has no significant state, -1 to never discard.
  -1,

  // Don't use initial delay unless the last request was an error.
  false,
};

namespace invalidation {

TiclInvalidationService::TiclInvalidationService(
    SigninManagerBase* signin,
    ProfileOAuth2TokenService* oauth2_token_service,
    Profile* profile)
    : profile_(profile),
      signin_manager_(signin),
      oauth2_token_service_(oauth2_token_service),
      invalidator_registrar_(new syncer::InvalidatorRegistrar()),
      request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy) {
}

TiclInvalidationService::~TiclInvalidationService() {
  DCHECK(CalledOnValidThread());
}

void TiclInvalidationService::Init() {
  DCHECK(CalledOnValidThread());

  invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs()));
  if (invalidator_storage_->GetInvalidatorClientId().empty()) {
    // This also clears any existing state.  We can't reuse old invalidator
    // state with the new ID anyway.
    invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId());
  }

  if (IsReadyToStart()) {
    StartInvalidator();
  }

  notification_registrar_.Add(this,
                              chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
                              content::Source<Profile>(profile_));
  oauth2_token_service_->AddObserver(this);
}

void TiclInvalidationService::InitForTest(syncer::Invalidator* invalidator) {
  // Here we perform the equivalent of Init() and StartInvalidator(), but with
  // some minor changes to account for the fact that we're injecting the
  // invalidator.
  invalidator_.reset(invalidator);

  invalidator_->RegisterHandler(this);
  invalidator_->UpdateRegisteredIds(
      this,
      invalidator_registrar_->GetAllRegisteredIds());
}

void TiclInvalidationService::RegisterInvalidationHandler(
    syncer::InvalidationHandler* handler) {
  DCHECK(CalledOnValidThread());
  DVLOG(2) << "Registering an invalidation handler";
  invalidator_registrar_->RegisterHandler(handler);
}

void TiclInvalidationService::UpdateRegisteredInvalidationIds(
    syncer::InvalidationHandler* handler,
    const syncer::ObjectIdSet& ids) {
  DCHECK(CalledOnValidThread());
  DVLOG(2) << "Registering ids: " << ids.size();
  invalidator_registrar_->UpdateRegisteredIds(handler, ids);
  if (invalidator_) {
    invalidator_->UpdateRegisteredIds(
        this,
        invalidator_registrar_->GetAllRegisteredIds());
  }
}

void TiclInvalidationService::UnregisterInvalidationHandler(
    syncer::InvalidationHandler* handler) {
  DCHECK(CalledOnValidThread());
  DVLOG(2) << "Unregistering";
  invalidator_registrar_->UnregisterHandler(handler);
  if (invalidator_) {
    invalidator_->UpdateRegisteredIds(
        this,
        invalidator_registrar_->GetAllRegisteredIds());
  }
}

syncer::InvalidatorState TiclInvalidationService::GetInvalidatorState() const {
  DCHECK(CalledOnValidThread());
  if (invalidator_) {
    DVLOG(2) << "GetInvalidatorState returning "
        << invalidator_->GetInvalidatorState();
    return invalidator_->GetInvalidatorState();
  } else {
    DVLOG(2) << "Invalidator currently stopped";
    return syncer::TRANSIENT_INVALIDATION_ERROR;
  }
}

std::string TiclInvalidationService::GetInvalidatorClientId() const {
  DCHECK(CalledOnValidThread());
  return invalidator_storage_->GetInvalidatorClientId();
}

void TiclInvalidationService::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK(CalledOnValidThread());
  DCHECK_EQ(type, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT);
  Logout();
}

void TiclInvalidationService::RequestAccessToken() {
  // Only one active request at a time.
  if (access_token_request_ != NULL)
    return;
  request_access_token_retry_timer_.Stop();
  OAuth2TokenService::ScopeSet oauth2_scopes;
  for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++)
    oauth2_scopes.insert(kOAuth2Scopes[i]);
  // Invalidate previous token, otherwise token service will return the same
  // token again.
  const std::string& account_id = oauth2_token_service_->GetPrimaryAccountId();
  oauth2_token_service_->InvalidateToken(account_id,
                                         oauth2_scopes,
                                         access_token_);
  access_token_.clear();
  access_token_request_ = oauth2_token_service_->StartRequest(account_id,
                                                              oauth2_scopes,
                                                              this);
}

void TiclInvalidationService::OnGetTokenSuccess(
    const OAuth2TokenService::Request* request,
    const std::string& access_token,
    const base::Time& expiration_time) {
  DCHECK_EQ(access_token_request_, request);
  access_token_request_.reset();
  // Reset backoff time after successful response.
  request_access_token_backoff_.Reset();
  access_token_ = access_token;
  if (!IsStarted() && IsReadyToStart()) {
    StartInvalidator();
  } else {
    UpdateInvalidatorCredentials();
  }
}

void TiclInvalidationService::OnGetTokenFailure(
    const OAuth2TokenService::Request* request,
    const GoogleServiceAuthError& error) {
  DCHECK_EQ(access_token_request_, request);
  DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
  access_token_request_.reset();
  switch (error.state()) {
    case GoogleServiceAuthError::CONNECTION_FAILED:
    case GoogleServiceAuthError::SERVICE_UNAVAILABLE: {
      // Transient error. Retry after some time.
      request_access_token_backoff_.InformOfRequest(false);
      request_access_token_retry_timer_.Start(
            FROM_HERE,
            request_access_token_backoff_.GetTimeUntilRelease(),
            base::Bind(&TiclInvalidationService::RequestAccessToken,
                       base::Unretained(this)));
      break;
    }
    case GoogleServiceAuthError::SERVICE_ERROR:
    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: {
      // This is a real auth error.
      // Report time since token was issued for invalid credentials error.
      base::Time auth_token_time =
          AboutSigninInternalsFactory::GetForProfile(profile_)->
              GetTokenTime(GaiaConstants::kGaiaOAuth2LoginRefreshToken);
      if (!auth_token_time.is_null()) {
        base::TimeDelta age = base::Time::Now() - auth_token_time;
        if (age < base::TimeDelta::FromHours(1)) {
          UMA_HISTOGRAM_CUSTOM_TIMES(
              "Sync.AuthInvalidationRejectedTokenAgeShort",
              age,
              base::TimeDelta::FromSeconds(1),
              base::TimeDelta::FromHours(1),
              50);
        }
        UMA_HISTOGRAM_COUNTS("Sync.AuthInvalidationRejectedTokenAgeLong",
                             age.InDays());
      }
      invalidator_registrar_->UpdateInvalidatorState(
          syncer::INVALIDATION_CREDENTIALS_REJECTED);
      break;
    }
    default: {
      // We have no way to notify the user of this.  Do nothing.
    }
  }
}

void TiclInvalidationService::OnRefreshTokenAvailable(
    const std::string& account_id) {
  if (oauth2_token_service_->GetPrimaryAccountId() == account_id) {
    if (!IsStarted() && IsReadyToStart()) {
      StartInvalidator();
    }
  }
}

void TiclInvalidationService::OnRefreshTokenRevoked(
    const std::string& account_id) {
  if (oauth2_token_service_->GetPrimaryAccountId() == account_id) {
    access_token_.clear();
    if (IsStarted()) {
      UpdateInvalidatorCredentials();
    }
  }
}

void TiclInvalidationService::OnInvalidatorStateChange(
    syncer::InvalidatorState state) {
  if (state == syncer::INVALIDATION_CREDENTIALS_REJECTED) {
    // This may be due to normal OAuth access token expiration.  If so, we must
    // fetch a new one using our refresh token.  Resetting the invalidator's
    // access token will not reset the invalidator's exponential backoff, so
    // it's safe to try to update the token every time we receive this signal.
    //
    // We won't be receiving any invalidations while the refresh is in progress,
    // we set our state to TRANSIENT_INVALIDATION_ERROR.  If the credentials
    // really are invalid, the refresh request should fail and
    // OnGetTokenFailure() will put us into a INVALIDATION_CREDENTIALS_REJECTED
    // state.
    invalidator_registrar_->UpdateInvalidatorState(
        syncer::TRANSIENT_INVALIDATION_ERROR);
    RequestAccessToken();
  } else {
    invalidator_registrar_->UpdateInvalidatorState(state);
  }
}

void TiclInvalidationService::OnIncomingInvalidation(
    const syncer::ObjectIdInvalidationMap& invalidation_map) {
  invalidator_registrar_->DispatchInvalidationsToHandlers(invalidation_map);
}

void TiclInvalidationService::Shutdown() {
  DCHECK(CalledOnValidThread());
  oauth2_token_service_->RemoveObserver(this);
  if (IsStarted()) {
    StopInvalidator();
  }
  invalidator_storage_.reset();
  invalidator_registrar_.reset();
}

bool TiclInvalidationService::IsReadyToStart() {
  if (profile_->IsManaged()) {
    DVLOG(2) << "Not starting TiclInvalidationService: User is managed.";
    return false;
  }

  if (signin_manager_->GetAuthenticatedUsername().empty()) {
    DVLOG(2) << "Not starting TiclInvalidationService: User is not signed in.";
    return false;
  }

  if (!oauth2_token_service_) {
    DVLOG(2)
        << "Not starting TiclInvalidationService: "
        << "OAuth2TokenService unavailable.";
    return false;
  }

  if (!oauth2_token_service_->RefreshTokenIsAvailable(
          oauth2_token_service_->GetPrimaryAccountId())) {
    DVLOG(2)
        << "Not starting TiclInvalidationServce: Waiting for refresh token.";
    return false;
  }

  return true;
}

bool TiclInvalidationService::IsStarted() {
  return invalidator_.get() != NULL;
}

void TiclInvalidationService::StartInvalidator() {
  DCHECK(CalledOnValidThread());
  DCHECK(!invalidator_);
  DCHECK(invalidator_storage_);
  DCHECK(!invalidator_storage_->GetInvalidatorClientId().empty());

  if (access_token_.empty()) {
    DVLOG(1)
        << "TiclInvalidationService: "
        << "Deferring start until we have an access token.";
    RequestAccessToken();
    return;
  }

  notifier::NotifierOptions options =
      ParseNotifierOptions(*CommandLine::ForCurrentProcess());
  options.request_context_getter = profile_->GetRequestContext();
  options.auth_mechanism = "X-OAUTH2";
  invalidator_.reset(new syncer::NonBlockingInvalidator(
          options,
          invalidator_storage_->GetInvalidatorClientId(),
          invalidator_storage_->GetSavedInvalidations(),
          invalidator_storage_->GetBootstrapData(),
          syncer::WeakHandle<syncer::InvalidationStateTracker>(
              invalidator_storage_->AsWeakPtr()),
          content::GetUserAgent(GURL())));

  UpdateInvalidatorCredentials();

  invalidator_->RegisterHandler(this);
  invalidator_->UpdateRegisteredIds(
      this,
      invalidator_registrar_->GetAllRegisteredIds());
}

void TiclInvalidationService::UpdateInvalidatorCredentials() {
  std::string email = signin_manager_->GetAuthenticatedUsername();

  DCHECK(!email.empty()) << "Expected user to be signed in.";

  DVLOG(2) << "UpdateCredentials: " << email;
  invalidator_->UpdateCredentials(email, access_token_);
}

void TiclInvalidationService::StopInvalidator() {
  DCHECK(invalidator_);
  invalidator_->UnregisterHandler(this);
  invalidator_.reset();
}

void TiclInvalidationService::Logout() {
  access_token_request_.reset();
  request_access_token_retry_timer_.Stop();

  if (IsStarted()) {
    StopInvalidator();
  }

  // This service always expects to have a valid invalidator storage.
  // So we must not only clear the old one, but also start a new one.
  invalidator_storage_->Clear();
  invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs()));
  invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId());
}

}  // namespace invalidation
