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 "sync/internal_api/public/attachments/attachment_downloader_impl.h" | 5 #include "sync/internal_api/public/attachments/attachment_downloader_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
9 #include "net/base/load_flags.h" | 9 #include "net/base/load_flags.h" |
10 #include "net/http/http_status_code.h" | 10 #include "net/http/http_status_code.h" |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 DCHECK(request == access_token_request_.get()); | 108 DCHECK(request == access_token_request_.get()); |
109 access_token_request_.reset(); | 109 access_token_request_.reset(); |
110 StateList::const_iterator iter; | 110 StateList::const_iterator iter; |
111 // Without access token all downloads fail. | 111 // Without access token all downloads fail. |
112 for (iter = requests_waiting_for_access_token_.begin(); | 112 for (iter = requests_waiting_for_access_token_.begin(); |
113 iter != requests_waiting_for_access_token_.end(); | 113 iter != requests_waiting_for_access_token_.end(); |
114 ++iter) { | 114 ++iter) { |
115 DownloadState* download_state = *iter; | 115 DownloadState* download_state = *iter; |
116 scoped_refptr<base::RefCountedString> null_attachment_data; | 116 scoped_refptr<base::RefCountedString> null_attachment_data; |
117 ReportResult( | 117 ReportResult( |
118 *download_state, DOWNLOAD_UNSPECIFIED_ERROR, null_attachment_data); | 118 *download_state, DOWNLOAD_TRANSIENT_ERROR, null_attachment_data); |
119 DCHECK(state_map_.find(download_state->attachment_url) != state_map_.end()); | 119 DCHECK(state_map_.find(download_state->attachment_url) != state_map_.end()); |
120 state_map_.erase(download_state->attachment_url); | 120 state_map_.erase(download_state->attachment_url); |
121 } | 121 } |
122 requests_waiting_for_access_token_.clear(); | 122 requests_waiting_for_access_token_.clear(); |
123 } | 123 } |
124 | 124 |
125 void AttachmentDownloaderImpl::OnURLFetchComplete( | 125 void AttachmentDownloaderImpl::OnURLFetchComplete( |
126 const net::URLFetcher* source) { | 126 const net::URLFetcher* source) { |
127 DCHECK(CalledOnValidThread()); | 127 DCHECK(CalledOnValidThread()); |
128 | 128 |
129 // Find DownloadState by url. | 129 // Find DownloadState by url. |
130 AttachmentUrl url = source->GetOriginalURL().spec(); | 130 AttachmentUrl url = source->GetOriginalURL().spec(); |
131 StateMap::iterator iter = state_map_.find(url); | 131 StateMap::iterator iter = state_map_.find(url); |
132 DCHECK(iter != state_map_.end()); | 132 DCHECK(iter != state_map_.end()); |
133 const DownloadState& download_state = *iter->second; | 133 const DownloadState& download_state = *iter->second; |
134 DCHECK(source == download_state.url_fetcher.get()); | 134 DCHECK(source == download_state.url_fetcher.get()); |
135 | 135 |
136 DownloadResult result = DOWNLOAD_UNSPECIFIED_ERROR; | 136 DownloadResult result = DOWNLOAD_TRANSIENT_ERROR; |
137 scoped_refptr<base::RefCountedString> attachment_data; | 137 scoped_refptr<base::RefCountedString> attachment_data; |
138 | 138 |
139 if (source->GetResponseCode() == net::HTTP_OK) { | 139 const int response_code = source->GetResponseCode(); |
| 140 if (response_code == net::HTTP_OK) { |
140 result = DOWNLOAD_SUCCESS; | 141 result = DOWNLOAD_SUCCESS; |
141 std::string data_as_string; | 142 std::string data_as_string; |
142 source->GetResponseAsString(&data_as_string); | 143 source->GetResponseAsString(&data_as_string); |
143 attachment_data = base::RefCountedString::TakeString(&data_as_string); | 144 attachment_data = base::RefCountedString::TakeString(&data_as_string); |
144 } else if (source->GetResponseCode() == net::HTTP_UNAUTHORIZED) { | 145 } else if (response_code == net::HTTP_UNAUTHORIZED) { |
| 146 // Server tells us we've got a bad token so invalidate it. |
145 OAuth2TokenServiceRequest::InvalidateToken(token_service_provider_.get(), | 147 OAuth2TokenServiceRequest::InvalidateToken(token_service_provider_.get(), |
146 account_id_, | 148 account_id_, |
147 oauth2_scopes_, | 149 oauth2_scopes_, |
148 download_state.access_token); | 150 download_state.access_token); |
149 // TODO(pavely): crbug/380437. This is transient error. Request new access | 151 // Fail the request, but indicate that it may be successful if retried. |
150 // token for this DownloadState. The only trick is to do it with exponential | 152 result = DOWNLOAD_TRANSIENT_ERROR; |
151 // backoff. | 153 } else if (response_code == net::HTTP_FORBIDDEN) { |
| 154 // User is not allowed to use attachments. Retrying won't help. |
| 155 result = DOWNLOAD_UNSPECIFIED_ERROR; |
| 156 } else if (response_code == net::URLFetcher::RESPONSE_CODE_INVALID) { |
| 157 result = DOWNLOAD_TRANSIENT_ERROR; |
152 } | 158 } |
153 ReportResult(download_state, result, attachment_data); | 159 ReportResult(download_state, result, attachment_data); |
154 state_map_.erase(iter); | 160 state_map_.erase(iter); |
155 } | 161 } |
156 | 162 |
157 scoped_ptr<net::URLFetcher> AttachmentDownloaderImpl::CreateFetcher( | 163 scoped_ptr<net::URLFetcher> AttachmentDownloaderImpl::CreateFetcher( |
158 const AttachmentUrl& url, | 164 const AttachmentUrl& url, |
159 const std::string& access_token) { | 165 const std::string& access_token) { |
160 scoped_ptr<net::URLFetcher> url_fetcher( | 166 scoped_ptr<net::URLFetcher> url_fetcher( |
161 net::URLFetcher::Create(GURL(url), net::URLFetcher::GET, this)); | 167 net::URLFetcher::Create(GURL(url), net::URLFetcher::GET, this)); |
| 168 url_fetcher->SetAutomaticallyRetryOn5xx(false); |
162 const std::string auth_header("Authorization: Bearer " + access_token); | 169 const std::string auth_header("Authorization: Bearer " + access_token); |
163 url_fetcher->AddExtraRequestHeader(auth_header); | 170 url_fetcher->AddExtraRequestHeader(auth_header); |
164 url_fetcher->SetRequestContext(url_request_context_getter_.get()); | 171 url_fetcher->SetRequestContext(url_request_context_getter_.get()); |
165 url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | | 172 url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | |
166 net::LOAD_DO_NOT_SEND_COOKIES | | 173 net::LOAD_DO_NOT_SEND_COOKIES | |
167 net::LOAD_DISABLE_CACHE); | 174 net::LOAD_DISABLE_CACHE); |
168 // TODO(maniscalco): Set an appropriate headers (User-Agent, what else?) on | 175 // TODO(maniscalco): Set an appropriate headers (User-Agent, what else?) on |
169 // the request (bug 371521). | 176 // the request (bug 371521). |
170 return url_fetcher.Pass(); | 177 return url_fetcher.Pass(); |
171 } | 178 } |
(...skipping 21 matching lines...) Expand all Loading... |
193 attachment.reset(new Attachment(Attachment::CreateWithId( | 200 attachment.reset(new Attachment(Attachment::CreateWithId( |
194 download_state.attachment_id, attachment_data))); | 201 download_state.attachment_id, attachment_data))); |
195 } | 202 } |
196 | 203 |
197 base::MessageLoop::current()->PostTask( | 204 base::MessageLoop::current()->PostTask( |
198 FROM_HERE, base::Bind(*iter, result, base::Passed(&attachment))); | 205 FROM_HERE, base::Bind(*iter, result, base::Passed(&attachment))); |
199 } | 206 } |
200 } | 207 } |
201 | 208 |
202 } // namespace syncer | 209 } // namespace syncer |
OLD | NEW |