// Copyright (c) 2010 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 is an application of a minimal host process in a Chromoting // system. It serves the purpose of gluing different pieces together // to make a functional host process for testing. // // It peforms the following functionality: // 1. Connect to the GTalk network and register the machine as a host. // 2. Accepts connection through libjingle. // 3. Receive mouse / keyboard events through libjingle. // 4. Sends screen capture through libjingle. #include #include #include #include "build/build_config.h" #include "base/at_exit.h" #include "base/command_line.h" #include "base/environment.h" #include "base/file_path.h" #include "base/logging.h" #include "base/nss_util.h" #include "base/scoped_nsautorelease_pool.h" #include "base/thread.h" #include "remoting/base/encoder_verbatim.h" #include "remoting/base/encoder_zlib.h" #include "remoting/host/capturer_fake.h" #include "remoting/host/chromoting_host.h" #include "remoting/host/chromoting_host_context.h" #include "remoting/host/json_host_config.h" #if defined(OS_WIN) #include "remoting/host/capturer_gdi.h" #include "remoting/host/event_executor_win.h" #elif defined(OS_LINUX) #include "remoting/host/capturer_linux.h" #include "remoting/host/event_executor_linux.h" #elif defined(OS_MACOSX) #include "remoting/host/capturer_mac.h" #include "remoting/host/event_executor_mac.h" #endif #if defined(OS_WIN) const std::wstring kDefaultConfigPath = L".ChromotingConfig.json"; const wchar_t kHomeDrive[] = L"HOMEDRIVE"; const wchar_t kHomePath[] = L"HOMEPATH"; const wchar_t* GetEnvironmentVar(const wchar_t* x) { return _wgetenv(x); } #else const std::string kDefaultConfigPath = ".ChromotingConfig.json"; static char* GetEnvironmentVar(const char* x) { return getenv(x); } #endif void ShutdownTask(MessageLoop* message_loop) { message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); } const std::string kFakeSwitchName = "fake"; const std::string kConfigSwitchName = "config"; const std::string kVerbatimSwitchName = "verbatim"; int main(int argc, char** argv) { // Needed for the Mac, so we don't leak objects when threads are created. base::ScopedNSAutoreleasePool pool; CommandLine::Init(argc, argv); const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); base::AtExitManager exit_manager; base::EnsureNSPRInit(); scoped_ptr capturer; scoped_ptr encoder; scoped_ptr event_handler; #if defined(OS_WIN) capturer.reset(new remoting::CapturerGdi()); event_handler.reset(new remoting::EventExecutorWin(capturer.get())); #elif defined(OS_LINUX) capturer.reset(new remoting::CapturerLinux()); event_handler.reset(new remoting::EventExecutorLinux(capturer.get())); #elif defined(OS_MACOSX) capturer.reset(new remoting::CapturerMac()); event_handler.reset(new remoting::EventExecutorMac(capturer.get())); #endif encoder.reset(new remoting::EncoderZlib()); // Check the argument to see if we should use a fake capturer and encoder. bool fake = cmd_line->HasSwitch(kFakeSwitchName); bool verbatim = cmd_line->HasSwitch(kVerbatimSwitchName); #if defined(OS_WIN) std::wstring path = GetEnvironmentVar(kHomeDrive); path += GetEnvironmentVar(kHomePath); #else std::string path = GetEnvironmentVar(base::env_vars::kHome); #endif FilePath config_path(path); config_path = config_path.Append(kDefaultConfigPath); if (cmd_line->HasSwitch(kConfigSwitchName)) { config_path = cmd_line->GetSwitchValuePath(kConfigSwitchName); } if (fake) { // Inject a fake capturer. LOG(INFO) << "Using a fake capturer."; capturer.reset(new remoting::CapturerFake()); } if (verbatim) { LOG(INFO) << "Using the verbatim encoder."; encoder.reset(new remoting::EncoderVerbatim()); } base::Thread file_io_thread("FileIO"); file_io_thread.Start(); scoped_refptr config( new remoting::JsonHostConfig( config_path, file_io_thread.message_loop_proxy())); if (!config->Read()) { LOG(ERROR) << "Failed to read configuration file " << config_path.value(); return 1; } // Allocate a chromoting context and starts it. remoting::ChromotingHostContext context; context.Start(); // Construct a chromoting host. scoped_refptr host = new remoting::ChromotingHost(&context, config, capturer.release(), encoder.release(), event_handler.release()); // Let the chromoting host run until the shutdown task is executed. MessageLoop message_loop(MessageLoop::TYPE_UI); host->Start(NewRunnableFunction(&ShutdownTask, &message_loop)); message_loop.Run(); // And then stop the chromoting context. context.Stop(); file_io_thread.Stop(); return 0; }