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 <atlbase.h> | 5 #include <atlbase.h> |
6 #include <security.h> | 6 #include <security.h> |
7 | 7 |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <iostream> | 9 #include <iostream> |
10 | 10 |
11 #include "base/at_exit.h" | 11 #include "base/at_exit.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
14 #include "base/guid.h" | 14 #include "base/guid.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/path_service.h" | 16 #include "base/path_service.h" |
17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
18 #include "base/utf_string_conversions.h" | 18 #include "base/utf_string_conversions.h" |
19 #include "chrome/installer/launcher_support/chrome_launcher_support.h" | 19 #include "base/win/scoped_handle.h" |
20 #include "cloud_print/service/service_state.h" | 20 #include "cloud_print/service/service_state.h" |
21 #include "cloud_print/service/service_switches.h" | 21 #include "cloud_print/service/service_switches.h" |
22 #include "cloud_print/service/win/chrome_launcher.h" | 22 #include "cloud_print/service/win/chrome_launcher.h" |
23 #include "cloud_print/service/win/service_controller.h" | 23 #include "cloud_print/service/win/service_controller.h" |
| 24 #include "cloud_print/service/win/service_listener.h" |
24 #include "cloud_print/service/win/service_utils.h" | 25 #include "cloud_print/service/win/service_utils.h" |
25 #include "printing/backend/print_backend.h" | 26 #include "cloud_print/service/win/setup_listener.h" |
26 | 27 |
27 namespace { | 28 namespace { |
28 | 29 |
29 const char kChromeIsNotAvalible[] = "\nChrome is not available\n"; | |
30 const char kChromeIsAvalible[] = "\nChrome is available\n"; | |
31 const wchar_t kRequirementsFileName[] = L"cloud_print_service_requirements.txt"; | |
32 const wchar_t kServiceStateFileName[] = L"Service State"; | 30 const wchar_t kServiceStateFileName[] = L"Service State"; |
33 | 31 |
34 void InvalidUsage() { | 32 void InvalidUsage() { |
35 base::FilePath service_path; | 33 base::FilePath service_path; |
36 CHECK(PathService::Get(base::FILE_EXE, &service_path)); | 34 CHECK(PathService::Get(base::FILE_EXE, &service_path)); |
37 | 35 |
38 std::cout << "Usage: "; | 36 std::cout << "Usage: "; |
39 std::cout << service_path.BaseName().value(); | 37 std::cout << service_path.BaseName().value(); |
40 std::cout << " ["; | 38 std::cout << " ["; |
41 std::cout << "["; | 39 std::cout << "["; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 if (input.empty() || input == "y") { | 104 if (input.empty() || input == "y") { |
107 return true; | 105 return true; |
108 } else if (input == "n") { | 106 } else if (input == "n") { |
109 return false; | 107 return false; |
110 } | 108 } |
111 } | 109 } |
112 } | 110 } |
113 | 111 |
114 } // namespace | 112 } // namespace |
115 | 113 |
| 114 |
116 class CloudPrintServiceModule | 115 class CloudPrintServiceModule |
117 : public ATL::CAtlServiceModuleT<CloudPrintServiceModule, IDS_SERVICENAME> { | 116 : public ATL::CAtlServiceModuleT<CloudPrintServiceModule, IDS_SERVICENAME> { |
118 public: | 117 public: |
119 typedef ATL::CAtlServiceModuleT<CloudPrintServiceModule, | 118 typedef ATL::CAtlServiceModuleT<CloudPrintServiceModule, |
120 IDS_SERVICENAME> Base; | 119 IDS_SERVICENAME> Base; |
121 | 120 |
122 CloudPrintServiceModule() | 121 CloudPrintServiceModule() |
123 : check_requirements_(false), | 122 : check_requirements_(false), |
124 controller_(new ServiceController(m_szServiceName)) { | 123 controller_(new ServiceController(m_szServiceName)) { |
125 } | 124 } |
(...skipping 20 matching lines...) Expand all Loading... |
146 } | 145 } |
147 return is_service; | 146 return is_service; |
148 } | 147 } |
149 | 148 |
150 HRESULT PreMessageLoop(int nShowCmd) { | 149 HRESULT PreMessageLoop(int nShowCmd) { |
151 HRESULT hr = Base::PreMessageLoop(nShowCmd); | 150 HRESULT hr = Base::PreMessageLoop(nShowCmd); |
152 if (FAILED(hr)) | 151 if (FAILED(hr)) |
153 return hr; | 152 return hr; |
154 | 153 |
155 if (check_requirements_) { | 154 if (check_requirements_) { |
156 hr = CheckRequirements(); | 155 CheckRequirements(); |
157 if (FAILED(hr)) | |
158 return hr; | |
159 // Don't run message loop and stop service. | |
160 return S_FALSE; | |
161 } else { | 156 } else { |
162 hr = StartConnector(); | 157 HRESULT hr = StartConnector(); |
163 if (FAILED(hr)) | 158 if (FAILED(hr)) |
164 return hr; | 159 return hr; |
165 } | 160 } |
166 | 161 |
167 LogEvent(_T("Service started/resumed")); | 162 LogEvent(_T("Service started/resumed")); |
168 SetServiceStatus(SERVICE_RUNNING); | 163 SetServiceStatus(SERVICE_RUNNING); |
169 | 164 |
170 return hr; | 165 return hr; |
171 } | 166 } |
172 | 167 |
173 HRESULT PostMessageLoop() { | 168 HRESULT PostMessageLoop() { |
174 StopConnector(); | 169 StopConnector(); |
| 170 setup_listener_.reset(); |
175 return Base::PostMessageLoop(); | 171 return Base::PostMessageLoop(); |
176 } | 172 } |
177 | 173 |
178 private: | 174 private: |
179 HRESULT ParseCommandLine(const CommandLine& command_line, bool* is_service) { | 175 HRESULT ParseCommandLine(const CommandLine& command_line, bool* is_service) { |
180 if (!is_service) | 176 if (!is_service) |
181 return E_INVALIDARG; | 177 return E_INVALIDARG; |
182 *is_service = false; | 178 *is_service = false; |
183 | 179 |
184 user_data_dir_ = command_line.GetSwitchValuePath(kUserDataDirSwitch); | 180 user_data_dir_ = command_line.GetSwitchValuePath(kUserDataDirSwitch); |
(...skipping 11 matching lines...) Expand all Loading... |
196 | 192 |
197 string16 run_as_user; | 193 string16 run_as_user; |
198 string16 run_as_password; | 194 string16 run_as_password; |
199 SelectWindowsAccount(&run_as_user, &run_as_password); | 195 SelectWindowsAccount(&run_as_user, &run_as_password); |
200 | 196 |
201 HRESULT hr = SetupServiceState(); | 197 HRESULT hr = SetupServiceState(); |
202 if (FAILED(hr)) | 198 if (FAILED(hr)) |
203 return hr; | 199 return hr; |
204 | 200 |
205 hr = controller_->InstallService(run_as_user, run_as_password, | 201 hr = controller_->InstallService(run_as_user, run_as_password, |
206 kServiceSwitch, user_data_dir_); | 202 kServiceSwitch, user_data_dir_, true); |
207 if (SUCCEEDED(hr) && command_line.HasSwitch(kStartSwitch)) | 203 if (SUCCEEDED(hr) && command_line.HasSwitch(kStartSwitch)) |
208 return controller_->StartService(); | 204 return controller_->StartService(); |
209 | 205 |
210 return hr; | 206 return hr; |
211 } | 207 } |
212 | 208 |
213 if (command_line.HasSwitch(kStartSwitch)) | 209 if (command_line.HasSwitch(kStartSwitch)) |
214 return controller_->StartService(); | 210 return controller_->StartService(); |
215 | 211 |
| 212 if (command_line.HasSwitch(kConsoleSwitch)) { |
| 213 check_requirements_ = command_line.HasSwitch(kRequirementsSwitch); |
| 214 ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE); |
| 215 HRESULT hr = Run(); |
| 216 ::SetConsoleCtrlHandler(NULL, FALSE); |
| 217 return hr; |
| 218 } |
| 219 |
216 if (command_line.HasSwitch(kServiceSwitch) || | 220 if (command_line.HasSwitch(kServiceSwitch) || |
217 command_line.HasSwitch(kRequirementsSwitch)) { | 221 command_line.HasSwitch(kRequirementsSwitch)) { |
218 *is_service = true; | 222 *is_service = true; |
219 check_requirements_ = command_line.HasSwitch(kRequirementsSwitch); | 223 check_requirements_ = command_line.HasSwitch(kRequirementsSwitch); |
220 return S_OK; | 224 return S_OK; |
221 } | 225 } |
222 | 226 |
223 if (command_line.HasSwitch(kConsoleSwitch)) { | |
224 ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE); | |
225 HRESULT hr = Run(); | |
226 ::SetConsoleCtrlHandler(NULL, FALSE); | |
227 return hr; | |
228 } | |
229 | 227 |
230 InvalidUsage(); | 228 InvalidUsage(); |
231 return S_FALSE; | 229 return S_FALSE; |
232 } | 230 } |
233 | 231 |
234 void SelectWindowsAccount(string16* run_as_user, string16* run_as_password) { | 232 void SelectWindowsAccount(string16* run_as_user, string16* run_as_password) { |
235 *run_as_user = GetCurrentUserName(); | 233 *run_as_user = GetCurrentUserName(); |
236 for (;;) { | 234 for (;;) { |
237 std::cout << "\nPlease provide Windows account to run service.\n"; | 235 std::cout << "\nPlease provide Windows account to run service.\n"; |
238 *run_as_user = ASCIIToWide(GetOption("Account as DOMAIN\\USERNAME", | 236 *run_as_user = ASCIIToWide(GetOption("Account as DOMAIN\\USERNAME", |
239 WideToASCII(*run_as_user), false)); | 237 WideToASCII(*run_as_user), false)); |
240 *run_as_password = ASCIIToWide(GetOption("Password", "", true)); | 238 *run_as_password = ASCIIToWide(GetOption("Password", "", true)); |
241 | 239 |
242 base::FilePath requirements_filename(user_data_dir_); | 240 SetupListener setup(*run_as_user); |
243 requirements_filename = | 241 if (FAILED(controller_->InstallService(*run_as_user, *run_as_password, |
244 requirements_filename.Append(kRequirementsFileName); | 242 kRequirementsSwitch, |
245 | 243 user_data_dir_, false))) { |
246 file_util::Delete(requirements_filename, false); | 244 LOG(ERROR) << "Failed to install service as " << *run_as_user << "."; |
247 if (file_util::PathExists(requirements_filename)) { | |
248 LOG(ERROR) << "Unable to delete " << | |
249 requirements_filename.value() << "."; | |
250 continue; | 245 continue; |
251 } | 246 } |
252 if (FAILED(controller_->InstallService(*run_as_user, *run_as_password, | 247 |
253 kRequirementsSwitch, | 248 bool service_started = SUCCEEDED(controller_->StartService()); |
254 user_data_dir_))) { | 249 |
255 continue; | 250 if (service_started && |
| 251 !setup.WaitResponce(base::TimeDelta::FromSeconds(30))) { |
| 252 LOG(ERROR) << "Failed to check environment for user " << *run_as_user |
| 253 << "."; |
256 } | 254 } |
257 bool service_started = SUCCEEDED(controller_->StartService()); | 255 |
258 controller_->UninstallService(); | 256 controller_->UninstallService(); |
259 if (!service_started) { | 257 if (!service_started) { |
260 LOG(ERROR) << "Failed to start service as " << *run_as_user << "."; | 258 LOG(ERROR) << "Failed to start service as " << *run_as_user << "."; |
261 continue; | 259 continue; |
262 } | 260 } |
263 std::string printers; | 261 if (setup.user_data_dir().empty()) { |
264 if (!file_util::PathExists(requirements_filename) || | 262 LOG(ERROR) << "Service can't access " << user_data_dir_.value() << "."; |
265 !file_util::ReadFileToString(requirements_filename, &printers)) { | |
266 LOG(ERROR) << "Service can't create " << requirements_filename.value(); | |
267 continue; | 263 continue; |
268 } | 264 } |
269 | 265 if (setup.chrome_path().empty()) { |
270 if (EndsWith(printers, kChromeIsNotAvalible, true)) { | 266 LOG(ERROR) << "Chrome is not available for " << *run_as_user << "."; |
271 LOG(ERROR) << kChromeIsNotAvalible << " for " << *run_as_user << "."; | 267 continue; |
| 268 } |
| 269 if (!setup.is_xps_availible()) { |
| 270 LOG(ERROR) << "XPS pack is not installed."; |
272 continue; | 271 continue; |
273 } | 272 } |
274 | 273 |
275 std::cout << "\nService requirements check result: \n"; | 274 std::cout << "\nService requirements check result: \n"; |
276 std::cout << printers << "\n"; | 275 std::cout << "Username: " << setup.user_name()<< "\n"; |
277 file_util::Delete(requirements_filename, false); | 276 std::cout << "Chrome: " << setup.chrome_path().value()<< "\n"; |
| 277 std::cout << "Printers:\n "; |
| 278 std::ostream_iterator<std::string> cout_it(std::cout, "\n "); |
| 279 std::copy(setup.printers().begin(), setup.printers().end(), cout_it); |
| 280 std::cout << "\n"; |
278 | 281 |
279 if (AskUser("Do you want to use " + WideToASCII(*run_as_user) + "?")) | 282 if (AskUser("Do you want to use " + WideToASCII(*run_as_user) + "?")) |
280 return; | 283 return; |
281 } | 284 } |
282 } | 285 } |
283 | 286 |
284 HRESULT SetupServiceState() { | 287 HRESULT SetupServiceState() { |
285 base::FilePath file = user_data_dir_.Append(kServiceStateFileName); | 288 base::FilePath file = user_data_dir_.Append(kServiceStateFileName); |
286 | 289 |
287 for (;;) { | 290 for (;;) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 return last_error ? HRESULT_FROM_WIN32(last_error) : E_FAIL; | 328 return last_error ? HRESULT_FROM_WIN32(last_error) : E_FAIL; |
326 } | 329 } |
327 } | 330 } |
328 } | 331 } |
329 } | 332 } |
330 } | 333 } |
331 | 334 |
332 return S_OK; | 335 return S_OK; |
333 } | 336 } |
334 | 337 |
335 HRESULT CheckRequirements() { | 338 void CheckRequirements() { |
336 base::FilePath requirements_filename(user_data_dir_); | 339 setup_listener_.reset(new ServiceListener(user_data_dir_)); |
337 requirements_filename = requirements_filename.Append(kRequirementsFileName); | |
338 std::string output; | |
339 output.append("Printers available for " + | |
340 WideToASCII(GetCurrentUserName()) + ":\n"); | |
341 scoped_refptr<printing::PrintBackend> backend( | |
342 printing::PrintBackend::CreateInstance(NULL)); | |
343 printing::PrinterList printer_list; | |
344 backend->EnumeratePrinters(&printer_list); | |
345 for (size_t i = 0; i < printer_list.size(); ++i) { | |
346 output += " "; | |
347 output += printer_list[i].printer_name; | |
348 output += "\n"; | |
349 } | |
350 base::FilePath chrome = chrome_launcher_support::GetAnyChromePath(); | |
351 output.append(chrome.empty() ? kChromeIsNotAvalible : kChromeIsAvalible); | |
352 file_util::WriteFile(requirements_filename, output.c_str(), output.size()); | |
353 return S_OK; | |
354 } | 340 } |
355 | 341 |
356 HRESULT StartConnector() { | 342 HRESULT StartConnector() { |
357 chrome_.reset(new ChromeLauncher(user_data_dir_)); | 343 chrome_.reset(new ChromeLauncher(user_data_dir_)); |
358 return chrome_->Start() ? S_OK : E_FAIL; | 344 return chrome_->Start() ? S_OK : E_FAIL; |
359 } | 345 } |
360 | 346 |
361 void StopConnector() { | 347 void StopConnector() { |
362 if (chrome_.get()) { | 348 if (chrome_.get()) { |
363 chrome_->Stop(); | 349 chrome_->Stop(); |
364 chrome_.reset(); | 350 chrome_.reset(); |
365 } | 351 } |
366 } | 352 } |
367 | 353 |
368 static BOOL WINAPI ConsoleCtrlHandler(DWORD type); | 354 static BOOL WINAPI ConsoleCtrlHandler(DWORD type); |
369 | 355 |
370 bool check_requirements_; | 356 bool check_requirements_; |
371 base::FilePath user_data_dir_; | 357 base::FilePath user_data_dir_; |
372 scoped_ptr<ChromeLauncher> chrome_; | 358 scoped_ptr<ChromeLauncher> chrome_; |
373 scoped_ptr<ServiceController> controller_; | 359 scoped_ptr<ServiceController> controller_; |
| 360 scoped_ptr<ServiceListener> setup_listener_; |
374 }; | 361 }; |
375 | 362 |
376 CloudPrintServiceModule _AtlModule; | 363 CloudPrintServiceModule _AtlModule; |
377 | 364 |
378 BOOL CloudPrintServiceModule::ConsoleCtrlHandler(DWORD type) { | 365 BOOL CloudPrintServiceModule::ConsoleCtrlHandler(DWORD type) { |
379 PostThreadMessage(_AtlModule.m_dwThreadID, WM_QUIT, 0, 0); | 366 PostThreadMessage(_AtlModule.m_dwThreadID, WM_QUIT, 0, 0); |
380 return TRUE; | 367 return TRUE; |
381 } | 368 } |
382 | 369 |
383 int main() { | 370 int main() { |
384 base::AtExitManager at_exit; | 371 base::AtExitManager at_exit; |
385 return _AtlModule.WinMain(0); | 372 return _AtlModule.WinMain(0); |
386 } | 373 } |
387 | 374 |
OLD | NEW |