blob: 4eba37509de7c48beb81097c382b6ebf9e6a7bc4 [file] [log] [blame]
// Copyright 2015 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 "services/authenticating_url_loader/authenticating_url_loader_factory_impl.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/services/authenticating_url_loader/public/interfaces/authenticating_url_loader.mojom.h"
#include "services/authenticating_url_loader/authenticating_url_loader_impl.h"
namespace mojo {
AuthenticatingURLLoaderFactoryImpl::AuthenticatingURLLoaderFactoryImpl(
mojo::InterfaceRequest<AuthenticatingURLLoaderFactory> request,
mojo::ApplicationImpl* app,
std::map<GURL, std::string>* cached_tokens)
: binding_(this, request.Pass()), app_(app), cached_tokens_(cached_tokens) {
app_->ConnectToService("mojo:network_service", &network_service_);
}
AuthenticatingURLLoaderFactoryImpl::~AuthenticatingURLLoaderFactoryImpl() {
}
std::string AuthenticatingURLLoaderFactoryImpl::GetCachedToken(
const GURL& url) {
GURL origin = url.GetOrigin();
if (cached_tokens_->find(origin) != cached_tokens_->end()) {
return (*cached_tokens_)[origin];
}
return "";
}
void AuthenticatingURLLoaderFactoryImpl::RetrieveToken(
const GURL& url,
const base::Callback<void(std::string)>& callback) {
if (!authentication_service_) {
callback.Run("");
return;
}
GURL origin = url.GetOrigin();
if (pendings_retrieve_token_.find(origin) == pendings_retrieve_token_.end()) {
if (cached_tokens_->find(origin) != cached_tokens_->end()) {
// Clear the cached token in case the request is due to that token being
// stale.
authentication_service_->ClearOAuth2Token((*cached_tokens_)[origin]);
cached_tokens_->erase(origin);
}
if (cached_accounts_.find(origin) != cached_accounts_.end()) {
OnAccountSelected(origin, cached_accounts_[origin], mojo::String());
return;
}
authentication_service_->SelectAccount(
base::Bind(&AuthenticatingURLLoaderFactoryImpl::OnAccountSelected,
base::Unretained(this), origin));
}
pendings_retrieve_token_[origin].push_back(callback);
}
void AuthenticatingURLLoaderFactoryImpl::OnURLLoaderError(
AuthenticatingURLLoaderImpl* url_loader) {
auto it = std::find_if(
url_loaders_.begin(), url_loaders_.end(),
[url_loader](const std::unique_ptr<AuthenticatingURLLoaderImpl>& p) {
return p.get() == url_loader;
});
DCHECK(it != url_loaders_.end());
url_loaders_.erase(it);
}
void AuthenticatingURLLoaderFactoryImpl::CreateAuthenticatingURLLoader(
mojo::InterfaceRequest<AuthenticatingURLLoader> loader_request) {
url_loaders_.push_back(std::unique_ptr<AuthenticatingURLLoaderImpl>(
new AuthenticatingURLLoaderImpl(loader_request.Pass(), this)));
}
void AuthenticatingURLLoaderFactoryImpl::SetAuthenticationService(
authentication::AuthenticationServicePtr authentication_service) {
// If the authentication service changes, all pending request needs to fail.
for (const auto& callbacks : pendings_retrieve_token_) {
for (const auto& callback : callbacks.second) {
callback.Run("");
}
}
pendings_retrieve_token_.clear();
authentication_service_ = authentication_service.Pass();
if (authentication_service_)
authentication_service_.set_error_handler(this);
}
void AuthenticatingURLLoaderFactoryImpl::OnConnectionError() {
SetAuthenticationService(nullptr);
}
void AuthenticatingURLLoaderFactoryImpl::OnAccountSelected(const GURL& origin,
mojo::String account,
mojo::String error) {
DCHECK(authentication_service_);
if (error) {
LOG(WARNING) << "Error (" << error << ") while selecting account";
ExecuteCallbacks(origin, "");
return;
}
cached_accounts_[origin] = account;
mojo::Array<mojo::String> scopes(1);
scopes[0] = "https://www.googleapis.com/auth/userinfo.email";
authentication_service_->GetOAuth2Token(
account, scopes.Pass(),
base::Bind(&AuthenticatingURLLoaderFactoryImpl::OnOAuth2TokenReceived,
base::Unretained(this), origin));
}
void AuthenticatingURLLoaderFactoryImpl::OnOAuth2TokenReceived(
const GURL& origin,
mojo::String token,
mojo::String error) {
if (error) {
LOG(WARNING) << "Error (" << error << ") while getting token";
ExecuteCallbacks(origin, "");
return;
}
std::string string_token(token);
(*cached_tokens_)[origin] = string_token;
ExecuteCallbacks(origin, string_token);
}
void AuthenticatingURLLoaderFactoryImpl::ExecuteCallbacks(
const GURL& origin,
const std::string& result) {
for (auto& callback : pendings_retrieve_token_[origin]) {
callback.Run(result);
}
pendings_retrieve_token_.erase(origin);
}
} // namespace mojo