190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "remoting/host/setup/me2me_native_messaging_host_main.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/at_exit.h" 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/command_line.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file.h" 100de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "base/i18n/icu_util.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/message_loop/message_loop.h" 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/run_loop.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/threading/thread.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "remoting/base/breakpad.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "remoting/base/url_request_context_getter.h" 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "remoting/host/host_exit_codes.h" 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "remoting/host/logging.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "remoting/host/native_messaging/pipe_messaging_channel.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "remoting/host/pairing_registry_delegate.h" 220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "remoting/host/setup/me2me_native_messaging_host.h" 23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "remoting/host/usage_stats_consent.h" 24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_MACOSX) 26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/mac/scoped_nsautorelease_pool.h" 27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif // defined(OS_MACOSX) 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/registry.h" 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/windows_version.h" 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "remoting/host/pairing_registry_delegate_win.h" 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // defined(OS_WIN) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using remoting::protocol::PairingRegistry; 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kParentWindowSwitchName[] = "parent-window"; 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace remoting { 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_WIN) 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool IsProcessElevated() { 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Conceptually, all processes running on a pre-VISTA version of Windows can 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // be considered "elevated". 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (base::win::GetVersion() < base::win::VERSION_VISTA) 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HANDLE process_token; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &process_token); 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::win::ScopedHandle scoped_process_token(process_token); 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Unlike TOKEN_ELEVATION_TYPE which returns TokenElevationTypeDefault when 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // UAC is turned off, TOKEN_ELEVATION will tell you the process is elevated. 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD size; 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TOKEN_ELEVATION elevation; 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetTokenInformation(process_token, TokenElevation, 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &elevation, sizeof(elevation), &size); 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return elevation.TokenIsElevated != 0; 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // defined(OS_WIN) 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int StartMe2MeNativeMessagingHost() { 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_MACOSX) 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Needed so we don't leak objects when threads are created. 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::mac::ScopedNSAutoreleasePool pool; 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif // defined(OS_MACOSX) 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // Required to find the ICU data file, used by some file_util routines. 740de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::i18n::InitializeICU(); 750de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(REMOTING_ENABLE_BREAKPAD) 77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Initialize Breakpad as early as possible. On Mac the command-line needs to 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // be initialized first, so that the preference for crash-reporting can be 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // looked up in the config file. 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (IsUsageStatsAllowed()) { 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InitializeCrashReporting(); 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif // defined(REMOTING_ENABLE_BREAKPAD) 84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Mac OS X requires that the main thread be a UI message loop in order to 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // receive distributed notifications from the System Preferences pane. An 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // IO thread is needed for the pairing registry and URL context getter. 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Thread io_thread("io_thread"); 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) io_thread.StartWithOptions( 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Thread file_thread("file_thread"); 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_thread.StartWithOptions( 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::MessageLoopForUI message_loop; 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::RunLoop run_loop; 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<DaemonController> daemon_controller = 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DaemonController::Create(); 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Pass handle of the native view to the controller so that the UAC prompts 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // are focused properly. 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::CommandLine* command_line = 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CommandLine::ForCurrentProcess(); 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int64 native_view_handle = 0; 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (command_line->HasSwitch(kParentWindowSwitchName)) { 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string native_view = 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) command_line->GetSwitchValueASCII(kParentWindowSwitchName); 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (base::StringToInt64(native_view, &native_view_handle)) { 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) daemon_controller->SetWindow(reinterpret_cast<void*>(native_view_handle)); 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(WARNING) << "Invalid parameter value --" << kParentWindowSwitchName 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "=" << native_view; 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::File read_file; 119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::File write_file; 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool needs_elevation = false; 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN) 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) needs_elevation = !IsProcessElevated(); 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (command_line->HasSwitch(kElevatingSwitchName)) { 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!needs_elevation); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The "elevate" switch is always accompanied by the "input" and "output" 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // switches whose values name named pipes that should be used in place of 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // stdin and stdout. 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(command_line->HasSwitch(kInputSwitchName)); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(command_line->HasSwitch(kOutputSwitchName)); 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // presubmit: allow wstring 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::wstring input_pipe_name = 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) command_line->GetSwitchValueNative(kInputSwitchName); 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // presubmit: allow wstring 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::wstring output_pipe_name = 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) command_line->GetSwitchValueNative(kOutputSwitchName); 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // A NULL SECURITY_ATTRIBUTES signifies that the handle can't be inherited 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) read_file = base::File(CreateFile( 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) input_pipe_name.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) FILE_ATTRIBUTE_NORMAL, NULL)); 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!read_file.IsValid()) { 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "CreateFile failed on '" << input_pipe_name << "'"; 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kInitializationFailed; 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) write_file = base::File(CreateFile( 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) output_pipe_name.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) FILE_ATTRIBUTE_NORMAL, NULL)); 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!write_file.IsValid()) { 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "CreateFile failed on '" << output_pipe_name << "'"; 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kInitializationFailed; 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // GetStdHandle() returns pseudo-handles for stdin and stdout even if 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the hosting executable specifies "Windows" subsystem. However the 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // returned handles are invalid in that case unless standard input and 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // output are redirected to a pipe or file. 162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) read_file = base::File(GetStdHandle(STD_INPUT_HANDLE)); 163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) write_file = base::File(GetStdHandle(STD_OUTPUT_HANDLE)); 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // After the native messaging channel starts the native messaging reader 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // will keep doing blocking read operations on the input named pipe. 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If any other thread tries to perform any operation on STDIN, it will also 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // block because the input named pipe is synchronous (non-overlapped). 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // It is pretty common for a DLL to query the device info (GetFileType) of 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // the STD* handles at startup. So any LoadLibrary request can potentially 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // be blocked. To prevent that from happening we close STDIN and STDOUT 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // handles as soon as we retrieve the corresponding file handles. 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SetStdHandle(STD_INPUT_HANDLE, NULL); 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SetStdHandle(STD_OUTPUT_HANDLE, NULL); 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#elif defined(OS_POSIX) 177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The files will be automatically closed. 178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) read_file = base::File(STDIN_FILENO); 179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) write_file = base::File(STDOUT_FILENO); 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#error Not implemented. 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // OAuth client (for credential requests). IO thread is used for blocking 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> url_request_context_getter( 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new URLRequestContextGetter(io_thread.task_runner(), 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_thread.task_runner())); 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<OAuthClient> oauth_client( 189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new OAuthClient(url_request_context_getter)); 190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) net::URLFetcher::SetIgnoreCertificateRequests(true); 192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Create the pairing registry. 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<PairingRegistry> pairing_registry; 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN) 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::win::RegKey root; 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LONG result = root.Open(HKEY_LOCAL_MACHINE, kPairingRegistryKeyName, 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) KEY_READ); 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result != ERROR_SUCCESS) { 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetLastError(result); 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PLOG(ERROR) << "Failed to open HKLM\\" << kPairingRegistryKeyName; 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kInitializationFailed; 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::win::RegKey unprivileged; 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result = unprivileged.Open(root.Handle(), kPairingRegistrySecretsKeyName, 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) needs_elevation ? KEY_READ : KEY_READ | KEY_WRITE); 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result != ERROR_SUCCESS) { 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetLastError(result); 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PLOG(ERROR) << "Failed to open HKLM\\" << kPairingRegistrySecretsKeyName 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "\\" << kPairingRegistrySecretsKeyName; 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kInitializationFailed; 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only try to open the privileged key if the current process is elevated. 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::win::RegKey privileged; 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!needs_elevation) { 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result = privileged.Open(root.Handle(), kPairingRegistryClientsKeyName, 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) KEY_READ | KEY_WRITE); 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result != ERROR_SUCCESS) { 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetLastError(result); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PLOG(ERROR) << "Failed to open HKLM\\" << kPairingRegistryKeyName << "\\" 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << kPairingRegistryClientsKeyName; 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kInitializationFailed; 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Initialize the pairing registry delegate and set the root keys. 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<PairingRegistryDelegateWin> delegate( 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new PairingRegistryDelegateWin()); 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!delegate->SetRootKeys(privileged.Take(), unprivileged.Take())) 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kInitializationFailed; 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pairing_registry = new PairingRegistry( 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci io_thread.task_runner(), 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate.PassAs<PairingRegistry::Delegate>()); 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else // defined(OS_WIN) 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pairing_registry = 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreatePairingRegistry(io_thread.task_runner()); 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // !defined(OS_WIN) 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Set up the native messaging channel. 2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<extensions::NativeMessagingChannel> channel( 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new PipeMessagingChannel(read_file.Pass(), write_file.Pass())); 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Create the native messaging host. 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<Me2MeNativeMessagingHost> host( 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new Me2MeNativeMessagingHost( 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) needs_elevation, 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static_cast<intptr_t>(native_view_handle), 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel.Pass(), 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) daemon_controller, 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pairing_registry, 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) oauth_client.Pass())); 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) host->Start(run_loop.QuitClosure()); 257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Run the loop until channel is alive. 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) run_loop.Run(); 260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return kSuccessExitCode; 261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int Me2MeNativeMessagingHostMain(int argc, char** argv) { 26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // This object instance is required by Chrome code (such as MessageLoop). 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::AtExitManager exit_manager; 26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CommandLine::Init(argc, argv); 26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) remoting::InitHostLogging(); 26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return StartMe2MeNativeMessagingHost(); 27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace remoting 274