OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "content/browser/renderer_host/buffered_resource_handler.h" | 5 #include "content/browser/renderer_host/buffered_resource_handler.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 std::string mime_type; | 157 std::string mime_type; |
158 request_->GetMimeType(&mime_type); | 158 request_->GetMimeType(&mime_type); |
159 | 159 |
160 std::string content_type_options; | 160 std::string content_type_options; |
161 request_->GetResponseHeaderByName("x-content-type-options", | 161 request_->GetResponseHeaderByName("x-content-type-options", |
162 &content_type_options); | 162 &content_type_options); |
163 | 163 |
164 const bool sniffing_blocked = | 164 const bool sniffing_blocked = |
165 LowerCaseEqualsASCII(content_type_options, "nosniff"); | 165 LowerCaseEqualsASCII(content_type_options, "nosniff"); |
166 const bool not_modified_status = | 166 const bool not_modified_status = |
167 response_->headers && response_->headers->response_code() == 304; | 167 (response_->head.headers && |
| 168 response_->head.headers->response_code() == 304); |
168 const bool we_would_like_to_sniff = not_modified_status ? | 169 const bool we_would_like_to_sniff = not_modified_status ? |
169 false : net::ShouldSniffMimeType(request_->url(), mime_type); | 170 false : net::ShouldSniffMimeType(request_->url(), mime_type); |
170 | 171 |
171 RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type); | 172 RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type); |
172 | 173 |
173 if (!sniffing_blocked && we_would_like_to_sniff) { | 174 if (!sniffing_blocked && we_would_like_to_sniff) { |
174 // We're going to look at the data before deciding what the content type | 175 // We're going to look at the data before deciding what the content type |
175 // is. That means we need to delay sending the ResponseStarted message | 176 // is. That means we need to delay sending the ResponseStarted message |
176 // over the IPC channel. | 177 // over the IPC channel. |
177 sniff_content_ = true; | 178 sniff_content_ = true; |
178 VLOG(1) << "To buffer: " << request_->url().spec(); | 179 VLOG(1) << "To buffer: " << request_->url().spec(); |
179 return true; | 180 return true; |
180 } | 181 } |
181 | 182 |
182 if (sniffing_blocked && mime_type.empty() && !not_modified_status) { | 183 if (sniffing_blocked && mime_type.empty() && !not_modified_status) { |
183 // Ugg. The server told us not to sniff the content but didn't give us a | 184 // Ugg. The server told us not to sniff the content but didn't give us a |
184 // mime type. What's a browser to do? Turns out, we're supposed to treat | 185 // mime type. What's a browser to do? Turns out, we're supposed to treat |
185 // the response as "text/plain". This is the most secure option. | 186 // the response as "text/plain". This is the most secure option. |
186 mime_type.assign("text/plain"); | 187 mime_type.assign("text/plain"); |
187 response_->mime_type.assign(mime_type); | 188 response_->head.mime_type.assign(mime_type); |
188 } | 189 } |
189 | 190 |
190 if (!not_modified_status && ShouldWaitForPlugins()) { | 191 if (!not_modified_status && ShouldWaitForPlugins()) { |
191 wait_for_plugins_ = true; | 192 wait_for_plugins_ = true; |
192 return true; | 193 return true; |
193 } | 194 } |
194 | 195 |
195 return false; | 196 return false; |
196 } | 197 } |
197 | 198 |
(...skipping 26 matching lines...) Expand all Loading... |
224 // SniffMimeType() returns false if there is not enough data to determine | 225 // SniffMimeType() returns false if there is not enough data to determine |
225 // the mime type. However, even if it returns false, it returns a new type | 226 // the mime type. However, even if it returns false, it returns a new type |
226 // that is probably better than the current one. | 227 // that is probably better than the current one. |
227 DCHECK_LT(bytes_read_, net::kMaxBytesToSniff); | 228 DCHECK_LT(bytes_read_, net::kMaxBytesToSniff); |
228 if (!finished_) { | 229 if (!finished_) { |
229 buffering_ = true; | 230 buffering_ = true; |
230 return true; | 231 return true; |
231 } | 232 } |
232 } | 233 } |
233 sniff_content_ = false; | 234 sniff_content_ = false; |
234 response_->mime_type.assign(new_type); | 235 response_->head.mime_type.assign(new_type); |
235 | 236 |
236 // We just sniffed the mime type, maybe there is a doctype to process. | 237 // We just sniffed the mime type, maybe there is a doctype to process. |
237 if (ShouldWaitForPlugins()) | 238 if (ShouldWaitForPlugins()) |
238 wait_for_plugins_ = true; | 239 wait_for_plugins_ = true; |
239 } | 240 } |
240 | 241 |
241 buffering_ = false; | 242 buffering_ = false; |
242 | 243 |
243 if (wait_for_plugins_) | 244 if (wait_for_plugins_) |
244 return true; | 245 return true; |
245 | 246 |
246 return false; | 247 return false; |
247 } | 248 } |
248 | 249 |
249 bool BufferedResourceHandler::CompleteResponseStarted(int request_id, | 250 bool BufferedResourceHandler::CompleteResponseStarted(int request_id, |
250 bool* defer) { | 251 bool* defer) { |
251 ResourceRequestInfoImpl* info = | 252 ResourceRequestInfoImpl* info = |
252 ResourceRequestInfoImpl::ForRequest(request_); | 253 ResourceRequestInfoImpl::ForRequest(request_); |
253 std::string mime_type; | 254 std::string mime_type; |
254 request_->GetMimeType(&mime_type); | 255 request_->GetMimeType(&mime_type); |
255 | 256 |
256 if (mime_type == "application/x-x509-user-cert") { | 257 if (mime_type == "application/x-x509-user-cert") { |
257 // Let X.509 certs be handled by the X509UserCertResourceHandler. | 258 // Let X.509 certs be handled by the X509UserCertResourceHandler. |
258 | 259 |
259 // This is entirely similar to how DownloadResourceHandler works except we | 260 // This is entirely similar to how DownloadResourceHandler works except we |
260 // are doing it for an X.509 client certificates. | 261 // are doing it for an X.509 client certificates. |
261 // TODO(darin): This does not belong here! | 262 // TODO(darin): This does not belong here! |
262 | 263 |
263 if (response_->headers && // Can be NULL if FTP. | 264 if (response_->head.headers && // Can be NULL if FTP. |
264 response_->headers->response_code() / 100 != 2) { | 265 response_->head.headers->response_code() / 100 != 2) { |
265 // The response code indicates that this is an error page, but we are | 266 // The response code indicates that this is an error page, but we are |
266 // expecting an X.509 user certificate. We follow Firefox here and show | 267 // expecting an X.509 user certificate. We follow Firefox here and show |
267 // our own error page instead of handling the error page as a | 268 // our own error page instead of handling the error page as a |
268 // certificate. | 269 // certificate. |
269 // TODO(abarth): We should abstract the response_code test, but this kind | 270 // TODO(abarth): We should abstract the response_code test, but this kind |
270 // of check is scattered throughout our codebase. | 271 // of check is scattered throughout our codebase. |
271 request_->CancelWithError(net::ERR_FILE_NOT_FOUND); | 272 request_->CancelWithError(net::ERR_FILE_NOT_FOUND); |
272 return false; | 273 return false; |
273 } | 274 } |
274 | 275 |
275 scoped_ptr<ResourceHandler> handler( | 276 scoped_ptr<ResourceHandler> handler( |
276 new X509UserCertResourceHandler(request_, | 277 new X509UserCertResourceHandler(request_, |
277 info->GetChildID(), | 278 info->GetChildID(), |
278 info->GetRouteID())); | 279 info->GetRouteID())); |
279 | 280 |
280 return UseAlternateResourceHandler(request_id, handler.Pass(), defer); | 281 return UseAlternateResourceHandler(request_id, handler.Pass(), defer); |
281 } | 282 } |
282 | 283 |
283 if (info->allow_download() && ShouldDownload(NULL)) { | 284 if (info->allow_download() && ShouldDownload(NULL)) { |
284 // Forward the data to the download thread. | 285 // Forward the data to the download thread. |
285 | 286 if (response_->head.headers && // Can be NULL if FTP. |
286 if (response_->headers && // Can be NULL if FTP. | 287 response_->head.headers->response_code() / 100 != 2) { |
287 response_->headers->response_code() / 100 != 2) { | |
288 // The response code indicates that this is an error page, but we don't | 288 // The response code indicates that this is an error page, but we don't |
289 // know how to display the content. We follow Firefox here and show our | 289 // know how to display the content. We follow Firefox here and show our |
290 // own error page instead of triggering a download. | 290 // own error page instead of triggering a download. |
291 // TODO(abarth): We should abstract the response_code test, but this kind | 291 // TODO(abarth): We should abstract the response_code test, but this kind |
292 // of check is scattered throughout our codebase. | 292 // of check is scattered throughout our codebase. |
293 request_->CancelWithError(net::ERR_FILE_NOT_FOUND); | 293 request_->CancelWithError(net::ERR_FILE_NOT_FOUND); |
294 return false; | 294 return false; |
295 } | 295 } |
296 | 296 |
297 info->set_is_download(true); | 297 info->set_is_download(true); |
(...skipping 23 matching lines...) Expand all Loading... |
321 PluginServiceImpl::GetInstance()->GetPlugins( | 321 PluginServiceImpl::GetInstance()->GetPlugins( |
322 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, AsWeakPtr())); | 322 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, AsWeakPtr())); |
323 return true; | 323 return true; |
324 } | 324 } |
325 | 325 |
326 // This test mirrors the decision that WebKit makes in | 326 // This test mirrors the decision that WebKit makes in |
327 // WebFrameLoaderClient::dispatchDecidePolicyForMIMEType. | 327 // WebFrameLoaderClient::dispatchDecidePolicyForMIMEType. |
328 bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { | 328 bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { |
329 if (need_plugin_list) | 329 if (need_plugin_list) |
330 *need_plugin_list = false; | 330 *need_plugin_list = false; |
331 std::string type = StringToLowerASCII(response_->mime_type); | 331 std::string type = StringToLowerASCII(response_->head.mime_type); |
332 | 332 |
333 // First, examine Content-Disposition. | 333 // First, examine Content-Disposition. |
334 std::string disposition; | 334 std::string disposition; |
335 request_->GetResponseHeaderByName("content-disposition", &disposition); | 335 request_->GetResponseHeaderByName("content-disposition", &disposition); |
336 if (!disposition.empty()) { | 336 if (!disposition.empty()) { |
337 net::HttpContentDisposition parsed_disposition(disposition, std::string()); | 337 net::HttpContentDisposition parsed_disposition(disposition, std::string()); |
338 if (parsed_disposition.is_attachment()) | 338 if (parsed_disposition.is_attachment()) |
339 return true; | 339 return true; |
340 } | 340 } |
341 | 341 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 | 440 |
441 bool defer = false; | 441 bool defer = false; |
442 if (!CompleteResponseStarted(request_id, &defer)) { | 442 if (!CompleteResponseStarted(request_id, &defer)) { |
443 controller()->Cancel(); | 443 controller()->Cancel(); |
444 } else if (!defer && needs_resume) { | 444 } else if (!defer && needs_resume) { |
445 controller()->Resume(); | 445 controller()->Resume(); |
446 } | 446 } |
447 } | 447 } |
448 | 448 |
449 } // namespace content | 449 } // namespace content |
OLD | NEW |