1// Copyright (c) 2012 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 "remoting/host/host_event_logger.h"
6
7#include <windows.h>
8#include <string>
9#include <vector>
10
11#include "base/memory/scoped_ptr.h"
12#include "base/memory/weak_ptr.h"
13#include "base/strings/string16.h"
14#include "base/strings/utf_string_conversions.h"
15#include "net/base/ip_endpoint.h"
16#include "remoting/host/host_status_monitor.h"
17#include "remoting/host/host_status_observer.h"
18#include "remoting/protocol/transport.h"
19
20#include "remoting_host_messages.h"
21
22namespace remoting {
23
24namespace {
25
26class HostEventLoggerWin : public HostEventLogger, public HostStatusObserver {
27 public:
28  HostEventLoggerWin(base::WeakPtr<HostStatusMonitor> monitor,
29                     const std::string& application_name);
30
31  virtual ~HostEventLoggerWin();
32
33  // HostStatusObserver implementation.  These methods will be called from the
34  // network thread.
35  virtual void OnClientAuthenticated(const std::string& jid) OVERRIDE;
36  virtual void OnClientDisconnected(const std::string& jid) OVERRIDE;
37  virtual void OnAccessDenied(const std::string& jid) OVERRIDE;
38  virtual void OnClientRouteChange(
39      const std::string& jid,
40      const std::string& channel_name,
41      const protocol::TransportRoute& route) OVERRIDE;
42  virtual void OnStart(const std::string& xmpp_login) OVERRIDE;
43  virtual void OnShutdown() OVERRIDE;
44
45 private:
46  void LogString(WORD type, DWORD event_id, const std::string& string);
47  void Log(WORD type, DWORD event_id, const std::vector<std::string>& strings);
48
49  base::WeakPtr<HostStatusMonitor> monitor_;
50
51  // The handle of the application event log.
52  HANDLE event_log_;
53
54  DISALLOW_COPY_AND_ASSIGN(HostEventLoggerWin);
55};
56
57} //namespace
58
59HostEventLoggerWin::HostEventLoggerWin(base::WeakPtr<HostStatusMonitor> monitor,
60                                       const std::string& application_name)
61    : monitor_(monitor),
62      event_log_(NULL) {
63  event_log_ = RegisterEventSourceW(
64      NULL, base::UTF8ToUTF16(application_name).c_str());
65  if (event_log_ != NULL) {
66    monitor_->AddStatusObserver(this);
67  } else {
68    PLOG(ERROR) << "Failed to register the event source: " << application_name;
69  }
70}
71
72HostEventLoggerWin::~HostEventLoggerWin() {
73  if (event_log_ != NULL) {
74    if (monitor_)
75      monitor_->RemoveStatusObserver(this);
76    DeregisterEventSource(event_log_);
77  }
78}
79
80void HostEventLoggerWin::OnClientAuthenticated(const std::string& jid) {
81  LogString(EVENTLOG_INFORMATION_TYPE, MSG_HOST_CLIENT_CONNECTED, jid);
82}
83
84void HostEventLoggerWin::OnClientDisconnected(const std::string& jid) {
85  LogString(EVENTLOG_INFORMATION_TYPE, MSG_HOST_CLIENT_DISCONNECTED, jid);
86}
87
88void HostEventLoggerWin::OnAccessDenied(const std::string& jid) {
89  LogString(EVENTLOG_ERROR_TYPE, MSG_HOST_CLIENT_ACCESS_DENIED, jid);
90}
91
92void HostEventLoggerWin::OnClientRouteChange(
93    const std::string& jid,
94    const std::string& channel_name,
95    const protocol::TransportRoute& route) {
96  std::vector<std::string> strings(5);
97  strings[0] = jid;
98  strings[1] = route.remote_address.ToString();
99  strings[2] = route.local_address.ToString();
100  strings[3] = channel_name;
101  strings[4] = protocol::TransportRoute::GetTypeString(route.type);
102  Log(EVENTLOG_INFORMATION_TYPE, MSG_HOST_CLIENT_ROUTING_CHANGED, strings);
103}
104
105void HostEventLoggerWin::OnShutdown() {
106  // TODO(rmsousa): Fix host shutdown to actually call this, and add a log line.
107}
108
109void HostEventLoggerWin::OnStart(const std::string& xmpp_login) {
110  LogString(EVENTLOG_INFORMATION_TYPE, MSG_HOST_STARTED, xmpp_login);
111}
112
113void HostEventLoggerWin::Log(WORD type,
114                             DWORD event_id,
115                             const std::vector<std::string>& strings) {
116  if (event_log_ == NULL)
117    return;
118
119  // ReportEventW() takes an array of raw string pointers. They should stay
120  // valid for the duration of the call.
121  std::vector<const WCHAR*> raw_strings(strings.size());
122  std::vector<base::string16> utf16_strings(strings.size());
123  for (size_t i = 0; i < strings.size(); ++i) {
124    utf16_strings[i] = base::UTF8ToUTF16(strings[i]);
125    raw_strings[i] = utf16_strings[i].c_str();
126  }
127
128  if (!ReportEventW(event_log_,
129                    type,
130                    HOST_CATEGORY,
131                    event_id,
132                    NULL,
133                    static_cast<WORD>(raw_strings.size()),
134                    0,
135                    &raw_strings[0],
136                    NULL)) {
137    PLOG(ERROR) << "Failed to write an event to the event log";
138  }
139}
140
141void HostEventLoggerWin::LogString(WORD type,
142                                   DWORD event_id,
143                                   const std::string& string) {
144  std::vector<std::string> strings;
145  strings.push_back(string);
146  Log(type, event_id, strings);
147}
148
149// static
150scoped_ptr<HostEventLogger> HostEventLogger::Create(
151    base::WeakPtr<HostStatusMonitor> monitor,
152    const std::string& application_name) {
153  return scoped_ptr<HostEventLogger>(
154      new HostEventLoggerWin(monitor, application_name));
155}
156
157}  // namespace remoting
158