| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/credential_provider/extension/service.h" |
| |
| #include "base/run_loop.h" |
| #include "base/task/single_thread_task_executor.h" |
| #include "chrome/credential_provider/extension/os_service_manager.h" |
| #include "chrome/credential_provider/extension/task_manager.h" |
| #include "chrome/credential_provider/gaiacp/logging.h" |
| |
| namespace credential_provider { |
| namespace extension { |
| |
| // static |
| Service** Service::GetInstanceStorage() { |
| static Service* instance = new Service(); |
| |
| return &instance; |
| } |
| |
| // static |
| Service* Service::Get() { |
| return *GetInstanceStorage(); |
| } |
| |
| DWORD Service::Run() { |
| return (this->*run_routine_)(); |
| } |
| |
| Service::Service() |
| : run_routine_(&Service::RunAsService), |
| service_status_(), |
| service_status_handle_(nullptr) { |
| service_status_.dwServiceType = SERVICE_WIN32_OWN_PROCESS; |
| service_status_.dwCurrentState = SERVICE_STOPPED; |
| service_status_.dwControlsAccepted = |
| SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN; |
| } |
| |
| Service::~Service() {} |
| |
| DWORD Service::RunAsService() { |
| LOGFN(VERBOSE); |
| |
| DWORD error_code = |
| extension::OSServiceManager::Get()->StartServiceCtrlDispatcher( |
| &Service::ServiceMain); |
| |
| if (error_code != ERROR_SUCCESS) { |
| LOGFN(ERROR) |
| << "OSServiceManager::StartServiceCtrlDispatcher failed with win32=" |
| << error_code; |
| } |
| |
| return error_code; |
| } |
| |
| void Service::StartMain() { |
| base::SingleThreadTaskExecutor main_task_executor; |
| |
| scoped_refptr<base::SingleThreadTaskRunner> main_task_runner = |
| main_task_executor.task_runner(); |
| |
| base::RunLoop run_loop; |
| quit_closure_ = run_loop.QuitClosure(); |
| |
| DWORD error_code = extension::OSServiceManager::Get()->RegisterCtrlHandler( |
| &Service::ServiceControlHandler, &service_status_handle_); |
| if (error_code != ERROR_SUCCESS) { |
| LOGFN(ERROR) << "OSServiceManager::RegisterCtrlHandler failed win32=" |
| << error_code; |
| return; |
| } |
| |
| service_status_.dwCurrentState = SERVICE_RUNNING; |
| |
| error_code = extension::OSServiceManager::Get()->SetServiceStatus( |
| service_status_handle_, service_status_); |
| if (error_code != ERROR_SUCCESS) { |
| LOGFN(ERROR) << "OSServiceManager::SetServiceStatus failed win32=" |
| << error_code; |
| return; |
| } |
| |
| TaskManager::Get()->RunTasks(main_task_runner); |
| |
| run_loop.Run(); |
| |
| service_status_.dwCurrentState = SERVICE_STOPPED; |
| service_status_.dwControlsAccepted = 0; |
| |
| error_code = extension::OSServiceManager::Get()->SetServiceStatus( |
| service_status_handle_, service_status_); |
| if (error_code != ERROR_SUCCESS) |
| LOGFN(ERROR) << "OSServiceManager::SetServiceStatus failed win32=" |
| << error_code; |
| } |
| |
| // static |
| VOID WINAPI Service::ServiceMain(DWORD argc /*unused*/, |
| WCHAR* argv[] /*unused*/) { |
| LOGFN(VERBOSE); |
| |
| Service* self = Service::Get(); |
| |
| // Run the service. |
| self->StartMain(); |
| } |
| |
| // static |
| VOID WINAPI Service::ServiceControlHandler(DWORD control) { |
| LOGFN(VERBOSE); |
| |
| Service* self = Service::Get(); |
| switch (control) { |
| case SERVICE_CONTROL_PRESHUTDOWN: |
| case SERVICE_CONTROL_STOP: |
| self->service_status_.dwCurrentState = SERVICE_STOP_PENDING; |
| |
| extension::OSServiceManager::Get()->SetServiceStatus( |
| self->service_status_handle_, self->service_status_); |
| std::move(self->quit_closure_).Run(); |
| |
| break; |
| default: |
| break; |
| } |
| } |
| |
| } // namespace extension |
| } // namespace credential_provider |