• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/safe_browsing/sandboxed_zip_analyzer.h"
6 
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "chrome/common/chrome_utility_messages.h"
13 #include "chrome/common/safe_browsing/zip_analyzer.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/browser/child_process_data.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/common/content_switches.h"
18 #include "ipc/ipc_message_macros.h"
19 #include "ipc/ipc_platform_file.h"
20 
21 using content::BrowserThread;
22 
23 namespace safe_browsing {
24 
SandboxedZipAnalyzer(const base::FilePath & zip_file,const ResultCallback & result_callback)25 SandboxedZipAnalyzer::SandboxedZipAnalyzer(
26     const base::FilePath& zip_file,
27     const ResultCallback& result_callback)
28     : zip_file_name_(zip_file),
29       callback_(result_callback),
30       callback_called_(false) {
31 }
32 
Start()33 void SandboxedZipAnalyzer::Start() {
34   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
35   // Starting the analyzer will block on opening the zip file, so run this
36   // on a worker thread.  The task does not need to block shutdown.
37   if (!BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
38           FROM_HERE,
39           base::Bind(&SandboxedZipAnalyzer::AnalyzeInSandbox, this),
40           base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {
41     NOTREACHED();
42   }
43 }
44 
~SandboxedZipAnalyzer()45 SandboxedZipAnalyzer::~SandboxedZipAnalyzer() {
46   // If we're using UtilityProcessHost, we may not be destroyed on
47   // the UI or IO thread.
48 }
49 
AnalyzeInSandbox()50 void SandboxedZipAnalyzer::AnalyzeInSandbox() {
51   zip_file_.Initialize(zip_file_name_,
52                        base::File::FLAG_OPEN | base::File::FLAG_READ);
53   if (!zip_file_.IsValid()) {
54     VLOG(1) << "Could not open zip file: " << zip_file_name_.value();
55     if (!BrowserThread::PostTask(
56             BrowserThread::IO, FROM_HERE,
57             base::Bind(&SandboxedZipAnalyzer::OnAnalyzeZipFileFinished, this,
58                        zip_analyzer::Results()))) {
59       NOTREACHED();
60     }
61     return;
62   }
63 
64   BrowserThread::PostTask(
65       BrowserThread::IO, FROM_HERE,
66       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 }
70 
OnMessageReceived(const IPC::Message & message)71 bool SandboxedZipAnalyzer::OnMessageReceived(const IPC::Message& message) {
72   bool handled = true;
73   IPC_BEGIN_MESSAGE_MAP(SandboxedZipAnalyzer, message)
74     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
75                         OnUtilityProcessStarted)
76     IPC_MESSAGE_HANDLER(
77         ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished,
78         OnAnalyzeZipFileFinished)
79     IPC_MESSAGE_UNHANDLED(handled = false)
80   IPC_END_MESSAGE_MAP()
81   return handled;
82 }
83 
OnAnalyzeZipFileFinished(const zip_analyzer::Results & results)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 
StartProcessOnIOThread()94 void SandboxedZipAnalyzer::StartProcessOnIOThread() {
95   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
96   utility_process_host_ = content::UtilityProcessHost::Create(
97       this,
98       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get())
99       ->AsWeakPtr();
100   utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
101   // Wait for the startup notification before sending the main IPC to the
102   // utility process, so that we can dup the file handle.
103 }
104 
OnUtilityProcessStarted()105 void SandboxedZipAnalyzer::OnUtilityProcessStarted() {
106   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
107   base::ProcessHandle utility_process =
108       content::RenderProcessHost::run_renderer_in_process() ?
109           base::GetCurrentProcessHandle() :
110           utility_process_host_->GetData().handle;
111 
112   if (utility_process == base::kNullProcessHandle) {
113     DLOG(ERROR) << "Child process handle is null";
114   }
115   utility_process_host_->Send(
116       new ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection(
117           IPC::TakeFileHandleForProcess(zip_file_.Pass(), utility_process)));
118 }
119 
120 }  // namespace safe_browsing
121