Home | History | Annotate | Download | only in google_apis
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/google_apis/request_sender.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/stl_util.h"
      9 #include "chrome/browser/google_apis/auth_service.h"
     10 #include "chrome/browser/google_apis/base_requests.h"
     11 
     12 namespace google_apis {
     13 
     14 RequestSender::RequestSender(
     15     AuthServiceInterface* auth_service,
     16     net::URLRequestContextGetter* url_request_context_getter,
     17     base::TaskRunner* blocking_task_runner,
     18     const std::string& custom_user_agent)
     19     : auth_service_(auth_service),
     20       url_request_context_getter_(url_request_context_getter),
     21       blocking_task_runner_(blocking_task_runner),
     22       custom_user_agent_(custom_user_agent),
     23       weak_ptr_factory_(this) {
     24   DCHECK(thread_checker_.CalledOnValidThread());
     25 }
     26 
     27 RequestSender::~RequestSender() {
     28   DCHECK(thread_checker_.CalledOnValidThread());
     29   STLDeleteContainerPointers(in_flight_requests_.begin(),
     30                              in_flight_requests_.end());
     31 }
     32 
     33 base::Closure RequestSender::StartRequestWithRetry(
     34     AuthenticatedRequestInterface* request) {
     35   DCHECK(thread_checker_.CalledOnValidThread());
     36 
     37   in_flight_requests_.insert(request);
     38 
     39   // TODO(kinaba): Stop relying on weak pointers. Move lifetime management
     40   // of the requests to request sender.
     41   base::Closure cancel_closure =
     42       base::Bind(&RequestSender::CancelRequest,
     43                  weak_ptr_factory_.GetWeakPtr(),
     44                  request->GetWeakPtr());
     45 
     46   if (!auth_service_->HasAccessToken()) {
     47     // Fetch OAuth2 access token from the refresh token first.
     48     auth_service_->StartAuthentication(
     49         base::Bind(&RequestSender::OnAccessTokenFetched,
     50                    weak_ptr_factory_.GetWeakPtr(),
     51                    request->GetWeakPtr()));
     52   } else {
     53     request->Start(auth_service_->access_token(),
     54                    custom_user_agent_,
     55                    base::Bind(&RequestSender::RetryRequest,
     56                               weak_ptr_factory_.GetWeakPtr()));
     57   }
     58 
     59   return cancel_closure;
     60 }
     61 
     62 void RequestSender::OnAccessTokenFetched(
     63     const base::WeakPtr<AuthenticatedRequestInterface>& request,
     64     GDataErrorCode code,
     65     const std::string& /* access_token */) {
     66   DCHECK(thread_checker_.CalledOnValidThread());
     67 
     68   // Do nothing if the request is canceled during authentication.
     69   if (!request.get())
     70     return;
     71 
     72   if (code == HTTP_SUCCESS) {
     73     DCHECK(auth_service_->HasAccessToken());
     74     StartRequestWithRetry(request.get());
     75   } else {
     76     request->OnAuthFailed(code);
     77   }
     78 }
     79 
     80 void RequestSender::RetryRequest(AuthenticatedRequestInterface* request) {
     81   DCHECK(thread_checker_.CalledOnValidThread());
     82 
     83   auth_service_->ClearAccessToken();
     84   // User authentication might have expired - rerun the request to force
     85   // auth token refresh.
     86   StartRequestWithRetry(request);
     87 }
     88 
     89 void RequestSender::CancelRequest(
     90     const base::WeakPtr<AuthenticatedRequestInterface>& request) {
     91   DCHECK(thread_checker_.CalledOnValidThread());
     92 
     93   // Do nothing if the request is already finished.
     94   if (!request.get())
     95     return;
     96   request->Cancel();
     97 }
     98 
     99 void RequestSender::RequestFinished(AuthenticatedRequestInterface* request) {
    100   in_flight_requests_.erase(request);
    101   delete request;
    102 }
    103 
    104 }  // namespace google_apis
    105