1ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// found in the LICENSE file.
4ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
5ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h"
6ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
7ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/bind.h"
8ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/callback.h"
9ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/location.h"
10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/logging.h"
11ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/process/process_handle.h"
12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/common/chrome_utility_messages.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/chrome_utility_extensions_messages.h"
14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/browser/child_process_data.h"
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/browser/utility_process_host.h"
16ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/browser/browser_thread.h"
17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ipc/ipc_message_macros.h"
18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ipc/ipc_platform_file.h"
19ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochSafeAudioVideoChecker::SafeAudioVideoChecker(
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::File file,
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::CopyOrMoveFileValidator::ResultCallback& callback)
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    : state_(INITIAL_STATE), file_(file.Pass()), callback_(callback) {
24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(!callback.is_null());
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid SafeAudioVideoChecker::Start() {
28e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ != INITIAL_STATE)
30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_ = PINGED_STATE;
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!file_.IsValid()) {
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback_.Run(base::File::FILE_ERROR_SECURITY);
35ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    state_ = FINISHED_STATE;
36ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  utility_process_host_ = content::UtilityProcessHost::Create(
40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      this, base::MessageLoopProxy::current())->AsWeakPtr();
41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
43ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
44ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochSafeAudioVideoChecker::~SafeAudioVideoChecker() {}
45ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
46ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid SafeAudioVideoChecker::OnProcessStarted() {
47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
48ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ != PINGED_STATE)
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_ = STARTED_STATE;
51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (utility_process_host_->GetData().handle == base::kNullProcessHandle)
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DLOG(ERROR) << "Child process handle is null";
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IPC::PlatformFileForTransit file_for_transit =
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      IPC::TakeFileHandleForProcess(file_.Pass(),
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                    utility_process_host_->GetData().handle);
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (file_for_transit == IPC::InvalidPlatformFileForTransit()) {
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OnCheckingFinished(false /* valid? */);
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const int64 kFileDecodeTimeInMS = 250;
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  utility_process_host_->Send(new ChromeUtilityMsg_CheckMediaFile(
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      kFileDecodeTimeInMS, file_for_transit));
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid SafeAudioVideoChecker::OnCheckingFinished(bool valid) {
67e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ != STARTED_STATE)
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_ = FINISHED_STATE;
71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback_.Run(valid ? base::File::FILE_OK :
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        base::File::FILE_ERROR_SECURITY);
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid SafeAudioVideoChecker::OnProcessCrashed(int exit_code) {
77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  OnCheckingFinished(false);
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool SafeAudioVideoChecker::OnMessageReceived(const IPC::Message& message) {
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool handled = true;
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IPC_BEGIN_MESSAGE_MAP(SafeAudioVideoChecker, message)
83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        OnProcessStarted)
85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_CheckMediaFile_Finished,
86ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        OnCheckingFinished)
87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    IPC_MESSAGE_UNHANDLED(handled = false)
88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IPC_END_MESSAGE_MAP()
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return handled;
90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
91