Index: chrome/browser/plugin_download_helper.cc |
=================================================================== |
--- chrome/browser/plugin_download_helper.cc (revision 0) |
+++ chrome/browser/plugin_download_helper.cc (revision 0) |
@@ -0,0 +1,190 @@ |
+// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/plugin_download_helper.h" |
+ |
+#if defined(OS_WIN) |
+#include <windows.h> |
+ |
+#include "base/file_util.h" |
+#include "chrome/browser/net/url_request_tracking.h" |
+#include "net/base/io_buffer.h" |
+ |
+PluginDownloadUrlHelper::PluginDownloadUrlHelper( |
+ const std::string& download_url, |
+ int source_child_unique_id, |
+ gfx::NativeWindow caller_window, |
+ PluginDownloadUrlHelper::DownloadDelegate* delegate) |
+ : download_file_request_(NULL), |
+ download_file_buffer_(new net::IOBuffer(kDownloadFileBufferSize)), |
+ download_file_caller_window_(caller_window), |
+ download_url_(download_url), |
+ download_source_child_unique_id_(source_child_unique_id), |
+ delegate_(delegate) { |
+ memset(download_file_buffer_->data(), 0, kDownloadFileBufferSize); |
+ download_file_.reset(new net::FileStream()); |
+} |
+ |
+PluginDownloadUrlHelper::~PluginDownloadUrlHelper() { |
+ if (download_file_request_) { |
+ delete download_file_request_; |
+ download_file_request_ = NULL; |
+ } |
+} |
+ |
+void PluginDownloadUrlHelper::InitiateDownload( |
+ URLRequestContext* request_context) { |
+ download_file_request_ = new URLRequest(GURL(download_url_), this); |
+ chrome_browser_net::SetOriginProcessUniqueIDForRequest( |
+ download_source_child_unique_id_, download_file_request_); |
+ download_file_request_->set_context(request_context); |
+ download_file_request_->Start(); |
+} |
+ |
+void PluginDownloadUrlHelper::OnAuthRequired( |
+ URLRequest* request, |
+ net::AuthChallengeInfo* auth_info) { |
+ URLRequest::Delegate::OnAuthRequired(request, auth_info); |
+ DownloadCompletedHelper(false); |
+} |
+ |
+void PluginDownloadUrlHelper::OnSSLCertificateError( |
+ URLRequest* request, |
+ int cert_error, |
+ net::X509Certificate* cert) { |
+ URLRequest::Delegate::OnSSLCertificateError(request, cert_error, cert); |
+ DownloadCompletedHelper(false); |
+} |
+ |
+void PluginDownloadUrlHelper::OnResponseStarted(URLRequest* request) { |
+ if (!download_file_->IsOpen()) { |
+ // This is safe because once the temp file has been safely created, an |
+ // attacker can't drop a symlink etc into place. |
+ file_util::CreateTemporaryFile(&download_file_path_); |
+ download_file_->Open(download_file_path_, |
+ base::PLATFORM_FILE_CREATE_ALWAYS | |
+ base::PLATFORM_FILE_READ | base::PLATFORM_FILE_WRITE); |
+ if (!download_file_->IsOpen()) { |
+ NOTREACHED(); |
+ OnDownloadCompleted(request); |
+ return; |
+ } |
+ } |
+ if (!request->status().is_success()) { |
+ OnDownloadCompleted(request); |
+ } else { |
+ // Initiate a read. |
+ int bytes_read = 0; |
+ if (!request->Read(download_file_buffer_, kDownloadFileBufferSize, |
+ &bytes_read)) { |
+ // If the error is not an IO pending, then we're done |
+ // reading. |
+ if (!request->status().is_io_pending()) { |
+ OnDownloadCompleted(request); |
+ } |
+ } else if (bytes_read == 0) { |
+ OnDownloadCompleted(request); |
+ } else { |
+ OnReadCompleted(request, bytes_read); |
+ } |
+ } |
+} |
+ |
+void PluginDownloadUrlHelper::OnReadCompleted(URLRequest* request, |
+ int bytes_read) { |
+ DCHECK(download_file_->IsOpen()); |
+ |
+ if (bytes_read == 0) { |
+ OnDownloadCompleted(request); |
+ return; |
+ } |
+ |
+ int request_bytes_read = bytes_read; |
+ |
+ while (request->status().is_success()) { |
+ int bytes_written = download_file_->Write(download_file_buffer_->data(), |
+ request_bytes_read, NULL); |
+ DCHECK((bytes_written < 0) || (bytes_written == request_bytes_read)); |
+ |
+ if ((bytes_written < 0) || (bytes_written != request_bytes_read)) { |
+ DownloadCompletedHelper(false); |
+ break; |
+ } |
+ |
+ // Start reading |
+ request_bytes_read = 0; |
+ if (!request->Read(download_file_buffer_, kDownloadFileBufferSize, |
+ &request_bytes_read)) { |
+ if (!request->status().is_io_pending()) { |
+ // If the error is not an IO pending, then we're done |
+ // reading. |
+ OnDownloadCompleted(request); |
+ } |
+ break; |
+ } else if (request_bytes_read == 0) { |
+ OnDownloadCompleted(request); |
+ break; |
+ } |
+ } |
+} |
+ |
+void PluginDownloadUrlHelper::OnDownloadCompleted(URLRequest* request) { |
+ bool success = true; |
+ if (!request->status().is_success()) { |
+ success = false; |
+ } else if (!download_file_->IsOpen()) { |
+ success = false; |
+ } |
+ |
+ DownloadCompletedHelper(success); |
+} |
+ |
+void PluginDownloadUrlHelper::DownloadCompletedHelper(bool success) { |
+ if (download_file_->IsOpen()) { |
+ download_file_.reset(); |
+ } |
+ |
+ if (success) { |
+ FilePath new_download_file_path = |
+ download_file_path_.DirName().AppendASCII( |
+ download_file_request_->url().ExtractFileName()); |
+ |
+ file_util::Delete(new_download_file_path, false); |
+ |
+ if (!file_util::ReplaceFileW(download_file_path_, |
+ new_download_file_path)) { |
+ DLOG(ERROR) << "Failed to rename file:" |
+ << download_file_path_.value() |
+ << " to file:" |
+ << new_download_file_path.value(); |
+ } else { |
+ download_file_path_ = new_download_file_path; |
+ } |
+ } |
+ |
+ if (delegate_) { |
+ delegate_->OnDownloadCompleted(download_file_path_, success); |
+ } else { |
+ std::wstring path = download_file_path_.value(); |
+ COPYDATASTRUCT download_file_data = {0}; |
+ download_file_data.cbData = |
+ static_cast<unsigned long>((path.length() + 1) * sizeof(wchar_t)); |
+ download_file_data.lpData = const_cast<wchar_t *>(path.c_str()); |
+ download_file_data.dwData = success; |
+ |
+ if (::IsWindow(download_file_caller_window_)) { |
+ ::SendMessage(download_file_caller_window_, WM_COPYDATA, NULL, |
+ reinterpret_cast<LPARAM>(&download_file_data)); |
+ } |
+ } |
+ |
+ // Don't access any members after this. |
+ delete this; |
+} |
+ |
+#endif // OS_WIN |
+ |
+ |
+ |
+ |
Property changes on: chrome\browser\plugin_download_helper.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |