| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/host/plugin/daemon_installer_win.h" | 5 #include "remoting/host/plugin/daemon_installer_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 11 #include "base/process_util.h" | 11 #include "base/process_util.h" |
| 12 #include "base/string16.h" | 12 #include "base/string16.h" |
| 13 #include "base/stringize_macros.h" | 13 #include "base/stringize_macros.h" |
| 14 #include "base/stringprintf.h" | 14 #include "base/stringprintf.h" |
| 15 #include "base/time.h" | 15 #include "base/time.h" |
| 16 #include "base/timer.h" | 16 #include "base/timer.h" |
| 17 #include "base/win/object_watcher.h" | 17 #include "base/win/object_watcher.h" |
| 18 #include "base/win/registry.h" | 18 #include "base/win/registry.h" |
| 19 #include "base/win/scoped_bstr.h" | 19 #include "base/win/scoped_bstr.h" |
| 20 #include "base/win/scoped_comptr.h" | 20 #include "base/win/scoped_comptr.h" |
| 21 #include "base/win/scoped_handle.h" | 21 #include "base/win/scoped_handle.h" |
| 22 #include "base/win/scoped_variant.h" |
| 23 #include "remoting/base/dispatch_win.h" |
| 22 | 24 |
| 23 namespace omaha { | 25 namespace omaha { |
| 24 #include "google_update/google_update_idl.h" | 26 #include "google_update/google_update_idl.h" |
| 25 } // namespace omaha | 27 } // namespace omaha |
| 26 | 28 |
| 27 #include "remoting/host/constants.h" | 29 #include "remoting/host/constants.h" |
| 28 | 30 |
| 29 using base::win::ScopedBstr; | 31 using base::win::ScopedBstr; |
| 30 using base::win::ScopedComPtr; | 32 using base::win::ScopedComPtr; |
| 33 using base::win::ScopedVariant; |
| 31 | 34 |
| 32 namespace { | 35 namespace { |
| 33 | 36 |
| 34 // The COM elevation moniker for Omaha. | 37 // The COM elevation moniker for Omaha. |
| 35 const char16 kOmahaElevationMoniker[] = | 38 const char16 kOmahaElevationMoniker[] = |
| 36 TO_L_STRING("Elevation:Administrator!new:GoogleUpdate.Update3WebMachine"); | 39 TO_L_STRING("Elevation:Administrator!new:GoogleUpdate.Update3WebMachine"); |
| 37 | 40 |
| 38 // The registry key where the configuration of Omaha is stored. | 41 // The registry key where the configuration of Omaha is stored. |
| 39 const char16 kOmahaUpdateKeyName[] = TO_L_STRING("Software\\Google\\Update"); | 42 const char16 kOmahaUpdateKeyName[] = TO_L_STRING("Software\\Google\\Update"); |
| 40 | 43 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 56 const int kOmahaPollIntervalMs = 500; | 59 const int kOmahaPollIntervalMs = 500; |
| 57 | 60 |
| 58 } // namespace | 61 } // namespace |
| 59 | 62 |
| 60 namespace remoting { | 63 namespace remoting { |
| 61 | 64 |
| 62 // This class implements on-demand installation of the Chromoting Host via | 65 // This class implements on-demand installation of the Chromoting Host via |
| 63 // per-machine Omaha instance. | 66 // per-machine Omaha instance. |
| 64 class DaemonComInstallerWin : public DaemonInstallerWin { | 67 class DaemonComInstallerWin : public DaemonInstallerWin { |
| 65 public: | 68 public: |
| 66 DaemonComInstallerWin(const ScopedComPtr<omaha::IGoogleUpdate3Web>& update3, | 69 DaemonComInstallerWin(const ScopedComPtr<IDispatch>& update3, |
| 67 const CompletionCallback& done); | 70 const CompletionCallback& done); |
| 68 | 71 |
| 69 // DaemonInstallerWin implementation. | 72 // DaemonInstallerWin implementation. |
| 70 virtual void Install() OVERRIDE; | 73 virtual void Install() OVERRIDE; |
| 71 | 74 |
| 72 private: | 75 private: |
| 73 // Polls the installation status performing state-specific actions (such as | 76 // Polls the installation status performing state-specific actions (such as |
| 74 // starting installation once download has finished). | 77 // starting installation once download has finished). |
| 75 void PollInstallationStatus(); | 78 void PollInstallationStatus(); |
| 76 | 79 |
| 77 // Omaha interfaces. | 80 // Omaha interfaces. |
| 78 ScopedComPtr<omaha::IAppWeb> app_; | 81 ScopedVariant app_; |
| 79 ScopedComPtr<omaha::IAppBundleWeb> bundle_; | 82 ScopedVariant bundle_; |
| 80 ScopedComPtr<omaha::IGoogleUpdate3Web> update3_; | 83 ScopedComPtr<IDispatch> update3_; |
| 81 | 84 |
| 82 base::Timer polling_timer_; | 85 base::Timer polling_timer_; |
| 83 }; | 86 }; |
| 84 | 87 |
| 85 // This class implements on-demand installation of the Chromoting Host by | 88 // This class implements on-demand installation of the Chromoting Host by |
| 86 // launching a per-user instance of Omaha and requesting elevation. | 89 // launching a per-user instance of Omaha and requesting elevation. |
| 87 class DaemonCommandLineInstallerWin | 90 class DaemonCommandLineInstallerWin |
| 88 : public DaemonInstallerWin, | 91 : public DaemonInstallerWin, |
| 89 public base::win::ObjectWatcher::Delegate { | 92 public base::win::ObjectWatcher::Delegate { |
| 90 public: | 93 public: |
| 91 DaemonCommandLineInstallerWin(const CompletionCallback& done); | 94 DaemonCommandLineInstallerWin(const CompletionCallback& done); |
| 92 ~DaemonCommandLineInstallerWin(); | 95 ~DaemonCommandLineInstallerWin(); |
| 93 | 96 |
| 94 // DaemonInstallerWin implementation. | 97 // DaemonInstallerWin implementation. |
| 95 virtual void Install() OVERRIDE; | 98 virtual void Install() OVERRIDE; |
| 96 | 99 |
| 97 // base::win::ObjectWatcher::Delegate implementation. | 100 // base::win::ObjectWatcher::Delegate implementation. |
| 98 virtual void OnObjectSignaled(HANDLE object) OVERRIDE; | 101 virtual void OnObjectSignaled(HANDLE object) OVERRIDE; |
| 99 | 102 |
| 100 private: | 103 private: |
| 101 // Handle of the launched process. | 104 // Handle of the launched process. |
| 102 base::win::ScopedHandle process_; | 105 base::win::ScopedHandle process_; |
| 103 | 106 |
| 104 // Used to determine when the launched process terminates. | 107 // Used to determine when the launched process terminates. |
| 105 base::win::ObjectWatcher process_watcher_; | 108 base::win::ObjectWatcher process_watcher_; |
| 106 }; | 109 }; |
| 107 | 110 |
| 108 DaemonComInstallerWin::DaemonComInstallerWin( | 111 DaemonComInstallerWin::DaemonComInstallerWin( |
| 109 const ScopedComPtr<omaha::IGoogleUpdate3Web>& update3, | 112 const ScopedComPtr<IDispatch>& update3, |
| 110 const CompletionCallback& done) | 113 const CompletionCallback& done) |
| 111 : DaemonInstallerWin(done), | 114 : DaemonInstallerWin(done), |
| 112 update3_(update3), | 115 update3_(update3), |
| 113 ALLOW_THIS_IN_INITIALIZER_LIST( | 116 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 114 polling_timer_( | 117 polling_timer_( |
| 115 FROM_HERE, | 118 FROM_HERE, |
| 116 base::TimeDelta::FromMilliseconds(kOmahaPollIntervalMs), | 119 base::TimeDelta::FromMilliseconds(kOmahaPollIntervalMs), |
| 117 base::Bind(&DaemonComInstallerWin::PollInstallationStatus, | 120 base::Bind(&DaemonComInstallerWin::PollInstallationStatus, |
| 118 base::Unretained(this)), | 121 base::Unretained(this)), |
| 119 false)) { | 122 false)) { |
| 120 } | 123 } |
| 121 | 124 |
| 122 void DaemonComInstallerWin::Install() { | 125 void DaemonComInstallerWin::Install() { |
| 123 // Create an app bundle. | 126 // Create an app bundle. |
| 124 ScopedComPtr<IDispatch> dispatch; | 127 HRESULT hr = dispatch::Invoke(update3_.get(), L"createAppBundleWeb", |
| 125 HRESULT hr = update3_->createAppBundleWeb(dispatch.Receive()); | 128 DISPATCH_METHOD, bundle_.Receive()); |
| 126 if (FAILED(hr)) { | 129 if (FAILED(hr)) { |
| 127 Done(hr); | 130 Done(hr); |
| 128 return; | 131 return; |
| 129 } | 132 } |
| 130 | 133 if (bundle_.type() != VT_DISPATCH) { |
| 131 hr = dispatch.QueryInterface(omaha::IID_IAppBundleWeb, bundle_.ReceiveVoid()); | 134 Done(DISP_E_TYPEMISMATCH); |
| 132 if (FAILED(hr)) { | |
| 133 Done(hr); | |
| 134 return; | 135 return; |
| 135 } | 136 } |
| 136 | 137 |
| 137 hr = bundle_->initialize(); | 138 hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"initialize", DISPATCH_METHOD, |
| 139 NULL); |
| 138 if (FAILED(hr)) { | 140 if (FAILED(hr)) { |
| 139 Done(hr); | 141 Done(hr); |
| 140 return; | 142 return; |
| 141 } | 143 } |
| 142 | 144 |
| 143 // Add Chromoting Host to the bundle. | 145 // Add Chromoting Host to the bundle. |
| 144 ScopedBstr appid(kHostOmahaAppid); | 146 ScopedVariant appid(kHostOmahaAppid); |
| 145 ScopedBstr empty(kOmahaEmpty); | 147 ScopedVariant empty(kOmahaEmpty); |
| 146 ScopedBstr language(kOmahaLanguage); | 148 ScopedVariant language(kOmahaLanguage); |
| 147 hr = bundle_->createApp(appid, empty, language, empty); | 149 hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"createApp", DISPATCH_METHOD, |
| 150 appid, empty, language, empty, NULL); |
| 148 if (FAILED(hr)) { | 151 if (FAILED(hr)) { |
| 149 Done(hr); | 152 Done(hr); |
| 150 return; | 153 return; |
| 151 } | 154 } |
| 152 | 155 |
| 153 hr = bundle_->checkForUpdate(); | 156 hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"checkForUpdate", |
| 157 DISPATCH_METHOD, NULL); |
| 154 if (FAILED(hr)) { | 158 if (FAILED(hr)) { |
| 155 Done(hr); | 159 Done(hr); |
| 156 return; | 160 return; |
| 157 } | 161 } |
| 158 | 162 |
| 159 dispatch.Release(); | 163 hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"appWeb", |
| 160 hr = bundle_->get_appWeb(0, dispatch.Receive()); | 164 DISPATCH_PROPERTYGET, ScopedVariant(0), app_.Receive()); |
| 161 if (FAILED(hr)) { | 165 if (FAILED(hr)) { |
| 162 Done(hr); | 166 Done(hr); |
| 163 return; | 167 return; |
| 164 } | 168 } |
| 165 | 169 if (app_.type() != VT_DISPATCH) { |
| 166 hr = dispatch.QueryInterface(omaha::IID_IAppWeb, | 170 Done(DISP_E_TYPEMISMATCH); |
| 167 app_.ReceiveVoid()); | |
| 168 if (FAILED(hr)) { | |
| 169 Done(hr); | |
| 170 return; | 171 return; |
| 171 } | 172 } |
| 172 | 173 |
| 173 // Now poll for the installation status. | 174 // Now poll for the installation status. |
| 174 PollInstallationStatus(); | 175 PollInstallationStatus(); |
| 175 } | 176 } |
| 176 | 177 |
| 177 void DaemonComInstallerWin::PollInstallationStatus() { | 178 void DaemonComInstallerWin::PollInstallationStatus() { |
| 178 // Get the current application installation state. | 179 // Get the current application installation state. |
| 179 // N.B. The object underlying the ICurrentState interface has static data that | 180 // N.B. The object underlying the ICurrentState interface has static data that |
| 180 // does not get updated as the server state changes. To get the most "current" | 181 // does not get updated as the server state changes. To get the most "current" |
| 181 // state, the currentState property needs to be queried again. | 182 // state, the currentState property needs to be queried again. |
| 182 ScopedComPtr<IDispatch> dispatch; | 183 ScopedVariant current_state; |
| 183 HRESULT hr = app_->get_currentState(dispatch.Receive()); | 184 HRESULT hr = dispatch::Invoke(V_DISPATCH(&app_), L"currentState", |
| 185 DISPATCH_PROPERTYGET, current_state.Receive()); |
| 184 if (FAILED(hr)) { | 186 if (FAILED(hr)) { |
| 185 Done(hr); | 187 Done(hr); |
| 186 return; | 188 return; |
| 187 } | 189 } |
| 190 if (current_state.type() != VT_DISPATCH) { |
| 191 Done(DISP_E_TYPEMISMATCH); |
| 192 return; |
| 193 } |
| 188 | 194 |
| 189 ScopedComPtr<omaha::ICurrentState> current_state; | 195 ScopedVariant state; |
| 190 hr = dispatch.QueryInterface(omaha::IID_ICurrentState, | 196 hr = dispatch::Invoke(V_DISPATCH(¤t_state), L"stateValue", |
| 191 current_state.ReceiveVoid()); | 197 DISPATCH_PROPERTYGET, state.Receive()); |
| 192 if (FAILED(hr)) { | 198 if (FAILED(hr)) { |
| 193 Done(hr); | 199 Done(hr); |
| 194 return; | 200 return; |
| 195 } | 201 } |
| 196 | 202 if (state.type() != VT_I4) { |
| 197 LONG state; | 203 Done(DISP_E_TYPEMISMATCH); |
| 198 hr = current_state->get_stateValue(&state); | |
| 199 if (FAILED(hr)) { | |
| 200 Done(hr); | |
| 201 return; | 204 return; |
| 202 } | 205 } |
| 203 | 206 |
| 204 // Perform state-specific actions. | 207 // Perform state-specific actions. |
| 205 switch (state) { | 208 switch (V_I4(&state)) { |
| 206 case omaha::STATE_INIT: | 209 case omaha::STATE_INIT: |
| 207 case omaha::STATE_WAITING_TO_CHECK_FOR_UPDATE: | 210 case omaha::STATE_WAITING_TO_CHECK_FOR_UPDATE: |
| 208 case omaha::STATE_CHECKING_FOR_UPDATE: | 211 case omaha::STATE_CHECKING_FOR_UPDATE: |
| 209 case omaha::STATE_WAITING_TO_DOWNLOAD: | 212 case omaha::STATE_WAITING_TO_DOWNLOAD: |
| 210 case omaha::STATE_RETRYING_DOWNLOAD: | 213 case omaha::STATE_RETRYING_DOWNLOAD: |
| 211 case omaha::STATE_DOWNLOADING: | 214 case omaha::STATE_DOWNLOADING: |
| 212 case omaha::STATE_WAITING_TO_INSTALL: | 215 case omaha::STATE_WAITING_TO_INSTALL: |
| 213 case omaha::STATE_INSTALLING: | 216 case omaha::STATE_INSTALLING: |
| 214 case omaha::STATE_PAUSED: | 217 case omaha::STATE_PAUSED: |
| 215 break; | 218 break; |
| 216 | 219 |
| 217 case omaha::STATE_UPDATE_AVAILABLE: | 220 case omaha::STATE_UPDATE_AVAILABLE: |
| 218 hr = bundle_->download(); | 221 hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"download", |
| 222 DISPATCH_METHOD, NULL); |
| 219 if (FAILED(hr)) { | 223 if (FAILED(hr)) { |
| 220 Done(hr); | 224 Done(hr); |
| 221 return; | 225 return; |
| 222 } | 226 } |
| 223 break; | 227 break; |
| 224 | 228 |
| 225 case omaha::STATE_DOWNLOAD_COMPLETE: | 229 case omaha::STATE_DOWNLOAD_COMPLETE: |
| 226 case omaha::STATE_EXTRACTING: | 230 case omaha::STATE_EXTRACTING: |
| 227 case omaha::STATE_APPLYING_DIFFERENTIAL_PATCH: | 231 case omaha::STATE_APPLYING_DIFFERENTIAL_PATCH: |
| 228 case omaha::STATE_READY_TO_INSTALL: | 232 case omaha::STATE_READY_TO_INSTALL: |
| 229 hr = bundle_->install(); | 233 hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"install", |
| 234 DISPATCH_METHOD, NULL); |
| 230 if (FAILED(hr)) { | 235 if (FAILED(hr)) { |
| 231 Done(hr); | 236 Done(hr); |
| 232 return; | 237 return; |
| 233 } | 238 } |
| 234 break; | 239 break; |
| 235 | 240 |
| 236 case omaha::STATE_INSTALL_COMPLETE: | 241 case omaha::STATE_INSTALL_COMPLETE: |
| 237 case omaha::STATE_NO_UPDATE: | 242 case omaha::STATE_NO_UPDATE: |
| 238 // Installation complete or not required. Report success. | 243 // Installation complete or not required. Report success. |
| 239 Done(S_OK); | 244 Done(S_OK); |
| 240 return; | 245 return; |
| 241 | 246 |
| 242 case omaha::STATE_ERROR: { | 247 case omaha::STATE_ERROR: { |
| 243 HRESULT error_code; | 248 ScopedVariant error_code; |
| 244 hr = current_state->get_errorCode(&error_code); | 249 hr = dispatch::Invoke(V_DISPATCH(¤t_state), L"errorCode", |
| 250 DISPATCH_PROPERTYGET, error_code.Receive()); |
| 245 if (FAILED(hr)) { | 251 if (FAILED(hr)) { |
| 246 error_code = hr; | 252 Done(hr); |
| 253 return; |
| 247 } | 254 } |
| 248 Done(error_code); | 255 if (error_code.type() != VT_UI4) { |
| 256 Done(DISP_E_TYPEMISMATCH); |
| 257 return; |
| 258 } |
| 259 Done(V_UI4(&error_code)); |
| 249 return; | 260 return; |
| 250 } | 261 } |
| 251 | 262 |
| 252 default: | 263 default: |
| 253 LOG(ERROR) << "Unknown bundle state: " << state << "."; | 264 LOG(ERROR) << "Unknown bundle state: " << V_I4(&state) << "."; |
| 254 Done(E_FAIL); | 265 Done(E_FAIL); |
| 255 return; | 266 return; |
| 256 } | 267 } |
| 257 | 268 |
| 258 // Keep polling. | 269 // Keep polling. |
| 259 polling_timer_.Reset(); | 270 polling_timer_.Reset(); |
| 260 } | 271 } |
| 261 | 272 |
| 262 DaemonCommandLineInstallerWin::DaemonCommandLineInstallerWin( | 273 DaemonCommandLineInstallerWin::DaemonCommandLineInstallerWin( |
| 263 const CompletionCallback& done) : DaemonInstallerWin(done) { | 274 const CompletionCallback& done) : DaemonInstallerWin(done) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 scoped_ptr<DaemonInstallerWin> DaemonInstallerWin::Create( | 343 scoped_ptr<DaemonInstallerWin> DaemonInstallerWin::Create( |
| 333 HWND window_handle, | 344 HWND window_handle, |
| 334 CompletionCallback done) { | 345 CompletionCallback done) { |
| 335 // Check if the machine instance of Omaha is available. | 346 // Check if the machine instance of Omaha is available. |
| 336 BIND_OPTS3 bind_options; | 347 BIND_OPTS3 bind_options; |
| 337 memset(&bind_options, 0, sizeof(bind_options)); | 348 memset(&bind_options, 0, sizeof(bind_options)); |
| 338 bind_options.cbStruct = sizeof(bind_options); | 349 bind_options.cbStruct = sizeof(bind_options); |
| 339 bind_options.hwnd = GetTopLevelWindow(window_handle); | 350 bind_options.hwnd = GetTopLevelWindow(window_handle); |
| 340 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; | 351 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; |
| 341 | 352 |
| 342 ScopedComPtr<omaha::IGoogleUpdate3Web> update3; | 353 ScopedComPtr<IDispatch> update3; |
| 343 HRESULT result = ::CoGetObject( | 354 HRESULT result = ::CoGetObject( |
| 344 kOmahaElevationMoniker, | 355 kOmahaElevationMoniker, |
| 345 &bind_options, | 356 &bind_options, |
| 346 omaha::IID_IGoogleUpdate3Web, | 357 IID_IDispatch, |
| 347 update3.ReceiveVoid()); | 358 update3.ReceiveVoid()); |
| 348 if (SUCCEEDED(result)) { | 359 if (SUCCEEDED(result)) { |
| 349 // The machine instance of Omaha is available and we successfully passed | 360 // The machine instance of Omaha is available and we successfully passed |
| 350 // the UAC prompt. | 361 // the UAC prompt. |
| 351 return scoped_ptr<DaemonInstallerWin>( | 362 return scoped_ptr<DaemonInstallerWin>( |
| 352 new DaemonComInstallerWin(update3, done)); | 363 new DaemonComInstallerWin(update3, done)); |
| 353 } else if (result == CO_E_CLASSSTRING) { | 364 } else if (result == CO_E_CLASSSTRING) { |
| 354 // The machine instance of Omaha is not available so we will have to run | 365 // The machine instance of Omaha is not available so we will have to run |
| 355 // GoogleUpdate.exe manually passing "needsadmin=True". This will cause | 366 // GoogleUpdate.exe manually passing "needsadmin=True". This will cause |
| 356 // Omaha to install the machine instance first and then install Chromoting | 367 // Omaha to install the machine instance first and then install Chromoting |
| (...skipping 22 matching lines...) Expand all Loading... |
| 379 HWND parent = GetAncestor(window, GA_PARENT); | 390 HWND parent = GetAncestor(window, GA_PARENT); |
| 380 if (parent == NULL) { | 391 if (parent == NULL) { |
| 381 return window; | 392 return window; |
| 382 } | 393 } |
| 383 | 394 |
| 384 window = parent; | 395 window = parent; |
| 385 } | 396 } |
| 386 } | 397 } |
| 387 | 398 |
| 388 } // namespace remoting | 399 } // namespace remoting |
| OLD | NEW |