| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "chrome/browser/renderer_host/redirect_to_file_resource_handler.h" | 5 #include "chrome/browser/renderer_host/redirect_to_file_resource_handler.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/file_util_proxy.h" | 8 #include "base/file_util_proxy.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/platform_file.h" | 10 #include "base/platform_file.h" |
| 11 #include "base/task.h" | 11 #include "base/task.h" |
| 12 #include "chrome/browser/child_process_security_policy.h" | 12 #include "chrome/browser/child_process_security_policy.h" |
| 13 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" | 13 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" |
| 14 #include "chrome/common/resource_response.h" | 14 #include "chrome/common/resource_response.h" |
| 15 #include "net/base/file_stream.h" | 15 #include "net/base/file_stream.h" |
| 16 #include "net/base/io_buffer.h" | 16 #include "net/base/io_buffer.h" |
| 17 #include "net/base/mime_sniffer.h" | 17 #include "net/base/mime_sniffer.h" |
| 18 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
| 19 #include "webkit/blob/deletable_file_reference.h" | |
| 20 | |
| 21 using webkit_blob::DeletableFileReference; | |
| 22 | 19 |
| 23 // TODO(darin): Use the buffer sizing algorithm from AsyncResourceHandler. | 20 // TODO(darin): Use the buffer sizing algorithm from AsyncResourceHandler. |
| 24 static const int kReadBufSize = 32768; | 21 static const int kReadBufSize = 32768; |
| 25 | 22 |
| 26 RedirectToFileResourceHandler::RedirectToFileResourceHandler( | 23 RedirectToFileResourceHandler::RedirectToFileResourceHandler( |
| 27 ResourceHandler* next_handler, | 24 ResourceHandler* next_handler, |
| 28 int process_id, | 25 int process_id, |
| 29 ResourceDispatcherHost* host) | 26 ResourceDispatcherHost* host) |
| 30 : callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 27 : callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 31 host_(host), | 28 host_(host), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 52 ResourceResponse* response, | 49 ResourceResponse* response, |
| 53 bool* defer) { | 50 bool* defer) { |
| 54 return next_handler_->OnRequestRedirected(request_id, new_url, response, | 51 return next_handler_->OnRequestRedirected(request_id, new_url, response, |
| 55 defer); | 52 defer); |
| 56 } | 53 } |
| 57 | 54 |
| 58 bool RedirectToFileResourceHandler::OnResponseStarted( | 55 bool RedirectToFileResourceHandler::OnResponseStarted( |
| 59 int request_id, | 56 int request_id, |
| 60 ResourceResponse* response) { | 57 ResourceResponse* response) { |
| 61 if (response->response_head.status.is_success()) { | 58 if (response->response_head.status.is_success()) { |
| 62 DCHECK(deletable_file_ && !deletable_file_->path().empty()); | 59 DCHECK(!file_path_.empty()); |
| 63 response->response_head.download_file_path = deletable_file_->path(); | 60 response->response_head.download_file_path = file_path_; |
| 64 } | 61 } |
| 65 return next_handler_->OnResponseStarted(request_id, response); | 62 return next_handler_->OnResponseStarted(request_id, response); |
| 66 } | 63 } |
| 67 | 64 |
| 68 bool RedirectToFileResourceHandler::OnWillStart(int request_id, | 65 bool RedirectToFileResourceHandler::OnWillStart(int request_id, |
| 69 const GURL& url, | 66 const GURL& url, |
| 70 bool* defer) { | 67 bool* defer) { |
| 71 request_id_ = request_id; | 68 request_id_ = request_id; |
| 72 if (!deletable_file_) { | 69 if (file_path_.empty()) { |
| 73 // Defer starting the request until we have created the temporary file. | 70 // Defer starting the request until we have created the temporary file. |
| 74 // TODO(darin): This is sub-optimal. We should not delay starting the | 71 // TODO(darin): This is sub-optimal. We should not delay starting the |
| 75 // network request like this. | 72 // network request like this. |
| 76 *defer = true; | 73 *defer = true; |
| 77 base::FileUtilProxy::CreateTemporary( | 74 base::FileUtilProxy::CreateTemporary( |
| 78 ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE), | 75 ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE), |
| 79 callback_factory_.NewCallback( | 76 callback_factory_.NewCallback( |
| 80 &RedirectToFileResourceHandler::DidCreateTemporaryFile)); | 77 &RedirectToFileResourceHandler::DidCreateTemporaryFile)); |
| 81 return true; | 78 return true; |
| 82 } | 79 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 | 116 |
| 120 // We use the buffer's offset field to record the end of the buffer. | 117 // We use the buffer's offset field to record the end of the buffer. |
| 121 | 118 |
| 122 int new_offset = buf_->offset() + *bytes_read; | 119 int new_offset = buf_->offset() + *bytes_read; |
| 123 DCHECK(new_offset <= buf_->capacity()); | 120 DCHECK(new_offset <= buf_->capacity()); |
| 124 buf_->set_offset(new_offset); | 121 buf_->set_offset(new_offset); |
| 125 | 122 |
| 126 if (BufIsFull()) | 123 if (BufIsFull()) |
| 127 host_->PauseRequest(process_id_, request_id, true); | 124 host_->PauseRequest(process_id_, request_id, true); |
| 128 | 125 |
| 129 if (*bytes_read > 0) | |
| 130 next_handler_->OnDataDownloaded(request_id, *bytes_read); | |
| 131 | |
| 132 return WriteMore(); | 126 return WriteMore(); |
| 133 } | 127 } |
| 134 | 128 |
| 135 bool RedirectToFileResourceHandler::OnResponseCompleted( | 129 bool RedirectToFileResourceHandler::OnResponseCompleted( |
| 136 int request_id, | 130 int request_id, |
| 137 const URLRequestStatus& status, | 131 const URLRequestStatus& status, |
| 138 const std::string& security_info) { | 132 const std::string& security_info) { |
| 139 return next_handler_->OnResponseCompleted(request_id, status, security_info); | 133 return next_handler_->OnResponseCompleted(request_id, status, security_info); |
| 140 } | 134 } |
| 141 | 135 |
| 142 void RedirectToFileResourceHandler::OnRequestClosed() { | 136 void RedirectToFileResourceHandler::OnRequestClosed() { |
| 137 next_handler_->OnRequestClosed(); |
| 138 |
| 139 // The renderer no longer has a WebURLLoader open to this request, so we can |
| 140 // close and unlink the file. |
| 141 |
| 143 // We require this explicit call to Close since file_stream_ was constructed | 142 // We require this explicit call to Close since file_stream_ was constructed |
| 144 // directly from a PlatformFile. | 143 // directly from a PlatformFile. |
| 145 file_stream_->Close(); | 144 file_stream_->Close(); |
| 146 file_stream_.reset(); | 145 file_stream_.reset(); |
| 147 deletable_file_ = NULL; | |
| 148 | 146 |
| 149 next_handler_->OnRequestClosed(); | 147 // TODO(dumi): delete the temp file when it's no longer needed. |
| 148 // TODO(dumi): revoke the privilege to upload this file. |
| 149 // base::FileUtilProxy::Delete( |
| 150 // ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE), |
| 151 // file_path_, NULL); |
| 150 } | 152 } |
| 151 | 153 |
| 152 RedirectToFileResourceHandler::~RedirectToFileResourceHandler() { | 154 RedirectToFileResourceHandler::~RedirectToFileResourceHandler() { |
| 153 DCHECK(!file_stream_.get()); | 155 DCHECK(!file_stream_.get()); |
| 154 } | 156 } |
| 155 | 157 |
| 156 void RedirectToFileResourceHandler::DidCreateTemporaryFile( | 158 void RedirectToFileResourceHandler::DidCreateTemporaryFile( |
| 157 base::PlatformFileError /*error_code*/, | 159 base::PlatformFileError /*error_code*/, |
| 158 base::PassPlatformFile file_handle, | 160 base::PassPlatformFile file_handle, |
| 159 FilePath file_path) { | 161 FilePath file_path) { |
| 160 deletable_file_ = DeletableFileReference::GetOrCreate( | 162 file_path_ = file_path; |
| 161 file_path, | |
| 162 ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE)); | |
| 163 file_stream_.reset(new net::FileStream(file_handle.ReleaseValue(), | 163 file_stream_.reset(new net::FileStream(file_handle.ReleaseValue(), |
| 164 base::PLATFORM_FILE_WRITE | | 164 base::PLATFORM_FILE_WRITE | |
| 165 base::PLATFORM_FILE_ASYNC)); | 165 base::PLATFORM_FILE_ASYNC)); |
| 166 host_->RegisterDownloadedTempFile( | 166 ChildProcessSecurityPolicy::GetInstance()->GrantUploadFile( |
| 167 process_id_, request_id_, deletable_file_.get()); | 167 process_id_, file_path); |
| 168 host_->StartDeferredRequest(process_id_, request_id_); | 168 host_->StartDeferredRequest(process_id_, request_id_); |
| 169 } | 169 } |
| 170 | 170 |
| 171 void RedirectToFileResourceHandler::DidWriteToFile(int result) { | 171 void RedirectToFileResourceHandler::DidWriteToFile(int result) { |
| 172 write_callback_pending_ = false; | 172 write_callback_pending_ = false; |
| 173 | 173 |
| 174 bool failed = false; | 174 bool failed = false; |
| 175 if (result > 0) { | 175 if (result > 0) { |
| 176 write_cursor_ += result; | 176 write_cursor_ += result; |
| 177 failed = !WriteMore(); | 177 failed = !WriteMore(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 } | 213 } |
| 214 } | 214 } |
| 215 | 215 |
| 216 bool RedirectToFileResourceHandler::BufIsFull() const { | 216 bool RedirectToFileResourceHandler::BufIsFull() const { |
| 217 // This is a hack to workaround BufferedResourceHandler's inability to | 217 // This is a hack to workaround BufferedResourceHandler's inability to |
| 218 // deal with a ResourceHandler that returns a buffer size of less than | 218 // deal with a ResourceHandler that returns a buffer size of less than |
| 219 // 2 * net::kMaxBytesToSniff from its OnWillRead method. | 219 // 2 * net::kMaxBytesToSniff from its OnWillRead method. |
| 220 // TODO(darin): Fix this retardation! | 220 // TODO(darin): Fix this retardation! |
| 221 return buf_->RemainingCapacity() <= (2 * net::kMaxBytesToSniff); | 221 return buf_->RemainingCapacity() <= (2 * net::kMaxBytesToSniff); |
| 222 } | 222 } |
| OLD | NEW |