1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/media/webrtc_logging_handler_host.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string>
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/bind.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/command_line.h"
117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/cpu.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/prefs/pref_service.h"
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/sys_info.h"
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/time/time.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/browser_process.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h"
20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/media/webrtc_log_list.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/media/webrtc_log_uploader.h"
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/media/webrtc_rtp_dump_handler.h"
238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/common/chrome_switches.h"
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/chrome_version_info.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/media/webrtc_logging_messages.h"
277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/common/partial_circular_buffer.h"
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/pref_names.h"
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/settings/cros_settings_names.h"
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/content_browser_client.h"
32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/public/browser/gpu_data_manager.h"
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "gpu/config/gpu_info.h"
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/base/address_family.h"
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_LINUX)
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/linux_util.h"
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_MACOSX)
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/mac/mac_util.h"
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chromeos/system/statistics_provider.h"
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using base::IntToString;
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using content::BrowserThread;
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace {
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_ANDROID)
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const size_t kWebRtcLogSize = 1 * 1024 * 1024;  // 1 MB
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#else
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const size_t kWebRtcLogSize = 6 * 1024 * 1024;  // 6 MB
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kLogNotStoppedOrNoLogOpen[] =
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    "Logging not stopped or no log open.";
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// For privacy reasons when logging IP addresses. The returned "sensitive
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// string" is for release builds a string with the end stripped away. Last
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// octet for IPv4 and last 80 bits (5 groups) for IPv6. String will be
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// "1.2.3.x" and "1.2.3::" respectively. For debug builds, the string is
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// not stripped.
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string IPAddressToSensitiveString(const net::IPAddressNumber& address) {
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(NDEBUG)
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string sensitive_address;
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (net::GetAddressFamily(address)) {
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case net::ADDRESS_FAMILY_IPV4: {
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address = net::IPAddressToString(address);
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      size_t find_pos = sensitive_address.rfind('.');
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (find_pos == std::string::npos)
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return std::string();
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address.resize(find_pos);
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address += ".x";
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case net::ADDRESS_FAMILY_IPV6: {
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // TODO(grunell): Create a string of format "1:2:3:x:x:x:x:x" to clarify
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // that the end has been stripped out.
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      net::IPAddressNumber sensitive_address_number = address;
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address_number.resize(net::kIPv6AddressSize - 10);
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address_number.resize(net::kIPv6AddressSize, 0);
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address = net::IPAddressToString(sensitive_address_number);
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case net::ADDRESS_FAMILY_UNSPECIFIED: {
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return sensitive_address;
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#else
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return net::IPAddressToString(address);
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FormatMetaDataAsLogMessage(
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const MetaDataMap& meta_data,
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string* message) {
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (MetaDataMap::const_iterator it = meta_data.begin();
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != meta_data.end(); ++it) {
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *message += it->first + ": " + it->second + '\n';
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Remove last '\n'.
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  message->resize(message->size() - 1);
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost(Profile* profile)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : BrowserMessageFilter(WebRtcLoggingMsgStart),
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      profile_(profile),
1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      logging_state_(CLOSED),
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      upload_log_on_render_close_(false) {
1198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(profile_);
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() {}
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::SetMetaData(
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const MetaDataMap& meta_data,
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const GenericDoneCallback& callback) {
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!callback.is_null());
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string error_message;
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ == CLOSED) {
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    meta_data_ = meta_data;
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (logging_state_ == STARTED) {
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    meta_data_ = meta_data;
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string meta_data_message;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FormatMetaDataAsLogMessage(meta_data_, &meta_data_message);
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LogToCircularBuffer(meta_data_message);
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error_message = "Meta data must be set before stop or upload.";
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool success = error_message.empty();
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                   base::Bind(callback, success,
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                              error_message));
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::StartLogging(
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const GenericDoneCallback& callback) {
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!callback.is_null());
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  start_callback_ = callback;
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ != CLOSED) {
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FireGenericDoneCallback(&start_callback_, false, "A log is already open");
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = STARTING;
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      &WebRtcLoggingHandlerHost::StartLoggingIfAllowed, this));
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::StopLogging(
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const GenericDoneCallback& callback) {
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!callback.is_null());
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  stop_callback_ = callback;
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ != STARTED) {
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FireGenericDoneCallback(&stop_callback_, false, "Logging not started");
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = STOPPING;
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Send(new WebRtcLoggingMsg_StopLogging());
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::UploadLog(const UploadDoneCallback& callback) {
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!callback.is_null());
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ != STOPPED) {
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!callback.is_null()) {
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          base::Bind(callback, false, "", kLogNotStoppedOrNoLogOpen));
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  upload_callback_ = callback;
189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  logging_state_ = UPLOADING;
190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  content::BrowserThread::PostTaskAndReplyWithResult(
191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      content::BrowserThread::FILE,
192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      FROM_HERE,
193effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 this),
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this));
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::UploadLogDone() {
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = CLOSED;
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) {
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!callback.is_null());
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GenericDoneCallback discard_callback = callback;
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ != STOPPED) {
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FireGenericDoneCallback(&discard_callback, false,
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            kLogNotStoppedOrNoLogOpen);
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  circular_buffer_.reset();
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  log_buffer_.reset();
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = CLOSED;
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  rtp_dump_handler_.reset();
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  stop_rtp_dump_callback_.Reset();
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  FireGenericDoneCallback(&discard_callback, true, "");
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcLoggingHandlerHost::LogMessage(const std::string& message) {
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BrowserThread::IO,
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser,
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          this,
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          WebRtcLoggingMessageData(base::Time::Now(), message)));
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void WebRtcLoggingHandlerHost::StartRtpDump(
23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    RtpDumpType type,
23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const GenericDoneCallback& callback,
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const content::RenderProcessHost::WebRtcStopRtpDumpCallback&
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        stop_callback) {
23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(stop_rtp_dump_callback_.is_null() ||
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         stop_rtp_dump_callback_.Equals(stop_callback));
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  stop_rtp_dump_callback_ = stop_callback;
24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!rtp_dump_handler_) {
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    content::BrowserThread::PostTaskAndReplyWithResult(
24546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        content::BrowserThread::FILE,
24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        FROM_HERE,
24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   this),
24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(&WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart,
25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   this,
25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   type,
25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   callback));
25346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  GenericDoneCallback start_callback = callback;
25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DoStartRtpDump(type, &start_callback);
258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void WebRtcLoggingHandlerHost::StopRtpDump(
26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    RtpDumpType type,
262010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const GenericDoneCallback& callback) {
26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!callback.is_null());
26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!rtp_dump_handler_) {
26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    GenericDoneCallback stop_callback = callback;
26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    FireGenericDoneCallback(
26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        &stop_callback, false, "RTP dump has not been started.");
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!stop_rtp_dump_callback_.is_null()) {
27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    BrowserThread::PostTask(
27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        BrowserThread::UI,
27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        FROM_HERE,
27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(stop_rtp_dump_callback_,
27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   type == RTP_DUMP_INCOMING || type == RTP_DUMP_BOTH,
27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   type == RTP_DUMP_OUTGOING || type == RTP_DUMP_BOTH));
28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
28146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  rtp_dump_handler_->StopDump(type, callback);
28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WebRtcLoggingHandlerHost::OnRtpPacket(scoped_ptr<uint8[]> packet_header,
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                           size_t header_length,
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                           size_t packet_length,
28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                           bool incoming) {
28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  BrowserThread::PostTask(
29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      BrowserThread::IO,
29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      FROM_HERE,
29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread,
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 this,
29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::Passed(&packet_header),
29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 header_length,
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 packet_length,
29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 incoming));
30046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
30146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
30246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread(
30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<uint8[]> packet_header,
30446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    size_t header_length,
30546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    size_t packet_length,
30646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bool incoming) {
30746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
30946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // |rtp_dump_handler_| could be NULL if we are waiting for the FILE thread to
31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // create/ensure the log directory.
31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (rtp_dump_handler_) {
31246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    rtp_dump_handler_->OnRtpPacket(
31346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        packet_header.get(), header_length, packet_length, incoming);
31446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void WebRtcLoggingHandlerHost::OnChannelClosing() {
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ == STARTED || logging_state_ == STOPPED) {
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (upload_log_on_render_close_) {
321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      logging_state_ = UPLOADING;
322c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      logging_started_time_ = base::Time();
32346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
324effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      content::BrowserThread::PostTaskAndReplyWithResult(
325effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          content::BrowserThread::FILE,
326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          FROM_HERE,
327effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
328effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                     this),
32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this));
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    } else {
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  content::BrowserMessageFilter::OnChannelClosing();
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void WebRtcLoggingHandlerHost::OnDestruct() const {
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BrowserThread::DeleteOnIOThread::Destruct(this);
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool WebRtcLoggingHandlerHost::OnMessageReceived(const IPC::Message& message) {
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool handled = true;
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(WebRtcLoggingHandlerHost, message)
345c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_AddLogMessages, OnAddLogMessages)
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_LoggingStopped,
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                        OnLoggingStoppedInRenderer)
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return handled;
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcLoggingHandlerHost::AddLogMessageFromBrowser(
355c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const WebRtcLoggingMessageData& message) {
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (logging_state_ == STARTED)
358c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LogToCircularBuffer(message.Format(logging_started_time_));
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
361c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid WebRtcLoggingHandlerHost::OnAddLogMessages(
362c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const std::vector<WebRtcLoggingMessageData>& messages) {
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
364c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (logging_state_ == STARTED || logging_state_ == STOPPING) {
365c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    for (size_t i = 0; i < messages.size(); ++i) {
366c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      LogToCircularBuffer(messages[i].Format(logging_started_time_));
367c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
368c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::OnLoggingStoppedInRenderer() {
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (logging_state_ != STOPPING) {
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If an out-of-order response is received, stop_callback_ may be invalid,
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // and must not be invoked.
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(ERROR) << "OnLoggingStoppedInRenderer invoked in state "
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                << logging_state_;
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BadMessageReceived();
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  logging_started_time_ = base::Time();
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = STOPPED;
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  FireGenericDoneCallback(&stop_callback_, true, "");
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::StartLoggingIfAllowed() {
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!g_browser_process->webrtc_log_uploader()->ApplyForStartLogging()) {
3894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    logging_state_ = CLOSED;
3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FireGenericDoneCallback(
3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          &start_callback_, false, "Cannot start, maybe the maximum number of "
3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "simultaneuos logs has been reached.");
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      &WebRtcLoggingHandlerHost::DoStartLogging, this));
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::DoStartLogging() {
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  log_buffer_.reset(new unsigned char[kWebRtcLogSize]);
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  circular_buffer_.reset(
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    new PartialCircularBuffer(log_buffer_.get(),
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              kWebRtcLogSize,
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              kWebRtcLogSize / 2,
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              false));
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
41023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      &WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread, this));
4117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
41323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread() {
4147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  net::NetworkInterfaceList network_list;
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  net::GetNetworkList(&network_list,
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
42123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      &WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread, this, network_list));
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
42423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread(
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const net::NetworkInterfaceList& network_list) {
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
42823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Log start time (current time). We don't use base/i18n/time_formatting.h
42923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // here because we don't want the format of the current locale.
43023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::Time::Exploded now = {0};
43123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::Time::Now().LocalExplode(&now);
43223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  LogToCircularBuffer(base::StringPrintf(
43323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      "Start %d-%02d-%02d %02d:%02d:%02d", now.year, now.month,
43423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      now.day_of_month, now.hour, now.minute, now.second));
43523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Write metadata if received before logging started.
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!meta_data_.empty()) {
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string info;
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FormatMetaDataAsLogMessage(meta_data_, &info);
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LogToCircularBuffer(info);
4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Chrome version
444116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  chrome::VersionInfo version_info;
445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LogToCircularBuffer("Chrome version: " + version_info.Version() + " " +
446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                      chrome::VersionInfo::GetVersionStringModifier());
447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // OS
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer(base::SysInfo::OperatingSystemName() + " " +
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      base::SysInfo::OperatingSystemVersion() + " " +
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      base::SysInfo::OperatingSystemArchitecture());
4527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_LINUX)
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer("Linux distribution: " + base::GetLinuxDistro());
4547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
4557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // CPU
4577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::CPU cpu;
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer(
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "Cpu: " + IntToString(cpu.family()) + "." + IntToString(cpu.model()) +
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "." + IntToString(cpu.stepping()) + ", x" +
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      IntToString(base::SysInfo::NumberOfProcessors()) + ", " +
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      IntToString(base::SysInfo::AmountOfPhysicalMemoryMB()) + "MB");
4637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string cpu_brand = cpu.cpu_brand();
4647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Workaround for crbug.com/249713.
465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(grunell): Remove workaround when bug is fixed.
4667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  size_t null_pos = cpu_brand.find('\0');
4677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (null_pos != std::string::npos)
4687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    cpu_brand.erase(null_pos);
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer("Cpu brand: " + cpu_brand);
4707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Computer model
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string computer_model = "Not available";
4737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_MACOSX)
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  computer_model = base::mac::GetModelIdentifier();
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#elif defined(OS_CHROMEOS)
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chromeos::system::StatisticsProvider::GetInstance()->
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetMachineStatistic(chromeos::system::kHardwareClassKey, &computer_model);
4787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer("Computer model: " + computer_model);
4807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // GPU
482424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  gpu::GPUInfo gpu_info = content::GpuDataManager::GetInstance()->GetGPUInfo();
4830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  LogToCircularBuffer(
484010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      "Gpu: machine-model-name=" + gpu_info.machine_model_name +
485010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ", machine-model-version=" + gpu_info.machine_model_version +
486010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ", vendor-id=" + IntToString(gpu_info.gpu.vendor_id) +
4870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ", device-id=" + IntToString(gpu_info.gpu.device_id) +
488010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ", driver-vendor=" + gpu_info.driver_vendor +
489010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ", driver-version=" + gpu_info.driver_version);
490010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  LogToCircularBuffer(
491010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      "OpenGL: gl-vendor=" + gpu_info.gl_vendor +
492010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ", gl-renderer=" + gpu_info.gl_renderer +
493010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ", gl-version=" + gpu_info.gl_version);
4947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Network interfaces
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer("Discovered " + IntToString(network_list.size()) +
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      " network interfaces:");
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (net::NetworkInterfaceList::const_iterator it = network_list.begin();
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       it != network_list.end(); ++it) {
500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LogToCircularBuffer("Name: " + it->friendly_name + ", Address: " +
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        IPAddressToSensitiveString(it->address));
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotifyLoggingStarted();
5057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
5067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::NotifyLoggingStarted() {
5087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Send(new WebRtcLoggingMsg_StartLogging());
510c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  logging_started_time_ = base::Time::Now();
5114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = STARTED;
5124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  FireGenericDoneCallback(&start_callback_, true, "");
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcLoggingHandlerHost::LogToCircularBuffer(const std::string& message) {
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(circular_buffer_.get());
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  circular_buffer_->Write(message.c_str(), message.length());
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const char eol = '\n';
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  circular_buffer_->Write(&eol, 1);
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
523effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbase::FilePath WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists() {
524effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
525effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::FilePath log_dir_path =
526effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath());
527effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::File::Error error;
528effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) {
529effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error;
530effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return base::FilePath();
531effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
532effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return log_dir_path;
533effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
534effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
53546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WebRtcLoggingHandlerHost::TriggerUpload(
536effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& log_directory) {
5374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
538010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(logging_state_, UPLOADING);
5394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (rtp_dump_handler_) {
54146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    BrowserThread::PostTask(
54246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        BrowserThread::UI,
54346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        FROM_HERE,
54446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(stop_rtp_dump_callback_, true, true));
54546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
54646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    rtp_dump_handler_->StopOngoingDumps(
54746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(&WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps,
54846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   this,
54946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   log_directory));
55046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
55146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
55246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
55346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DoUploadLogAndRtpDumps(log_directory);
55446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
55546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
55646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps(
55746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const base::FilePath& log_directory) {
5584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebRtcLogUploadDoneData upload_done_data;
559effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  upload_done_data.log_path = log_directory;
56046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
56146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (rtp_dump_handler_) {
56246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    WebRtcRtpDumpHandler::ReleasedDumps rtp_dumps(
56346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        rtp_dump_handler_->ReleaseDumps());
56446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    upload_done_data.incoming_rtp_dump = rtp_dumps.incoming_dump_path;
56546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    upload_done_data.outgoing_rtp_dump = rtp_dumps.outgoing_dump_path;
56646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
56746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    rtp_dump_handler_.reset();
56846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    stop_rtp_dump_callback_.Reset();
56946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
57046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  upload_done_data.callback = upload_callback_;
5724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  upload_done_data.host = this;
5734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  upload_callback_.Reset();
574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
5764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      &WebRtcLogUploader::LoggingStoppedDoUpload,
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Unretained(g_browser_process->webrtc_log_uploader()),
5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Passed(&log_buffer_),
579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      kWebRtcLogSize,
5804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      meta_data_,
5814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      upload_done_data));
5824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  meta_data_.clear();
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  circular_buffer_.reset();
5854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::FireGenericDoneCallback(
58846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    GenericDoneCallback* callback,
58946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bool success,
5904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::string& error_message) {
5914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
5924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!(*callback).is_null());
59346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  content::BrowserThread::PostTask(
59446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      content::BrowserThread::UI,
59546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      FROM_HERE,
59646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(*callback, success, error_message));
5974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  (*callback).Reset();
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
59946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
60046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart(
60146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    RtpDumpType type,
60246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    GenericDoneCallback callback,
60346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const base::FilePath& dump_dir) {
60446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
60546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
60646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // |rtp_dump_handler_| may be non-NULL if StartRtpDump is called again before
60746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // GetLogDirectoryAndEnsureExists returns on the FILE thread for a previous
60846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // StartRtpDump.
60946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!rtp_dump_handler_)
61046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    rtp_dump_handler_.reset(new WebRtcRtpDumpHandler(dump_dir));
61146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
61246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DoStartRtpDump(type, &callback);
61346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
61446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
61546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WebRtcLoggingHandlerHost::DoStartRtpDump(RtpDumpType type,
61646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                              GenericDoneCallback* callback) {
61746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
61846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(rtp_dump_handler_);
61946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
62046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::string error;
62146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
62246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool result = rtp_dump_handler_->StartDump(type, &error);
62346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  FireGenericDoneCallback(callback, result, error);
62446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
625