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 "remoting/host/it2me/it2me_native_messaging_host_main.h" 6 7#include "base/at_exit.h" 8#include "base/command_line.h" 9#include "base/i18n/icu_util.h" 10#include "base/message_loop/message_loop.h" 11#include "base/run_loop.h" 12#include "media/base/media.h" 13#include "net/socket/ssl_server_socket.h" 14#include "remoting/base/breakpad.h" 15#include "remoting/base/resources.h" 16#include "remoting/host/host_exit_codes.h" 17#include "remoting/host/it2me/it2me_native_messaging_host.h" 18#include "remoting/host/logging.h" 19#include "remoting/host/native_messaging/pipe_messaging_channel.h" 20#include "remoting/host/usage_stats_consent.h" 21 22#if defined(OS_LINUX) 23#include <gtk/gtk.h> 24#include <X11/Xlib.h> 25#endif // defined(OS_LINUX) 26 27#if defined(OS_MACOSX) 28#include "base/mac/scoped_nsautorelease_pool.h" 29#endif // defined(OS_MACOSX) 30 31#if defined(OS_WIN) 32#include <commctrl.h> 33#endif // defined(OS_WIN) 34 35namespace remoting { 36 37// Creates a It2MeNativeMessagingHost instance, attaches it to stdin/stdout and 38// runs the message loop until It2MeNativeMessagingHost signals shutdown. 39int StartIt2MeNativeMessagingHost() { 40#if defined(OS_MACOSX) 41 // Needed so we don't leak objects when threads are created. 42 base::mac::ScopedNSAutoreleasePool pool; 43#endif // defined(OS_MACOSX) 44 45#if defined(REMOTING_ENABLE_BREAKPAD) 46 // Initialize Breakpad as early as possible. On Mac the command-line needs to 47 // be initialized first, so that the preference for crash-reporting can be 48 // looked up in the config file. 49 if (IsUsageStatsAllowed()) { 50 InitializeCrashReporting(); 51 } 52#endif // defined(REMOTING_ENABLE_BREAKPAD) 53 54#if defined(OS_WIN) 55 // Register and initialize common controls. 56 INITCOMMONCONTROLSEX info; 57 info.dwSize = sizeof(info); 58 info.dwICC = ICC_STANDARD_CLASSES; 59 InitCommonControlsEx(&info); 60#endif // defined(OS_WIN) 61 62 // Required to find the ICU data file, used by some file_util routines. 63 base::i18n::InitializeICU(); 64 65 remoting::LoadResources(""); 66 67 // Cannot use TOOLKIT_GTK because it is not defined when aura is enabled. 68#if defined(OS_LINUX) 69 // Required in order for us to run multiple X11 threads. 70 XInitThreads(); 71 72 // Required for any calls into GTK functions, such as the Disconnect and 73 // Continue windows. Calling with NULL arguments because we don't have 74 // any command line arguments for gtk to consume. 75 gtk_init(NULL, NULL); 76#endif // OS_LINUX 77 78 // Enable support for SSL server sockets, which must be done while still 79 // single-threaded. 80 net::EnableSSLServerSockets(); 81 82 // Ensures runtime specific CPU features are initialized. 83 media::InitializeCPUSpecificMediaFeatures(); 84 85#if defined(OS_WIN) 86 // GetStdHandle() returns pseudo-handles for stdin and stdout even if 87 // the hosting executable specifies "Windows" subsystem. However the returned 88 // handles are invalid in that case unless standard input and output are 89 // redirected to a pipe or file. 90 base::File read_file(GetStdHandle(STD_INPUT_HANDLE)); 91 base::File write_file(GetStdHandle(STD_OUTPUT_HANDLE)); 92 93 // After the native messaging channel starts the native messaging reader 94 // will keep doing blocking read operations on the input named pipe. 95 // If any other thread tries to perform any operation on STDIN, it will also 96 // block because the input named pipe is synchronous (non-overlapped). 97 // It is pretty common for a DLL to query the device info (GetFileType) of 98 // the STD* handles at startup. So any LoadLibrary request can potentially 99 // be blocked. To prevent that from happening we close STDIN and STDOUT 100 // handles as soon as we retrieve the corresponding file handles. 101 SetStdHandle(STD_INPUT_HANDLE, NULL); 102 SetStdHandle(STD_OUTPUT_HANDLE, NULL); 103#elif defined(OS_POSIX) 104 // The files are automatically closed. 105 base::File read_file(STDIN_FILENO); 106 base::File write_file(STDOUT_FILENO); 107#else 108#error Not implemented. 109#endif 110 111 base::MessageLoopForUI message_loop; 112 base::RunLoop run_loop; 113 114 scoped_refptr<AutoThreadTaskRunner> task_runner = 115 new remoting::AutoThreadTaskRunner(message_loop.message_loop_proxy(), 116 run_loop.QuitClosure()); 117 118 scoped_ptr<It2MeHostFactory> factory(new It2MeHostFactory()); 119 120 // Set up the native messaging channel. 121 scoped_ptr<extensions::NativeMessagingChannel> channel( 122 new PipeMessagingChannel(read_file.Pass(), write_file.Pass())); 123 124 scoped_ptr<It2MeNativeMessagingHost> host(new It2MeNativeMessagingHost( 125 task_runner, channel.Pass(), factory.Pass())); 126 host->Start(run_loop.QuitClosure()); 127 128 // Run the loop until channel is alive. 129 run_loop.Run(); 130 131 return kSuccessExitCode; 132} 133 134int It2MeNativeMessagingHostMain(int argc, char** argv) { 135 // This object instance is required by Chrome code (such as MessageLoop). 136 base::AtExitManager exit_manager; 137 138 base::CommandLine::Init(argc, argv); 139 remoting::InitHostLogging(); 140 141 return StartIt2MeNativeMessagingHost(); 142} 143 144} // namespace remoting 145