diff options
-rw-r--r-- | cloud_print/cloud_print.gyp | 8 | ||||
-rw-r--r-- | cloud_print/service/service.gyp | 5 | ||||
-rw-r--r-- | cloud_print/service/win/cloud_print_service.cc | 101 | ||||
-rw-r--r-- | cloud_print/service/win/cloud_print_service.rc | 2 | ||||
-rw-r--r-- | cloud_print/service/win/service_controller.cc | 12 | ||||
-rw-r--r-- | cloud_print/service/win/service_controller.h | 5 | ||||
-rw-r--r-- | cloud_print/service/win/service_ipc_unittest.cc | 46 | ||||
-rw-r--r-- | cloud_print/service/win/service_listener.cc | 104 | ||||
-rw-r--r-- | cloud_print/service/win/service_listener.h | 41 | ||||
-rw-r--r-- | cloud_print/service/win/service_utils.cc | 2 | ||||
-rw-r--r-- | cloud_print/service/win/service_utils.h | 2 | ||||
-rw-r--r-- | cloud_print/service/win/setup_listener.cc | 124 | ||||
-rw-r--r-- | cloud_print/service/win/setup_listener.h | 83 |
13 files changed, 468 insertions, 67 deletions
diff --git a/cloud_print/cloud_print.gyp b/cloud_print/cloud_print.gyp index 30d7e9f..8994449 100644 --- a/cloud_print/cloud_print.gyp +++ b/cloud_print/cloud_print.gyp @@ -88,6 +88,7 @@ 'conditions': [ ['OS=="win"', { 'sources': [ + 'service/win/service_ipc_unittest.cc', 'virtual_driver/win/port_monitor/port_monitor_unittest.cc', ], 'dependencies': [ @@ -95,6 +96,13 @@ ], }], ], + 'msvs_settings': { + 'VCLinkerTool': { + 'AdditionalDependencies': [ + 'secur32.lib', + ], + }, + }, }, ], } diff --git a/cloud_print/service/service.gyp b/cloud_print/service/service.gyp index 9dc7975..8e11395 100644 --- a/cloud_print/service/service.gyp +++ b/cloud_print/service/service.gyp @@ -35,6 +35,7 @@ 'dependencies': [ '<(DEPTH)/base/base.gyp:base', '<(DEPTH)/build/temp_gyp/googleurl.gyp:googleurl', + '<(DEPTH)/ipc/ipc.gyp:ipc', '<(DEPTH)/net/net.gyp:net', '<(DEPTH)/printing/printing.gyp:printing', ], @@ -57,8 +58,12 @@ 'win/local_security_policy.h', 'win/service_controller.cc', 'win/service_controller.h', + 'win/service_listener.cc', + 'win/service_listener.h', 'win/service_utils.cc', 'win/service_utils.h', + 'win/setup_listener.cc', + 'win/setup_listener.h', ], }, { diff --git a/cloud_print/service/win/cloud_print_service.cc b/cloud_print/service/win/cloud_print_service.cc index c1299c8..0bc922e 100644 --- a/cloud_print/service/win/cloud_print_service.cc +++ b/cloud_print/service/win/cloud_print_service.cc @@ -16,19 +16,17 @@ #include "base/path_service.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "chrome/installer/launcher_support/chrome_launcher_support.h" +#include "base/win/scoped_handle.h" #include "cloud_print/service/service_state.h" #include "cloud_print/service/service_switches.h" #include "cloud_print/service/win/chrome_launcher.h" #include "cloud_print/service/win/service_controller.h" +#include "cloud_print/service/win/service_listener.h" #include "cloud_print/service/win/service_utils.h" -#include "printing/backend/print_backend.h" +#include "cloud_print/service/win/setup_listener.h" namespace { -const char kChromeIsNotAvalible[] = "\nChrome is not available\n"; -const char kChromeIsAvalible[] = "\nChrome is available\n"; -const wchar_t kRequirementsFileName[] = L"cloud_print_service_requirements.txt"; const wchar_t kServiceStateFileName[] = L"Service State"; void InvalidUsage() { @@ -113,6 +111,7 @@ bool AskUser(const std::string& request) { } // namespace + class CloudPrintServiceModule : public ATL::CAtlServiceModuleT<CloudPrintServiceModule, IDS_SERVICENAME> { public: @@ -153,13 +152,9 @@ class CloudPrintServiceModule return hr; if (check_requirements_) { - hr = CheckRequirements(); - if (FAILED(hr)) - return hr; - // Don't run message loop and stop service. - return S_FALSE; + CheckRequirements(); } else { - hr = StartConnector(); + HRESULT hr = StartConnector(); if (FAILED(hr)) return hr; } @@ -172,6 +167,7 @@ class CloudPrintServiceModule HRESULT PostMessageLoop() { StopConnector(); + setup_listener_.reset(); return Base::PostMessageLoop(); } @@ -203,7 +199,7 @@ class CloudPrintServiceModule return hr; hr = controller_->InstallService(run_as_user, run_as_password, - kServiceSwitch, user_data_dir_); + kServiceSwitch, user_data_dir_, true); if (SUCCEEDED(hr) && command_line.HasSwitch(kStartSwitch)) return controller_->StartService(); @@ -213,6 +209,14 @@ class CloudPrintServiceModule if (command_line.HasSwitch(kStartSwitch)) return controller_->StartService(); + if (command_line.HasSwitch(kConsoleSwitch)) { + check_requirements_ = command_line.HasSwitch(kRequirementsSwitch); + ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE); + HRESULT hr = Run(); + ::SetConsoleCtrlHandler(NULL, FALSE); + return hr; + } + if (command_line.HasSwitch(kServiceSwitch) || command_line.HasSwitch(kRequirementsSwitch)) { *is_service = true; @@ -220,12 +224,6 @@ class CloudPrintServiceModule return S_OK; } - if (command_line.HasSwitch(kConsoleSwitch)) { - ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE); - HRESULT hr = Run(); - ::SetConsoleCtrlHandler(NULL, FALSE); - return hr; - } InvalidUsage(); return S_FALSE; @@ -239,42 +237,47 @@ class CloudPrintServiceModule WideToASCII(*run_as_user), false)); *run_as_password = ASCIIToWide(GetOption("Password", "", true)); - base::FilePath requirements_filename(user_data_dir_); - requirements_filename = - requirements_filename.Append(kRequirementsFileName); - - file_util::Delete(requirements_filename, false); - if (file_util::PathExists(requirements_filename)) { - LOG(ERROR) << "Unable to delete " << - requirements_filename.value() << "."; - continue; - } + SetupListener setup(*run_as_user); if (FAILED(controller_->InstallService(*run_as_user, *run_as_password, kRequirementsSwitch, - user_data_dir_))) { + user_data_dir_, false))) { + LOG(ERROR) << "Failed to install service as " << *run_as_user << "."; continue; } + bool service_started = SUCCEEDED(controller_->StartService()); + + if (service_started && + !setup.WaitResponce(base::TimeDelta::FromSeconds(30))) { + LOG(ERROR) << "Failed to check environment for user " << *run_as_user + << "."; + } + controller_->UninstallService(); if (!service_started) { LOG(ERROR) << "Failed to start service as " << *run_as_user << "."; continue; } - std::string printers; - if (!file_util::PathExists(requirements_filename) || - !file_util::ReadFileToString(requirements_filename, &printers)) { - LOG(ERROR) << "Service can't create " << requirements_filename.value(); + if (setup.user_data_dir().empty()) { + LOG(ERROR) << "Service can't access " << user_data_dir_.value() << "."; continue; } - - if (EndsWith(printers, kChromeIsNotAvalible, true)) { - LOG(ERROR) << kChromeIsNotAvalible << " for " << *run_as_user << "."; + if (setup.chrome_path().empty()) { + LOG(ERROR) << "Chrome is not available for " << *run_as_user << "."; + continue; + } + if (!setup.is_xps_availible()) { + LOG(ERROR) << "XPS pack is not installed."; continue; } std::cout << "\nService requirements check result: \n"; - std::cout << printers << "\n"; - file_util::Delete(requirements_filename, false); + std::cout << "Username: " << setup.user_name()<< "\n"; + std::cout << "Chrome: " << setup.chrome_path().value()<< "\n"; + std::cout << "Printers:\n "; + std::ostream_iterator<std::string> cout_it(std::cout, "\n "); + std::copy(setup.printers().begin(), setup.printers().end(), cout_it); + std::cout << "\n"; if (AskUser("Do you want to use " + WideToASCII(*run_as_user) + "?")) return; @@ -332,25 +335,8 @@ class CloudPrintServiceModule return S_OK; } - HRESULT CheckRequirements() { - base::FilePath requirements_filename(user_data_dir_); - requirements_filename = requirements_filename.Append(kRequirementsFileName); - std::string output; - output.append("Printers available for " + - WideToASCII(GetCurrentUserName()) + ":\n"); - scoped_refptr<printing::PrintBackend> backend( - printing::PrintBackend::CreateInstance(NULL)); - printing::PrinterList printer_list; - backend->EnumeratePrinters(&printer_list); - for (size_t i = 0; i < printer_list.size(); ++i) { - output += " "; - output += printer_list[i].printer_name; - output += "\n"; - } - base::FilePath chrome = chrome_launcher_support::GetAnyChromePath(); - output.append(chrome.empty() ? kChromeIsNotAvalible : kChromeIsAvalible); - file_util::WriteFile(requirements_filename, output.c_str(), output.size()); - return S_OK; + void CheckRequirements() { + setup_listener_.reset(new ServiceListener(user_data_dir_)); } HRESULT StartConnector() { @@ -371,6 +357,7 @@ class CloudPrintServiceModule base::FilePath user_data_dir_; scoped_ptr<ChromeLauncher> chrome_; scoped_ptr<ServiceController> controller_; + scoped_ptr<ServiceListener> setup_listener_; }; CloudPrintServiceModule _AtlModule; diff --git a/cloud_print/service/win/cloud_print_service.rc b/cloud_print/service/win/cloud_print_service.rc index 294a495..42a18cd 100644 --- a/cloud_print/service/win/cloud_print_service.rc +++ b/cloud_print/service/win/cloud_print_service.rc @@ -1,4 +1,4 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2013 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. diff --git a/cloud_print/service/win/service_controller.cc b/cloud_print/service/win/service_controller.cc index 428f282..792c757 100644 --- a/cloud_print/service/win/service_controller.cc +++ b/cloud_print/service/win/service_controller.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 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. @@ -114,7 +114,8 @@ HRESULT ServiceController::StopService() { HRESULT ServiceController::InstallService(const string16& user, const string16& password, const std::string& run_switch, - const base::FilePath& user_data_dir) { + const base::FilePath& user_data_dir, + bool auto_start) { // TODO(vitalybuka): consider "lite" version if we don't want unregister // printers here. HRESULT hr = UninstallService(); @@ -152,9 +153,10 @@ HRESULT ServiceController::InstallService(const string16& user, ServiceHandle service( ::CreateService( scm, name_.c_str(), name_.c_str(), SERVICE_ALL_ACCESS, - SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, - command_line.GetCommandLineString().c_str(), NULL, NULL, NULL, - user.empty() ? NULL : user.c_str(), + SERVICE_WIN32_OWN_PROCESS, + auto_start ? SERVICE_AUTO_START : SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, command_line.GetCommandLineString().c_str(), + NULL, NULL, NULL, user.empty() ? NULL : user.c_str(), password.empty() ? NULL : password.c_str())); if (!service.IsValid()) { diff --git a/cloud_print/service/win/service_controller.h b/cloud_print/service/win/service_controller.h index 4e06059..4f5553b 100644 --- a/cloud_print/service/win/service_controller.h +++ b/cloud_print/service/win/service_controller.h @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 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. @@ -26,7 +26,8 @@ class ServiceController { HRESULT InstallService(const string16& user, const string16& password, const std::string& run_switch, - const base::FilePath& user_data_dir); + const base::FilePath& user_data_dir, + bool auto_start); HRESULT UninstallService(); diff --git a/cloud_print/service/win/service_ipc_unittest.cc b/cloud_print/service/win/service_ipc_unittest.cc new file mode 100644 index 0000000..095e8d2 --- /dev/null +++ b/cloud_print/service/win/service_ipc_unittest.cc @@ -0,0 +1,46 @@ +// Copyright 2013 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 "base/files/scoped_temp_dir.h" +#include "base/threading/platform_thread.h" +#include "base/time.h" +#include "cloud_print/service/win/service_listener.h" +#include "cloud_print/service/win/service_utils.h" +#include "cloud_print/service/win/setup_listener.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(ServiceIpcTest, Timeout) { + SetupListener setup(GetCurrentUserName()); + ASSERT_FALSE(setup.WaitResponce(base::TimeDelta::FromSeconds(3))); +} + +TEST(ServiceIpcTest, Sequence) { + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + SetupListener setup(GetCurrentUserName()); + ServiceListener service(temp_dir.path()); + ASSERT_TRUE(setup.WaitResponce(base::TimeDelta::FromSeconds(30))); + EXPECT_EQ(setup.user_data_dir(), temp_dir.path()); + EXPECT_EQ(setup.user_name(), GetCurrentUserName()); +} + +TEST(ServiceIpcTest, ReverseSequence) { + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + ServiceListener service(temp_dir.path()); + base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); + SetupListener setup(GetCurrentUserName()); + ASSERT_TRUE(setup.WaitResponce(base::TimeDelta::FromSeconds(30))); + EXPECT_EQ(setup.user_data_dir(), temp_dir.path()); + EXPECT_EQ(setup.user_name(), GetCurrentUserName()); +} + +TEST(ServiceIpcTest, InvaludUser) { + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + SetupListener setup(L"guest"); + ServiceListener service(temp_dir.path()); + ASSERT_FALSE(setup.WaitResponce(base::TimeDelta::FromSeconds(3))); +} + diff --git a/cloud_print/service/win/service_listener.cc b/cloud_print/service/win/service_listener.cc new file mode 100644 index 0000000..a69f4ef --- /dev/null +++ b/cloud_print/service/win/service_listener.cc @@ -0,0 +1,104 @@ +// Copyright 2013 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 "cloud_print/service/win/service_listener.h" + +#include "base/bind.h" +#include "base/file_util.h" +#include "base/files/file_path.h" +#include "base/json/json_writer.h" +#include "base/threading/thread.h" +#include "base/values.h" +#include "chrome/installer/launcher_support/chrome_launcher_support.h" +#include "cloud_print/service/win/service_utils.h" +#include "cloud_print/service/win/setup_listener.h" +#include "ipc/ipc_channel.h" +#include "printing/backend/print_backend.h" +#include "printing/backend/win_helper.h" + +namespace { + +std::string GetEnvironment(const base::FilePath& user_data_dir) { + scoped_refptr<printing::PrintBackend> backend( + printing::PrintBackend::CreateInstance(NULL)); + printing::PrinterList printer_list; + backend->EnumeratePrinters(&printer_list); + scoped_ptr<base::ListValue> printers(new base::ListValue()); + for (size_t i = 0; i < printer_list.size(); ++i) { + printers->AppendString(printer_list[i].printer_name); + } + + base::DictionaryValue environment; + environment.Set(SetupListener::kPrintersJsonValueName, printers.release()); + environment.SetBoolean(SetupListener::kXpsAvailibleJsonValueName, + printing::XPSModule::Init()); + environment.SetString(SetupListener::kUserNameJsonValueName, + GetCurrentUserName()); + environment.SetString(SetupListener::kChromePathJsonValueName, + chrome_launcher_support::GetAnyChromePath().value()); + if (file_util::DirectoryExists(user_data_dir)) { + base::FilePath temp_file; + if (file_util::CreateTemporaryFileInDir(user_data_dir, &temp_file)) { + DCHECK(file_util::PathExists(temp_file)); + environment.SetString(SetupListener::kUserDataDirJsonValueName, + user_data_dir.value()); + file_util::Delete(temp_file, false); + } + } + + std::string result; + base::JSONWriter::Write(&environment, &result); + return result; +} + +} // namespace + +ServiceListener::ServiceListener(const base::FilePath& user_data_dir) + : ipc_thread_(new base::Thread("ipc_thread")), + user_data_dir_(user_data_dir) { + ipc_thread_->StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0)); + ipc_thread_->message_loop()->PostTask(FROM_HERE, + base::Bind(&ServiceListener::Connect, + base::Unretained(this))); +} + +ServiceListener::~ServiceListener() { + ipc_thread_->message_loop()->PostTask(FROM_HERE, + base::Bind(&ServiceListener::Disconnect, + base::Unretained(this))); + ipc_thread_->Stop(); +} + +bool ServiceListener::OnMessageReceived(const IPC::Message& msg) { + return true; +} + +void ServiceListener::OnChannelConnected(int32 peer_pid) { + IPC::Message* message = new IPC::Message(0, 0, IPC::Message::PRIORITY_NORMAL); + message->WriteString(GetEnvironment(user_data_dir_)); + channel_->Send(message); +} + +void ServiceListener::Disconnect() { + channel_.reset(); +} + +void ServiceListener::Connect() { + base::win::ScopedHandle handle( + ::CreateFile(SetupListener::kSetupPipeName, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, + SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION | + FILE_FLAG_OVERLAPPED, NULL)); + if (handle.IsValid()) { + channel_.reset(new IPC::Channel(IPC::ChannelHandle(handle), + IPC::Channel::MODE_CLIENT, this)); + channel_->Connect(); + } else { + ipc_thread_->message_loop()->PostDelayedTask( + FROM_HERE, + base::Bind(&ServiceListener::Connect, base::Unretained(this)), + base::TimeDelta::FromMilliseconds(500)); + } +} + diff --git a/cloud_print/service/win/service_listener.h b/cloud_print/service/win/service_listener.h new file mode 100644 index 0000000..cdbc451 --- /dev/null +++ b/cloud_print/service/win/service_listener.h @@ -0,0 +1,41 @@ +// Copyright 2013 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. + +#ifndef CLOUD_PRINT_SERVICE_SERVICE_LISTENER_H_ +#define CLOUD_PRINT_SERVICE_SERVICE_LISTENER_H_ + +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" +#include "ipc/ipc_listener.h" + +namespace base { +class Thread; +} // base + +namespace IPC { +class Channel; +} // IPC + +// Simple IPC listener to run on service side to collect service environment and +// to send back to setup utility. +class ServiceListener : public IPC::Listener { + public: + explicit ServiceListener(const base::FilePath& user_data_dir); + virtual ~ServiceListener(); + + virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; + virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; + + private: + void Disconnect(); + void Connect(); + + scoped_ptr<base::Thread> ipc_thread_; + scoped_ptr<IPC::Channel> channel_; + base::FilePath user_data_dir_; +}; + +#endif // CLOUD_PRINT_SERVICE_SERVICE_LISTENER_H_ + diff --git a/cloud_print/service/win/service_utils.cc b/cloud_print/service/win/service_utils.cc index acd8c3f..fc06271 100644 --- a/cloud_print/service/win/service_utils.cc +++ b/cloud_print/service/win/service_utils.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 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. diff --git a/cloud_print/service/win/service_utils.h b/cloud_print/service/win/service_utils.h index c3cbfa2..33abb65 100644 --- a/cloud_print/service/win/service_utils.h +++ b/cloud_print/service/win/service_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 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. diff --git a/cloud_print/service/win/setup_listener.cc b/cloud_print/service/win/setup_listener.cc new file mode 100644 index 0000000..3bd4b73 --- /dev/null +++ b/cloud_print/service/win/setup_listener.cc @@ -0,0 +1,124 @@ +// Copyright 2013 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 "cloud_print/service/win/setup_listener.h" + +#include <atlbase.h> +#include <atlsecurity.h> + +#include "base/bind.h" +#include "base/guid.h" +#include "base/json/json_reader.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/platform_thread.h" +#include "base/threading/thread.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "ipc/ipc_channel.h" + +const char SetupListener::kXpsAvailibleJsonValueName[] = "xps_availible"; +const char SetupListener::kChromePathJsonValueName[] = "chrome_path"; +const char SetupListener::kPrintersJsonValueName[] = "printers"; +const char SetupListener::kUserDataDirJsonValueName[] = "user_data_dir"; +const char SetupListener::kUserNameJsonValueName[] = "user_name"; +const wchar_t SetupListener::kSetupPipeName[] = + L"\\\\.\\pipe\\CloudPrintServiceSetup"; + +SetupListener::SetupListener(const string16& user) + : done_event_(new base::WaitableEvent(true, false)), + ipc_thread_(new base::Thread("ipc_thread")), + succeded_(false), + is_xps_availible_(false) { + ipc_thread_->StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0)); + ipc_thread_->message_loop()->PostTask(FROM_HERE, + base::Bind(&SetupListener::Connect, + base::Unretained(this), + user)); +} + +SetupListener::~SetupListener() { + ipc_thread_->message_loop()->PostTask(FROM_HERE, + base::Bind(&SetupListener::Disconnect, + base::Unretained(this))); + ipc_thread_->Stop(); +} + +bool SetupListener::OnMessageReceived(const IPC::Message& msg) { + PickleIterator iter(msg); + std::string json_string; + if (!iter.ReadString(&json_string)) + return false; + scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); + const base::DictionaryValue* dictionary = NULL; + if (!value || !value->GetAsDictionary(&dictionary) || !dictionary) { + LOG(ERROR) << "Invalid response from service"; + return false; + } + + const base::ListValue* printers = NULL; + if (dictionary->GetList(kPrintersJsonValueName, &printers) && printers) { + for (size_t i = 0; i < printers->GetSize(); ++i) { + std::string printer; + if (printers->GetString(i, &printer) && !printer.empty()) + printers_.push_back(printer); + } + } + dictionary->GetBoolean(kXpsAvailibleJsonValueName, &is_xps_availible_); + dictionary->GetString(kUserNameJsonValueName, &user_name_); + + string16 chrome_path; + dictionary->GetString(kChromePathJsonValueName, &chrome_path); + chrome_path_ = base::FilePath(chrome_path); + + string16 user_data_dir; + dictionary->GetString(kUserDataDirJsonValueName, &user_data_dir); + user_data_dir_ = base::FilePath(user_data_dir); + + succeded_ = true; + done_event_->Signal(); + return true; +} + +void SetupListener::OnChannelError() { + done_event_->Signal(); +} + +bool SetupListener::WaitResponce(const base::TimeDelta& delta) { + return done_event_->TimedWait(delta) && succeded_; +} + +void SetupListener::Disconnect() { + channel_.reset(); + ipc_thread_->message_loop()->QuitWhenIdle(); +} + +void SetupListener::Connect(const string16& user) { + ATL::CDacl dacl; + + ATL::CSid user_sid; + if (!user_sid.LoadAccount(user.c_str())) { + LOG(ERROR) << "Unable to load Sid for" << user; + } else { + dacl.AddAllowedAce(user_sid, GENERIC_READ | GENERIC_WRITE); + } + + ATL::CSecurityDesc desk; + desk.SetDacl(dacl); + + ATL::CSecurityAttributes attribs(desk); + + base::win::ScopedHandle pipe( + CreateNamedPipe(kSetupPipeName, + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | + FILE_FLAG_FIRST_PIPE_INSTANCE, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, + IPC::Channel::kReadBufferSize, + IPC::Channel::kReadBufferSize, 5000, &attribs)); + if (pipe.IsValid()) { + channel_.reset(new IPC::Channel(IPC::ChannelHandle(pipe), + IPC::Channel::MODE_SERVER, this)); + channel_->Connect(); + } +} + diff --git a/cloud_print/service/win/setup_listener.h b/cloud_print/service/win/setup_listener.h new file mode 100644 index 0000000..0be7acf --- /dev/null +++ b/cloud_print/service/win/setup_listener.h @@ -0,0 +1,83 @@ +// Copyright 2013 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. + +#ifndef CLOUD_PRINT_SERVICE_SETUP_LISTENER_H_ +#define CLOUD_PRINT_SERVICE_SETUP_LISTENER_H_ + +#include <string> +#include <vector> + +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" +#include "base/string16.h" +#include "ipc/ipc_listener.h" + +namespace base { +class Thread; +class TimeDelta; +class WaitableEvent; +} // base + +namespace IPC { +class Channel; +} // IPC + +// Simple IPC listener to run on setup utility size wait message with data about +// environment from service process. +class SetupListener : public IPC::Listener { + public: + static const char kXpsAvailibleJsonValueName[]; + static const char kChromePathJsonValueName[]; + static const char kPrintersJsonValueName[]; + static const char kUserDataDirJsonValueName[]; + static const char kUserNameJsonValueName[]; + static const wchar_t kSetupPipeName[]; + + explicit SetupListener(const string16& user); + virtual ~SetupListener(); + + virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; + virtual void OnChannelError() OVERRIDE; + + bool WaitResponce(const base::TimeDelta& delta); + + const base::FilePath& chrome_path() const { + return chrome_path_; + } + + const base::FilePath& user_data_dir() const { + return user_data_dir_; + } + + const string16& user_name() const { + return user_name_; + } + + const std::vector<std::string>& printers() const { + return printers_; + } + + bool is_xps_availible() const { + return is_xps_availible_; + } + + private: + void Disconnect(); + void Connect(const string16& user); + + base::FilePath chrome_path_; + base::FilePath user_data_dir_; + string16 user_name_; + std::vector<std::string> printers_; + bool is_xps_availible_; + bool succeded_; + + scoped_ptr<base::WaitableEvent> done_event_; + scoped_ptr<base::Thread> ipc_thread_; + scoped_ptr<IPC::Channel> channel_; +}; + +#endif // CLOUD_PRINT_SERVICE_SETUP_LISTENER_H_ + |