cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / cloud_print / service / win / cloud_print_service_config.cc
blobce31e19c1b27af99a84c128188e26579b8aae20f
1 // Copyright 2013 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.
5 #include <atlbase.h>
6 #include <atlapp.h> // NOLINT
8 #include "base/at_exit.h"
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/command_line.h"
12 #include "base/file_util.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/string16.h"
15 #include "base/threading/thread.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "cloud_print/common/win/cloud_print_utils.h"
18 #include "cloud_print/resources.h"
19 #include "cloud_print/service/service_state.h"
20 #include "cloud_print/service/win/chrome_launcher.h"
21 #include "cloud_print/service/win/service_controller.h"
22 #include "cloud_print/service/win/service_utils.h"
23 #include "cloud_print/service/win/setup_listener.h"
25 using cloud_print::LoadLocalString;
26 using cloud_print::GetErrorMessage;
28 class SetupDialog : public base::RefCounted<SetupDialog>,
29 public ATL::CDialogImpl<SetupDialog> {
30 public:
31 // Enables accelerators.
32 class MessageFilter : public base::MessageLoopForUI::MessageFilter {
33 public:
34 explicit MessageFilter(SetupDialog* dialog) : dialog_(dialog){}
35 virtual ~MessageFilter() {};
37 // MessageLoopForUI::MessageFilter
38 virtual bool ProcessMessage(const MSG& msg) OVERRIDE {
39 MSG msg2 = msg;
40 return dialog_->IsDialogMessage(&msg2) != FALSE;
43 private:
44 scoped_refptr<SetupDialog> dialog_;
47 typedef ATL::CDialogImpl<SetupDialog> Base;
48 enum { IDD = IDD_SETUP_DIALOG };
50 BEGIN_MSG_MAP(SetupDialog)
51 MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
52 MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnCtrColor)
53 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
54 COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
55 COMMAND_ID_HANDLER(IDC_START, OnStart)
56 COMMAND_ID_HANDLER(IDC_INSTALL, OnInstall)
57 COMMAND_ID_HANDLER(IDC_LOGGING, OnLogging)
58 END_MSG_MAP()
60 SetupDialog();
61 private:
62 // Window Message Handlers
63 LRESULT OnInitDialog(UINT message, WPARAM wparam, LPARAM lparam,
64 BOOL& handled);
65 LRESULT OnCtrColor(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled);
66 LRESULT OnCancel(UINT, INT nIdentifier, HWND, BOOL& handled);
67 LRESULT OnStart(UINT, INT nIdentifier, HWND, BOOL& handled);
68 LRESULT OnInstall(UINT, INT nIdentifier, HWND, BOOL& handled);
69 LRESULT OnLogging(UINT, INT nIdentifier, HWND, BOOL& handled);
70 LRESULT OnDestroy(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled);
72 void PostUITask(const base::Closure& task);
73 void PostIOTask(const base::Closure& task);
75 // UI Calls.
77 // Disables all controls after users actions.
78 void DisableControls();
79 // Updates state of controls after when we received service status.
80 void SetState(ServiceController::State state, const string16& user,
81 bool is_logging_enabled);
82 // Show message box with error.
83 void ShowErrorMessageBox(const string16& error_message);
84 // Show use message box instructions how to deal with opened Chrome window.
85 void AskToCloseChrome();
86 string16 GetDlgItemText(int id) const;
87 string16 GetUser() const;
88 string16 GetPassword() const;
89 bool IsLoggingEnabled() const;
90 bool IsInstalled() const {
91 return state_ > ServiceController::STATE_NOT_FOUND;
94 // IO Calls.
95 // Installs service.
96 void Install(const string16& user, const string16& password,
97 bool enable_logging);
98 // Starts service.
99 void Start();
100 // Stops service.
101 void Stop();
102 // Uninstall service.
103 void Uninstall();
104 // Update service state.
105 void UpdateState();
106 // Posts task to UI thread to show error using string id.
107 void ShowError(int string_id);
108 // Posts task to UI thread to show error using string.
109 void ShowError(const string16& error_message);
110 // Posts task to UI thread to show error using error code.
111 void ShowError(HRESULT hr);
113 ServiceController::State state_;
114 base::Thread worker_;
116 base::MessageLoop* ui_loop_;
117 base::MessageLoop* io_loop_;
119 ServiceController controller_;
122 SetupDialog::SetupDialog()
123 : state_(ServiceController::STATE_NOT_FOUND),
124 worker_("worker") {
125 ui_loop_ = base::MessageLoop::current();
126 DCHECK(ui_loop_->IsType(base::MessageLoop::TYPE_UI));
128 worker_.StartWithOptions(
129 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
130 io_loop_ = worker_.message_loop();
131 DCHECK(io_loop_->IsType(base::MessageLoop::TYPE_IO));
134 void SetupDialog::PostUITask(const base::Closure& task) {
135 ui_loop_->PostTask(FROM_HERE, task);
138 void SetupDialog::PostIOTask(const base::Closure& task) {
139 io_loop_->PostTask(FROM_HERE, task);
142 void SetupDialog::ShowErrorMessageBox(const string16& error_message) {
143 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_UI));
144 MessageBox(error_message.c_str(),
145 LoadLocalString(IDS_OPERATION_FAILED_TITLE).c_str(),
146 MB_ICONERROR | MB_OK);
149 void SetupDialog::AskToCloseChrome() {
150 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_UI));
151 MessageBox(LoadLocalString(IDS_ADD_PRINTERS_USING_CHROME).c_str(),
152 LoadLocalString(IDS_CONTINUE_IN_CHROME_TITLE).c_str(),
153 MB_OK);
156 void SetupDialog::SetState(ServiceController::State status,
157 const string16& user,
158 bool is_logging_enabled) {
159 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_UI));
160 state_ = status;
162 DWORD status_string = 0;
163 switch(status) {
164 case ServiceController::STATE_NOT_FOUND:
165 status_string = IDS_SERVICE_NOT_FOUND;
166 break;
167 case ServiceController::STATE_STOPPED:
168 status_string = IDS_SERVICE_STOPPED;
169 break;
170 case ServiceController::STATE_RUNNING:
171 status_string = IDS_SERVICE_RUNNING;
172 break;
174 SetDlgItemText(IDC_STATUS,
175 status_string ? LoadLocalString(status_string).c_str() : L"");
176 if (IsInstalled()) {
177 SetDlgItemText(IDC_USER, user.c_str());
178 CheckDlgButton(IDC_LOGGING,
179 is_logging_enabled ? BST_CHECKED : BST_UNCHECKED);
182 ATL::CWindow start_button = GetDlgItem(IDC_START);
183 DWORD start_string = (status == ServiceController::STATE_STOPPED) ?
184 IDS_SERVICE_START : IDS_SERVICE_STOP;
185 start_button.SetWindowText(LoadLocalString(start_string).c_str());
186 start_button.ShowWindow(IsInstalled() ? SW_SHOW : SW_HIDE);
187 start_button.EnableWindow(TRUE);
189 ATL::CWindow install_button = GetDlgItem(IDC_INSTALL);
190 DWORD install_string = IsInstalled() ? IDS_SERVICE_UNINSTALL :
191 IDS_SERVICE_INSTALL;
192 install_button.SetWindowText(LoadLocalString(install_string).c_str());
193 install_button.ShowWindow(SW_SHOW);
194 install_button.EnableWindow(TRUE);
196 if (!IsInstalled()) {
197 GetDlgItem(IDC_USER).EnableWindow(TRUE);
198 GetDlgItem(IDC_PASSWORD).EnableWindow(TRUE);
199 GetDlgItem(IDC_LOGGING).EnableWindow(TRUE);
203 LRESULT SetupDialog::OnInitDialog(UINT message, WPARAM wparam, LPARAM lparam,
204 BOOL& handled) {
205 ATLVERIFY(CenterWindow());
207 WTL::CIcon icon;
208 if (icon.LoadIcon(MAKEINTRESOURCE(IDI_ICON))) {
209 SetIcon(icon);
212 SetWindowText(LoadLocalString(IDS_SETUP_PROGRAM_NAME).c_str());
213 SetDlgItemText(IDC_STATE_LABEL, LoadLocalString(IDS_STATE_LABEL).c_str());
214 SetDlgItemText(IDC_USER_LABEL, LoadLocalString(IDS_USER_LABEL).c_str());
215 SetDlgItemText(IDC_PASSWORD_LABEL,
216 LoadLocalString(IDS_PASSWORD_LABEL).c_str());
217 SetDlgItemText(IDC_LOGGING, LoadLocalString(IDS_LOGGING_LABEL).c_str());
218 SetDlgItemText(IDCANCEL, LoadLocalString(IDS_CLOSE).c_str());
220 SetState(ServiceController::STATE_UNKNOWN, L"", false);
221 DisableControls();
223 SetDlgItemText(IDC_USER, GetCurrentUserName().c_str());
225 PostIOTask(base::Bind(&SetupDialog::UpdateState, this));
227 return 0;
230 LRESULT SetupDialog::OnCtrColor(UINT message, WPARAM wparam, LPARAM lparam,
231 BOOL& handled) {
232 HWND window = reinterpret_cast<HWND>(lparam);
233 if (GetDlgItem(IDC_LOGO).m_hWnd == window) {
234 return reinterpret_cast<LRESULT>(::GetStockObject(WHITE_BRUSH));
236 return 0;
239 LRESULT SetupDialog::OnStart(UINT, INT nIdentifier, HWND, BOOL& handled) {
240 DisableControls();
241 DCHECK(IsInstalled());
242 if (state_ == ServiceController::STATE_RUNNING)
243 PostIOTask(base::Bind(&SetupDialog::Stop, this));
244 else
245 PostIOTask(base::Bind(&SetupDialog::Start, this));
246 return 0;
249 LRESULT SetupDialog::OnInstall(UINT, INT nIdentifier, HWND, BOOL& handled) {
250 DisableControls();
251 if (IsInstalled()) {
252 PostIOTask(base::Bind(&SetupDialog::Uninstall, this));
253 } else {
254 PostIOTask(base::Bind(&SetupDialog::Install, this, GetUser(),
255 GetPassword(), IsLoggingEnabled()));
257 return 0;
260 LRESULT SetupDialog::OnLogging(UINT, INT nIdentifier, HWND, BOOL& handled) {
261 CheckDlgButton(IDC_LOGGING, IsLoggingEnabled()? BST_UNCHECKED : BST_CHECKED);
262 return 0;
265 LRESULT SetupDialog::OnCancel(UINT, INT nIdentifier, HWND, BOOL& handled) {
266 DestroyWindow();
267 return 0;
270 LRESULT SetupDialog::OnDestroy(UINT message, WPARAM wparam, LPARAM lparam,
271 BOOL& handled) {
272 base::MessageLoop::current()->PostTask(FROM_HERE,
273 base::MessageLoop::QuitClosure());
274 return 1;
277 void SetupDialog::DisableControls() {
278 GetDlgItem(IDC_START).EnableWindow(FALSE);
279 GetDlgItem(IDC_INSTALL).EnableWindow(FALSE);
280 GetDlgItem(IDC_USER).EnableWindow(FALSE);
281 GetDlgItem(IDC_PASSWORD).EnableWindow(FALSE);
282 GetDlgItem(IDC_LOGGING).EnableWindow(FALSE);
285 string16 SetupDialog::GetDlgItemText(int id) const {
286 const ATL::CWindow& item = GetDlgItem(id);
287 size_t length = item.GetWindowTextLength();
288 string16 result(length + 1, L'\0');
289 result.resize(item.GetWindowText(&result[0], result.size()));
290 return result;
293 string16 SetupDialog::GetUser() const {
294 return GetDlgItemText(IDC_USER);
297 string16 SetupDialog::GetPassword() const{
298 return GetDlgItemText(IDC_PASSWORD);
301 bool SetupDialog::IsLoggingEnabled() const{
302 return IsDlgButtonChecked(IDC_LOGGING) == BST_CHECKED;
305 void SetupDialog::UpdateState() {
306 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_IO));
307 controller_.UpdateState();
308 PostUITask(base::Bind(&SetupDialog::SetState, this, controller_.state(),
309 controller_.user(), controller_.is_logging_enabled()));
312 void SetupDialog::ShowError(const string16& error_message) {
313 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_IO));
314 PostUITask(base::Bind(&SetupDialog::SetState,
315 this,
316 ServiceController::STATE_UNKNOWN,
317 L"",
318 false));
319 PostUITask(base::Bind(&SetupDialog::ShowErrorMessageBox, this,
320 error_message));
321 LOG(ERROR) << error_message;
324 void SetupDialog::ShowError(int string_id) {
325 ShowError(cloud_print::LoadLocalString(string_id));
328 void SetupDialog::ShowError(HRESULT hr) {
329 ShowError(GetErrorMessage(hr));
332 void SetupDialog::Install(const string16& user, const string16& password,
333 bool enable_logging) {
334 // Don't forget to update state on exit.
335 base::ScopedClosureRunner scoped_update_status(
336 base::Bind(&SetupDialog::UpdateState, this));
338 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_IO));
340 SetupListener setup(GetUser());
341 HRESULT hr = controller_.InstallCheckService(user, password,
342 base::FilePath());
343 if (FAILED(hr))
344 return ShowError(hr);
347 // Always uninstall service after requirements check.
348 base::ScopedClosureRunner scoped_uninstall(
349 base::Bind(base::IgnoreResult(&ServiceController::UninstallService),
350 base::Unretained(&controller_)));
352 hr = controller_.StartService();
353 if (FAILED(hr))
354 return ShowError(hr);
356 if (!setup.WaitResponce(base::TimeDelta::FromSeconds(30)))
357 return ShowError(IDS_ERROR_FAILED_START_SERVICE);
360 if (setup.user_data_dir().empty())
361 return ShowError(IDS_ERROR_NO_DATA_DIR);
363 if (setup.chrome_path().empty())
364 return ShowError(IDS_ERROR_NO_CHROME);
366 if (!setup.is_xps_available())
367 return ShowError(IDS_ERROR_NO_XPS);
369 base::FilePath file = setup.user_data_dir();
370 file = file.Append(chrome::kServiceStateFileName);
372 std::string proxy_id;
373 std::string contents;
375 if (base::ReadFileToString(file, &contents)) {
376 ServiceState service_state;
377 if (service_state.FromString(contents))
378 proxy_id = service_state.proxy_id();
380 PostUITask(base::Bind(&SetupDialog::AskToCloseChrome, this));
381 contents = ChromeLauncher::CreateServiceStateFile(proxy_id, setup.printers());
383 if (contents.empty())
384 return ShowError(IDS_ERROR_FAILED_CREATE_CONFIG);
386 size_t written = file_util::WriteFile(file, contents.c_str(),
387 contents.size());
388 if (written != contents.size()) {
389 DWORD last_error = GetLastError();
390 if (!last_error)
391 return ShowError(IDS_ERROR_FAILED_CREATE_CONFIG);
392 return ShowError(HRESULT_FROM_WIN32(last_error));
395 hr = controller_.InstallConnectorService(user, password, base::FilePath(),
396 enable_logging);
397 if (FAILED(hr))
398 return ShowError(hr);
400 hr = controller_.StartService();
401 if (FAILED(hr))
402 return ShowError(hr);
405 void SetupDialog::Start() {
406 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_IO));
407 HRESULT hr = controller_.StartService();
408 if (FAILED(hr))
409 ShowError(hr);
410 UpdateState();
413 void SetupDialog::Stop() {
414 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_IO));
415 HRESULT hr = controller_.StopService();
416 if (FAILED(hr))
417 ShowError(hr);
418 UpdateState();
421 void SetupDialog::Uninstall() {
422 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_IO));
423 HRESULT hr = controller_.UninstallService();
424 if (FAILED(hr))
425 ShowError(hr);
426 UpdateState();
429 class CloudPrintServiceConfigModule
430 : public ATL::CAtlExeModuleT<CloudPrintServiceConfigModule> {
433 CloudPrintServiceConfigModule _AtlModule;
435 int WINAPI WinMain(__in HINSTANCE hInstance,
436 __in HINSTANCE hPrevInstance,
437 __in LPSTR lpCmdLine,
438 __in int nCmdShow) {
439 base::AtExitManager at_exit;
440 CommandLine::Init(0, NULL);
442 base::MessageLoopForUI loop;
443 scoped_refptr<SetupDialog> dialog(new SetupDialog());
444 dialog->Create(NULL);
445 dialog->ShowWindow(SW_SHOW);
446 scoped_ptr<SetupDialog::MessageFilter> filter(
447 new SetupDialog::MessageFilter(dialog));
448 loop.SetMessageFilter(filter.Pass());
450 loop.Run();
451 return 0;