- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / sandboxed_zip_analyzer.cc
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/platform_file.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "chrome/common/chrome_utility_messages.h"
14 #include "chrome/common/safe_browsing/zip_analyzer.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/child_process_data.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/common/content_switches.h"
19 #include "ipc/ipc_message_macros.h"
20 #include "ipc/ipc_platform_file.h"
21
22 using content::BrowserThread;
23
24 namespace safe_browsing {
25
26 SandboxedZipAnalyzer::SandboxedZipAnalyzer(
27     const base::FilePath& zip_file,
28     const ResultCallback& result_callback)
29     : zip_file_(zip_file),
30       callback_(result_callback),
31       callback_called_(false) {
32 }
33
34 void SandboxedZipAnalyzer::Start() {
35   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
36   // Starting the analyzer will block on opening the zip file, so run this
37   // on a worker thread.  The task does not need to block shutdown.
38   if (!BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
39           FROM_HERE,
40           base::Bind(&SandboxedZipAnalyzer::AnalyzeInSandbox, this),
41           base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {
42     NOTREACHED();
43   }
44 }
45
46 SandboxedZipAnalyzer::~SandboxedZipAnalyzer() {
47   // If we're using UtilityProcessHost, we may not be destroyed on
48   // the UI or IO thread.
49 }
50
51 void SandboxedZipAnalyzer::AnalyzeInSandbox() {
52   zip_platform_file_ = base::CreatePlatformFile(
53       zip_file_,
54       base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
55       NULL,   // created
56       NULL);  // error_code
57   if (zip_platform_file_ == base::kInvalidPlatformFileValue) {
58     VLOG(1) << "Could not open zip file: " << zip_file_.value();
59     if (!BrowserThread::PostTask(
60             BrowserThread::IO, FROM_HERE,
61             base::Bind(&SandboxedZipAnalyzer::OnAnalyzeZipFileFinished, this,
62                        zip_analyzer::Results()))) {
63       NOTREACHED();
64     }
65     return;
66   }
67
68   BrowserThread::PostTask(
69       BrowserThread::IO, FROM_HERE,
70       base::Bind(&SandboxedZipAnalyzer::StartProcessOnIOThread, this));
71   // The file will be closed on the IO thread once it has been handed
72   // off to the child process.
73 }
74
75 bool SandboxedZipAnalyzer::OnMessageReceived(const IPC::Message& message) {
76   bool handled = true;
77   IPC_BEGIN_MESSAGE_MAP(SandboxedZipAnalyzer, message)
78     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
79                         OnUtilityProcessStarted)
80     IPC_MESSAGE_HANDLER(
81         ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished,
82         OnAnalyzeZipFileFinished)
83     IPC_MESSAGE_UNHANDLED(handled = false)
84   IPC_END_MESSAGE_MAP()
85   return handled;
86 }
87
88 void SandboxedZipAnalyzer::OnAnalyzeZipFileFinished(
89     const zip_analyzer::Results& results) {
90   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
91   if (callback_called_)
92     return;
93   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
94                           base::Bind(callback_, results));
95   callback_called_ = true;
96 }
97
98 void SandboxedZipAnalyzer::StartProcessOnIOThread() {
99   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
100   utility_process_host_ = content::UtilityProcessHost::Create(
101       this,
102       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get())
103       ->AsWeakPtr();
104   utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
105   // Wait for the startup notification before sending the main IPC to the
106   // utility process, so that we can dup the file handle.
107 }
108
109 void SandboxedZipAnalyzer::OnUtilityProcessStarted() {
110   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
111   base::ProcessHandle utility_process =
112       content::RenderProcessHost::run_renderer_in_process() ?
113           base::GetCurrentProcessHandle() :
114           utility_process_host_->GetData().handle;
115
116   if (utility_process == base::kNullProcessHandle) {
117     DLOG(ERROR) << "Child process handle is null";
118   }
119   utility_process_host_->Send(
120       new ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection(
121           IPC::GetFileHandleForProcess(
122               zip_platform_file_,
123               utility_process,
124               true /* close_source_handle */)));
125 }
126
127 }  // namespace safe_browsing