| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "services/authenticating_url_loader/authenticating_url_loader_impl.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "mojo/services/network/public/interfaces/network_service.mojom.h" | |
| 10 | |
| 11 namespace mojo { | |
| 12 | |
| 13 AuthenticatingURLLoaderImpl::AuthenticatingURLLoaderImpl( | |
| 14 InterfaceRequest<AuthenticatingURLLoader> request, | |
| 15 AuthenticatingURLLoaderFactoryImpl* factory) | |
| 16 : binding_(this, request.Pass()), | |
| 17 factory_(factory), | |
| 18 request_authorization_state_(REQUEST_INITIAL) { | |
| 19 binding_.set_error_handler(this); | |
| 20 } | |
| 21 | |
| 22 AuthenticatingURLLoaderImpl::~AuthenticatingURLLoaderImpl() { | |
| 23 } | |
| 24 | |
| 25 void AuthenticatingURLLoaderImpl::Start( | |
| 26 URLRequestPtr request, | |
| 27 const Callback<void(URLResponsePtr)>& callback) { | |
| 28 // TODO(blundell): If we need to handle requests with bodies, we'll need to | |
| 29 // do something here. | |
| 30 if (request->body) { | |
| 31 LOG(ERROR) | |
| 32 << "Cannot pass a request to AuthenticatingURLLoader that has a body"; | |
| 33 callback.Run(nullptr); | |
| 34 return; | |
| 35 } | |
| 36 url_ = GURL(request->url); | |
| 37 auto_follow_redirects_ = request->auto_follow_redirects; | |
| 38 bypass_cache_ = request->bypass_cache; | |
| 39 headers_ = request->headers.Clone(); | |
| 40 pending_request_callback_ = callback; | |
| 41 std::string token = factory_->GetCachedToken(url_); | |
| 42 if (token != "") { | |
| 43 auto auth_header = HttpHeader::New(); | |
| 44 auth_header->name = "Authorization"; | |
| 45 auth_header->value = "Bearer " + token; | |
| 46 request->headers.push_back(auth_header.Pass()); | |
| 47 } | |
| 48 StartNetworkRequest(request.Pass()); | |
| 49 } | |
| 50 | |
| 51 void AuthenticatingURLLoaderImpl::FollowRedirect( | |
| 52 const Callback<void(URLResponsePtr)>& callback) { | |
| 53 mojo::String error; | |
| 54 | |
| 55 if (!url_.is_valid() || !url_loader_) { | |
| 56 error = "No redirect to follow"; | |
| 57 } | |
| 58 | |
| 59 if (auto_follow_redirects_) { | |
| 60 error = | |
| 61 "FollowRedirect() should not be " | |
| 62 "called when auto_follow_redirects has been set"; | |
| 63 } | |
| 64 | |
| 65 if (request_authorization_state_ != REQUEST_INITIAL) { | |
| 66 error = "Not in the right state to follow a redirect"; | |
| 67 } | |
| 68 | |
| 69 if (!error.is_null()) { | |
| 70 LOG(ERROR) << "AuthenticatingURLLoader: " << error; | |
| 71 callback.Run(nullptr); | |
| 72 return; | |
| 73 } | |
| 74 | |
| 75 pending_request_callback_ = callback; | |
| 76 FollowRedirectInternal(); | |
| 77 } | |
| 78 | |
| 79 void AuthenticatingURLLoaderImpl::StartNetworkRequest(URLRequestPtr request) { | |
| 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; | |
| 104 } | |
| 105 | |
| 106 url_loader_.reset(); | |
| 107 | |
| 108 if (response->status_code != 401 || | |
| 109 request_authorization_state_ == REQUEST_USED_FRESH_AUTH_SERVICE_TOKEN) { | |
| 110 pending_request_callback_.Run(response.Pass()); | |
| 111 return; | |
| 112 } | |
| 113 | |
| 114 pending_response_ = response.Pass(); | |
| 115 | |
| 116 DCHECK(request_authorization_state_ == REQUEST_INITIAL || | |
| 117 request_authorization_state_ == | |
| 118 REQUEST_USED_CURRENT_AUTH_SERVICE_TOKEN); | |
| 119 if (request_authorization_state_ == REQUEST_INITIAL) { | |
| 120 request_authorization_state_ = REQUEST_USED_CURRENT_AUTH_SERVICE_TOKEN; | |
| 121 } else { | |
| 122 request_authorization_state_ = REQUEST_USED_FRESH_AUTH_SERVICE_TOKEN; | |
| 123 } | |
| 124 factory_->RetrieveToken( | |
| 125 url_, base::Bind(&AuthenticatingURLLoaderImpl::OnOAuth2TokenReceived, | |
| 126 base::Unretained(this))); | |
| 127 return; | |
| 128 } | |
| 129 | |
| 130 void AuthenticatingURLLoaderImpl::FollowRedirectInternal() { | |
| 131 DCHECK(url_.is_valid()); | |
| 132 DCHECK(url_loader_); | |
| 133 DCHECK(request_authorization_state_ == REQUEST_INITIAL); | |
| 134 | |
| 135 url_loader_->FollowRedirect(base::Bind( | |
| 136 &AuthenticatingURLLoaderImpl::OnLoadComplete, base::Unretained(this))); | |
| 137 } | |
| 138 | |
| 139 void AuthenticatingURLLoaderImpl::OnOAuth2TokenReceived(std::string token) { | |
| 140 if (token.empty()) { | |
| 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; | |
| 150 if (headers_) | |
| 151 headers = headers_.Clone(); | |
| 152 headers.push_back(auth_header.Pass()); | |
| 153 | |
| 154 URLRequestPtr request(mojo::URLRequest::New()); | |
| 155 request->url = url_.spec(); | |
| 156 request->auto_follow_redirects = false; | |
| 157 request->bypass_cache = bypass_cache_; | |
| 158 request->headers = headers.Pass(); | |
| 159 | |
| 160 StartNetworkRequest(request.Pass()); | |
| 161 } | |
| 162 | |
| 163 } // namespace mojo | |
| OLD | NEW |