1// Copyright 2013 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/media_galleries/fileapi/safe_audio_video_checker.h"
6
7#include "base/bind.h"
8#include "base/callback.h"
9#include "base/location.h"
10#include "base/logging.h"
11#include "base/process/process_handle.h"
12#include "chrome/common/chrome_utility_messages.h"
13#include "content/public/browser/child_process_data.h"
14#include "content/public/browser/utility_process_host.h"
15#include "content/public/browser/browser_thread.h"
16#include "ipc/ipc_message_macros.h"
17#include "ipc/ipc_platform_file.h"
18
19SafeAudioVideoChecker::SafeAudioVideoChecker(
20    base::File file,
21    const fileapi::CopyOrMoveFileValidator::ResultCallback& callback)
22    : state_(INITIAL_STATE),
23      file_(file.Pass()),
24      callback_(callback) {
25  DCHECK(!callback.is_null());
26}
27
28void SafeAudioVideoChecker::Start() {
29  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
30  if (state_ != INITIAL_STATE)
31    return;
32  state_ = PINGED_STATE;
33
34  if (!file_.IsValid()) {
35    callback_.Run(base::File::FILE_ERROR_SECURITY);
36    state_ = FINISHED_STATE;
37    return;
38  }
39
40  utility_process_host_ = content::UtilityProcessHost::Create(
41      this, base::MessageLoopProxy::current())->AsWeakPtr();
42  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
43}
44
45SafeAudioVideoChecker::~SafeAudioVideoChecker() {}
46
47void SafeAudioVideoChecker::OnProcessStarted() {
48  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
49  if (state_ != PINGED_STATE)
50    return;
51  state_ = STARTED_STATE;
52
53  if (utility_process_host_->GetData().handle == base::kNullProcessHandle)
54    DLOG(ERROR) << "Child process handle is null";
55  IPC::PlatformFileForTransit file_for_transit =
56      IPC::TakeFileHandleForProcess(file_.Pass(),
57                                    utility_process_host_->GetData().handle);
58  const int64 kFileDecodeTimeInMS = 250;
59  utility_process_host_->Send(new ChromeUtilityMsg_CheckMediaFile(
60      kFileDecodeTimeInMS, file_for_transit));
61}
62
63void SafeAudioVideoChecker::OnCheckingFinished(bool valid) {
64  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
65  if (state_ != STARTED_STATE)
66    return;
67  state_ = FINISHED_STATE;
68
69  callback_.Run(valid ? base::File::FILE_OK :
70                        base::File::FILE_ERROR_SECURITY);
71}
72
73void SafeAudioVideoChecker::OnProcessCrashed(int exit_code) {
74  OnCheckingFinished(false);
75}
76
77bool SafeAudioVideoChecker::OnMessageReceived(const IPC::Message& message) {
78  bool handled = true;
79  IPC_BEGIN_MESSAGE_MAP(SafeAudioVideoChecker, message)
80    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
81        OnProcessStarted)
82    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_CheckMediaFile_Finished,
83        OnCheckingFinished)
84    IPC_MESSAGE_UNHANDLED(handled = false)
85  IPC_END_MESSAGE_MAP()
86  return handled;
87}
88