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 35 namespace remoting { 36 37 // Creates a It2MeNativeMessagingHost instance, attaches it to stdin/stdout and 38 // runs the message loop until It2MeNativeMessagingHost signals shutdown. 39 int 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 134 int 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