root/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. callback_called_
  2. Start
  3. AnalyzeInSandbox
  4. OnMessageReceived
  5. OnAnalyzeZipFileFinished
  6. StartProcessOnIOThread
  7. OnUtilityProcessStarted

// Copyright (c) 2012 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/safe_browsing/sandboxed_zip_analyzer.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/platform_file.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/common/chrome_utility_messages.h"
#include "chrome/common/safe_browsing/zip_analyzer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"

using content::BrowserThread;

namespace safe_browsing {

SandboxedZipAnalyzer::SandboxedZipAnalyzer(
    const base::FilePath& zip_file,
    const ResultCallback& result_callback)
    : zip_file_name_(zip_file),
      callback_(result_callback),
      callback_called_(false) {
}

void SandboxedZipAnalyzer::Start() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  // Starting the analyzer will block on opening the zip file, so run this
  // on a worker thread.  The task does not need to block shutdown.
  if (!BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
          FROM_HERE,
          base::Bind(&SandboxedZipAnalyzer::AnalyzeInSandbox, this),
          base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {
    NOTREACHED();
  }
}

SandboxedZipAnalyzer::~SandboxedZipAnalyzer() {
  // If we're using UtilityProcessHost, we may not be destroyed on
  // the UI or IO thread.
}

void SandboxedZipAnalyzer::AnalyzeInSandbox() {
  zip_file_.Initialize(zip_file_name_,
                       base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!zip_file_.IsValid()) {
    VLOG(1) << "Could not open zip file: " << zip_file_name_.value();
    if (!BrowserThread::PostTask(
            BrowserThread::IO, FROM_HERE,
            base::Bind(&SandboxedZipAnalyzer::OnAnalyzeZipFileFinished, this,
                       zip_analyzer::Results()))) {
      NOTREACHED();
    }
    return;
  }

  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&SandboxedZipAnalyzer::StartProcessOnIOThread, this));
  // The file will be closed on the IO thread once it has been handed
  // off to the child process.
}

bool SandboxedZipAnalyzer::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(SandboxedZipAnalyzer, message)
    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
                        OnUtilityProcessStarted)
    IPC_MESSAGE_HANDLER(
        ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished,
        OnAnalyzeZipFileFinished)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void SandboxedZipAnalyzer::OnAnalyzeZipFileFinished(
    const zip_analyzer::Results& results) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (callback_called_)
    return;
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                          base::Bind(callback_, results));
  callback_called_ = true;
}

void SandboxedZipAnalyzer::StartProcessOnIOThread() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  utility_process_host_ = content::UtilityProcessHost::Create(
      this,
      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get())
      ->AsWeakPtr();
  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
  // Wait for the startup notification before sending the main IPC to the
  // utility process, so that we can dup the file handle.
}

void SandboxedZipAnalyzer::OnUtilityProcessStarted() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  base::ProcessHandle utility_process =
      content::RenderProcessHost::run_renderer_in_process() ?
          base::GetCurrentProcessHandle() :
          utility_process_host_->GetData().handle;

  if (utility_process == base::kNullProcessHandle) {
    DLOG(ERROR) << "Child process handle is null";
  }
  utility_process_host_->Send(
      new ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection(
          IPC::TakeFileHandleForProcess(zip_file_.Pass(), utility_process)));
}

}  // namespace safe_browsing

/* [<][>][^][v][top][bottom][index][help] */