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 "base/at_exit.h" 6 #include "base/command_line.h" 7 #include "base/message_loop/message_loop.h" 8 #include "base/run_loop.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "net/url_request/url_fetcher.h" 11 #include "remoting/host/host_exit_codes.h" 12 #include "remoting/host/logging.h" 13 #include "remoting/host/pairing_registry_delegate.h" 14 #include "remoting/host/setup/me2me_native_messaging_host.h" 15 16 namespace { 17 18 const char kParentWindowSwitchName[] = "parent-window"; 19 20 } // namespace 21 22 namespace remoting { 23 24 int Me2MeNativeMessagingHostMain() { 25 #if defined(OS_WIN) 26 // GetStdHandle() returns pseudo-handles for stdin and stdout even if 27 // the hosting executable specifies "Windows" subsystem. However the returned 28 // handles are invalid in that case unless standard input and output are 29 // redirected to a pipe or file. 30 base::PlatformFile read_file = GetStdHandle(STD_INPUT_HANDLE); 31 base::PlatformFile write_file = GetStdHandle(STD_OUTPUT_HANDLE); 32 #elif defined(OS_POSIX) 33 base::PlatformFile read_file = STDIN_FILENO; 34 base::PlatformFile write_file = STDOUT_FILENO; 35 #else 36 #error Not implemented. 37 #endif 38 39 // Mac OS X requires that the main thread be a UI message loop in order to 40 // receive distributed notifications from the System Preferences pane. An 41 // IO thread is needed for the pairing registry and URL context getter. 42 base::Thread io_thread("io_thread"); 43 io_thread.StartWithOptions( 44 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); 45 46 base::MessageLoopForUI message_loop; 47 base::RunLoop run_loop; 48 49 scoped_refptr<DaemonController> daemon_controller = 50 DaemonController::Create(); 51 52 // Pass handle of the native view to the controller so that the UAC prompts 53 // are focused properly. 54 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 55 if (command_line->HasSwitch(kParentWindowSwitchName)) { 56 std::string native_view = 57 command_line->GetSwitchValueASCII(kParentWindowSwitchName); 58 int64 native_view_handle = 0; 59 if (base::StringToInt64(native_view, &native_view_handle)) { 60 daemon_controller->SetWindow(reinterpret_cast<void*>(native_view_handle)); 61 } else { 62 LOG(WARNING) << "Invalid parameter value --" << kParentWindowSwitchName 63 << "=" << native_view; 64 } 65 } 66 67 // OAuth client (for credential requests). 68 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter( 69 new URLRequestContextGetter(io_thread.message_loop_proxy())); 70 scoped_ptr<OAuthClient> oauth_client( 71 new OAuthClient(url_request_context_getter)); 72 73 net::URLFetcher::SetIgnoreCertificateRequests(true); 74 75 // Create the pairing registry and native messaging host. 76 scoped_refptr<protocol::PairingRegistry> pairing_registry = 77 CreatePairingRegistry(io_thread.message_loop_proxy()); 78 79 // Set up the native messaging channel. 80 scoped_ptr<NativeMessagingChannel> channel( 81 new NativeMessagingChannel(read_file, write_file)); 82 83 scoped_ptr<Me2MeNativeMessagingHost> host( 84 new Me2MeNativeMessagingHost(channel.Pass(), 85 daemon_controller, 86 pairing_registry, 87 oauth_client.Pass())); 88 host->Start(run_loop.QuitClosure()); 89 90 // Run the loop until channel is alive. 91 run_loop.Run(); 92 return kSuccessExitCode; 93 } 94 95 } // namespace remoting 96 97 int main(int argc, char** argv) { 98 // This object instance is required by Chrome code (such as MessageLoop). 99 base::AtExitManager exit_manager; 100 101 CommandLine::Init(argc, argv); 102 remoting::InitHostLogging(); 103 104 return remoting::Me2MeNativeMessagingHostMain(); 105 } 106