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 |