// 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 "google_apis/common/request_sender.h" #include #include "base/bind.h" #include "base/task/sequenced_task_runner.h" #include "google_apis/common/auth_service.h" #include "google_apis/common/base_requests.h" namespace google_apis { RequestSender::RequestSender( std::unique_ptr auth_service, scoped_refptr url_loader_factory, const scoped_refptr& blocking_task_runner, const std::string& custom_user_agent, const net::NetworkTrafficAnnotationTag& traffic_annotation) : auth_service_(std::move(auth_service)), url_loader_factory_(url_loader_factory), blocking_task_runner_(blocking_task_runner), custom_user_agent_(custom_user_agent), traffic_annotation_(traffic_annotation) {} RequestSender::~RequestSender() { DCHECK(thread_checker_.CalledOnValidThread()); } base::RepeatingClosure RequestSender::StartRequestWithAuthRetry( std::unique_ptr request) { DCHECK(thread_checker_.CalledOnValidThread()); AuthenticatedRequestInterface* request_ptr = request.get(); in_flight_requests_.insert(std::move(request)); return StartRequestWithAuthRetryInternal(request_ptr); } base::RepeatingClosure RequestSender::StartRequestWithAuthRetryInternal( AuthenticatedRequestInterface* request) { // TODO(kinaba): Stop relying on weak pointers. Move lifetime management // of the requests to request sender. base::RepeatingClosure cancel_closure = base::BindRepeating( &RequestSender::CancelRequest, weak_ptr_factory_.GetWeakPtr(), request->GetWeakPtr()); if (!auth_service_->HasAccessToken()) { // Fetch OAuth2 access token from the refresh token first. auth_service_->StartAuthentication( base::BindOnce(&RequestSender::OnAccessTokenFetched, weak_ptr_factory_.GetWeakPtr(), request->GetWeakPtr())); } else { request->Start(auth_service_->access_token(), custom_user_agent_, base::BindRepeating(&RequestSender::RetryRequest, weak_ptr_factory_.GetWeakPtr())); } return cancel_closure; } void RequestSender::OnAccessTokenFetched( const base::WeakPtr& request, ApiErrorCode code, const std::string& /* access_token */) { DCHECK(thread_checker_.CalledOnValidThread()); // Do nothing if the request is canceled during authentication. if (!request.get()) return; if (code == HTTP_SUCCESS) { DCHECK(auth_service_->HasAccessToken()); StartRequestWithAuthRetryInternal(request.get()); } else { request->OnAuthFailed(code); } } void RequestSender::RetryRequest(AuthenticatedRequestInterface* request) { DCHECK(thread_checker_.CalledOnValidThread()); auth_service_->ClearAccessToken(); // User authentication might have expired - rerun the request to force // auth token refresh. StartRequestWithAuthRetryInternal(request); } void RequestSender::CancelRequest( const base::WeakPtr& request) { DCHECK(thread_checker_.CalledOnValidThread()); // Do nothing if the request is already finished. if (!request.get()) return; request->Cancel(); } void RequestSender::RequestFinished(AuthenticatedRequestInterface* request) { auto it = in_flight_requests_.find(request); if (it == in_flight_requests_.end()) { // Various BatchUpload tests in DriveApiRequestsTest will commit requests // using this RequestSender without actually starting them on it. In that // case, there's nothing to be done, so just return. return; } in_flight_requests_.erase(it); } } // namespace google_apis