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