Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome_frame/ready_mode/internal/registry_ready_mode_state.h" | 5 #include "chrome_frame/ready_mode/internal/registry_ready_mode_state.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/process_util.h" | 10 #include "base/process_util.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "base/time.h" | 12 #include "base/time.h" |
| 13 #include "base/task.h" | 13 #include "base/task.h" |
| 14 #include "base/win/registry.h" | 14 #include "base/win/registry.h" |
| 15 #include "base/win/scoped_comptr.h" | 15 #include "base/win/scoped_comptr.h" |
| 16 #include "base/win/scoped_handle.h" | 16 #include "base/win/scoped_handle.h" |
| 17 #include "base/win/windows_version.h" | |
| 17 #include "chrome/installer/util/browser_distribution.h" | 18 #include "chrome/installer/util/browser_distribution.h" |
| 18 #include "chrome/installer/util/google_update_constants.h" | 19 #include "chrome/installer/util/google_update_constants.h" |
| 19 #include "chrome/installer/util/master_preferences.h" | 20 #include "chrome/installer/util/master_preferences.h" |
| 20 #include "chrome/installer/util/util_constants.h" | 21 #include "chrome/installer/util/util_constants.h" |
| 22 #include "chrome_frame/chrome_launcher_utils.h" | |
| 21 #include "chrome_frame/ready_mode/ready_mode.h" | 23 #include "chrome_frame/ready_mode/ready_mode.h" |
| 22 #include "google_update_idl.h" // NOLINT | |
| 23 | 24 |
| 24 namespace { | 25 namespace { |
| 25 | 26 |
| 26 // Looks up a command entry in the registry and attempts to execute it directly. | 27 // Looks up a command entry in the registry and attempts to execute it directly. |
| 27 // Returns the new process handle, which the caller is responsible for closing, | 28 // Returns the new process handle, which the caller is responsible for closing, |
| 28 // or NULL upon failure. | 29 // or NULL upon failure. |
| 29 HANDLE LaunchCommandDirectly(const std::wstring& command_field) { | 30 HANDLE LaunchCommandDirectly(const std::wstring& command_field) { |
| 30 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 31 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| 31 std::wstring version_key_name(dist->GetVersionKey()); | 32 std::wstring version_key_name(dist->GetVersionKey()); |
| 32 | 33 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 46 } | 47 } |
| 47 } | 48 } |
| 48 } | 49 } |
| 49 return NULL; | 50 return NULL; |
| 50 } | 51 } |
| 51 | 52 |
| 52 // Attempts to launch a command using the ProcessLauncher. Returns a handle to | 53 // Attempts to launch a command using the ProcessLauncher. Returns a handle to |
| 53 // the launched process, which the caller is responsible for closing, or NULL | 54 // the launched process, which the caller is responsible for closing, or NULL |
| 54 // upon failure. | 55 // upon failure. |
| 55 HANDLE LaunchCommandViaProcessLauncher(const std::wstring& command_field) { | 56 HANDLE LaunchCommandViaProcessLauncher(const std::wstring& command_field) { |
| 56 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 57 HANDLE launched_process = NULL; |
| 57 | 58 |
| 58 base::win::ScopedComPtr<IProcessLauncher> ipl; | 59 scoped_ptr<CommandLine> command_line( |
| 59 HRESULT hr = ipl.CreateInstance(__uuidof(ProcessLauncherClass)); | 60 chrome_launcher::CreateUpdateCommandLine(command_field)); |
| 60 | 61 |
| 61 if (FAILED(hr)) { | 62 if (command_line != NULL) |
| 62 DLOG(ERROR) << "Failed to instantiate IProcessLauncher: " | 63 base::LaunchApp(*command_line, false, true, &launched_process); |
| 63 << base::StringPrintf("0x%08x", hr); | |
| 64 } else { | |
| 65 ULONG_PTR phandle = NULL; | |
| 66 DWORD id = GetCurrentProcessId(); | |
| 67 | 64 |
| 68 hr = ipl->LaunchCmdElevated(dist->GetAppGuid().c_str(), | 65 return launched_process; |
| 69 command_field.c_str(), id, &phandle); | |
| 70 if (SUCCEEDED(hr)) | |
| 71 return reinterpret_cast<HANDLE>(phandle); | |
| 72 | |
| 73 DLOG(ERROR) << "Failed to invoke IProcessLauncher::LaunchCmdElevated: " | |
| 74 << base::StringPrintf("0x%08x", hr); | |
| 75 } | |
| 76 | |
| 77 return NULL; | |
| 78 } | 66 } |
| 79 | 67 |
| 80 // Waits for the provided process to exit, and verifies that its exit code | 68 // Waits for the provided process to exit, and verifies that its exit code |
| 81 // corresponds to one of the known "success" codes for the installer. If the | 69 // corresponds to one of the known "success" codes for the installer. If the |
| 82 // exit code cannot be retrieved, or if it signals failure, returns false. | 70 // exit code cannot be retrieved, or if it signals failure, returns false. |
| 83 bool CheckProcessExitCode(HANDLE handle) { | 71 bool CheckProcessExitCode(HANDLE handle) { |
| 84 // TODO(erikwright): Use RegisterWaitForSingleObject to wait | 72 // TODO(erikwright): Use RegisterWaitForSingleObject to wait |
| 85 // asynchronously. | 73 // asynchronously. |
| 86 DWORD wait_result = WaitForSingleObject(handle, 5000); // (ms) | 74 DWORD wait_result = WaitForSingleObject(handle, 5000); // (ms) |
| 87 | 75 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 107 | 95 |
| 108 if (wait_result == WAIT_ABANDONED) | 96 if (wait_result == WAIT_ABANDONED) |
| 109 DLOG(ERROR) << "Unexpeced WAIT_ABANDONED while waiting on child process."; | 97 DLOG(ERROR) << "Unexpeced WAIT_ABANDONED while waiting on child process."; |
| 110 | 98 |
| 111 if (wait_result == WAIT_TIMEOUT) | 99 if (wait_result == WAIT_TIMEOUT) |
| 112 DLOG(ERROR) << "Timeout while waiting on child process."; | 100 DLOG(ERROR) << "Timeout while waiting on child process."; |
| 113 | 101 |
| 114 return false; | 102 return false; |
| 115 } | 103 } |
| 116 | 104 |
| 105 // If we are running on XP (no protected mode) or in a high-integrity process, | |
| 106 // we can invoke the installer directly. If not, we will have to go via the | |
| 107 // ProcessLauncher. | |
| 108 bool CanLaunchDirectly() { | |
| 109 if (base::win::GetVersion() < base::win::VERSION_VISTA) | |
| 110 return true; | |
| 111 | |
| 112 base::IntegrityLevel integrity_level = base::INTEGRITY_UNKNOWN; | |
| 113 if (!base::GetProcessIntegrityLevel(base::GetCurrentProcessHandle(), | |
| 114 &integrity_level)) { | |
| 115 DLOG(ERROR) << "Failed to determine process integrity level."; | |
| 116 return false; | |
| 117 } | |
| 118 | |
| 119 return integrity_level == base::HIGH_INTEGRITY; | |
| 120 } | |
|
erikwright (departed)
2011/01/24 17:17:14
By "Done", I meant, I added an implementation comm
| |
| 121 | |
| 117 // Attempts to launch the specified command either directly or via the | 122 // Attempts to launch the specified command either directly or via the |
| 118 // ProcessLauncher. Returns true if the command is launched and returns a | 123 // ProcessLauncher. Returns true if the command is launched and returns a |
| 119 // success code. | 124 // success code. |
| 120 bool LaunchAndCheckCommand(const std::wstring& command_field) { | 125 bool LaunchAndCheckCommand(const std::wstring& command_field) { |
| 121 base::win::ScopedHandle handle; | 126 base::win::ScopedHandle handle; |
| 122 | 127 |
| 123 handle.Set(LaunchCommandDirectly(command_field)); | 128 if (CanLaunchDirectly()) |
| 129 handle.Set(LaunchCommandDirectly(command_field)); | |
| 130 else | |
| 131 handle.Set(LaunchCommandViaProcessLauncher(command_field)); | |
| 132 | |
| 124 if (handle.IsValid() && CheckProcessExitCode(handle)) | 133 if (handle.IsValid() && CheckProcessExitCode(handle)) |
|
robertshield
2011/01/24 15:08:42
This appears to wait for 5 seconds whereas chrome_
erikwright (departed)
2011/01/24 17:17:14
Yes. chrome_launcher will live as long as the elev
| |
| 125 return true; | 134 return true; |
| 126 | 135 |
| 127 handle.Set(LaunchCommandViaProcessLauncher(command_field)); | |
| 128 if (handle.IsValid() && CheckProcessExitCode(handle)) | |
| 129 return true; | |
| 130 | |
| 131 DLOG(ERROR) << "Command " << command_field << " could not be launched."; | 136 DLOG(ERROR) << "Command " << command_field << " could not be launched."; |
| 132 return false; | 137 return false; |
| 133 } | 138 } |
| 134 | 139 |
| 135 } // namespace | 140 } // namespace |
| 136 | 141 |
| 137 RegistryReadyModeState::RegistryReadyModeState( | 142 RegistryReadyModeState::RegistryReadyModeState( |
| 138 const std::wstring& key_name, base::TimeDelta temporary_decline_duration, | 143 const std::wstring& key_name, base::TimeDelta temporary_decline_duration, |
| 139 Observer* observer) | 144 Observer* observer) |
| 140 : key_name_(key_name), | 145 : key_name_(key_name), |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 | 241 |
| 237 void RegistryReadyModeState::PermanentlyDeclineChromeFrame() { | 242 void RegistryReadyModeState::PermanentlyDeclineChromeFrame() { |
| 238 if (LaunchAndCheckCommand(google_update::kRegCFOptOutCmdField)) | 243 if (LaunchAndCheckCommand(google_update::kRegCFOptOutCmdField)) |
| 239 RefreshStateAndNotify(); | 244 RefreshStateAndNotify(); |
| 240 } | 245 } |
| 241 | 246 |
| 242 void RegistryReadyModeState::AcceptChromeFrame() { | 247 void RegistryReadyModeState::AcceptChromeFrame() { |
| 243 if (LaunchAndCheckCommand(google_update::kRegCFOptInCmdField)) | 248 if (LaunchAndCheckCommand(google_update::kRegCFOptInCmdField)) |
| 244 NotifyObserver(); | 249 NotifyObserver(); |
| 245 } | 250 } |
| OLD | NEW |