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