Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: services/authenticating_url_loader/authenticating_url_loader_interceptor.cc

Issue 1155283003: Change AuthenticatingURLLoader to be a URLLoaderInterceptor (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Address review Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "services/authenticating_url_loader/authenticating_url_loader_impl.h" 5 #include "services/authenticating_url_loader/authenticating_url_loader_intercept or.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "mojo/services/network/public/interfaces/network_service.mojom.h" 9 #include "mojo/services/network/public/interfaces/network_service.mojom.h"
10 10
11 namespace mojo { 11 namespace mojo {
12 12
13 AuthenticatingURLLoaderImpl::AuthenticatingURLLoaderImpl( 13 AuthenticatingURLLoaderInterceptor::AuthenticatingURLLoaderInterceptor(
14 InterfaceRequest<AuthenticatingURLLoader> request, 14 mojo::InterfaceRequest<URLLoaderInterceptor> request,
15 AuthenticatingURLLoaderFactoryImpl* factory) 15 AuthenticatingURLLoaderInterceptorFactory* factory)
16 : binding_(this, request.Pass()), 16 : binding_(this, request.Pass()),
17 factory_(factory), 17 factory_(factory),
18 request_authorization_state_(REQUEST_INITIAL) { 18 request_authorization_state_(REQUEST_INITIAL) {
19 binding_.set_error_handler(this); 19 binding_.set_error_handler(this);
20 } 20 }
21 21
22 AuthenticatingURLLoaderImpl::~AuthenticatingURLLoaderImpl() { 22 AuthenticatingURLLoaderInterceptor::~AuthenticatingURLLoaderInterceptor() {
23 } 23 }
24 24
25 void AuthenticatingURLLoaderImpl::Start( 25 void AuthenticatingURLLoaderInterceptor::InterceptRequest(
26 URLRequestPtr request, 26 mojo::URLRequestPtr request,
27 const Callback<void(URLResponsePtr)>& callback) { 27 const InterceptRequestCallback& callback) {
28 // TODO(blundell): If we need to handle requests with bodies, we'll need to 28 // TODO(blundell): If we need to handle requests with bodies, we'll need to
29 // do something here. 29 // do something here.
30 if (request->body) { 30 if (request->body) {
31 LOG(ERROR) 31 LOG(ERROR) << "Cannot pass a request to AuthenticatingURLLoaderInterceptor"
32 << "Cannot pass a request to AuthenticatingURLLoader that has a body"; 32 "that has a body";
33 callback.Run(nullptr); 33 callback.Run(nullptr);
34 return; 34 return;
35 } 35 }
36 pending_interception_callback_ = callback;
36 url_ = GURL(request->url); 37 url_ = GURL(request->url);
37 auto_follow_redirects_ = request->auto_follow_redirects; 38 auto_follow_redirects_ = request->auto_follow_redirects;
39 request->auto_follow_redirects = false;
38 bypass_cache_ = request->bypass_cache; 40 bypass_cache_ = request->bypass_cache;
39 headers_ = request->headers.Clone(); 41 headers_ = request->headers.Clone();
40 pending_request_callback_ = callback; 42
41 std::string token = factory_->GetCachedToken(url_); 43 std::string token = factory_->GetCachedToken(url_);
42 if (token != "") { 44 if (token != "") {
43 auto auth_header = HttpHeader::New(); 45 auto auth_header = HttpHeader::New();
44 auth_header->name = "Authorization"; 46 auth_header->name = "Authorization";
45 auth_header->value = "Bearer " + token; 47 auth_header->value = "Bearer " + token;
46 request->headers.push_back(auth_header.Pass()); 48 request->headers.push_back(auth_header.Pass());
47 } 49 }
48 StartNetworkRequest(request.Pass()); 50
51 StartRequest(request.Pass());
49 } 52 }
50 53
51 void AuthenticatingURLLoaderImpl::FollowRedirect( 54 void AuthenticatingURLLoaderInterceptor::InterceptFollowRedirect(
52 const Callback<void(URLResponsePtr)>& callback) { 55 const InterceptResponseCallback& callback) {
53 mojo::String error; 56 mojo::String error;
54 57
55 if (!url_.is_valid() || !url_loader_) { 58 if (!url_.is_valid()) {
56 error = "No redirect to follow"; 59 error = "No redirect to follow";
57 } 60 }
58 61
59 if (auto_follow_redirects_) { 62 if (auto_follow_redirects_) {
60 error = 63 error =
61 "FollowRedirect() should not be " 64 "InterceptFollowRedirect() should not be "
62 "called when auto_follow_redirects has been set"; 65 "called when auto_follow_redirects has been set";
63 } 66 }
64 67
65 if (request_authorization_state_ != REQUEST_INITIAL) { 68 if (request_authorization_state_ != REQUEST_INITIAL) {
66 error = "Not in the right state to follow a redirect"; 69 error = "Not in the right state to follow a redirect";
67 } 70 }
68 71
69 if (!error.is_null()) { 72 if (!error.is_null()) {
70 LOG(ERROR) << "AuthenticatingURLLoader: " << error; 73 LOG(ERROR) << "AuthenticatingURLLoaderInterceptor: " << error;
71 callback.Run(nullptr); 74 callback.Run(nullptr);
72 return; 75 return;
73 } 76 }
74 77
75 pending_request_callback_ = callback; 78 // If there is no cached token, have the URLLoader follow the redirect
76 FollowRedirectInternal(); 79 // itself.
77 } 80 std::string token = factory_->GetCachedToken(url_);
78 81 if (token == "") {
79 void AuthenticatingURLLoaderImpl::StartNetworkRequest(URLRequestPtr request) { 82 callback.Run(nullptr);
80 factory_->network_service()->CreateURLLoader(mojo::GetProxy(&url_loader_));
81 url_loader_->Start(request.Pass(),
82 base::Bind(&AuthenticatingURLLoaderImpl::OnLoadComplete,
83 base::Unretained(this)));
84 }
85
86 void AuthenticatingURLLoaderImpl::OnConnectionError() {
87 factory_->OnURLLoaderError(this);
88 // The factory deleted this object.
89 }
90
91 void AuthenticatingURLLoaderImpl::OnLoadComplete(URLResponsePtr response) {
92 if (response->redirect_url) {
93 url_ = GURL(response->redirect_url);
94 request_authorization_state_ = REQUEST_INITIAL;
95
96 if (auto_follow_redirects_) {
97 FollowRedirectInternal();
98 } else {
99 // NOTE: We do not reset |url_loader_| here as it will be needed if the
100 // client calls |FollowRedirect()|.
101 pending_request_callback_.Run(response.Pass());
102 }
103 return; 83 return;
104 } 84 }
105 85
106 url_loader_.reset(); 86 pending_interception_callback_ = callback;
87 StartRequest(BuildRequest(token));
88 }
107 89
108 if (response->status_code != 401 || 90 void AuthenticatingURLLoaderInterceptor::InterceptResponse(
91 mojo::URLResponsePtr response,
92 const InterceptResponseCallback& callback) {
93 pending_interception_callback_ = callback;
94 pending_response_ = response.Pass();
95
96 if (pending_response_->status_code != 401 ||
109 request_authorization_state_ == REQUEST_USED_FRESH_AUTH_SERVICE_TOKEN) { 97 request_authorization_state_ == REQUEST_USED_FRESH_AUTH_SERVICE_TOKEN) {
110 pending_request_callback_.Run(response.Pass()); 98 if (pending_response_->redirect_url) {
99 url_ = GURL(pending_response_->redirect_url);
100 request_authorization_state_ = REQUEST_INITIAL;
101 if (auto_follow_redirects_) {
102 // If there is no cached token, have the URLLoader follow the
103 // redirect itself.
104 std::string token = factory_->GetCachedToken(url_);
105 if (token == "")
106 pending_interception_callback_.Run(nullptr);
107 else
108 StartRequest(BuildRequest(token));
109 return;
110 }
111 }
112
113 URLLoaderInterceptorResponsePtr interceptor_response =
114 URLLoaderInterceptorResponse::New();
115 interceptor_response->response = pending_response_.Pass();
116 pending_interception_callback_.Run(interceptor_response.Pass());
111 return; 117 return;
112 } 118 }
113 119
114 pending_response_ = response.Pass();
115
116 DCHECK(request_authorization_state_ == REQUEST_INITIAL || 120 DCHECK(request_authorization_state_ == REQUEST_INITIAL ||
117 request_authorization_state_ == 121 request_authorization_state_ ==
118 REQUEST_USED_CURRENT_AUTH_SERVICE_TOKEN); 122 REQUEST_USED_CURRENT_AUTH_SERVICE_TOKEN);
119 if (request_authorization_state_ == REQUEST_INITIAL) { 123 if (request_authorization_state_ == REQUEST_INITIAL) {
120 request_authorization_state_ = REQUEST_USED_CURRENT_AUTH_SERVICE_TOKEN; 124 request_authorization_state_ = REQUEST_USED_CURRENT_AUTH_SERVICE_TOKEN;
121 } else { 125 } else {
122 request_authorization_state_ = REQUEST_USED_FRESH_AUTH_SERVICE_TOKEN; 126 request_authorization_state_ = REQUEST_USED_FRESH_AUTH_SERVICE_TOKEN;
123 } 127 }
124 factory_->RetrieveToken( 128 factory_->RetrieveToken(
125 url_, base::Bind(&AuthenticatingURLLoaderImpl::OnOAuth2TokenReceived, 129 url_,
126 base::Unretained(this))); 130 base::Bind(&AuthenticatingURLLoaderInterceptor::OnOAuth2TokenReceived,
127 return; 131 base::Unretained(this)));
128 } 132 }
129 133
130 void AuthenticatingURLLoaderImpl::FollowRedirectInternal() { 134 void AuthenticatingURLLoaderInterceptor::OnConnectionError() {
131 DCHECK(url_.is_valid()); 135 factory_->OnInterceptorError(this);
132 DCHECK(url_loader_); 136 // The factory deleted this object.
133 DCHECK(request_authorization_state_ == REQUEST_INITIAL);
134
135 url_loader_->FollowRedirect(base::Bind(
136 &AuthenticatingURLLoaderImpl::OnLoadComplete, base::Unretained(this)));
137 } 137 }
138 138
139 void AuthenticatingURLLoaderImpl::OnOAuth2TokenReceived(std::string token) { 139 URLRequestPtr AuthenticatingURLLoaderInterceptor::BuildRequest(
140 if (token.empty()) { 140 std::string token) {
141 LOG(ERROR) << "Error while getting token";
142 pending_request_callback_.Run(pending_response_.Pass());
143 return;
144 }
145
146 auto auth_header = HttpHeader::New();
147 auth_header->name = "Authorization";
148 auth_header->value = "Bearer " + token;
149 Array<HttpHeaderPtr> headers; 141 Array<HttpHeaderPtr> headers;
150 if (headers_) 142 if (headers_)
151 headers = headers_.Clone(); 143 headers = headers_.Clone();
152 headers.push_back(auth_header.Pass()); 144
145 if (token == "")
146 token = factory_->GetCachedToken(url_);
147
148 if (token != "") {
149 auto auth_header = HttpHeader::New();
150 auth_header->name = "Authorization";
151 auth_header->value = "Bearer " + token;
152 headers.push_back(auth_header.Pass());
153 }
153 154
154 URLRequestPtr request(mojo::URLRequest::New()); 155 URLRequestPtr request(mojo::URLRequest::New());
155 request->url = url_.spec(); 156 request->url = url_.spec();
156 request->auto_follow_redirects = false; 157 request->auto_follow_redirects = false;
157 request->bypass_cache = bypass_cache_; 158 request->bypass_cache = bypass_cache_;
158 request->headers = headers.Pass(); 159 request->headers = headers.Pass();
159 160
160 StartNetworkRequest(request.Pass()); 161 return request.Pass();
162 }
163
164 void AuthenticatingURLLoaderInterceptor::StartRequest(
165 mojo::URLRequestPtr request) {
166 URLLoaderInterceptorResponsePtr interceptor_response =
167 URLLoaderInterceptorResponse::New();
168 interceptor_response->request = request.Pass();
169 pending_interception_callback_.Run(interceptor_response.Pass());
170 }
171
172 void AuthenticatingURLLoaderInterceptor::OnOAuth2TokenReceived(
173 std::string token) {
174 URLLoaderInterceptorResponsePtr interceptor_response =
175 URLLoaderInterceptorResponse::New();
176
177 if (token.empty()) {
178 LOG(ERROR) << "Error while getting token";
179 interceptor_response->response = pending_response_.Pass();
180 } else {
181 interceptor_response->request = BuildRequest(token);
182 }
183
184 pending_interception_callback_.Run(interceptor_response.Pass());
161 } 185 }
162 186
163 } // namespace mojo 187 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698