// Copyright (c) 2012 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/extensions/api/push_messaging/push_messaging_api.h"

#include <set>

#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_system_factory.h"
#include "chrome/browser/extensions/token_cache/token_cache_service.h"
#include "chrome/browser/extensions/token_cache/token_cache_service_factory.h"
#include "chrome/browser/invalidation/invalidation_service.h"
#include "chrome/browser/invalidation/invalidation_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/common/extensions/api/push_messaging.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_set.h"
#include "chrome/common/extensions/permissions/api_permission.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "google_apis/gaia/gaia_constants.h"
#include "url/gurl.h"

using content::BrowserThread;

const char kChannelIdSeparator[] = "/";
const char kUserNotSignedIn[] = "The user is not signed in.";
const char kUserAccessTokenFailure[] =
    "Cannot obtain access token for the user.";
const int kObfuscatedGaiaIdTimeoutInDays = 30;

namespace extensions {

namespace glue = api::push_messaging;

PushMessagingEventRouter::PushMessagingEventRouter(Profile* profile)
    : profile_(profile) {
}

PushMessagingEventRouter::~PushMessagingEventRouter() {}

void PushMessagingEventRouter::TriggerMessageForTest(
    const std::string& extension_id,
    int subchannel,
    const std::string& payload) {
  OnMessage(extension_id, subchannel, payload);
}

void PushMessagingEventRouter::OnMessage(const std::string& extension_id,
                                         int subchannel,
                                         const std::string& payload) {
  glue::Message message;
  message.subchannel_id = subchannel;
  message.payload = payload;

  DVLOG(2) << "PushMessagingEventRouter::OnMessage"
           << " payload = '" << payload
           << "' subchannel = '" << subchannel
           << "' extension = '" << extension_id << "'";

  scoped_ptr<base::ListValue> args(glue::OnMessage::Create(message));
  scoped_ptr<extensions::Event> event(new extensions::Event(
      glue::OnMessage::kEventName, args.Pass()));
  event->restrict_to_profile = profile_;
  ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
      extension_id, event.Pass());
}

// GetChannelId class functions

PushMessagingGetChannelIdFunction::PushMessagingGetChannelIdFunction()
    : interactive_(false) {}

PushMessagingGetChannelIdFunction::~PushMessagingGetChannelIdFunction() {}

