OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/extensions/app_host_installer.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/callback.h" | |
9 #include "base/logging.h" | |
10 #include "base/process_util.h" | |
11 #include "base/string16.h" | |
12 #include "chrome/common/extensions/extension.h" | |
benwells
2012/10/04 07:53:01
Nit: Move includes like string16, logging, process
huangs
2012/10/04 22:56:42
Done.
| |
13 #include "content/public/browser/browser_thread.h" | |
14 | |
15 #if defined(OS_WIN) | |
16 #include <windows.h> | |
17 #include "base/win/object_watcher.h" | |
18 #include "base/win/registry.h" | |
19 #include "chrome/installer/launcher_support/chrome_launcher_support.h" | |
20 #endif | |
21 | |
22 namespace { | |
23 | |
24 #if defined(OS_WIN) | |
25 | |
26 // TODO(huangs) Refactor the constants: http://crbug.com/148538 | |
27 const wchar_t kGoogleRegClientsKey[] = L"Software\\Google\\Update\\Clients"; | |
28 | |
29 // Copied from chrome_appid.cc. | |
30 const wchar_t kBinariesAppGuid[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}"; | |
31 | |
32 // Copied from google_update_constants.cc | |
33 const wchar_t kRegCommandLineField[] = L"CommandLine"; | |
34 const wchar_t kRegCommandsKey[] = L"Commands"; | |
35 | |
36 // Copied from util_constants.cc. | |
37 const wchar_t kCmdQuickEnableApplicationHost[] = | |
38 L"quick-enable-application-host"; | |
39 | |
40 class QuickEnableWatcher : public base::win::ObjectWatcher::Delegate { | |
41 public: | |
42 QuickEnableWatcher(const base::Callback<void(bool)>& callback) | |
43 : callback_(callback) { | |
benwells
2012/10/04 07:53:01
Nit: {} (on one line)
huangs
2012/10/04 22:56:42
Done.
| |
44 } | |
45 | |
46 // base::win::ObjectWatcher::Delegate implementation. | |
47 void OnObjectSignaled(HANDLE object) { | |
erikwright (departed)
2012/10/04 01:28:16
virtual ... OVERRIDE
#include compiler_specific
huangs
2012/10/04 22:56:42
Done.
| |
48 int exit_code = 0; | |
49 base::TerminationStatus status( | |
benwells
2012/10/04 07:53:01
I'm not at all familiar withe ObjectWatcher. What
huangs
2012/10/04 22:56:42
If process crashes, then it will return. If it ru
| |
50 base::GetTerminationStatus(object, &exit_code)); | |
51 if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION) { | |
52 callback_.Run(true); | |
53 } else { | |
54 LOG(ERROR) << "App Host install failed, status = " << status | |
55 << ", exit code = " << exit_code; | |
56 callback_.Run(false); | |
57 } | |
58 callback_.Reset(); | |
59 } | |
60 | |
61 private: | |
62 base::Callback<void(bool)> callback_; | |
63 | |
64 DISALLOW_COPY_AND_ASSIGN(QuickEnableWatcher); | |
65 }; | |
66 | |
67 // Reads the path to app_host.exe from the value "UninstallString" within the | |
68 // App Host's "ClientState" registry key. | |
erikwright (departed)
2012/10/04 01:28:16
"returns an empty string if the path does not exis
huangs
2012/10/04 22:56:42
Done.
| |
69 string16 GetQuickEnableAppHostCommand(bool system_level) { | |
70 HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | |
71 string16 subkey(kGoogleRegClientsKey); | |
72 subkey.append(1, L'\\').append(kBinariesAppGuid) | |
73 .append(1, L'\\').append(kRegCommandsKey) | |
74 .append(1, L'\\').append(kCmdQuickEnableApplicationHost); | |
75 base::win::RegKey reg_key; | |
76 string16 cmd; | |
77 if (reg_key.Open(root_key, subkey.c_str(), | |
78 KEY_QUERY_VALUE) == ERROR_SUCCESS) { | |
79 // If read is unsuccessful, |cmd| remains empty. | |
80 reg_key.ReadValue(kRegCommandLineField, &cmd); | |
81 } | |
82 return cmd; | |
83 } | |
84 | |
85 // Launches the Google Update command to quick-enable App Host. | |
86 // Returns true if the command is launched. | |
87 bool LaunchQuickEnableAppHost(base::win::ScopedHandle* process) { | |
88 DCHECK(!process->IsValid()); | |
89 bool success = false; | |
90 | |
91 string16 cmd_str(GetQuickEnableAppHostCommand(true)); | |
92 if (cmd_str.empty()) { // Try user-level if absent from system-level. | |
93 cmd_str = GetQuickEnableAppHostCommand(false); | |
94 } | |
95 if (!cmd_str.empty()) { | |
96 VLOG(1) << "Quick-enabling application host: " << cmd_str; | |
97 if (!base::LaunchProcess(cmd_str, base::LaunchOptions(), | |
98 process->Receive())) { | |
99 LOG(ERROR) << "Failed to quick-enable application host."; | |
100 } | |
101 success = process->IsValid(); | |
102 } | |
103 return success; | |
104 } | |
105 | |
106 #endif | |
107 | |
108 } // namespace | |
109 | |
110 namespace extensions { | |
111 | |
112 AppHostInstaller::AppHostInstaller() { | |
benwells
2012/10/04 07:53:01
Nit: {}
huangs
2012/10/04 22:56:42
Done.
| |
113 } | |
114 | |
115 // static | |
116 bool AppHostInstaller::IsAppHostInstallRequired(const Extension& extension) { | |
117 #if defined(OS_WIN) | |
118 return extension.is_platform_app() && | |
119 !chrome_launcher_support::IsAppHostPresent(); | |
120 #else | |
121 return false; | |
122 #endif | |
123 } | |
124 | |
125 void AppHostInstaller::InstallAppHost( | |
126 const base::Callback<void(bool)>& callback) { | |
127 #if defined(OS_WIN) | |
128 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); | |
129 DCHECK(!process_.IsValid()); | |
130 if (FAILED(LaunchQuickEnableAppHost(&process_))) { | |
erikwright (departed)
2012/10/04 01:28:16
FAILED is for HRESULTS.
if (!Launch...()) {...}
huangs
2012/10/04 22:56:42
Done.
| |
131 callback.Run(false); | |
132 } else { | |
133 DCHECK(process_.IsValid()); | |
134 DCHECK(!delegate_.get()); | |
135 delegate_.reset(new QuickEnableWatcher(callback)); | |
erikwright (departed)
2012/10/04 01:28:16
Although I think it's technically OK, I'd like to
huangs
2012/10/04 22:56:42
Done.
| |
136 watcher_.StartWatching(process_, delegate_.get()); | |
137 } | |
138 #else | |
139 NOTREACHED() << "Attempt to install the App Host on an unsupported platform."; | |
140 callback.Run(false); | |
141 #endif | |
142 } | |
143 | |
144 } // namespace extensions | |
OLD | NEW |