Chromium Code Reviews| 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 "chrome/browser/safe_browsing/sandboxed_zip_analyzer.h" | 5 #include "chrome/browser/safe_browsing/sandboxed_zip_analyzer.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/files/file_util.h" | |
| 9 #include "base/location.h" | 10 #include "base/location.h" |
| 10 #include "base/logging.h" | 11 #include "base/logging.h" |
| 11 #include "base/threading/sequenced_worker_pool.h" | 12 #include "base/threading/sequenced_worker_pool.h" |
| 12 #include "chrome/common/chrome_utility_messages.h" | 13 #include "chrome/common/chrome_utility_messages.h" |
| 13 #include "chrome/common/safe_browsing/zip_analyzer.h" | 14 #include "chrome/common/safe_browsing/zip_analyzer_results.h" |
| 14 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
| 15 #include "content/public/browser/child_process_data.h" | 16 #include "content/public/browser/child_process_data.h" |
| 16 #include "content/public/browser/render_process_host.h" | 17 #include "content/public/browser/render_process_host.h" |
| 17 #include "content/public/common/content_switches.h" | 18 #include "content/public/common/content_switches.h" |
| 18 #include "ipc/ipc_message_macros.h" | 19 #include "ipc/ipc_message_macros.h" |
| 19 #include "ipc/ipc_platform_file.h" | 20 #include "ipc/ipc_platform_file.h" |
| 20 | 21 |
| 21 using content::BrowserThread; | 22 using content::BrowserThread; |
| 22 | 23 |
| 23 namespace safe_browsing { | 24 namespace safe_browsing { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 38 FROM_HERE, | 39 FROM_HERE, |
| 39 base::Bind(&SandboxedZipAnalyzer::AnalyzeInSandbox, this), | 40 base::Bind(&SandboxedZipAnalyzer::AnalyzeInSandbox, this), |
| 40 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) { | 41 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) { |
| 41 NOTREACHED(); | 42 NOTREACHED(); |
| 42 } | 43 } |
| 43 } | 44 } |
| 44 | 45 |
| 45 SandboxedZipAnalyzer::~SandboxedZipAnalyzer() { | 46 SandboxedZipAnalyzer::~SandboxedZipAnalyzer() { |
| 46 // If we're using UtilityProcessHost, we may not be destroyed on | 47 // If we're using UtilityProcessHost, we may not be destroyed on |
| 47 // the UI or IO thread. | 48 // the UI or IO thread. |
| 49 CloseTemporaryFile(); | |
| 48 } | 50 } |
| 49 | 51 |
| 50 void SandboxedZipAnalyzer::AnalyzeInSandbox() { | 52 void SandboxedZipAnalyzer::AnalyzeInSandbox() { |
| 53 // This zip file will be closed on the IO thread once it has been handed | |
| 54 // off to the child process. | |
| 51 zip_file_.Initialize(zip_file_name_, | 55 zip_file_.Initialize(zip_file_name_, |
| 52 base::File::FLAG_OPEN | base::File::FLAG_READ); | 56 base::File::FLAG_OPEN | base::File::FLAG_READ); |
| 53 if (!zip_file_.IsValid()) { | 57 if (!zip_file_.IsValid()) { |
| 54 DVLOG(1) << "Could not open zip file: " << zip_file_name_.value(); | 58 DVLOG(1) << "Could not open zip file: " << zip_file_name_.value(); |
| 55 if (!BrowserThread::PostTask( | 59 if (!BrowserThread::PostTask( |
| 56 BrowserThread::IO, FROM_HERE, | 60 BrowserThread::IO, FROM_HERE, |
| 57 base::Bind(&SandboxedZipAnalyzer::OnAnalyzeZipFileFinished, this, | 61 base::Bind(&SandboxedZipAnalyzer::OnAnalyzeZipFileFinished, this, |
| 58 zip_analyzer::Results()))) { | 62 zip_analyzer::Results()))) { |
| 59 NOTREACHED(); | 63 NOTREACHED(); |
| 60 } | 64 } |
| 61 return; | 65 return; |
| 62 } | 66 } |
| 63 | 67 |
| 68 // This temp file will be closed in the blocking pool when results from the | |
| 69 // analyzer return. | |
| 70 base::FilePath temp_path; | |
| 71 if (base::CreateTemporaryFile(&temp_path)) { | |
| 72 temp_file_.Initialize(temp_path, (base::File::FLAG_CREATE_ALWAYS | | |
| 73 base::File::FLAG_READ | | |
| 74 base::File::FLAG_WRITE | | |
| 75 base::File::FLAG_TEMPORARY | | |
| 76 base::File::FLAG_DELETE_ON_CLOSE)); | |
| 77 } | |
| 78 DVLOG_IF(1, !temp_file_.IsValid()) | |
| 79 << "Could not open temporary output file: " << temp_path.value(); | |
| 80 | |
| 64 BrowserThread::PostTask( | 81 BrowserThread::PostTask( |
| 65 BrowserThread::IO, FROM_HERE, | 82 BrowserThread::IO, FROM_HERE, |
| 66 base::Bind(&SandboxedZipAnalyzer::StartProcessOnIOThread, this)); | 83 base::Bind(&SandboxedZipAnalyzer::StartProcessOnIOThread, this)); |
| 67 // The file will be closed on the IO thread once it has been handed | |
| 68 // off to the child process. | |
| 69 } | 84 } |
| 70 | 85 |
| 71 bool SandboxedZipAnalyzer::OnMessageReceived(const IPC::Message& message) { | 86 bool SandboxedZipAnalyzer::OnMessageReceived(const IPC::Message& message) { |
| 72 bool handled = true; | 87 bool handled = true; |
| 73 IPC_BEGIN_MESSAGE_MAP(SandboxedZipAnalyzer, message) | 88 IPC_BEGIN_MESSAGE_MAP(SandboxedZipAnalyzer, message) |
| 74 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, | 89 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, |
| 75 OnUtilityProcessStarted) | 90 OnUtilityProcessStarted) |
| 76 IPC_MESSAGE_HANDLER( | 91 IPC_MESSAGE_HANDLER( |
| 77 ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished, | 92 ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished, |
| 78 OnAnalyzeZipFileFinished) | 93 OnAnalyzeZipFileFinished) |
| 79 IPC_MESSAGE_UNHANDLED(handled = false) | 94 IPC_MESSAGE_UNHANDLED(handled = false) |
| 80 IPC_END_MESSAGE_MAP() | 95 IPC_END_MESSAGE_MAP() |
| 81 return handled; | 96 return handled; |
| 82 } | 97 } |
| 83 | 98 |
| 84 void SandboxedZipAnalyzer::OnAnalyzeZipFileFinished( | 99 void SandboxedZipAnalyzer::OnAnalyzeZipFileFinished( |
| 85 const zip_analyzer::Results& results) { | 100 const zip_analyzer::Results& results) { |
| 86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 87 if (callback_called_) | 102 if (callback_called_) |
| 88 return; | 103 return; |
| 89 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 104 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 90 base::Bind(callback_, results)); | 105 base::Bind(callback_, results)); |
| 91 callback_called_ = true; | 106 callback_called_ = true; |
| 107 CloseTemporaryFile(); | |
| 92 } | 108 } |
| 93 | 109 |
| 94 void SandboxedZipAnalyzer::StartProcessOnIOThread() { | 110 void SandboxedZipAnalyzer::StartProcessOnIOThread() { |
| 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 96 utility_process_host_ = content::UtilityProcessHost::Create( | 112 utility_process_host_ = content::UtilityProcessHost::Create( |
| 97 this, | 113 this, |
| 98 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()) | 114 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()) |
| 99 ->AsWeakPtr(); | 115 ->AsWeakPtr(); |
| 100 utility_process_host_->Send(new ChromeUtilityMsg_StartupPing); | 116 utility_process_host_->Send(new ChromeUtilityMsg_StartupPing); |
| 101 // Wait for the startup notification before sending the main IPC to the | 117 // Wait for the startup notification before sending the main IPC to the |
| 102 // utility process, so that we can dup the file handle. | 118 // utility process, so that we can dup the file handle. |
| 103 } | 119 } |
| 104 | 120 |
| 121 void SandboxedZipAnalyzer::CloseTemporaryFile() { | |
|
mattm
2015/03/23 01:53:40
nit: I'd move this so that StartProcessOnIOThread
grt (UTC plus 2)
2015/03/23 13:29:16
Done. I also made the order in the .h match that h
| |
| 122 if (!temp_file_.IsValid()) | |
| 123 return; | |
| 124 // Close the temporary file in the blocking pool since doing so will delete | |
| 125 // the file. | |
| 126 if (!BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( | |
| 127 FROM_HERE, base::Bind(&base::File::Close, | |
| 128 base::Owned(new base::File(temp_file_.Pass()))), | |
| 129 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) { | |
| 130 NOTREACHED(); | |
| 131 } | |
| 132 } | |
| 133 | |
| 105 void SandboxedZipAnalyzer::OnUtilityProcessStarted() { | 134 void SandboxedZipAnalyzer::OnUtilityProcessStarted() { |
| 106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 107 base::ProcessHandle utility_process = | 136 base::ProcessHandle utility_process = |
| 108 content::RenderProcessHost::run_renderer_in_process() ? | 137 content::RenderProcessHost::run_renderer_in_process() ? |
| 109 base::GetCurrentProcessHandle() : | 138 base::GetCurrentProcessHandle() : |
| 110 utility_process_host_->GetData().handle; | 139 utility_process_host_->GetData().handle; |
| 111 | 140 |
| 112 if (utility_process == base::kNullProcessHandle) { | 141 if (utility_process == base::kNullProcessHandle) { |
| 113 DLOG(ERROR) << "Child process handle is null"; | 142 DLOG(ERROR) << "Child process handle is null"; |
| 114 } | 143 } |
| 115 utility_process_host_->Send( | 144 utility_process_host_->Send( |
| 116 new ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection( | 145 new ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection( |
| 117 IPC::TakeFileHandleForProcess(zip_file_.Pass(), utility_process))); | 146 IPC::TakeFileHandleForProcess(zip_file_.Pass(), utility_process), |
| 147 IPC::GetFileHandleForProcess(temp_file_.GetPlatformFile(), | |
| 148 utility_process, | |
| 149 false /* !close_source_handle */))); | |
| 118 } | 150 } |
| 119 | 151 |
| 120 } // namespace safe_browsing | 152 } // namespace safe_browsing |
| OLD | NEW |