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. 4 5#include "cloud_print/service/win/service_listener.h" 6 7#include "base/bind.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" 19 20namespace { 21 22std::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); 30 } 31 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 (base::CreateDirectory(user_data_dir)) { 41 base::FilePath temp_file; 42 if (base::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); 47 } 48 } 49 50 std::string result; 51 base::JSONWriter::Write(&environment, &result); 52 return result; 53} 54 55} // namespace 56 57ServiceListener::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))); 64} 65 66ServiceListener::~ServiceListener() { 67 ipc_thread_->message_loop()->PostTask(FROM_HERE, 68 base::Bind(&ServiceListener::Disconnect, 69 base::Unretained(this))); 70 ipc_thread_->Stop(); 71} 72 73bool ServiceListener::OnMessageReceived(const IPC::Message& msg) { 74 return true; 75} 76 77void 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); 81} 82 83void ServiceListener::Disconnect() { 84 channel_.reset(); 85} 86 87void 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_ = IPC::Channel::CreateClient(IPC::ChannelHandle(handle), 95 this); 96 channel_->Connect(); 97 } else { 98 ipc_thread_->message_loop()->PostDelayedTask( 99 FROM_HERE, 100 base::Bind(&ServiceListener::Connect, base::Unretained(this)), 101 base::TimeDelta::FromMilliseconds(500)); 102 } 103} 104 105