Home | History | Annotate | Download | only in win
      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/files/file_path.h"
      9 #include "base/files/file_util.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 
     20 namespace {
     21 
     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);
     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 
     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)));
     64 }
     65 
     66 ServiceListener::~ServiceListener() {
     67   ipc_thread_->message_loop()->PostTask(FROM_HERE,
     68                                         base::Bind(&ServiceListener::Disconnect,
     69                                                    base::Unretained(this)));
     70   ipc_thread_->Stop();
     71 }
     72 
     73 bool ServiceListener::OnMessageReceived(const IPC::Message& msg) {
     74   return true;
     75 }
     76 
     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);
     81 }
     82 
     83 void ServiceListener::Disconnect() {
     84   channel_.reset();
     85 }
     86 
     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_ = IPC::Channel::CreateClient(IPC::ChannelHandle(handle.Get()),
     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