summaryrefslogtreecommitdiffstats
path: root/cloud_print/service/win/service_listener.cc
blob: 96c6bbf28d6a799fda521b5f521a629c9d0960d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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::kXpsAvailableJsonValueName,
                         printing::XPSModule::Init());
  environment.SetString(SetupListener::kUserNameJsonValueName,
                        GetCurrentUserName());
  environment.SetString(SetupListener::kChromePathJsonValueName,
                        chrome_launcher_support::GetAnyChromePath().value());
  if (file_util::CreateDirectory(user_data_dir)) {
    base::FilePath temp_file;
    if (file_util::CreateTemporaryFileInDir(user_data_dir, &temp_file)) {
      DCHECK(base::PathExists(temp_file));
      environment.SetString(SetupListener::kUserDataDirJsonValueName,
                            user_data_dir.value());
      base::DeleteFile(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(base::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));
  }
}