webrtc_logging_handler_host.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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"
12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/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"
228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/common/chrome_switches.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/media/webrtc_logging_messages.h"
257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/common/partial_circular_buffer.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/pref_names.h"
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/settings/cros_settings_names.h"
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/content_browser_client.h"
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/public/browser/gpu_data_manager.h"
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "gpu/config/gpu_info.h"
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/base/address_family.h"
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_LINUX)
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/linux_util.h"
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_MACOSX)
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/mac/mac_util.h"
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS)
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chromeos/system/statistics_provider.h"
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using base::IntToString;
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using content::BrowserThread;
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_ANDROID)
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const size_t kWebRtcLogSize = 1 * 1024 * 1024;  // 1 MB
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#else
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const size_t kWebRtcLogSize = 6 * 1024 * 1024;  // 6 MB
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace {
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kLogNotStoppedOrNoLogOpen[] =
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    "Logging not stopped or no log open.";
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// For privacy reasons when logging IP addresses. The returned "sensitive
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// string" is for release builds a string with the end stripped away. Last
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// octet for IPv4 and last 80 bits (5 groups) for IPv6. String will be
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// "1.2.3.x" and "1.2.3::" respectively. For debug builds, the string is
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// not stripped.
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string IPAddressToSensitiveString(const net::IPAddressNumber& address) {
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(NDEBUG)
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string sensitive_address;
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (net::GetAddressFamily(address)) {
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case net::ADDRESS_FAMILY_IPV4: {
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address = net::IPAddressToString(address);
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      size_t find_pos = sensitive_address.rfind('.');
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (find_pos == std::string::npos)
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return std::string();
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address.resize(find_pos);
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address += ".x";
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case net::ADDRESS_FAMILY_IPV6: {
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // TODO(grunell): Create a string of format "1:2:3:x:x:x:x:x" to clarify
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // that the end has been stripped out.
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      net::IPAddressNumber sensitive_address_number = address;
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address_number.resize(net::kIPv6AddressSize - 10);
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address_number.resize(net::kIPv6AddressSize, 0);
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sensitive_address = net::IPAddressToString(sensitive_address_number);
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case net::ADDRESS_FAMILY_UNSPECIFIED: {
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return sensitive_address;
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#else
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return net::IPAddressToString(address);
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FormatMetaDataAsLogMessage(
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const MetaDataMap& meta_data,
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string* message) {
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (MetaDataMap::const_iterator it = meta_data.begin();
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != meta_data.end(); ++it) {
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *message += it->first + ": " + it->second + '\n';
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Remove last '\n'.
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  message->resize(message->size() - 1);
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost(Profile* profile)
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : BrowserMessageFilter(WebRtcLoggingMsgStart),
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      profile_(profile),
1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      logging_state_(CLOSED),
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      upload_log_on_render_close_(false) {
1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(profile_);
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() {}
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::SetMetaData(
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const MetaDataMap& meta_data,
1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const GenericDoneCallback& callback) {
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!callback.is_null());
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string error_message;
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ == CLOSED) {
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    meta_data_ = meta_data;
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (logging_state_ == STARTED) {
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    meta_data_ = meta_data;
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string meta_data_message;
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FormatMetaDataAsLogMessage(meta_data_, &meta_data_message);
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LogToCircularBuffer(meta_data_message);
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else {
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error_message = "Meta data must be set before stop or upload.";
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool success = error_message.empty();
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                   base::Bind(callback, success,
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                              error_message));
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::StartLogging(
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const GenericDoneCallback& callback) {
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!callback.is_null());
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  start_callback_ = callback;
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ != CLOSED) {
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FireGenericDoneCallback(&start_callback_, false, "A log is already open");
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = STARTING;
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      &WebRtcLoggingHandlerHost::StartLoggingIfAllowed, this));
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::StopLogging(
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const GenericDoneCallback& callback) {
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!callback.is_null());
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  stop_callback_ = callback;
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ != STARTED) {
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FireGenericDoneCallback(&stop_callback_, false, "Logging not started");
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = STOPPING;
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Send(new WebRtcLoggingMsg_StopLogging());
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::UploadLog(const UploadDoneCallback& callback) {
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!callback.is_null());
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ != STOPPED) {
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!callback.is_null()) {
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          base::Bind(callback, false, "", kLogNotStoppedOrNoLogOpen));
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  upload_callback_ = callback;
187effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  content::BrowserThread::PostTaskAndReplyWithResult(
188effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      content::BrowserThread::FILE,
189effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      FROM_HERE,
190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 this),
192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(&WebRtcLoggingHandlerHost::TriggerUploadLog, this));
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::UploadLogDone() {
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = CLOSED;
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) {
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!callback.is_null());
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GenericDoneCallback discard_callback = callback;
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ != STOPPED) {
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FireGenericDoneCallback(&discard_callback, false,
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            kLogNotStoppedOrNoLogOpen);
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  circular_buffer_.reset();
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  log_buffer_.reset();
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = CLOSED;
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  FireGenericDoneCallback(&discard_callback, true, "");
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcLoggingHandlerHost::LogMessage(const std::string& message) {
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BrowserThread::IO,
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser, this, message));
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void WebRtcLoggingHandlerHost::OnChannelClosing() {
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (logging_state_ == STARTED || logging_state_ == STOPPED) {
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (upload_log_on_render_close_) {
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      logging_state_ = STOPPED;
230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      content::BrowserThread::PostTaskAndReplyWithResult(
231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          content::BrowserThread::FILE,
232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          FROM_HERE,
233effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                     this),
235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          base::Bind(&WebRtcLoggingHandlerHost::TriggerUploadLog, this));
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    } else {
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  content::BrowserMessageFilter::OnChannelClosing();
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void WebRtcLoggingHandlerHost::OnDestruct() const {
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BrowserThread::DeleteOnIOThread::Destruct(this);
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool WebRtcLoggingHandlerHost::OnMessageReceived(const IPC::Message& message,
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 bool* message_was_ok) {
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool handled = true;
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP_EX(WebRtcLoggingHandlerHost, message, *message_was_ok)
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_AddLogMessage, OnAddLogMessage)
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_LoggingStopped,
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                        OnLoggingStoppedInRenderer)
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IPC_END_MESSAGE_MAP_EX()
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return handled;
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcLoggingHandlerHost::AddLogMessageFromBrowser(
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& message) {
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (logging_state_ == STARTED)
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LogToCircularBuffer(message);
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcLoggingHandlerHost::OnAddLogMessage(const std::string& message) {
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (logging_state_ == STARTED || logging_state_ == STOPPING)
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LogToCircularBuffer(message);
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::OnLoggingStoppedInRenderer() {
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (logging_state_ != STOPPING) {
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If an out-of-order response is received, stop_callback_ may be invalid,
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // and must not be invoked.
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(ERROR) << "OnLoggingStoppedInRenderer invoked in state "
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                << logging_state_;
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BadMessageReceived();
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = STOPPED;
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  FireGenericDoneCallback(&stop_callback_, true, "");
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::StartLoggingIfAllowed() {
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!g_browser_process->webrtc_log_uploader()->ApplyForStartLogging()) {
2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    logging_state_ = CLOSED;
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FireGenericDoneCallback(
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          &start_callback_, false, "Cannot start, maybe the maximum number of "
2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "simultaneuos logs has been reached.");
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      &WebRtcLoggingHandlerHost::DoStartLogging, this));
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::DoStartLogging() {
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  log_buffer_.reset(new unsigned char[kWebRtcLogSize]);
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  circular_buffer_.reset(
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    new PartialCircularBuffer(log_buffer_.get(),
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              kWebRtcLogSize,
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              kWebRtcLogSize / 2,
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              false));
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
31223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      &WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread, this));
3137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
31523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread() {
3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  net::NetworkInterfaceList network_list;
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  net::GetNetworkList(&network_list,
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
32323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      &WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread, this, network_list));
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
32623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread(
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const net::NetworkInterfaceList& network_list) {
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
33023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Log start time (current time). We don't use base/i18n/time_formatting.h
33123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // here because we don't want the format of the current locale.
33223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::Time::Exploded now = {0};
33323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::Time::Now().LocalExplode(&now);
33423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  LogToCircularBuffer(base::StringPrintf(
33523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      "Start %d-%02d-%02d %02d:%02d:%02d", now.year, now.month,
33623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      now.day_of_month, now.hour, now.minute, now.second));
33723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Write metadata if received before logging started.
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!meta_data_.empty()) {
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string info;
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FormatMetaDataAsLogMessage(meta_data_, &info);
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LogToCircularBuffer(info);
3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // OS
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer(base::SysInfo::OperatingSystemName() + " " +
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      base::SysInfo::OperatingSystemVersion() + " " +
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      base::SysInfo::OperatingSystemArchitecture());
3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_LINUX)
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer("Linux distribution: " + base::GetLinuxDistro());
3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // CPU
3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::CPU cpu;
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer(
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "Cpu: " + IntToString(cpu.family()) + "." + IntToString(cpu.model()) +
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "." + IntToString(cpu.stepping()) + ", x" +
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      IntToString(base::SysInfo::NumberOfProcessors()) + ", " +
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      IntToString(base::SysInfo::AmountOfPhysicalMemoryMB()) + "MB");
3607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string cpu_brand = cpu.cpu_brand();
3617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Workaround for crbug.com/249713.
362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(grunell): Remove workaround when bug is fixed.
3637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  size_t null_pos = cpu_brand.find('\0');
3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (null_pos != std::string::npos)
3657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    cpu_brand.erase(null_pos);
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer("Cpu brand: " + cpu_brand);
3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Computer model
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string computer_model = "Not available";
3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_MACOSX)
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  computer_model = base::mac::GetModelIdentifier();
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#elif defined(OS_CHROMEOS)
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chromeos::system::StatisticsProvider::GetInstance()->
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetMachineStatistic(chromeos::system::kHardwareClassKey, &computer_model);
3757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer("Computer model: " + computer_model);
3777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // GPU
379424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  gpu::GPUInfo gpu_info = content::GpuDataManager::GetInstance()->GetGPUInfo();
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer("Gpu: machine-model='" + gpu_info.machine_model +
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      "', vendor-id=" + IntToString(gpu_info.gpu.vendor_id) +
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      ", device-id=" + IntToString(gpu_info.gpu.device_id) +
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      ", driver-vendor='" + gpu_info.driver_vendor +
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      "', driver-version=" + gpu_info.driver_version);
3857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Network interfaces
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LogToCircularBuffer("Discovered " + IntToString(network_list.size()) +
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      " network interfaces:");
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (net::NetworkInterfaceList::const_iterator it = network_list.begin();
390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       it != network_list.end(); ++it) {
391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LogToCircularBuffer("Name: " + it->friendly_name + ", Address: " +
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        IPAddressToSensitiveString(it->address));
393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotifyLoggingStarted();
3967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::NotifyLoggingStarted() {
3997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Send(new WebRtcLoggingMsg_StartLogging());
4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = STARTED;
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  FireGenericDoneCallback(&start_callback_, true, "");
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcLoggingHandlerHost::LogToCircularBuffer(const std::string& message) {
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(circular_buffer_.get());
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  circular_buffer_->Write(message.c_str(), message.length());
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const char eol = '\n';
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  circular_buffer_->Write(&eol, 1);
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
413effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbase::FilePath WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists() {
414effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
415effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::FilePath log_dir_path =
416effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath());
417effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::File::Error error;
418effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) {
419effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error;
420effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return base::FilePath();
421effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
422effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return log_dir_path;
423effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
424effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
425effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid WebRtcLoggingHandlerHost::TriggerUploadLog(
426effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& log_directory) {
4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(logging_state_ == STOPPED);
4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging_state_ = UPLOADING;
4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebRtcLogUploadDoneData upload_done_data;
432effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
433effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  upload_done_data.log_path = log_directory;
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  upload_done_data.callback = upload_callback_;
4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  upload_done_data.host = this;
4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  upload_callback_.Reset();
437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      &WebRtcLogUploader::LoggingStoppedDoUpload,
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Unretained(g_browser_process->webrtc_log_uploader()),
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Passed(&log_buffer_),
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      kWebRtcLogSize,
4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      meta_data_,
4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      upload_done_data));
4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  meta_data_.clear();
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  circular_buffer_.reset();
4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRtcLoggingHandlerHost::FireGenericDoneCallback(
4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    GenericDoneCallback* callback, bool success,
4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::string& error_message) {
4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!(*callback).is_null());
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                   base::Bind(*callback, success,
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                              error_message));
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  (*callback).Reset();
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
460