Index: remoting/host/setup/daemon_installer_win.cc |
diff --git a/remoting/host/setup/daemon_installer_win.cc b/remoting/host/setup/daemon_installer_win.cc |
deleted file mode 100644 |
index a125dfeb819b550892b0614dd1b854e6d8919a28..0000000000000000000000000000000000000000 |
--- a/remoting/host/setup/daemon_installer_win.cc |
+++ /dev/null |
@@ -1,412 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "remoting/host/setup/daemon_installer_win.h" |
- |
-#include <windows.h> |
- |
-#include "base/bind.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/process/launch.h" |
-#include "base/strings/string16.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/time/time.h" |
-#include "base/timer/timer.h" |
-#include "base/win/object_watcher.h" |
-#include "base/win/registry.h" |
-#include "base/win/scoped_bstr.h" |
-#include "base/win/scoped_comptr.h" |
-#include "base/win/scoped_handle.h" |
-#include "base/win/scoped_variant.h" |
-#include "base/win/windows_version.h" |
-#include "google_update/google_update_idl.h" |
-#include "remoting/base/dispatch_win.h" |
-#include "remoting/host/win/omaha.h" |
- |
-using base::win::ScopedBstr; |
-using base::win::ScopedComPtr; |
-using base::win::ScopedVariant; |
- |
-namespace { |
- |
-// ProgID of the per-machine Omaha COM server. |
-const wchar_t kGoogleUpdate[] = L"GoogleUpdate.Update3WebMachine"; |
- |
-// The COM elevation moniker for the per-machine Omaha COM server. |
-const wchar_t kGoogleUpdateElevationMoniker[] = |
- L"Elevation:Administrator!new:GoogleUpdate.Update3WebMachine"; |
- |
-// The registry key where the configuration of Omaha is stored. |
-const wchar_t kOmahaUpdateKeyName[] = L"Software\\Google\\Update"; |
- |
-// The name of the value where the full path to GoogleUpdate.exe is stored. |
-const wchar_t kOmahaPathValueName[] = L"path"; |
- |
-// The command line format string for GoogleUpdate.exe |
-const wchar_t kGoogleUpdateCommandLineFormat[] = |
- L"\"%ls\" /install \"bundlename=Chromoting%%20Host&appguid=%ls&" |
- L"appname=Chromoting%%20Host&needsadmin=True&lang=%ls\""; |
- |
-// TODO(alexeypa): Get the desired laungage from the web app. |
-const wchar_t kOmahaLanguage[] = L"en"; |
- |
-// An empty string for optional parameters. |
-const wchar_t kOmahaEmpty[] = L""; |
- |
-// The installation status polling interval. |
-const int kOmahaPollIntervalMs = 500; |
- |
-} // namespace |
- |
-namespace remoting { |
- |
-// This class implements on-demand installation of the Chromoting Host via |
-// per-machine Omaha instance. |
-class DaemonComInstallerWin : public DaemonInstallerWin { |
- public: |
- DaemonComInstallerWin(const ScopedComPtr<IDispatch>& update3, |
- const CompletionCallback& done); |
- |
- // DaemonInstallerWin implementation. |
- virtual void Install() override; |
- |
- private: |
- // Polls the installation status performing state-specific actions (such as |
- // starting installation once download has finished). |
- void PollInstallationStatus(); |
- |
- // Omaha interfaces. |
- ScopedVariant app_; |
- ScopedVariant bundle_; |
- ScopedComPtr<IDispatch> update3_; |
- |
- base::Timer polling_timer_; |
-}; |
- |
-// This class implements on-demand installation of the Chromoting Host by |
-// launching a per-user instance of Omaha and requesting elevation. |
-class DaemonCommandLineInstallerWin |
- : public DaemonInstallerWin, |
- public base::win::ObjectWatcher::Delegate { |
- public: |
- DaemonCommandLineInstallerWin(const CompletionCallback& done); |
- ~DaemonCommandLineInstallerWin(); |
- |
- // DaemonInstallerWin implementation. |
- virtual void Install() override; |
- |
- // base::win::ObjectWatcher::Delegate implementation. |
- virtual void OnObjectSignaled(HANDLE object) override; |
- |
- private: |
- // Handle of the launched process. |
- base::Process process_; |
- |
- // Used to determine when the launched process terminates. |
- base::win::ObjectWatcher process_watcher_; |
-}; |
- |
-DaemonComInstallerWin::DaemonComInstallerWin( |
- const ScopedComPtr<IDispatch>& update3, |
- const CompletionCallback& done) |
- : DaemonInstallerWin(done), |
- update3_(update3), |
- polling_timer_( |
- FROM_HERE, |
- base::TimeDelta::FromMilliseconds(kOmahaPollIntervalMs), |
- base::Bind(&DaemonComInstallerWin::PollInstallationStatus, |
- base::Unretained(this)), |
- false) { |
-} |
- |
-void DaemonComInstallerWin::Install() { |
- // Create an app bundle. |
- HRESULT hr = dispatch::Invoke(update3_.get(), L"createAppBundleWeb", |
- DISPATCH_METHOD, bundle_.Receive()); |
- if (FAILED(hr)) { |
- Done(hr); |
- return; |
- } |
- if (bundle_.type() != VT_DISPATCH) { |
- Done(DISP_E_TYPEMISMATCH); |
- return; |
- } |
- |
- hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"initialize", DISPATCH_METHOD, |
- nullptr); |
- if (FAILED(hr)) { |
- Done(hr); |
- return; |
- } |
- |
- // Add Chromoting Host to the bundle. |
- ScopedVariant appid(kHostOmahaAppid); |
- ScopedVariant empty(kOmahaEmpty); |
- ScopedVariant language(kOmahaLanguage); |
- hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"createApp", DISPATCH_METHOD, |
- appid, empty, language, empty, nullptr); |
- if (FAILED(hr)) { |
- Done(hr); |
- return; |
- } |
- |
- hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"checkForUpdate", |
- DISPATCH_METHOD, nullptr); |
- if (FAILED(hr)) { |
- Done(hr); |
- return; |
- } |
- |
- hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"appWeb", |
- DISPATCH_PROPERTYGET, ScopedVariant(0), app_.Receive()); |
- if (FAILED(hr)) { |
- Done(hr); |
- return; |
- } |
- if (app_.type() != VT_DISPATCH) { |
- Done(DISP_E_TYPEMISMATCH); |
- return; |
- } |
- |
- // Now poll for the installation status. |
- PollInstallationStatus(); |
-} |
- |
-void DaemonComInstallerWin::PollInstallationStatus() { |
- // Get the current application installation state. |
- // N.B. The object underlying the ICurrentState interface has static data that |
- // does not get updated as the server state changes. To get the most "current" |
- // state, the currentState property needs to be queried again. |
- ScopedVariant current_state; |
- HRESULT hr = dispatch::Invoke(V_DISPATCH(&app_), L"currentState", |
- DISPATCH_PROPERTYGET, current_state.Receive()); |
- if (FAILED(hr)) { |
- Done(hr); |
- return; |
- } |
- if (current_state.type() != VT_DISPATCH) { |
- Done(DISP_E_TYPEMISMATCH); |
- return; |
- } |
- |
- ScopedVariant state; |
- hr = dispatch::Invoke(V_DISPATCH(¤t_state), L"stateValue", |
- DISPATCH_PROPERTYGET, state.Receive()); |
- if (state.type() != VT_I4) { |
- Done(DISP_E_TYPEMISMATCH); |
- return; |
- } |
- |
- // Perform state-specific actions. |
- switch (V_I4(&state)) { |
- case STATE_INIT: |
- case STATE_WAITING_TO_CHECK_FOR_UPDATE: |
- case STATE_CHECKING_FOR_UPDATE: |
- case STATE_WAITING_TO_DOWNLOAD: |
- case STATE_RETRYING_DOWNLOAD: |
- case STATE_DOWNLOADING: |
- case STATE_WAITING_TO_INSTALL: |
- case STATE_INSTALLING: |
- case STATE_PAUSED: |
- break; |
- |
- case STATE_UPDATE_AVAILABLE: |
- hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"download", |
- DISPATCH_METHOD, nullptr); |
- if (FAILED(hr)) { |
- Done(hr); |
- return; |
- } |
- break; |
- |
- case STATE_DOWNLOAD_COMPLETE: |
- case STATE_EXTRACTING: |
- case STATE_APPLYING_DIFFERENTIAL_PATCH: |
- case STATE_READY_TO_INSTALL: |
- hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"install", |
- DISPATCH_METHOD, nullptr); |
- if (FAILED(hr)) { |
- Done(hr); |
- return; |
- } |
- break; |
- |
- case STATE_INSTALL_COMPLETE: |
- case STATE_NO_UPDATE: |
- // Installation complete or not required. Report success. |
- Done(S_OK); |
- return; |
- |
- case STATE_ERROR: { |
- ScopedVariant error_code; |
- hr = dispatch::Invoke(V_DISPATCH(¤t_state), L"errorCode", |
- DISPATCH_PROPERTYGET, error_code.Receive()); |
- if (FAILED(hr)) { |
- Done(hr); |
- return; |
- } |
- if (error_code.type() != VT_UI4) { |
- Done(DISP_E_TYPEMISMATCH); |
- return; |
- } |
- Done(V_UI4(&error_code)); |
- return; |
- } |
- |
- default: |
- LOG(ERROR) << "Unknown bundle state: " << V_I4(&state) << "."; |
- Done(E_FAIL); |
- return; |
- } |
- |
- // Keep polling. |
- polling_timer_.Reset(); |
-} |
- |
-DaemonCommandLineInstallerWin::DaemonCommandLineInstallerWin( |
- const CompletionCallback& done) : DaemonInstallerWin(done) { |
-} |
- |
-DaemonCommandLineInstallerWin::~DaemonCommandLineInstallerWin() { |
- process_watcher_.StopWatching(); |
-} |
- |
-void DaemonCommandLineInstallerWin::Install() { |
- // Get the full path to GoogleUpdate.exe from the registry. |
- base::win::RegKey update_key; |
- LONG result = update_key.Open(HKEY_CURRENT_USER, |
- kOmahaUpdateKeyName, |
- KEY_READ); |
- if (result != ERROR_SUCCESS) { |
- Done(HRESULT_FROM_WIN32(result)); |
- return; |
- } |
- |
- // presubmit: allow wstring |
- std::wstring google_update; |
- result = update_key.ReadValue(kOmahaPathValueName, &google_update); |
- if (result != ERROR_SUCCESS) { |
- Done(HRESULT_FROM_WIN32(result)); |
- return; |
- } |
- |
- // Launch the updater process and wait for its termination. |
- base::string16 command_line = base::WideToUTF16( |
- base::StringPrintf(kGoogleUpdateCommandLineFormat, |
- google_update.c_str(), |
- kHostOmahaAppid, |
- kOmahaLanguage)); |
- |
- base::LaunchOptions options; |
- process_ = base::LaunchProcess(command_line, options); |
- if (!process_.IsValid()) { |
- result = GetLastError(); |
- Done(HRESULT_FROM_WIN32(result)); |
- return; |
- } |
- |
- if (!process_watcher_.StartWatching(process_.Handle(), this)) { |
- result = GetLastError(); |
- Done(HRESULT_FROM_WIN32(result)); |
- return; |
- } |
-} |
- |
-void DaemonCommandLineInstallerWin::OnObjectSignaled(HANDLE object) { |
- // Check if the updater process returned success. |
- DWORD exit_code; |
- if (GetExitCodeProcess(process_.Handle(), &exit_code) && exit_code == 0) { |
- Done(S_OK); |
- } else { |
- Done(E_FAIL); |
- } |
-} |
- |
-DaemonInstallerWin::DaemonInstallerWin(const CompletionCallback& done) |
- : done_(done) { |
-} |
- |
-DaemonInstallerWin::~DaemonInstallerWin() { |
-} |
- |
-void DaemonInstallerWin::Done(HRESULT result) { |
- CompletionCallback done = done_; |
- done_.Reset(); |
- done.Run(result); |
-} |
- |
-// static |
-scoped_ptr<DaemonInstallerWin> DaemonInstallerWin::Create( |
- HWND window_handle, |
- CompletionCallback done) { |
- HRESULT result = E_FAIL; |
- ScopedComPtr<IDispatch> update3; |
- |
- // Check if the machine instance of Omaha is available. The COM elevation is |
- // supported on Vista+, so on XP/W2K3 we assume that we are running under |
- // a privileged user and get ACCESS_DENIED later if we are not. |
- if (base::win::GetVersion() < base::win::VERSION_VISTA) { |
- CLSID class_id; |
- result = CLSIDFromProgID(kGoogleUpdate, &class_id); |
- if (SUCCEEDED(result)) { |
- result = CoCreateInstance(class_id, |
- nullptr, |
- CLSCTX_LOCAL_SERVER, |
- IID_IDispatch, |
- update3.ReceiveVoid()); |
- } |
- } else { |
- BIND_OPTS3 bind_options; |
- memset(&bind_options, 0, sizeof(bind_options)); |
- bind_options.cbStruct = sizeof(bind_options); |
- bind_options.hwnd = GetTopLevelWindow(window_handle); |
- bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; |
- result = CoGetObject(kGoogleUpdateElevationMoniker, |
- &bind_options, |
- IID_IDispatch, |
- update3.ReceiveVoid()); |
- } |
- |
- if (result == CO_E_CLASSSTRING) { |
- // The machine instance of Omaha is not available so we will have to run |
- // GoogleUpdate.exe manually passing "needsadmin=True". This will cause |
- // Omaha to install the machine instance first and then install Chromoting |
- // Host. |
- return make_scoped_ptr(new DaemonCommandLineInstallerWin(done)); |
- } |
- |
- if (!SUCCEEDED(result)) { |
- // The user declined the UAC prompt or some other error occured. |
- done.Run(result); |
- return nullptr; |
- } |
- |
- // The machine instance of Omaha is available and we successfully passed |
- // the UAC prompt. |
- return make_scoped_ptr(new DaemonComInstallerWin(update3, done)); |
-} |
- |
-HWND GetTopLevelWindow(HWND window) { |
- if (window == nullptr) { |
- return nullptr; |
- } |
- |
- for (;;) { |
- LONG style = GetWindowLong(window, GWL_STYLE); |
- if ((style & WS_OVERLAPPEDWINDOW) == WS_OVERLAPPEDWINDOW || |
- (style & WS_POPUP) == WS_POPUP) { |
- return window; |
- } |
- |
- HWND parent = GetAncestor(window, GA_PARENT); |
- if (parent == nullptr) { |
- return window; |
- } |
- |
- window = parent; |
- } |
-} |
- |
-} // namespace remoting |