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 "cloud_print/service/win/service_listener.h"
8 #include "base/file_util.h"
9 #include "base/files/file_path.h"
10 #include "base/json/json_writer.h"
11 #include "base/threading/thread.h"
12 #include "base/values.h"
13 #include "chrome/installer/launcher_support/chrome_launcher_support.h"
14 #include "cloud_print/service/win/service_utils.h"
15 #include "cloud_print/service/win/setup_listener.h"
16 #include "ipc/ipc_channel.h"
17 #include "printing/backend/print_backend.h"
18 #include "printing/backend/win_helper.h"
22 std::string GetEnvironment(const base::FilePath& user_data_dir) {
23 scoped_refptr<printing::PrintBackend> backend(
24 printing::PrintBackend::CreateInstance(NULL));
25 printing::PrinterList printer_list;
26 backend->EnumeratePrinters(&printer_list);
27 scoped_ptr<base::ListValue> printers(new base::ListValue());
28 for (size_t i = 0; i < printer_list.size(); ++i) {
29 printers->AppendString(printer_list[i].printer_name);
32 base::DictionaryValue environment;
33 environment.Set(SetupListener::kPrintersJsonValueName, printers.release());
34 environment.SetBoolean(SetupListener::kXpsAvailableJsonValueName,
35 printing::XPSModule::Init());
36 environment.SetString(SetupListener::kUserNameJsonValueName,
37 GetCurrentUserName());
38 environment.SetString(SetupListener::kChromePathJsonValueName,
39 chrome_launcher_support::GetAnyChromePath().value());
40 if (file_util::CreateDirectory(user_data_dir)) {
41 base::FilePath temp_file;
42 if (file_util::CreateTemporaryFileInDir(user_data_dir, &temp_file)) {
43 DCHECK(base::PathExists(temp_file));
44 environment.SetString(SetupListener::kUserDataDirJsonValueName,
45 user_data_dir.value());
46 base::DeleteFile(temp_file, false);
51 base::JSONWriter::Write(&environment, &result);
57 ServiceListener::ServiceListener(const base::FilePath& user_data_dir)
58 : ipc_thread_(new base::Thread("ipc_thread")),
59 user_data_dir_(user_data_dir) {
60 ipc_thread_->StartWithOptions(
61 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
62 ipc_thread_->message_loop()->PostTask(
63 FROM_HERE, base::Bind(&ServiceListener::Connect, base::Unretained(this)));
66 ServiceListener::~ServiceListener() {
67 ipc_thread_->message_loop()->PostTask(FROM_HERE,
68 base::Bind(&ServiceListener::Disconnect,
69 base::Unretained(this)));
73 bool ServiceListener::OnMessageReceived(const IPC::Message& msg) {
77 void ServiceListener::OnChannelConnected(int32 peer_pid) {
78 IPC::Message* message = new IPC::Message(0, 0, IPC::Message::PRIORITY_NORMAL);
79 message->WriteString(GetEnvironment(user_data_dir_));
80 channel_->Send(message);
83 void ServiceListener::Disconnect() {
87 void ServiceListener::Connect() {
88 base::win::ScopedHandle handle(
89 ::CreateFile(SetupListener::kSetupPipeName, GENERIC_READ | GENERIC_WRITE,
90 0, NULL, OPEN_EXISTING,
91 SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
92 FILE_FLAG_OVERLAPPED, NULL));
93 if (handle.IsValid()) {
94 channel_.reset(new IPC::Channel(IPC::ChannelHandle(handle),
95 IPC::Channel::MODE_CLIENT, this));
98 ipc_thread_->message_loop()->PostDelayedTask(
100 base::Bind(&ServiceListener::Connect, base::Unretained(this)),
101 base::TimeDelta::FromMilliseconds(500));