summaryrefslogtreecommitdiffstats
path: root/chrome/browser/media/webrtc_logging_handler_host.h
blob: d62d6ccfc539ce2259c7f67b5a21f74674d79c89 (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
// 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.

#ifndef CHROME_BROWSER_MEDIA_WEBRTC_LOGGING_HANDLER_HOST_H_
#define CHROME_BROWSER_MEDIA_WEBRTC_LOGGING_HANDLER_HOST_H_

#include "base/basictypes.h"
#include "base/memory/shared_memory.h"
#include "chrome/browser/media/rtp_dump_type.h"
#include "chrome/browser/media/webrtc_rtp_dump_handler.h"
#include "chrome/common/media/webrtc_logging_message_data.h"
#include "chrome/common/partial_circular_buffer.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/render_process_host.h"
#include "net/base/network_interfaces.h"

namespace net {
class URLRequestContextGetter;
}  // namespace net

class Profile;
class WebRtcLogUploader;

#if defined(OS_ANDROID)
const size_t kWebRtcLogSize = 1 * 1024 * 1024;  // 1 MB
#else
const size_t kWebRtcLogSize = 6 * 1024 * 1024;  // 6 MB
#endif

typedef std::map<std::string, std::string> MetaDataMap;

struct WebRtcLogPaths {
  base::FilePath log_path;  // todo: rename to directory.
  base::FilePath incoming_rtp_dump;
  base::FilePath outgoing_rtp_dump;
};

class WebRtcLogBuffer {
 public:
  WebRtcLogBuffer();
  ~WebRtcLogBuffer();

  void Log(const std::string& message);

  // Returns a circular buffer instance for reading the internal log buffer.
  // Must only be called after the log has been marked as complete
  // (see SetComplete) and the caller must ensure that the WebRtcLogBuffer
  // instance remains in scope for the lifetime of the returned circular buffer.
  PartialCircularBuffer Read();

  // Switches the buffer to read-only mode, where access to the internal
  // buffer is allowed from different threads than were used to contribute
  // to the log.  Calls to Log() won't be allowed after calling
  // SetComplete() and the call to SetComplete() must be done on the same
  // thread as constructed the buffer and calls Log().
  void SetComplete();

 private:
  base::ThreadChecker thread_checker_;
  uint8 buffer_[kWebRtcLogSize];
  PartialCircularBuffer circular_;
  bool read_only_;
};

// WebRtcLoggingHandlerHost handles operations regarding the WebRTC logging:
// - Opens a shared memory buffer that the handler in the render process
//   writes to.
// - Writes basic machine info to the log.
// - Informs the handler in the render process when to stop logging.
// - Closes the shared memory (and thereby discarding it) or triggers uploading
//   of the log.
// - Detects when channel, i.e. renderer, is going away and possibly triggers
//   uploading the log.
class WebRtcLoggingHandlerHost : public content::BrowserMessageFilter {
 public:
  typedef base::Callback<void(bool, const std::string&)> GenericDoneCallback;
  typedef base::Callback<void(bool, const std::string&, const std::string&)>
      UploadDoneCallback;
  typedef base::Callback<void(const std::string&)>
      AudioDebugRecordingsErrorCallback;
  typedef base::Callback<void(const std::string&, bool, bool)>
      AudioDebugRecordingsCallback;

  WebRtcLoggingHandlerHost(Profile* profile, WebRtcLogUploader* log_uploader);

  // Sets meta data that will be uploaded along with the log and also written
  // in the beginning of the log. Must be called on the IO thread before calling
  // StartLogging.
  void SetMetaData(scoped_ptr<MetaDataMap> meta_data,
                   const GenericDoneCallback& callback);

  // Opens a log and starts logging. Must be called on the IO thread.
  void StartLogging(const GenericDoneCallback& callback);

  // Stops logging. Log will remain open until UploadLog or DiscardLog is
  // called. Must be called on the IO thread.
  void StopLogging(const GenericDoneCallback& callback);

  // Uploads the log and the RTP dumps. Discards the local copy. May only be
  // called after logging has stopped. Must be called on the IO thread.
  void UploadLog(const UploadDoneCallback& callback);

  // Uploads a log that was previously saved via a call to StoreLog().
  // Otherwise operates in the same way as UploadLog.
  void UploadStoredLog(const std::string& log_id,
                       const UploadDoneCallback& callback);

  // Called by WebRtcLogUploader when uploading has finished. Must be called on
  // the IO thread.
  void UploadLogDone();

  // Discards the log and the RTP dumps. May only be called after logging has
  // stopped. Must be called on the IO thread.
  void DiscardLog(const GenericDoneCallback& callback);

  // Stores the log locally using a hash of log_id + security origin.
  void StoreLog(const std::string& log_id, const GenericDoneCallback& callback);

  // Adds a message to the log.
  // This method must be called on the IO thread.
  void LogMessage(const std::string& message);

  // May be called on any thread. |upload_log_on_render_close_| is used
  // for decision making and it's OK if it changes before the execution based
  // on that decision has finished.
  void set_upload_log_on_render_close(bool should_upload) {
    upload_log_on_render_close_ = should_upload;
  }

  // Starts dumping the RTP headers for the specified direction. Must be called
  // on the IO thread. |type| specifies which direction(s) of RTP packets should
  // be dumped. |callback| will be called when starting the dump is done.
  // |stop_callback| will be called when StopRtpDump is called.
  void StartRtpDump(RtpDumpType type,
                    const GenericDoneCallback& callback,
                    const content::RenderProcessHost::WebRtcStopRtpDumpCallback&
                        stop_callback);

  // Stops dumping the RTP headers for the specified direction. Must be called
  // on the IO thread. |type| specifies which direction(s) of RTP packet dumping
  // should be stopped. |callback| will be called when stopping the dump is
  // done.
  void StopRtpDump(RtpDumpType type, const GenericDoneCallback& callback);

  // Called when an RTP packet is sent or received. Must be called on the UI
  // thread.
  void OnRtpPacket(scoped_ptr<uint8[]> packet_header,
                   size_t header_length,
                   size_t packet_length,
                   bool incoming);

  // Starts an audio debug recording. The recording lasts the given |delay|,
  // unless |delay| is zero, in which case recording will continue until
  // StopAudioDebugRecordings() is explicitly invoked.
  // |callback| is invoked once recording stops. If |delay| is zero
  // |callback| is invoked once recording starts.
  // If a recording was already in progress, |error_callback| is invoked instead
  // of |callback|.
  void StartAudioDebugRecordings(
      content::RenderProcessHost* host,
      base::TimeDelta delay,
      const AudioDebugRecordingsCallback& callback,
      const AudioDebugRecordingsErrorCallback& error_callback);

  // Stops an audio debug recording. |callback| is invoked once recording
  // stops. If no recording was in progress, |error_callback| is invoked instead
  // of |callback|.
  void StopAudioDebugRecordings(
      content::RenderProcessHost* host,
      const AudioDebugRecordingsCallback& callback,
      const AudioDebugRecordingsErrorCallback& error_callback);

 private:
  // States used for protecting from function calls made at non-allowed points
  // in time. For example, StartLogging() is only allowed in CLOSED state.
  // Transitions: SetMetaData(): CLOSED -> CLOSED.
  //              StartLogging(): CLOSED -> STARTING.
  //              Start done: STARTING -> STARTED.
  //              StopLogging(): STARTED -> STOPPING.
  //              Stop done: STOPPING -> STOPPED.
  //              UploadLog(): STOPPED -> UPLOADING.
  //              Upload done: UPLOADING -> CLOSED.
  //              DiscardLog(): STOPPED -> CLOSED.
  enum LoggingState {
    CLOSED,    // Logging not started, no log in memory.
    STARTING,  // Start logging is in progress.
    STARTED,   // Logging started.
    STOPPING,  // Stop logging is in progress.
    STOPPED,   // Logging has been stopped, log still open in memory.
  };

  friend class content::BrowserThread;
  friend class base::DeleteHelper<WebRtcLoggingHandlerHost>;

  ~WebRtcLoggingHandlerHost() override;

  // BrowserMessageFilter implementation.
  void OnChannelClosing() override;
  void OnDestruct() const override;
  bool OnMessageReceived(const IPC::Message& message) override;

  // Handles log message requests from renderer process.
  void OnAddLogMessages(const std::vector<WebRtcLoggingMessageData>& messages);
  void OnLoggingStoppedInRenderer();

  void LogInitialInfoOnFileThread(const GenericDoneCallback& callback);
  void LogInitialInfoOnIOThread(const net::NetworkInterfaceList& network_list,
                                const GenericDoneCallback& callback);

  // Called after stopping RTP dumps.
  void StoreLogContinue(const std::string& log_id,
      const GenericDoneCallback& callback);

  // Writes a formatted log |message| to the |circular_buffer_|.
  void LogToCircularBuffer(const std::string& message);

  // Gets the log directory path for |profile_| and ensure it exists. Must be
  // called on the FILE thread.
  base::FilePath GetLogDirectoryAndEnsureExists();

  void TriggerUpload(const UploadDoneCallback& callback,
                     const base::FilePath& log_directory);

  void StoreLogInDirectory(const std::string& log_id,
                           scoped_ptr<WebRtcLogPaths> log_paths,
                           const GenericDoneCallback& done_callback,
                           const base::FilePath& directory);

  void UploadStoredLogOnFileThread(const std::string& log_id,
                                   const UploadDoneCallback& callback);

  // A helper for TriggerUpload to do the real work.
  void DoUploadLogAndRtpDumps(const base::FilePath& log_directory,
                              const UploadDoneCallback& callback);

  // Create the RTP dump handler and start dumping. Must be called after making
  // sure the log directory exists.
  void CreateRtpDumpHandlerAndStart(RtpDumpType type,
                                    const GenericDoneCallback& callback,
                                    const base::FilePath& dump_dir);

  // A helper for starting RTP dump assuming the RTP dump handler has been
  // created.
  void DoStartRtpDump(RtpDumpType type, const GenericDoneCallback& callback);

  // Adds the packet to the dump on IO thread.
  void DumpRtpPacketOnIOThread(scoped_ptr<uint8[]> packet_header,
                               size_t header_length,
                               size_t packet_length,
                               bool incoming);

  bool ReleaseRtpDumps(WebRtcLogPaths* log_paths);

  void FireGenericDoneCallback(
      const WebRtcLoggingHandlerHost::GenericDoneCallback& callback,
      bool success,
      const std::string& error_message);

  // Helper for starting audio debug recordings.
  void DoStartAudioDebugRecordings(
      content::RenderProcessHost* host,
      base::TimeDelta delay,
      const AudioDebugRecordingsCallback& callback,
      const AudioDebugRecordingsErrorCallback& error_callback,
      const base::FilePath& log_directory);

  // Helper for stopping audio debug recordings.
  void DoStopAudioDebugRecordings(
      content::RenderProcessHost* host,
      bool is_manual_stop,
      uint64_t audio_debug_recordings_id,
      const AudioDebugRecordingsCallback& callback,
      const AudioDebugRecordingsErrorCallback& error_callback,
      const base::FilePath& log_directory);

  scoped_ptr<WebRtcLogBuffer> log_buffer_;

  // The profile associated with our renderer process.
  Profile* const profile_;

  // These are only accessed on the IO thread, except when in STARTING state. In
  // this state we are protected since entering any function that alters the
  // state is not allowed.
  scoped_ptr<MetaDataMap> meta_data_;

  // These are only accessed on the IO thread.
  GenericDoneCallback stop_callback_;

  // Only accessed on the IO thread, except when in STARTING, STOPPING or
  // UPLOADING state if the action fails and the state must be reset. In these
  // states however, we are protected since entering any function that alters
  // the state is not allowed.
  LoggingState logging_state_;

  // Only accessed on the IO thread.
  bool upload_log_on_render_close_;

  // This is the handle to be passed to the render process. It's stored so that
  // it doesn't have to be passed on when posting messages between threads.
  // It's only accessed on the IO thread.
  base::SharedMemoryHandle foreign_memory_handle_;

  // The system time in ms when logging is started. Reset when logging_state_
  // changes to STOPPED.
  base::Time logging_started_time_;

  // The RTP dump handler responsible for creating the RTP header dump files.
  scoped_ptr<WebRtcRtpDumpHandler> rtp_dump_handler_;

  // The callback to call when StopRtpDump is called.
  content::RenderProcessHost::WebRtcStopRtpDumpCallback stop_rtp_dump_callback_;

  // A pointer to the log uploader that's shared for all profiles.
  // Ownership lies with the browser process.
  WebRtcLogUploader* const log_uploader_;

  // Must be accessed on the UI thread.
  bool is_audio_debug_recordings_in_progress_;

  // This counter allows saving each debug recording in separate files.
  uint64_t current_audio_debug_recordings_id_;

  DISALLOW_COPY_AND_ASSIGN(WebRtcLoggingHandlerHost);
};

#endif  // CHROME_BROWSER_MEDIA_WEBRTC_LOGGING_HANDLER_HOST_H_