1// Copyright 2014 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#ifndef EXTENSIONS_BROWSER_API_CAST_CHANNEL_LOGGER_H_
6#define EXTENSIONS_BROWSER_API_CAST_CHANNEL_LOGGER_H_
7
8#include <deque>
9#include <map>
10
11#include "base/basictypes.h"
12#include "base/memory/linked_ptr.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/threading/thread_checker.h"
15#include "extensions/browser/api/cast_channel/cast_socket.h"
16#include "extensions/browser/api/cast_channel/logger_util.h"
17#include "extensions/common/api/cast_channel/logging.pb.h"
18#include "net/base/ip_endpoint.h"
19
20namespace base {
21class TickClock;
22}
23
24namespace extensions {
25namespace core_api {
26namespace cast_channel {
27
28struct AuthResult;
29
30static const int kMaxSocketsToLog = 50;
31static const int kMaxEventsPerSocket = 2000;
32
33// Logs information of each channel and sockets and exports the log as
34// a blob. Logger is done on the IO thread.
35class Logger : public base::RefCounted<Logger> {
36 public:
37  // |clock|: Clock used for generating timestamps for the events. Owned by
38  // this class.
39  // |unix_epoch_time_ticks|: The TimeTicks that corresponds to Unix epoch.
40  Logger(scoped_ptr<base::TickClock> clock,
41         base::TimeTicks unix_epoch_time_ticks);
42
43  // For newly created sockets. Will create an event and log a
44  // CAST_SOCKET_CREATED event.
45  void LogNewSocketEvent(const CastSocket& cast_socket);
46
47  void LogSocketEvent(int channel_id, proto::EventType event_type);
48  void LogSocketEventWithDetails(int channel_id,
49                                 proto::EventType event_type,
50                                 const std::string& details);
51
52  // For events that involves socket / crypto operations that returns a value.
53  void LogSocketEventWithRv(int channel_id,
54                            proto::EventType event_type,
55                            int rv);
56
57  // For *_STATE_CHANGED events.
58  void LogSocketReadyState(int channel_id, proto::ReadyState new_state);
59  void LogSocketConnectState(int channel_id, proto::ConnectionState new_state);
60  void LogSocketReadState(int channel_id, proto::ReadState new_state);
61  void LogSocketWriteState(int channel_id, proto::WriteState new_state);
62  void LogSocketErrorState(int channel_id, proto::ErrorState new_state);
63
64  // For AUTH_CHALLENGE_REPLY event.
65  void LogSocketChallengeReplyEvent(int channel_id,
66                                    const AuthResult& auth_result);
67
68  void LogSocketEventForMessage(int channel_id,
69                                proto::EventType event_type,
70                                const std::string& message_namespace,
71                                const std::string& details);
72
73  // Assembles logs collected so far and return it as a serialized Log proto,
74  // compressed in gzip format.
75  // If serialization or compression failed, returns a NULL pointer.
76  // |length|: If successful, assigned with size of compressed content.
77  scoped_ptr<char[]> GetLogs(size_t* length) const;
78
79  // Clears the internal map.
80  void Reset();
81
82  // Returns the last errors logged for |channel_id|.  If the the logs for
83  // |channel_id| are evicted before this is called, returns a LastErrors with
84  // no errors.  This may happen if errors are logged and retrieved in different
85  // tasks.
86  LastErrors GetLastErrors(int channel_id) const;
87
88 private:
89  friend class base::RefCounted<Logger>;
90  ~Logger();
91
92  struct AggregatedSocketEventLog {
93   public:
94    AggregatedSocketEventLog();
95    ~AggregatedSocketEventLog();
96
97    // Partially constructed AggregatedSocketEvent proto populated by Logger.
98    // Contains top level info such as channel ID, IP end point and channel
99    // auth type.
100    proto::AggregatedSocketEvent aggregated_socket_event;
101    // Events to be assigned to the AggregatedSocketEvent proto. Contains the
102    // most recent |kMaxEventsPerSocket| entries. The oldest events are
103    // evicted as new events are logged.
104    std::deque<proto::SocketEvent> socket_events;
105
106    // The most recent errors logged for the socket.
107    LastErrors last_errors;
108  };
109
110  typedef std::map<int, linked_ptr<AggregatedSocketEventLog> >
111      AggregatedSocketEventLogMap;
112
113  // Returns a SocketEvent proto with common fields (EventType, timestamp)
114  // populated.
115  proto::SocketEvent CreateEvent(proto::EventType event_type);
116
117  // Records |event| associated with |channel_id|.
118  // If the internal map is already logging maximum number of sockets and this
119  // is a new socket, the socket with the smallest channel id will be discarded.
120  // Returns a reference to the AggregatedSocketEvent proto created/modified.
121  proto::AggregatedSocketEvent& LogSocketEvent(
122      int channel_id,
123      const proto::SocketEvent& socket_event);
124
125  scoped_ptr<base::TickClock> clock_;
126  AggregatedSocketEventLogMap aggregated_socket_events_;
127  base::TimeTicks unix_epoch_time_ticks_;
128
129  // Log proto holding global statistics.
130  proto::Log log_;
131
132  base::ThreadChecker thread_checker_;
133
134  DISALLOW_COPY_AND_ASSIGN(Logger);
135};
136}  // namespace cast_channel
137}  // namespace api
138}  // namespace extensions
139
140#endif  // EXTENSIONS_BROWSER_API_CAST_CHANNEL_LOGGER_H_
141