| 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 std::string mime_type; | 154 std::string mime_type; |
| 155 request_->GetMimeType(&mime_type); | 155 request_->GetMimeType(&mime_type); |
| 156 | 156 |
| 157 std::string content_type_options; | 157 std::string content_type_options; |
| 158 request_->GetResponseHeaderByName("x-content-type-options", | 158 request_->GetResponseHeaderByName("x-content-type-options", |
| 159 &content_type_options); | 159 &content_type_options); |
| 160 | 160 |
| 161 const bool sniffing_blocked = | 161 const bool sniffing_blocked = |
| 162 LowerCaseEqualsASCII(content_type_options, "nosniff"); | 162 LowerCaseEqualsASCII(content_type_options, "nosniff"); |
| 163 const bool not_modified_status = | 163 const bool not_modified_status = |
| 164 response_->headers && response_->headers->response_code() == 304; | 164 (response_->data.headers && |
| 165 response_->data.headers->response_code() == 304); |
| 165 const bool we_would_like_to_sniff = not_modified_status ? | 166 const bool we_would_like_to_sniff = not_modified_status ? |
| 166 false : net::ShouldSniffMimeType(request_->url(), mime_type); | 167 false : net::ShouldSniffMimeType(request_->url(), mime_type); |
| 167 | 168 |
| 168 RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type); | 169 RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type); |
| 169 | 170 |
| 170 if (!sniffing_blocked && we_would_like_to_sniff) { | 171 if (!sniffing_blocked && we_would_like_to_sniff) { |
| 171 // We're going to look at the data before deciding what the content type | 172 // We're going to look at the data before deciding what the content type |
| 172 // is. That means we need to delay sending the ResponseStarted message | 173 // is. That means we need to delay sending the ResponseStarted message |
| 173 // over the IPC channel. | 174 // over the IPC channel. |
| 174 sniff_content_ = true; | 175 sniff_content_ = true; |
| 175 VLOG(1) << "To buffer: " << request_->url().spec(); | 176 VLOG(1) << "To buffer: " << request_->url().spec(); |
| 176 return true; | 177 return true; |
| 177 } | 178 } |
| 178 | 179 |
| 179 if (sniffing_blocked && mime_type.empty() && !not_modified_status) { | 180 if (sniffing_blocked && mime_type.empty() && !not_modified_status) { |
| 180 // Ugg. The server told us not to sniff the content but didn't give us a | 181 // Ugg. The server told us not to sniff the content but didn't give us a |
| 181 // mime type. What's a browser to do? Turns out, we're supposed to treat | 182 // mime type. What's a browser to do? Turns out, we're supposed to treat |
| 182 // the response as "text/plain". This is the most secure option. | 183 // the response as "text/plain". This is the most secure option. |
| 183 mime_type.assign("text/plain"); | 184 mime_type.assign("text/plain"); |
| 184 response_->mime_type.assign(mime_type); | 185 response_->data.mime_type.assign(mime_type); |
| 185 } | 186 } |
| 186 | 187 |
| 187 if (!not_modified_status && ShouldWaitForPlugins()) { | 188 if (!not_modified_status && ShouldWaitForPlugins()) { |
| 188 wait_for_plugins_ = true; | 189 wait_for_plugins_ = true; |
| 189 return true; | 190 return true; |
| 190 } | 191 } |
| 191 | 192 |
| 192 return false; | 193 return false; |
| 193 } | 194 } |
| 194 | 195 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 221 // SniffMimeType() returns false if there is not enough data to determine | 222 // SniffMimeType() returns false if there is not enough data to determine |
| 222 // the mime type. However, even if it returns false, it returns a new type | 223 // the mime type. However, even if it returns false, it returns a new type |
| 223 // that is probably better than the current one. | 224 // that is probably better than the current one. |
| 224 DCHECK_LT(bytes_read_, net::kMaxBytesToSniff); | 225 DCHECK_LT(bytes_read_, net::kMaxBytesToSniff); |
| 225 if (!finished_) { | 226 if (!finished_) { |
| 226 buffering_ = true; | 227 buffering_ = true; |
| 227 return true; | 228 return true; |
| 228 } | 229 } |
| 229 } | 230 } |
| 230 sniff_content_ = false; | 231 sniff_content_ = false; |
| 231 response_->mime_type.assign(new_type); | 232 response_->data.mime_type.assign(new_type); |
| 232 | 233 |
| 233 // We just sniffed the mime type, maybe there is a doctype to process. | 234 // We just sniffed the mime type, maybe there is a doctype to process. |
| 234 if (ShouldWaitForPlugins()) | 235 if (ShouldWaitForPlugins()) |
| 235 wait_for_plugins_ = true; | 236 wait_for_plugins_ = true; |
| 236 } | 237 } |
| 237 | 238 |
| 238 buffering_ = false; | 239 buffering_ = false; |
| 239 | 240 |
| 240 if (wait_for_plugins_) | 241 if (wait_for_plugins_) |
| 241 return true; | 242 return true; |
| 242 | 243 |
| 243 return false; | 244 return false; |
| 244 } | 245 } |
| 245 | 246 |
| 246 bool BufferedResourceHandler::CompleteResponseStarted(int request_id) { | 247 bool BufferedResourceHandler::CompleteResponseStarted(int request_id) { |
| 247 ResourceRequestInfoImpl* info = | 248 ResourceRequestInfoImpl* info = |
| 248 ResourceRequestInfoImpl::ForRequest(request_); | 249 ResourceRequestInfoImpl::ForRequest(request_); |
| 249 std::string mime_type; | 250 std::string mime_type; |
| 250 request_->GetMimeType(&mime_type); | 251 request_->GetMimeType(&mime_type); |
| 251 | 252 |
| 252 // Check if this is an X.509 certificate, if yes, let it be handled | 253 // Check if this is an X.509 certificate, if yes, let it be handled |
| 253 // by X509UserCertResourceHandler. | 254 // by X509UserCertResourceHandler. |
| 254 if (mime_type == "application/x-x509-user-cert") { | 255 if (mime_type == "application/x-x509-user-cert") { |
| 255 // This is entirely similar to how DownloadResourceThrottle works except we | 256 // This is entirely similar to how DownloadResourceThrottle works except we |
| 256 // are doing it for an X.509 client certificates. | 257 // are doing it for an X.509 client certificates. |
| 257 // TODO(darin): This does not belong here! | 258 // TODO(darin): This does not belong here! |
| 258 | 259 |
| 259 if (response_->headers && // Can be NULL if FTP. | 260 if (response_->data.headers && // Can be NULL if FTP. |
| 260 response_->headers->response_code() / 100 != 2) { | 261 response_->data.headers->response_code() / 100 != 2) { |
| 261 // The response code indicates that this is an error page, but we are | 262 // The response code indicates that this is an error page, but we are |
| 262 // expecting an X.509 user certificate. We follow Firefox here and show | 263 // expecting an X.509 user certificate. We follow Firefox here and show |
| 263 // our own error page instead of handling the error page as a | 264 // our own error page instead of handling the error page as a |
| 264 // certificate. | 265 // certificate. |
| 265 // TODO(abarth): We should abstract the response_code test, but this kind | 266 // TODO(abarth): We should abstract the response_code test, but this kind |
| 266 // of check is scattered throughout our codebase. | 267 // of check is scattered throughout our codebase. |
| 267 request_->CancelWithError(net::ERR_FILE_NOT_FOUND); | 268 request_->CancelWithError(net::ERR_FILE_NOT_FOUND); |
| 268 return false; | 269 return false; |
| 269 } | 270 } |
| 270 | 271 |
| 271 X509UserCertResourceHandler* x509_cert_handler = | 272 X509UserCertResourceHandler* x509_cert_handler = |
| 272 new X509UserCertResourceHandler(request_, | 273 new X509UserCertResourceHandler(request_, |
| 273 info->GetChildID(), | 274 info->GetChildID(), |
| 274 info->GetRouteID()); | 275 info->GetRouteID()); |
| 275 if (!UseAlternateResourceHandler(request_id, x509_cert_handler)) | 276 if (!UseAlternateResourceHandler(request_id, x509_cert_handler)) |
| 276 return false; | 277 return false; |
| 277 } | 278 } |
| 278 | 279 |
| 279 // Check to see if we should forward the data from this request to the | 280 // Check to see if we should forward the data from this request to the |
| 280 // download thread. | 281 // download thread. |
| 281 // TODO(paulg): Only download if the context from the renderer allows it. | 282 // TODO(paulg): Only download if the context from the renderer allows it. |
| 282 if (info->allow_download() && ShouldDownload(NULL)) { | 283 if (info->allow_download() && ShouldDownload(NULL)) { |
| 283 if (response_->headers && // Can be NULL if FTP. | 284 if (response_->data.headers && // Can be NULL if FTP. |
| 284 response_->headers->response_code() / 100 != 2) { | 285 response_->data.headers->response_code() / 100 != 2) { |
| 285 // The response code indicates that this is an error page, but we don't | 286 // The response code indicates that this is an error page, but we don't |
| 286 // know how to display the content. We follow Firefox here and show our | 287 // know how to display the content. We follow Firefox here and show our |
| 287 // own error page instead of triggering a download. | 288 // own error page instead of triggering a download. |
| 288 // TODO(abarth): We should abstract the response_code test, but this kind | 289 // TODO(abarth): We should abstract the response_code test, but this kind |
| 289 // of check is scattered throughout our codebase. | 290 // of check is scattered throughout our codebase. |
| 290 request_->CancelWithError(net::ERR_FILE_NOT_FOUND); | 291 request_->CancelWithError(net::ERR_FILE_NOT_FOUND); |
| 291 return false; | 292 return false; |
| 292 } | 293 } |
| 293 | 294 |
| 294 info->set_is_download(true); | 295 info->set_is_download(true); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 PluginServiceImpl::GetInstance()->GetPlugins( | 329 PluginServiceImpl::GetInstance()->GetPlugins( |
| 329 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, this)); | 330 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, this)); |
| 330 return true; | 331 return true; |
| 331 } | 332 } |
| 332 | 333 |
| 333 // This test mirrors the decision that WebKit makes in | 334 // This test mirrors the decision that WebKit makes in |
| 334 // WebFrameLoaderClient::dispatchDecidePolicyForMIMEType. | 335 // WebFrameLoaderClient::dispatchDecidePolicyForMIMEType. |
| 335 bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { | 336 bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { |
| 336 if (need_plugin_list) | 337 if (need_plugin_list) |
| 337 *need_plugin_list = false; | 338 *need_plugin_list = false; |
| 338 std::string type = StringToLowerASCII(response_->mime_type); | 339 std::string type = StringToLowerASCII(response_->data.mime_type); |
| 339 | 340 |
| 340 // First, examine Content-Disposition. | 341 // First, examine Content-Disposition. |
| 341 std::string disposition; | 342 std::string disposition; |
| 342 request_->GetResponseHeaderByName("content-disposition", &disposition); | 343 request_->GetResponseHeaderByName("content-disposition", &disposition); |
| 343 if (!disposition.empty()) { | 344 if (!disposition.empty()) { |
| 344 net::HttpContentDisposition parsed_disposition(disposition, std::string()); | 345 net::HttpContentDisposition parsed_disposition(disposition, std::string()); |
| 345 if (parsed_disposition.is_attachment()) | 346 if (parsed_disposition.is_attachment()) |
| 346 return true; | 347 return true; |
| 347 } | 348 } |
| 348 | 349 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 ResourceRequestInfoImpl::ForRequest(request_); | 455 ResourceRequestInfoImpl::ForRequest(request_); |
| 455 int child_id = info->GetChildID(); | 456 int child_id = info->GetChildID(); |
| 456 int request_id = info->GetRequestID(); | 457 int request_id = info->GetRequestID(); |
| 457 | 458 |
| 458 host_->PauseRequest(child_id, request_id, false); | 459 host_->PauseRequest(child_id, request_id, false); |
| 459 if (!CompleteResponseStarted(request_id)) | 460 if (!CompleteResponseStarted(request_id)) |
| 460 host_->CancelRequest(child_id, request_id, false); | 461 host_->CancelRequest(child_id, request_id, false); |
| 461 } | 462 } |
| 462 | 463 |
| 463 } // namespace content | 464 } // namespace content |
| OLD | NEW |