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(); | |
50 } | |
51 | |
52 void SandboxedZipAnalyzer::CloseTemporaryFile() { | |
53 if (!temp_file_.IsValid()) | |
54 return; | |
55 // Close the temporary file in the blocking pool since doing so will delete | |
56 // the file. | |
57 if (!BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( | |
58 FROM_HERE, base::Bind(&base::File::Close, | |
59 base::Owned(new base::File(temp_file_.Pass()))), | |
60 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) { | |
61 NOTREACHED(); | |
62 } | |
48 } | 63 } |
49 | 64 |
50 void SandboxedZipAnalyzer::AnalyzeInSandbox() { | 65 void SandboxedZipAnalyzer::AnalyzeInSandbox() { |
66 // This zip file will be closed on the IO thread once it has been handed | |
67 // off to the child process. | |
51 zip_file_.Initialize(zip_file_name_, | 68 zip_file_.Initialize(zip_file_name_, |
Tom Sepez
2015/03/23 17:15:55
Not part of your CL, but while we're looking at it
grt (UTC plus 2)
2015/03/23 17:22:13
No worries. zip_file_name_ is the path to the file
| |
52 base::File::FLAG_OPEN | base::File::FLAG_READ); | 69 base::File::FLAG_OPEN | base::File::FLAG_READ); |
53 if (!zip_file_.IsValid()) { | 70 if (!zip_file_.IsValid()) { |
54 DVLOG(1) << "Could not open zip file: " << zip_file_name_.value(); | 71 DVLOG(1) << "Could not open zip file: " << zip_file_name_.value(); |
55 if (!BrowserThread::PostTask( | 72 if (!BrowserThread::PostTask( |
56 BrowserThread::IO, FROM_HERE, | 73 BrowserThread::IO, FROM_HERE, |
57 base::Bind(&SandboxedZipAnalyzer::OnAnalyzeZipFileFinished, this, | 74 base::Bind(&SandboxedZipAnalyzer::OnAnalyzeZipFileFinished, this, |
58 zip_analyzer::Results()))) { | 75 zip_analyzer::Results()))) { |
59 NOTREACHED(); | 76 NOTREACHED(); |
60 } | 77 } |
61 return; | 78 return; |
62 } | 79 } |
63 | 80 |
81 // This temp file will be closed in the blocking pool when results from the | |
82 // analyzer return. | |
83 base::FilePath temp_path; | |
84 if (base::CreateTemporaryFile(&temp_path)) { | |
85 temp_file_.Initialize(temp_path, (base::File::FLAG_CREATE_ALWAYS | | |
86 base::File::FLAG_READ | | |
87 base::File::FLAG_WRITE | | |
88 base::File::FLAG_TEMPORARY | | |
89 base::File::FLAG_DELETE_ON_CLOSE)); | |
90 } | |
91 DVLOG_IF(1, !temp_file_.IsValid()) | |
92 << "Could not open temporary output file: " << temp_path.value(); | |
93 | |
64 BrowserThread::PostTask( | 94 BrowserThread::PostTask( |
65 BrowserThread::IO, FROM_HERE, | 95 BrowserThread::IO, FROM_HERE, |
66 base::Bind(&SandboxedZipAnalyzer::StartProcessOnIOThread, this)); | 96 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 } | 97 } |
70 | 98 |
71 bool SandboxedZipAnalyzer::OnMessageReceived(const IPC::Message& message) { | 99 bool SandboxedZipAnalyzer::OnMessageReceived(const IPC::Message& message) { |
72 bool handled = true; | 100 bool handled = true; |
73 IPC_BEGIN_MESSAGE_MAP(SandboxedZipAnalyzer, message) | 101 IPC_BEGIN_MESSAGE_MAP(SandboxedZipAnalyzer, message) |
74 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, | 102 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, |
75 OnUtilityProcessStarted) | 103 OnUtilityProcessStarted) |
76 IPC_MESSAGE_HANDLER( | 104 IPC_MESSAGE_HANDLER( |
77 ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished, | 105 ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished, |
78 OnAnalyzeZipFileFinished) | 106 OnAnalyzeZipFileFinished) |
79 IPC_MESSAGE_UNHANDLED(handled = false) | 107 IPC_MESSAGE_UNHANDLED(handled = false) |
80 IPC_END_MESSAGE_MAP() | 108 IPC_END_MESSAGE_MAP() |
81 return handled; | 109 return handled; |
82 } | 110 } |
83 | 111 |
84 void SandboxedZipAnalyzer::OnAnalyzeZipFileFinished( | |
85 const zip_analyzer::Results& results) { | |
86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
87 if (callback_called_) | |
88 return; | |
89 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
90 base::Bind(callback_, results)); | |
91 callback_called_ = true; | |
92 } | |
93 | |
94 void SandboxedZipAnalyzer::StartProcessOnIOThread() { | 112 void SandboxedZipAnalyzer::StartProcessOnIOThread() { |
95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
96 utility_process_host_ = content::UtilityProcessHost::Create( | 114 utility_process_host_ = content::UtilityProcessHost::Create( |
97 this, | 115 this, |
98 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()) | 116 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()) |
99 ->AsWeakPtr(); | 117 ->AsWeakPtr(); |
100 utility_process_host_->Send(new ChromeUtilityMsg_StartupPing); | 118 utility_process_host_->Send(new ChromeUtilityMsg_StartupPing); |
101 // Wait for the startup notification before sending the main IPC to the | 119 // Wait for the startup notification before sending the main IPC to the |
102 // utility process, so that we can dup the file handle. | 120 // utility process, so that we can dup the file handle. |
103 } | 121 } |
104 | 122 |
105 void SandboxedZipAnalyzer::OnUtilityProcessStarted() { | 123 void SandboxedZipAnalyzer::OnUtilityProcessStarted() { |
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
107 base::ProcessHandle utility_process = | 125 base::ProcessHandle utility_process = |
108 content::RenderProcessHost::run_renderer_in_process() ? | 126 content::RenderProcessHost::run_renderer_in_process() ? |
109 base::GetCurrentProcessHandle() : | 127 base::GetCurrentProcessHandle() : |
110 utility_process_host_->GetData().handle; | 128 utility_process_host_->GetData().handle; |
111 | 129 |
112 if (utility_process == base::kNullProcessHandle) { | 130 if (utility_process == base::kNullProcessHandle) { |
113 DLOG(ERROR) << "Child process handle is null"; | 131 DLOG(ERROR) << "Child process handle is null"; |
114 } | 132 } |
115 utility_process_host_->Send( | 133 utility_process_host_->Send( |
116 new ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection( | 134 new ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection( |
117 IPC::TakeFileHandleForProcess(zip_file_.Pass(), utility_process))); | 135 IPC::TakeFileHandleForProcess(zip_file_.Pass(), utility_process), |
136 IPC::GetFileHandleForProcess(temp_file_.GetPlatformFile(), | |
137 utility_process, | |
138 false /* !close_source_handle */))); | |
139 } | |
140 | |
141 void SandboxedZipAnalyzer::OnAnalyzeZipFileFinished( | |
142 const zip_analyzer::Results& results) { | |
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
144 if (callback_called_) | |
145 return; | |
146 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
147 base::Bind(callback_, results)); | |
148 callback_called_ = true; | |
149 CloseTemporaryFile(); | |
118 } | 150 } |
119 | 151 |
120 } // namespace safe_browsing | 152 } // namespace safe_browsing |
OLD | NEW |