Home | History | Annotate | Download | only in it2me
      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