Commit 950c6e87 authored by treib's avatar treib Committed by Commit bot

PermissionRequestCreatorApiary: Support for multiple simultaneous requests.

BUG=412402

Review URL: https://codereview.chromium.org/592353002

Cr-Commit-Position: refs/heads/master@{#296173}
parent bb311dd3
......@@ -35,6 +35,27 @@ const char kState[] = "PENDING";
static const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
struct PermissionRequestCreatorApiary::Request {
Request(const GURL& url_requested, const base::Closure& callback);
~Request();
GURL url_requested;
base::Closure callback;
scoped_ptr<OAuth2TokenService::Request> access_token_request;
std::string access_token;
bool access_token_expired;
scoped_ptr<net::URLFetcher> url_fetcher;
};
PermissionRequestCreatorApiary::Request::Request(const GURL& url_requested,
const base::Closure& callback)
: url_requested(url_requested),
callback(callback),
access_token_expired(false) {
}
PermissionRequestCreatorApiary::Request::~Request() {}
PermissionRequestCreatorApiary::PermissionRequestCreatorApiary(
OAuth2TokenService* oauth2_token_service,
scoped_ptr<SupervisedUserSigninManagerWrapper> signin_wrapper,
......@@ -42,8 +63,7 @@ PermissionRequestCreatorApiary::PermissionRequestCreatorApiary(
: OAuth2TokenService::Consumer("permissions_creator"),
oauth2_token_service_(oauth2_token_service),
signin_wrapper_(signin_wrapper.Pass()),
context_(context),
access_token_expired_(false) {}
context_(context) {}
PermissionRequestCreatorApiary::~PermissionRequestCreatorApiary() {}
......@@ -64,9 +84,8 @@ PermissionRequestCreatorApiary::CreateWithProfile(Profile* profile) {
void PermissionRequestCreatorApiary::CreatePermissionRequest(
const GURL& url_requested,
const base::Closure& callback) {
url_requested_ = url_requested;
callback_ = callback;
StartFetching();
requests_.push_back(new Request(url_requested, callback));
StartFetching(requests_.back());
}
std::string PermissionRequestCreatorApiary::GetApiScopeToUse() const {
......@@ -79,10 +98,10 @@ std::string PermissionRequestCreatorApiary::GetApiScopeToUse() const {
}
}
void PermissionRequestCreatorApiary::StartFetching() {
void PermissionRequestCreatorApiary::StartFetching(Request* request) {
OAuth2TokenService::ScopeSet scopes;
scopes.insert(GetApiScopeToUse());
access_token_request_ = oauth2_token_service_->StartRequest(
request->access_token_request = oauth2_token_service_->StartRequest(
signin_wrapper_->GetAccountIdToUse(), scopes, this);
}
......@@ -90,63 +109,83 @@ void PermissionRequestCreatorApiary::OnGetTokenSuccess(
const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) {
DCHECK_EQ(access_token_request_.get(), request);
access_token_ = access_token;
RequestIterator it = requests_.begin();
while (it != requests_.end()) {
if (request == (*it)->access_token_request.get())
break;
++it;
}
DCHECK(it != requests_.end());
(*it)->access_token = access_token;
GURL url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kPermissionRequestApiUrl));
const int id = 0;
url_fetcher_.reset(URLFetcher::Create(id, url, URLFetcher::POST, this));
(*it)->url_fetcher.reset(URLFetcher::Create(id, url, URLFetcher::POST, this));
url_fetcher_->SetRequestContext(context_);
url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SAVE_COOKIES);
url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(kNumRetries);
url_fetcher_->AddExtraRequestHeader(
(*it)->url_fetcher->SetRequestContext(context_);
(*it)->url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SAVE_COOKIES);
(*it)->url_fetcher->SetAutomaticallyRetryOnNetworkChanges(kNumRetries);
(*it)->url_fetcher->AddExtraRequestHeader(
base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str()));
base::DictionaryValue dict;
dict.SetStringWithoutPathExpansion("namespace", kNamespace);
dict.SetStringWithoutPathExpansion("objectRef", url_requested_.spec());
dict.SetStringWithoutPathExpansion("objectRef", (*it)->url_requested.spec());
dict.SetStringWithoutPathExpansion("state", kState);
std::string body;
base::JSONWriter::Write(&dict, &body);
url_fetcher_->SetUploadData("application/json", body);
(*it)->url_fetcher->SetUploadData("application/json", body);
url_fetcher_->Start();
(*it)->url_fetcher->Start();
}
void PermissionRequestCreatorApiary::OnGetTokenFailure(
const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) {
DCHECK_EQ(access_token_request_.get(), request);
callback_.Run();
callback_.Reset();
RequestIterator it = requests_.begin();
while (it != requests_.end()) {
if (request == (*it)->access_token_request.get())
break;
++it;
}
DCHECK(it != requests_.end());
(*it)->callback.Run();
requests_.erase(it);
}
void PermissionRequestCreatorApiary::OnURLFetchComplete(
const URLFetcher* source) {
RequestIterator it = requests_.begin();
while (it != requests_.end()) {
if (source == (*it)->url_fetcher.get())
break;
++it;
}
DCHECK(it != requests_.end());
const net::URLRequestStatus& status = source->GetStatus();
if (!status.is_success()) {
DispatchNetworkError(status.error());
DispatchNetworkError(it, status.error());
return;
}
int response_code = source->GetResponseCode();
if (response_code == net::HTTP_UNAUTHORIZED && !access_token_expired_) {
access_token_expired_ = true;
if (response_code == net::HTTP_UNAUTHORIZED && !(*it)->access_token_expired) {
(*it)->access_token_expired = true;
OAuth2TokenService::ScopeSet scopes;
scopes.insert(GetApiScopeToUse());
oauth2_token_service_->InvalidateToken(
signin_wrapper_->GetAccountIdToUse(), scopes, access_token_);
StartFetching();
signin_wrapper_->GetAccountIdToUse(), scopes, (*it)->access_token);
StartFetching(*it);
return;
}
if (response_code != net::HTTP_OK) {
DLOG(WARNING) << "HTTP error " << response_code;
DispatchGoogleServiceAuthError(
GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
it, GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
return;
}
......@@ -155,25 +194,27 @@ void PermissionRequestCreatorApiary::OnURLFetchComplete(
scoped_ptr<base::Value> value(base::JSONReader::Read(response_body));
base::DictionaryValue* dict = NULL;
if (!value || !value->GetAsDictionary(&dict)) {
DispatchNetworkError(net::ERR_INVALID_RESPONSE);
DispatchNetworkError(it, net::ERR_INVALID_RESPONSE);
return;
}
std::string id;
if (!dict->GetString(kIdKey, &id)) {
DispatchNetworkError(net::ERR_INVALID_RESPONSE);
DispatchNetworkError(it, net::ERR_INVALID_RESPONSE);
return;
}
callback_.Run();
callback_.Reset();
(*it)->callback.Run();
requests_.erase(it);
}
void PermissionRequestCreatorApiary::DispatchNetworkError(int error_code) {
void PermissionRequestCreatorApiary::DispatchNetworkError(RequestIterator it,
int error_code) {
DispatchGoogleServiceAuthError(
GoogleServiceAuthError::FromConnectionError(error_code));
it, GoogleServiceAuthError::FromConnectionError(error_code));
}
void PermissionRequestCreatorApiary::DispatchGoogleServiceAuthError(
RequestIterator it,
const GoogleServiceAuthError& error) {
callback_.Run();
callback_.Reset();
(*it)->callback.Run();
requests_.erase(it);
}
......@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "chrome/browser/supervised_user/permission_request_creator.h"
#include "google_apis/gaia/oauth2_token_service.h"
#include "net/url_request/url_fetcher_delegate.h"
......@@ -43,6 +44,9 @@ class PermissionRequestCreatorApiary : public PermissionRequestCreator,
const base::Closure& callback) OVERRIDE;
private:
struct Request;
typedef ScopedVector<Request>::iterator RequestIterator;
// OAuth2TokenService::Consumer implementation:
virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
const std::string& access_token,
......@@ -57,20 +61,17 @@ class PermissionRequestCreatorApiary : public PermissionRequestCreator,
// Requests an access token, which is the first thing we need. This is where
// we restart when the returned access token has expired.
void StartFetching();
void StartFetching(Request* request);
void DispatchNetworkError(int error_code);
void DispatchGoogleServiceAuthError(const GoogleServiceAuthError& error);
void DispatchNetworkError(RequestIterator it, int error_code);
void DispatchGoogleServiceAuthError(RequestIterator it,
const GoogleServiceAuthError& error);
OAuth2TokenService* oauth2_token_service_;
scoped_ptr<SupervisedUserSigninManagerWrapper> signin_wrapper_;
base::Closure callback_;
net::URLRequestContextGetter* context_;
GURL url_requested_;
scoped_ptr<OAuth2TokenService::Request> access_token_request_;
std::string access_token_;
bool access_token_expired_;
scoped_ptr<net::URLFetcher> url_fetcher_;
ScopedVector<Request> requests_;
};
#endif // CHROME_BROWSER_SUPERVISED_USER_PERMISSION_REQUEST_CREATOR_APIARY_H_
......@@ -165,7 +165,6 @@ SupervisedUserService::SupervisedUserService(Profile* profile)
elevated_for_testing_(false),
did_init_(false),
did_shutdown_(false),
waiting_for_permissions_(false),
weak_ptr_factory_(this) {
}
......@@ -546,9 +545,6 @@ void SupervisedUserService::LoadBlacklist(const base::FilePath& path) {
}
bool SupervisedUserService::AccessRequestsEnabled() {
if (waiting_for_permissions_)
return false;
ProfileSyncService* service =
ProfileSyncServiceFactory::GetForProfile(profile_);
GoogleServiceAuthError::State state = service->GetAuthError().state();
......@@ -559,14 +555,12 @@ bool SupervisedUserService::AccessRequestsEnabled() {
}
void SupervisedUserService::OnPermissionRequestIssued() {
waiting_for_permissions_ = false;
// TODO(akuegel): Figure out how to show the result of issuing the permission
// request in the UI. Currently, we assume the permission request was created
// successfully.
}
void SupervisedUserService::AddAccessRequest(const GURL& url) {
waiting_for_permissions_ = true;
permissions_creator_->CreatePermissionRequest(
SupervisedUserURLFilter::Normalize(url),
base::Bind(&SupervisedUserService::OnPermissionRequestIssued,
......
......@@ -5,7 +5,9 @@
#ifndef CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_SERVICE_H_
#define CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_SERVICE_H_
#include <map>
#include <set>
#include <string>
#include <vector>
#include "base/callback.h"
......@@ -324,9 +326,6 @@ class SupervisedUserService : public KeyedService,
// Used to create permission requests.
scoped_ptr<PermissionRequestCreator> permissions_creator_;
// True iff we are waiting for a permission request to be issued.
bool waiting_for_permissions_;
base::WeakPtrFactory<SupervisedUserService> weak_ptr_factory_;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment