OLD | NEW |
---|---|
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_impl.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 |
(...skipping 24 matching lines...) Expand all Loading... | |
35 if (request->body) { | 35 if (request->body) { |
36 LOG(ERROR) | 36 LOG(ERROR) |
37 << "Cannot pass a request to AuthenticatingURLLoader that has a body"; | 37 << "Cannot pass a request to AuthenticatingURLLoader that has a body"; |
38 callback.Run(nullptr); | 38 callback.Run(nullptr); |
39 return; | 39 return; |
40 } | 40 } |
41 url_ = request->url; | 41 url_ = request->url; |
42 auto_follow_redirects_ = request->auto_follow_redirects; | 42 auto_follow_redirects_ = request->auto_follow_redirects; |
43 bypass_cache_ = request->bypass_cache; | 43 bypass_cache_ = request->bypass_cache; |
44 headers_ = request->headers.Clone(); | 44 headers_ = request->headers.Clone(); |
45 pending_start_callback_ = callback; | 45 pending_request_callback_ = callback; |
46 StartNetworkRequest(request.Pass()); | 46 StartNetworkRequest(request.Pass()); |
47 } | 47 } |
48 | 48 |
49 void AuthenticatingURLLoaderImpl::FollowRedirect( | |
50 const Callback<void(URLResponsePtr)>& callback) { | |
51 DCHECK(!auto_follow_redirects_); | |
qsr
2015/05/27 14:29:36
You should not dcheck on a wrong usage of your API
blundell
2015/06/03 10:55:11
Done.
| |
52 pending_request_callback_ = callback; | |
53 FollowRedirectInternal(); | |
54 } | |
55 | |
49 void AuthenticatingURLLoaderImpl::StartNetworkRequest(URLRequestPtr request) { | 56 void AuthenticatingURLLoaderImpl::StartNetworkRequest(URLRequestPtr request) { |
50 network_service_->CreateURLLoader(mojo::GetProxy(&url_loader_)); | 57 network_service_->CreateURLLoader(mojo::GetProxy(&url_loader_)); |
51 url_loader_->Start(request.Pass(), | 58 url_loader_->Start(request.Pass(), |
52 base::Bind(&AuthenticatingURLLoaderImpl::OnLoadComplete, | 59 base::Bind(&AuthenticatingURLLoaderImpl::OnLoadComplete, |
53 base::Unretained(this))); | 60 base::Unretained(this))); |
54 } | 61 } |
55 | 62 |
56 void AuthenticatingURLLoaderImpl::OnConnectionError() { | 63 void AuthenticatingURLLoaderImpl::OnConnectionError() { |
57 connection_error_callback_.Run(this); | 64 connection_error_callback_.Run(this); |
58 // The callback deleted this object. | 65 // The callback deleted this object. |
59 } | 66 } |
60 | 67 |
61 void AuthenticatingURLLoaderImpl::OnLoadComplete(URLResponsePtr response) { | 68 void AuthenticatingURLLoaderImpl::OnLoadComplete(URLResponsePtr response) { |
62 url_loader_.reset(); | 69 if (response->redirect_url) { |
63 if (response->status_code != 401 || !authentication_service_ || | 70 url_ = response->redirect_url; |
64 request_authorization_state_ == REQUEST_AUTHORIZED_WITH_FRESH_TOKEN) { | 71 username_ = nullptr; |
65 pending_start_callback_.Run(response.Pass()); | 72 request_authorization_state_ = REQUEST_NOT_AUTHORIZED; |
73 | |
74 if (auto_follow_redirects_) { | |
75 FollowRedirectInternal(); | |
76 } else { | |
77 // NOTE: We do not reset |url_loader_| here as it will be needed if the | |
78 // client calls |FollowRedirect()|. | |
79 pending_request_callback_.Run(response.Pass()); | |
80 } | |
66 return; | 81 return; |
67 } | 82 } |
68 | 83 |
84 url_loader_.reset(); | |
85 | |
86 if (response->status_code != 401 || !authentication_service_ || | |
87 request_authorization_state_ == REQUEST_AUTHORIZED_WITH_FRESH_TOKEN) { | |
88 pending_request_callback_.Run(response.Pass()); | |
89 return; | |
90 } | |
91 | |
69 pending_response_ = response.Pass(); | 92 pending_response_ = response.Pass(); |
70 | 93 |
71 if (request_authorization_state_ == REQUEST_NOT_AUTHORIZED) { | 94 if (request_authorization_state_ == REQUEST_NOT_AUTHORIZED) { |
72 DCHECK(!username_); | 95 DCHECK(!username_); |
73 request_authorization_state_ = REQUEST_AUTHORIZED_WITH_CACHED_TOKEN; | 96 request_authorization_state_ = REQUEST_AUTHORIZED_WITH_CACHED_TOKEN; |
74 authentication_service_->SelectAccount( | 97 authentication_service_->SelectAccount( |
75 base::Bind(&AuthenticatingURLLoaderImpl::OnAccountSelected, | 98 base::Bind(&AuthenticatingURLLoaderImpl::OnAccountSelected, |
76 base::Unretained(this))); | 99 base::Unretained(this))); |
77 return; | 100 return; |
78 } | 101 } |
79 | 102 |
80 DCHECK(request_authorization_state_ == REQUEST_AUTHORIZED_WITH_CACHED_TOKEN); | 103 DCHECK(request_authorization_state_ == REQUEST_AUTHORIZED_WITH_CACHED_TOKEN); |
81 // Clear the cached token in case the failure was due to that token being | 104 // Clear the cached token in case the failure was due to that token being |
82 // stale and try again. If a fresh token doesn't work, we'll have to give up. | 105 // stale and try again. If a fresh token doesn't work, we'll have to give up. |
83 DCHECK(authentication_service_); | 106 DCHECK(authentication_service_); |
84 DCHECK(username_); | 107 DCHECK(username_); |
85 authentication_service_->ClearOAuth2Token(token_); | 108 authentication_service_->ClearOAuth2Token(token_); |
86 token_ = String(); | 109 token_ = String(); |
87 request_authorization_state_ = REQUEST_AUTHORIZED_WITH_FRESH_TOKEN; | 110 request_authorization_state_ = REQUEST_AUTHORIZED_WITH_FRESH_TOKEN; |
88 OnAccountSelected(username_, String()); | 111 OnAccountSelected(username_, String()); |
89 } | 112 } |
90 | 113 |
114 void AuthenticatingURLLoaderImpl::FollowRedirectInternal() { | |
115 DCHECK(url_); | |
116 DCHECK(url_loader_); | |
117 DCHECK(!username_); | |
118 DCHECK(request_authorization_state_ == REQUEST_NOT_AUTHORIZED); | |
119 | |
120 url_loader_->FollowRedirect(base::Bind( | |
121 &AuthenticatingURLLoaderImpl::OnLoadComplete, base::Unretained(this))); | |
122 } | |
123 | |
91 void AuthenticatingURLLoaderImpl::OnAccountSelected(String username, | 124 void AuthenticatingURLLoaderImpl::OnAccountSelected(String username, |
92 String error) { | 125 String error) { |
93 if (error) { | 126 if (error) { |
94 LOG(ERROR) << "Error (" << error << ") while selecting account"; | 127 LOG(ERROR) << "Error (" << error << ") while selecting account"; |
95 pending_start_callback_.Run(pending_response_.Pass()); | 128 pending_request_callback_.Run(pending_response_.Pass()); |
96 return; | 129 return; |
97 } | 130 } |
98 | 131 |
99 DCHECK(username); | 132 DCHECK(username); |
100 username_ = username; | 133 username_ = username; |
101 | 134 |
102 mojo::Array<mojo::String> scopes(1); | 135 mojo::Array<mojo::String> scopes(1); |
103 scopes[0] = "https://www.googleapis.com/auth/userinfo.email"; | 136 scopes[0] = "https://www.googleapis.com/auth/userinfo.email"; |
104 | 137 |
105 authentication_service_->GetOAuth2Token( | 138 authentication_service_->GetOAuth2Token( |
106 username, scopes.Pass(), | 139 username, scopes.Pass(), |
107 base::Bind(&AuthenticatingURLLoaderImpl::OnOAuth2TokenReceived, | 140 base::Bind(&AuthenticatingURLLoaderImpl::OnOAuth2TokenReceived, |
108 base::Unretained(this))); | 141 base::Unretained(this))); |
109 } | 142 } |
110 | 143 |
111 void AuthenticatingURLLoaderImpl::OnOAuth2TokenReceived(String token, | 144 void AuthenticatingURLLoaderImpl::OnOAuth2TokenReceived(String token, |
112 String error) { | 145 String error) { |
113 if (error) { | 146 if (error) { |
114 LOG(ERROR) << "Error (" << error << ") while getting token"; | 147 LOG(ERROR) << "Error (" << error << ") while getting token"; |
115 pending_start_callback_.Run(pending_response_.Pass()); | 148 pending_request_callback_.Run(pending_response_.Pass()); |
116 return; | 149 return; |
117 } | 150 } |
118 | 151 |
119 DCHECK(token); | 152 DCHECK(token); |
120 token_ = token; | 153 token_ = token; |
121 mojo::Array<mojo::String> headers(0); | 154 mojo::Array<mojo::String> headers(0); |
122 if (headers_) | 155 if (headers_) |
123 headers = headers_.Clone(); | 156 headers = headers_.Clone(); |
124 headers.push_back("Authorization: Bearer " + token.get()); | 157 headers.push_back("Authorization: Bearer " + token.get()); |
125 | 158 |
126 URLRequestPtr request(mojo::URLRequest::New()); | 159 URLRequestPtr request(mojo::URLRequest::New()); |
127 request->url = url_; | 160 request->url = url_; |
128 request->auto_follow_redirects = auto_follow_redirects_; | 161 request->auto_follow_redirects = false; |
129 request->bypass_cache = bypass_cache_; | 162 request->bypass_cache = bypass_cache_; |
130 request->headers = headers.Pass(); | 163 request->headers = headers.Pass(); |
131 | 164 |
132 StartNetworkRequest(request.Pass()); | 165 StartNetworkRequest(request.Pass()); |
133 } | 166 } |
134 | 167 |
135 void AuthenticatingURLLoaderImpl::SetAuthenticationService( | 168 void AuthenticatingURLLoaderImpl::SetAuthenticationService( |
136 authentication::AuthenticationService* authentication_service) { | 169 authentication::AuthenticationService* authentication_service) { |
137 authentication_service_ = authentication_service; | 170 authentication_service_ = authentication_service; |
138 if (authentication_service || !pending_response_) | 171 if (authentication_service || !pending_response_) |
139 return; | 172 return; |
140 | 173 |
141 // We need authentication but have no AuthenticationService. | 174 // We need authentication but have no AuthenticationService. |
142 DCHECK(!pending_start_callback_.is_null()); | 175 DCHECK(!pending_request_callback_.is_null()); |
143 pending_start_callback_.Run(pending_response_.Pass()); | 176 pending_request_callback_.Run(pending_response_.Pass()); |
144 } | 177 } |
145 | 178 |
146 } // namespace mojo | 179 } // namespace mojo |
OLD | NEW |