// 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.
//
// This file implements the Windows service controlling Me2Me host processes
// running within user sessions.

#include "remoting/host/desktop_process.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/debug/alias.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "ipc/ipc_channel_proxy.h"
#include "remoting/base/auto_thread.h"
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/host/chromoting_messages.h"
#include "remoting/host/desktop_environment.h"
#include "remoting/host/desktop_session_agent.h"

namespace remoting {

DesktopProcess::DesktopProcess(
    scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
    scoped_refptr<AutoThreadTaskRunner> input_task_runner,
    const std::string& daemon_channel_name)
    : caller_task_runner_(caller_task_runner),
      input_task_runner_(input_task_runner),
      daemon_channel_name_(daemon_channel_name) {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());
  DCHECK(base::MessageLoopForUI::IsCurrent());
}

DesktopProcess::~DesktopProcess() {
  DCHECK(!daemon_channel_);
  DCHECK(!desktop_agent_.get());
}

DesktopEnvironmentFactory& DesktopProcess::desktop_environment_factory() {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());

  return *desktop_environment_factory_;
}

void DesktopProcess::OnNetworkProcessDisconnected() {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());

  OnChannelError();
}

void DesktopProcess::InjectSas() {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());

  daemon_channel_->Send(new ChromotingDesktopDaemonMsg_InjectSas());
}

bool DesktopProcess::OnMessageReceived(const IPC::Message& message) {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());

  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(DesktopProcess, message)
    IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()

  CHECK(handled) << "Received unexpected IPC type: " << message.type();
  return handled;
}

void DesktopProcess::OnChannelConnected(int32 peer_pid) {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());

  VLOG(1) << "IPC: desktop <- daemon (" << peer_pid << ")";
}

void DesktopProcess::OnChannelError() {
  // Shutdown the desktop process.
  daemon_channel_.reset();
  if (desktop_agent_.get()) {
    desktop_agent_->Stop();
    desktop_agent_ = NULL;
  }

  caller_task_runner_ = NULL;
  input_task_runner_ = NULL;
  desktop_environment_factory_.reset();
}

bool DesktopProcess::Start(
    scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory) {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());
  DCHECK(!desktop_environment_factory_);
  DCHECK(desktop_environment_factory);

  desktop_environment_factory_ = desktop_environment_factory.Pass();

  // Launch the audio capturing thread.
  scoped_refptr<AutoThreadTaskRunner> audio_task_runner;
#if defined(OS_WIN)
  // On Windows the AudioCapturer requires COM, so we run a single-threaded
  // apartment, which requires a UI thread.
  audio_task_runner =
      AutoThread::CreateWithLoopAndComInitTypes("ChromotingAudioThread",
                                                caller_task_runner_,
                                                base::MessageLoop::TYPE_UI,
                                                AutoThread::COM_INIT_STA);
#else // !defined(OS_WIN)
  audio_task_runner = AutoThread::CreateWithType(
      "ChromotingAudioThread", caller_task_runner_, base::MessageLoop::TYPE_IO);
#endif  // !defined(OS_WIN)

  // Launch the I/O thread.
  scoped_refptr<AutoThreadTaskRunner> io_task_runner =
      AutoThread::CreateWithType(
          "I/O thread", caller_task_runner_, base::MessageLoop::TYPE_IO);

  // Launch the video capture thread.
  scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner =
      AutoThread::Create("Video capture thread", caller_task_runner_);

  // Create a desktop agent.
  desktop_agent_ = new DesktopSessionAgent(audio_task_runner,
                                           caller_task_runner_,
                                           input_task_runner_,
                                           io_task_runner,
                                           video_capture_task_runner);

  // Start the agent and create an IPC channel to talk to it.
  IPC::PlatformFileForTransit desktop_pipe;
  if (!desktop_agent_->Start(AsWeakPtr(), &desktop_pipe)) {
    desktop_agent_ = NULL;
    caller_task_runner_ = NULL;
    input_task_runner_ = NULL;
    desktop_environment_factory_.reset();
    return false;
  }

  // Connect to the daemon.
  daemon_channel_ = IPC::ChannelProxy::Create(daemon_channel_name_,
                                              IPC::Channel::MODE_CLIENT,
                                              this,
                                              io_task_runner.get());

  // Pass |desktop_pipe| to the daemon.
  daemon_channel_->Send(
      new ChromotingDesktopDaemonMsg_DesktopAttached(desktop_pipe));

  return true;
}

void DesktopProcess::OnCrash(const std::string& function_name,
                             const std::string& file_name,
                             const int& line_number) {
  char message[1024];
  base::snprintf(message, sizeof(message),
                 "Requested by %s at %s, line %d.",
                 function_name.c_str(), file_name.c_str(), line_number);
  base::debug::Alias(message);

  // The daemon requested us to crash the process.
  CHECK(false) << message;
}

} // namespace remoting
