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