bool PushMessagingGetChannelIdFunction::RunImpl() {
  // Fetch the function arguments.
  scoped_ptr<glue::GetChannelId::Params> params(
      glue::GetChannelId::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  if (params && params->interactive) {
    interactive_ = *params->interactive;
  }

  // Balanced in ReportResult()
  AddRef();

  if (!IsUserLoggedIn()) {
    if (interactive_) {
      ProfileOAuth2TokenServiceFactory::GetForProfile(profile())
          ->AddObserver(this);
      LoginUIServiceFactory::GetForProfile(profile())->ShowLoginPopup();
      return true;
    } else {
      error_ = kUserNotSignedIn;
      ReportResult(std::string(), error_);
      return false;
    }
  }

  DVLOG(2) << "Logged in profile name: " << profile()->GetProfileName();

  StartAccessTokenFetch();
  return true;
}

void PushMessagingGetChannelIdFunction::StartAccessTokenFetch() {
  std::vector<std::string> scope_vector =
      extensions::ObfuscatedGaiaIdFetcher::GetScopes();
  OAuth2TokenService::ScopeSet scopes(scope_vector.begin(), scope_vector.end());
  ProfileOAuth2TokenService* token_service =
      ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
  fetcher_access_token_request_ = token_service->StartRequest(
      token_service->GetPrimaryAccountId(), scopes, this);
}

void PushMessagingGetChannelIdFunction::OnRefreshTokenAvailable(
    const std::string& account_id) {
  ProfileOAuth2TokenServiceFactory::GetForProfile(profile())
      ->RemoveObserver(this);
  DVLOG(2) << "Newly logged in: " << profile()->GetProfileName();
  StartAccessTokenFetch();
}

void PushMessagingGetChannelIdFunction::OnGetTokenSuccess(
    const OAuth2TokenService::Request* request,
    const std::string& access_token,
    const base::Time& expiration_time) {
  DCHECK_EQ(fetcher_access_token_request_.get(), request);
  fetcher_access_token_request_.reset();

  StartGaiaIdFetch(access_token);
}

void PushMessagingGetChannelIdFunction::OnGetTokenFailure(
    const OAuth2TokenService::Request* request,
    const GoogleServiceAuthError& error) {
  DCHECK_EQ(fetcher_access_token_request_.get(), request);
  fetcher_access_token_request_.reset();

  // TODO(fgorski): We are currently ignoring the error passed in upon failure.
  // It should be revisited when we are working on improving general error
  // handling for the identity related code.
  DVLOG(1) << "Cannot obtain access token for this user "
           << error.error_message() << " " << error.state();
  error_ = kUserAccessTokenFailure;
  ReportResult(std::string(), error_);
}

void PushMessagingGetChannelIdFunction::StartGaiaIdFetch(
    const std::string& access_token) {
  // Start the async fetch of the Gaia Id.
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  net::URLRequestContextGetter* context = profile()->GetRequestContext();
  fetcher_.reset(new ObfuscatedGaiaIdFetcher(context, this, access_token));

  // Get the token cache and see if we have already cached a Gaia Id.
  TokenCacheService* token_cache =
      TokenCacheServiceFactory::GetForProfile(profile());

  // Check the cache, if we already have a Gaia ID, use it instead of
  // fetching the ID over the network.
  const std::string& gaia_id =
      token_cache->RetrieveToken(GaiaConstants::kObfuscatedGaiaId);
  if (!gaia_id.empty()) {
    ReportResult(gaia_id, std::string());
    return;
  }

  fetcher_->Start();
}

// Check if the user is logged in.
bool PushMessagingGetChannelIdFunction::IsUserLoggedIn() const {
  ProfileOAuth2TokenService* token_service =
      ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
  return token_service->RefreshTokenIsAvailable(
      token_service->GetPrimaryAccountId());
}

void PushMessagingGetChannelIdFunction::ReportResult(
    const std::string& gaia_id, const std::string& error_string) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  BuildAndSendResult(gaia_id, error_string);

  // Cache the obfuscated ID locally. It never changes for this user,
  // and if we call the web API too often, we get errors due to rate limiting.
  if (!gaia_id.empty()) {
    base::TimeDelta timeout =
        base::TimeDelta::FromDays(kObfuscatedGaiaIdTimeoutInDays);
    TokenCacheService* token_cache =
        TokenCacheServiceFactory::GetForProfile(profile());
    token_cache->StoreToken(GaiaConstants::kObfuscatedGaiaId, gaia_id,
                            timeout);
  }

  // Balanced in RunImpl.
  Release();
}

void PushMessagingGetChannelIdFunction::BuildAndSendResult(
    const std::string& gaia_id, const std::string& error_message) {
  std::string channel_id;
  if (!gaia_id.empty()) {
    channel_id = gaia_id;
    channel_id += kChannelIdSeparator;
    channel_id += extension_id();
  }

  // TODO(petewil): It may be a good idea to further
  // obfuscate the channel ID to prevent the user's obfuscated Gaia Id
  // from being readily obtained.  Security review will tell us if we need to.

  // Create a ChannelId results object and set the fields.
  glue::ChannelIdResult result;
  result.channel_id = channel_id;
  SetError(error_message);
  results_ = glue::GetChannelId::Results::Create(result);

  bool success = error_message.empty() && !gaia_id.empty();
  SendResponse(success);
}

void PushMessagingGetChannelIdFunction::OnObfuscatedGaiaIdFetchSuccess(
    const std::string& gaia_id) {
  ReportResult(gaia_id, std::string());
}

