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