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 |