void PushMessagingGetChannelIdFunction::OnObfuscatedGaiaIdFetchFailure(
      const GoogleServiceAuthError& error) {
  std::string error_text = error.error_message();
  // If the error message is blank, see if we can set it from the state.
  if (error_text.empty() &&
      (0 != error.state())) {
    error_text = base::IntToString(error.state());
  }

  DVLOG(1) << "GetChannelId status: '" << error_text << "'";

  // If we had bad credentials, try the logon again.
  switch (error.state()) {
    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
    case GoogleServiceAuthError::ACCOUNT_DELETED:
    case GoogleServiceAuthError::ACCOUNT_DISABLED: {
      if (interactive_) {
        LoginUIService* login_ui_service =
            LoginUIServiceFactory::GetForProfile(profile());
        // content::NotificationObserver will be called if token is issued.
        login_ui_service->ShowLoginPopup();
      } else {
        ReportResult(std::string(), error_text);
      }
      return;
    }
    default:
      // Return error to caller.
      ReportResult(std::string(), error_text);
      return;
  }
}

PushMessagingAPI::PushMessagingAPI(Profile* profile) : profile_(profile) {
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
                 content::Source<Profile>(profile_->GetOriginalProfile()));
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
                 content::Source<Profile>(profile_->GetOriginalProfile()));
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
                 content::Source<Profile>(profile_->GetOriginalProfile()));
}

PushMessagingAPI::~PushMessagingAPI() {
}

// static
PushMessagingAPI* PushMessagingAPI::Get(Profile* profile) {
  return ProfileKeyedAPIFactory<PushMessagingAPI>::GetForProfile(profile);
}

void PushMessagingAPI::Shutdown() {
  event_router_.reset();
  handler_.reset();
}

static base::LazyInstance<ProfileKeyedAPIFactory<PushMessagingAPI> >
g_factory = LAZY_INSTANCE_INITIALIZER;

// static
ProfileKeyedAPIFactory<PushMessagingAPI>*
PushMessagingAPI::GetFactoryInstance() {
  return &g_factory.Get();
}

void PushMessagingAPI::Observe(int type,
                               const content::NotificationSource& source,
                               const content::NotificationDetails& details) {
  invalidation::InvalidationService* invalidation_service =
      invalidation::InvalidationServiceFactory::GetForProfile(profile_);
  // This may be NULL; for example, for the ChromeOS guest user. In these cases,
  // just return without setting up anything, since it won't work anyway.
  if (!invalidation_service)
    return;

  if (!event_router_)
    event_router_.reset(new PushMessagingEventRouter(profile_));
  if (!handler_) {
    handler_.reset(new PushMessagingInvalidationHandler(
        invalidation_service, event_router_.get()));
  }
  switch (type) {
    case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
      const Extension* extension =
          content::Details<const InstalledExtensionInfo>(details)->extension;
      if (extension->HasAPIPermission(APIPermission::kPushMessaging)) {
        handler_->SuppressInitialInvalidationsForExtension(extension->id());
      }
      break;
    }
    case chrome::NOTIFICATION_EXTENSION_LOADED: {
      const Extension* extension = content::Details<Extension>(details).ptr();
      if (extension->HasAPIPermission(APIPermission::kPushMessaging)) {
        handler_->RegisterExtension(extension->id());
      }
      break;
    }
    case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
      const Extension* extension =
          content::Details<UnloadedExtensionInfo>(details)->extension;
      if (extension->HasAPIPermission(APIPermission::kPushMessaging)) {
        handler_->UnregisterExtension(extension->id());
      }
      break;
    }
    default:
      NOTREACHED();
  }
}

void PushMessagingAPI::SetMapperForTest(
    scoped_ptr<PushMessagingInvalidationMapper> mapper) {
  handler_ = mapper.Pass();
}

template <>
void ProfileKeyedAPIFactory<PushMessagingAPI>::DeclareFactoryDependencies() {
  DependsOn(ExtensionSystemFactory::GetInstance());
  DependsOn(invalidation::InvalidationServiceFactory::GetInstance());
}

}  // namespace extensions
