No dual_mode on Win10+ shortcuts.
[chromium-blink-merge.git] / chrome / browser / media / webrtc_logging_handler_host.cc
blobe97f9992e1974d5bfb75a7ddd6b157fc388e6a77
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/media/webrtc_logging_handler_host.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/cpu.h"
12 #include "base/files/file_util.h"
13 #include "base/logging.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/sys_info.h"
17 #include "base/time/time.h"
18 #include "chrome/browser/bad_message.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/chromeos/settings/cros_settings.h"
21 #include "chrome/browser/media/webrtc_log_list.h"
22 #include "chrome/browser/media/webrtc_log_uploader.h"
23 #include "chrome/browser/media/webrtc_rtp_dump_handler.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/chrome_version_info.h"
27 #include "chrome/common/media/webrtc_logging_messages.h"
28 #include "chromeos/settings/cros_settings_names.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/content_browser_client.h"
31 #include "content/public/browser/gpu_data_manager.h"
32 #include "content/public/browser/render_process_host.h"
33 #include "gpu/config/gpu_info.h"
34 #include "net/base/address_family.h"
35 #include "net/base/ip_address_number.h"
36 #include "net/url_request/url_request_context_getter.h"
38 #if defined(OS_LINUX)
39 #include "base/linux_util.h"
40 #endif
42 #if defined(OS_MACOSX)
43 #include "base/mac/mac_util.h"
44 #endif
46 #if defined(OS_CHROMEOS)
47 #include "chromeos/system/statistics_provider.h"
48 #endif
50 using base::IntToString;
51 using content::BrowserThread;
53 namespace {
55 const char kLogNotStoppedOrNoLogOpen[] =
56 "Logging not stopped or no log open.";
58 // For privacy reasons when logging IP addresses. The returned "sensitive
59 // string" is for release builds a string with the end stripped away. Last
60 // octet for IPv4 and last 80 bits (5 groups) for IPv6. String will be
61 // "1.2.3.x" and "1.2.3::" respectively. For debug builds, the string is
62 // not stripped.
63 std::string IPAddressToSensitiveString(const net::IPAddressNumber& address) {
64 #if defined(NDEBUG)
65 std::string sensitive_address;
66 switch (net::GetAddressFamily(address)) {
67 case net::ADDRESS_FAMILY_IPV4: {
68 sensitive_address = net::IPAddressToString(address);
69 size_t find_pos = sensitive_address.rfind('.');
70 if (find_pos == std::string::npos)
71 return std::string();
72 sensitive_address.resize(find_pos);
73 sensitive_address += ".x";
74 break;
76 case net::ADDRESS_FAMILY_IPV6: {
77 // TODO(grunell): Create a string of format "1:2:3:x:x:x:x:x" to clarify
78 // that the end has been stripped out.
79 net::IPAddressNumber sensitive_address_number = address;
80 sensitive_address_number.resize(net::kIPv6AddressSize - 10);
81 sensitive_address_number.resize(net::kIPv6AddressSize, 0);
82 sensitive_address = net::IPAddressToString(sensitive_address_number);
83 break;
85 case net::ADDRESS_FAMILY_UNSPECIFIED: {
86 break;
89 return sensitive_address;
90 #else
91 return net::IPAddressToString(address);
92 #endif
95 void FormatMetaDataAsLogMessage(
96 const MetaDataMap& meta_data,
97 std::string* message) {
98 for (MetaDataMap::const_iterator it = meta_data.begin();
99 it != meta_data.end(); ++it) {
100 *message += it->first + ": " + it->second + '\n';
102 // Remove last '\n'.
103 message->resize(message->size() - 1);
106 void FireGenericDoneCallback(
107 const WebRtcLoggingHandlerHost::GenericDoneCallback& callback,
108 bool success,
109 const std::string& error_message) {
110 DCHECK_CURRENTLY_ON(BrowserThread::IO);
111 DCHECK(!callback.is_null());
112 content::BrowserThread::PostTask(
113 content::BrowserThread::UI,
114 FROM_HERE,
115 base::Bind(callback, success, error_message));
118 void FireAndResetGenericDoneCallback(
119 WebRtcLoggingHandlerHost::GenericDoneCallback* callback,
120 bool success,
121 const std::string& error_message) {
122 FireGenericDoneCallback(*callback, success, error_message);
123 callback->Reset();
126 } // namespace
128 WebRtcLogBuffer::WebRtcLogBuffer()
129 : buffer_(),
130 circular_(&buffer_[0], sizeof(buffer_), sizeof(buffer_) / 2, false),
131 read_only_(false) {
134 WebRtcLogBuffer::~WebRtcLogBuffer() {
135 DCHECK(read_only_ || thread_checker_.CalledOnValidThread());
138 void WebRtcLogBuffer::Log(const std::string& message) {
139 DCHECK(thread_checker_.CalledOnValidThread());
140 DCHECK(!read_only_);
141 circular_.Write(message.c_str(), message.length());
142 const char eol = '\n';
143 circular_.Write(&eol, 1);
146 PartialCircularBuffer WebRtcLogBuffer::Read() {
147 DCHECK(thread_checker_.CalledOnValidThread());
148 DCHECK(read_only_);
149 return PartialCircularBuffer(&buffer_[0], sizeof(buffer_));
152 void WebRtcLogBuffer::SetComplete() {
153 DCHECK(thread_checker_.CalledOnValidThread());
154 DCHECK(!read_only_) << "Already set? (programmer error)";
155 read_only_ = true;
156 // Detach from the current thread so that we can check reads on a different
157 // thread. This is to make sure that Read()s still happen on one thread only.
158 thread_checker_.DetachFromThread();
161 WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost(Profile* profile)
162 : BrowserMessageFilter(WebRtcLoggingMsgStart),
163 profile_(profile),
164 logging_state_(CLOSED),
165 upload_log_on_render_close_(false) {
166 DCHECK(profile_);
169 WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() {}
171 void WebRtcLoggingHandlerHost::SetMetaData(
172 scoped_ptr<MetaDataMap> meta_data,
173 const GenericDoneCallback& callback) {
174 DCHECK_CURRENTLY_ON(BrowserThread::IO);
175 DCHECK(!callback.is_null());
177 std::string error_message;
178 if (logging_state_ == CLOSED) {
179 if (!meta_data_.get())
180 meta_data_ = meta_data.Pass();
181 } else if (logging_state_ == STARTED) {
182 std::string meta_data_message;
183 FormatMetaDataAsLogMessage(*meta_data.get(), &meta_data_message);
184 LogToCircularBuffer(meta_data_message);
185 } else {
186 error_message = "Meta data must be set before stop or upload.";
189 if (error_message.empty() && meta_data.get()) {
190 // Keep the meta data around for uploading separately from the log.
191 for (const auto& it : *meta_data.get())
192 (*meta_data_.get())[it.first] = it.second;
195 FireGenericDoneCallback(callback, error_message.empty(), error_message);
198 void WebRtcLoggingHandlerHost::StartLogging(
199 const GenericDoneCallback& callback) {
200 DCHECK_CURRENTLY_ON(BrowserThread::IO);
201 DCHECK(!callback.is_null());
203 if (logging_state_ != CLOSED) {
204 FireGenericDoneCallback(callback, false, "A log is already open");
205 return;
208 logging_state_ = STARTING;
209 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
210 &WebRtcLoggingHandlerHost::StartLoggingIfAllowed, this, callback));
213 void WebRtcLoggingHandlerHost::StopLogging(
214 const GenericDoneCallback& callback) {
215 DCHECK_CURRENTLY_ON(BrowserThread::IO);
216 DCHECK(!callback.is_null());
218 if (logging_state_ != STARTED) {
219 FireGenericDoneCallback(callback, false, "Logging not started");
220 return;
223 stop_callback_ = callback;
224 logging_state_ = STOPPING;
225 Send(new WebRtcLoggingMsg_StopLogging());
228 void WebRtcLoggingHandlerHost::UploadLog(const UploadDoneCallback& callback) {
229 DCHECK_CURRENTLY_ON(BrowserThread::IO);
230 DCHECK(!callback.is_null());
232 if (logging_state_ != STOPPED) {
233 if (!callback.is_null()) {
234 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
235 base::Bind(callback, false, "", kLogNotStoppedOrNoLogOpen));
237 return;
240 content::BrowserThread::PostTaskAndReplyWithResult(
241 content::BrowserThread::FILE,
242 FROM_HERE,
243 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
244 this),
245 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this, callback));
248 void WebRtcLoggingHandlerHost::UploadStoredLog(
249 const std::string& log_id,
250 const UploadDoneCallback& callback) {
251 DCHECK_CURRENTLY_ON(BrowserThread::IO);
252 DCHECK(!callback.is_null());
254 content::BrowserThread::PostTask(content::BrowserThread::FILE,
255 FROM_HERE,
256 base::Bind(&WebRtcLoggingHandlerHost::UploadStoredLogOnFileThread,
257 this, log_id, callback));
260 void WebRtcLoggingHandlerHost::UploadStoredLogOnFileThread(
261 const std::string& log_id,
262 const UploadDoneCallback& callback) {
263 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
265 WebRtcLogUploadDoneData upload_data;
266 upload_data.log_path = GetLogDirectoryAndEnsureExists();
267 upload_data.callback = callback;
268 upload_data.host = this;
269 upload_data.local_log_id = log_id;
271 g_browser_process->webrtc_log_uploader()->UploadStoredLog(upload_data);
274 void WebRtcLoggingHandlerHost::UploadLogDone() {
275 DCHECK_CURRENTLY_ON(BrowserThread::IO);
276 logging_state_ = CLOSED;
279 void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) {
280 DCHECK_CURRENTLY_ON(BrowserThread::IO);
281 DCHECK(!callback.is_null());
283 if (logging_state_ != STOPPED) {
284 FireGenericDoneCallback(callback, false, kLogNotStoppedOrNoLogOpen);
285 return;
287 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
288 log_buffer_.reset();
289 meta_data_.reset();
290 logging_state_ = CLOSED;
291 rtp_dump_handler_.reset();
292 stop_rtp_dump_callback_.Reset();
293 FireGenericDoneCallback(callback, true, "");
296 // Stores the log locally using a hash of log_id + security origin.
297 void WebRtcLoggingHandlerHost::StoreLog(
298 const std::string& log_id,
299 const GenericDoneCallback& callback) {
300 DCHECK_CURRENTLY_ON(BrowserThread::IO);
301 DCHECK(!callback.is_null());
303 if (logging_state_ != STOPPED) {
304 FireGenericDoneCallback(callback, false, kLogNotStoppedOrNoLogOpen);
305 return;
308 if (rtp_dump_handler_) {
309 BrowserThread::PostTask(
310 BrowserThread::UI,
311 FROM_HERE,
312 base::Bind(stop_rtp_dump_callback_, true, true));
314 rtp_dump_handler_->StopOngoingDumps(
315 base::Bind(&WebRtcLoggingHandlerHost::StoreLogContinue,
316 this, log_id, callback));
317 return;
320 StoreLogContinue(log_id, callback);
323 void WebRtcLoggingHandlerHost::StoreLogContinue(
324 const std::string& log_id,
325 const GenericDoneCallback& callback) {
326 DCHECK_CURRENTLY_ON(BrowserThread::IO);
327 DCHECK(!callback.is_null());
329 scoped_ptr<WebRtcLogPaths> log_paths(new WebRtcLogPaths());
330 ReleaseRtpDumps(log_paths.get());
332 content::BrowserThread::PostTaskAndReplyWithResult(
333 content::BrowserThread::FILE,
334 FROM_HERE,
335 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
336 this),
337 base::Bind(&WebRtcLoggingHandlerHost::StoreLogInDirectory, this, log_id,
338 Passed(&log_paths), callback));
341 void WebRtcLoggingHandlerHost::LogMessage(const std::string& message) {
342 BrowserThread::PostTask(
343 BrowserThread::IO,
344 FROM_HERE,
345 base::Bind(
346 &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser,
347 this,
348 WebRtcLoggingMessageData(base::Time::Now(), message)));
351 void WebRtcLoggingHandlerHost::StartRtpDump(
352 RtpDumpType type,
353 const GenericDoneCallback& callback,
354 const content::RenderProcessHost::WebRtcStopRtpDumpCallback&
355 stop_callback) {
356 DCHECK_CURRENTLY_ON(BrowserThread::IO);
357 DCHECK(stop_rtp_dump_callback_.is_null() ||
358 stop_rtp_dump_callback_.Equals(stop_callback));
360 stop_rtp_dump_callback_ = stop_callback;
362 if (!rtp_dump_handler_) {
363 content::BrowserThread::PostTaskAndReplyWithResult(
364 content::BrowserThread::FILE,
365 FROM_HERE,
366 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
367 this),
368 base::Bind(&WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart,
369 this,
370 type,
371 callback));
372 return;
375 DoStartRtpDump(type, callback);
378 void WebRtcLoggingHandlerHost::StopRtpDump(
379 RtpDumpType type,
380 const GenericDoneCallback& callback) {
381 DCHECK_CURRENTLY_ON(BrowserThread::IO);
382 DCHECK(!callback.is_null());
384 if (!rtp_dump_handler_) {
385 FireGenericDoneCallback(callback, false, "RTP dump has not been started.");
386 return;
389 if (!stop_rtp_dump_callback_.is_null()) {
390 BrowserThread::PostTask(
391 BrowserThread::UI,
392 FROM_HERE,
393 base::Bind(stop_rtp_dump_callback_,
394 type == RTP_DUMP_INCOMING || type == RTP_DUMP_BOTH,
395 type == RTP_DUMP_OUTGOING || type == RTP_DUMP_BOTH));
398 rtp_dump_handler_->StopDump(type, callback);
401 void WebRtcLoggingHandlerHost::OnRtpPacket(scoped_ptr<uint8[]> packet_header,
402 size_t header_length,
403 size_t packet_length,
404 bool incoming) {
405 DCHECK_CURRENTLY_ON(BrowserThread::UI);
407 BrowserThread::PostTask(
408 BrowserThread::IO,
409 FROM_HERE,
410 base::Bind(&WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread,
411 this,
412 base::Passed(&packet_header),
413 header_length,
414 packet_length,
415 incoming));
418 void WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread(
419 scoped_ptr<uint8[]> packet_header,
420 size_t header_length,
421 size_t packet_length,
422 bool incoming) {
423 DCHECK_CURRENTLY_ON(BrowserThread::IO);
425 // |rtp_dump_handler_| could be NULL if we are waiting for the FILE thread to
426 // create/ensure the log directory.
427 if (rtp_dump_handler_) {
428 rtp_dump_handler_->OnRtpPacket(
429 packet_header.get(), header_length, packet_length, incoming);
433 void WebRtcLoggingHandlerHost::OnChannelClosing() {
434 DCHECK_CURRENTLY_ON(BrowserThread::IO);
435 if (logging_state_ == STARTED || logging_state_ == STOPPED) {
436 if (upload_log_on_render_close_) {
437 logging_started_time_ = base::Time();
439 content::BrowserThread::PostTaskAndReplyWithResult(
440 content::BrowserThread::FILE,
441 FROM_HERE,
442 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
443 this),
444 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this,
445 UploadDoneCallback()));
446 } else {
447 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
450 content::BrowserMessageFilter::OnChannelClosing();
453 void WebRtcLoggingHandlerHost::OnDestruct() const {
454 BrowserThread::DeleteOnIOThread::Destruct(this);
457 bool WebRtcLoggingHandlerHost::OnMessageReceived(const IPC::Message& message) {
458 DCHECK_CURRENTLY_ON(BrowserThread::IO);
459 bool handled = true;
460 IPC_BEGIN_MESSAGE_MAP(WebRtcLoggingHandlerHost, message)
461 IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_AddLogMessages, OnAddLogMessages)
462 IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_LoggingStopped,
463 OnLoggingStoppedInRenderer)
464 IPC_MESSAGE_UNHANDLED(handled = false)
465 IPC_END_MESSAGE_MAP()
467 return handled;
470 void WebRtcLoggingHandlerHost::AddLogMessageFromBrowser(
471 const WebRtcLoggingMessageData& message) {
472 DCHECK_CURRENTLY_ON(BrowserThread::IO);
473 if (logging_state_ == STARTED)
474 LogToCircularBuffer(message.Format(logging_started_time_));
477 void WebRtcLoggingHandlerHost::OnAddLogMessages(
478 const std::vector<WebRtcLoggingMessageData>& messages) {
479 DCHECK_CURRENTLY_ON(BrowserThread::IO);
480 if (logging_state_ == STARTED || logging_state_ == STOPPING) {
481 for (size_t i = 0; i < messages.size(); ++i) {
482 LogToCircularBuffer(messages[i].Format(logging_started_time_));
487 void WebRtcLoggingHandlerHost::OnLoggingStoppedInRenderer() {
488 DCHECK_CURRENTLY_ON(BrowserThread::IO);
489 if (logging_state_ != STOPPING) {
490 // If an out-of-order response is received, stop_callback_ may be invalid,
491 // and must not be invoked.
492 DLOG(ERROR) << "OnLoggingStoppedInRenderer invoked in state "
493 << logging_state_;
494 bad_message::ReceivedBadMessage(
495 this, bad_message::WRLHH_LOGGING_STOPPED_BAD_STATE);
496 return;
498 logging_started_time_ = base::Time();
499 logging_state_ = STOPPED;
500 FireAndResetGenericDoneCallback(&stop_callback_, true, "");
503 void WebRtcLoggingHandlerHost::StartLoggingIfAllowed(
504 const GenericDoneCallback& callback) {
505 DCHECK_CURRENTLY_ON(BrowserThread::UI);
506 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
507 &WebRtcLoggingHandlerHost::DoStartLogging, this,
508 g_browser_process->webrtc_log_uploader()->ApplyForStartLogging(),
509 callback));
512 void WebRtcLoggingHandlerHost::DoStartLogging(
513 bool permissions_granted,
514 const GenericDoneCallback& callback) {
515 DCHECK_CURRENTLY_ON(BrowserThread::IO);
516 if (logging_state_ != STARTING) {
517 FireGenericDoneCallback(callback, false, "Logging cancelled.");
518 return;
521 if (!permissions_granted) {
522 logging_state_ = CLOSED;
523 FireGenericDoneCallback(callback, false,
524 "Cannot start, maybe the maximum number of "
525 "simultaneuos logs has been reached.");
526 return;
529 DCHECK(!log_buffer_.get());
530 log_buffer_.reset(new WebRtcLogBuffer());
531 if (!meta_data_.get())
532 meta_data_.reset(new MetaDataMap());
534 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
535 &WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread, this, callback));
538 void WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread(
539 const GenericDoneCallback& callback) {
540 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
542 net::NetworkInterfaceList network_list;
543 net::GetNetworkList(&network_list,
544 net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
546 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
547 &WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread, this, network_list,
548 callback));
551 void WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread(
552 const net::NetworkInterfaceList& network_list,
553 const GenericDoneCallback& callback) {
554 DCHECK_CURRENTLY_ON(BrowserThread::IO);
555 if (logging_state_ != STARTING) {
556 FireGenericDoneCallback(callback, false, "Logging cancelled.");
557 return;
560 // Log start time (current time). We don't use base/i18n/time_formatting.h
561 // here because we don't want the format of the current locale.
562 base::Time::Exploded now = {0};
563 base::Time::Now().LocalExplode(&now);
564 LogToCircularBuffer(base::StringPrintf(
565 "Start %d-%02d-%02d %02d:%02d:%02d", now.year, now.month,
566 now.day_of_month, now.hour, now.minute, now.second));
568 // Write metadata if received before logging started.
569 if (meta_data_.get() && !meta_data_->empty()) {
570 std::string info;
571 FormatMetaDataAsLogMessage(*meta_data_.get(), &info);
572 LogToCircularBuffer(info);
575 // Chrome version
576 chrome::VersionInfo version_info;
577 LogToCircularBuffer("Chrome version: " + version_info.Version() + " " +
578 chrome::VersionInfo::GetVersionStringModifier());
580 // OS
581 LogToCircularBuffer(base::SysInfo::OperatingSystemName() + " " +
582 base::SysInfo::OperatingSystemVersion() + " " +
583 base::SysInfo::OperatingSystemArchitecture());
584 #if defined(OS_LINUX)
585 LogToCircularBuffer("Linux distribution: " + base::GetLinuxDistro());
586 #endif
588 // CPU
589 base::CPU cpu;
590 LogToCircularBuffer(
591 "Cpu: " + IntToString(cpu.family()) + "." + IntToString(cpu.model()) +
592 "." + IntToString(cpu.stepping()) + ", x" +
593 IntToString(base::SysInfo::NumberOfProcessors()) + ", " +
594 IntToString(base::SysInfo::AmountOfPhysicalMemoryMB()) + "MB");
595 std::string cpu_brand = cpu.cpu_brand();
596 // Workaround for crbug.com/249713.
597 // TODO(grunell): Remove workaround when bug is fixed.
598 size_t null_pos = cpu_brand.find('\0');
599 if (null_pos != std::string::npos)
600 cpu_brand.erase(null_pos);
601 LogToCircularBuffer("Cpu brand: " + cpu_brand);
603 // Computer model
604 std::string computer_model = "Not available";
605 #if defined(OS_MACOSX)
606 computer_model = base::mac::GetModelIdentifier();
607 #elif defined(OS_CHROMEOS)
608 chromeos::system::StatisticsProvider::GetInstance()->
609 GetMachineStatistic(chromeos::system::kHardwareClassKey, &computer_model);
610 #endif
611 LogToCircularBuffer("Computer model: " + computer_model);
613 // GPU
614 gpu::GPUInfo gpu_info = content::GpuDataManager::GetInstance()->GetGPUInfo();
615 LogToCircularBuffer(
616 "Gpu: machine-model-name=" + gpu_info.machine_model_name +
617 ", machine-model-version=" + gpu_info.machine_model_version +
618 ", vendor-id=" + IntToString(gpu_info.gpu.vendor_id) +
619 ", device-id=" + IntToString(gpu_info.gpu.device_id) +
620 ", driver-vendor=" + gpu_info.driver_vendor +
621 ", driver-version=" + gpu_info.driver_version);
622 LogToCircularBuffer(
623 "OpenGL: gl-vendor=" + gpu_info.gl_vendor +
624 ", gl-renderer=" + gpu_info.gl_renderer +
625 ", gl-version=" + gpu_info.gl_version);
627 // Network interfaces
628 LogToCircularBuffer("Discovered " + IntToString(network_list.size()) +
629 " network interfaces:");
630 for (net::NetworkInterfaceList::const_iterator it = network_list.begin();
631 it != network_list.end(); ++it) {
632 LogToCircularBuffer(
633 "Name: " + it->friendly_name + ", Address: " +
634 IPAddressToSensitiveString(it->address) + ", Type: " +
635 net::NetworkChangeNotifier::ConnectionTypeToString(it->type));
638 NotifyLoggingStarted(callback);
641 void WebRtcLoggingHandlerHost::NotifyLoggingStarted(
642 const GenericDoneCallback& callback) {
643 DCHECK_CURRENTLY_ON(BrowserThread::IO);
644 DCHECK_EQ(logging_state_, STARTING);
645 Send(new WebRtcLoggingMsg_StartLogging());
646 logging_started_time_ = base::Time::Now();
647 logging_state_ = STARTED;
648 FireGenericDoneCallback(callback, true, "");
651 void WebRtcLoggingHandlerHost::LogToCircularBuffer(const std::string& message) {
652 DCHECK_CURRENTLY_ON(BrowserThread::IO);
653 DCHECK_NE(logging_state_, CLOSED);
654 log_buffer_->Log(message);
657 base::FilePath WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists() {
658 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
659 base::FilePath log_dir_path =
660 WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath());
661 base::File::Error error;
662 if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) {
663 DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error;
664 return base::FilePath();
666 return log_dir_path;
669 void WebRtcLoggingHandlerHost::TriggerUpload(
670 const UploadDoneCallback& callback,
671 const base::FilePath& log_directory) {
672 DCHECK_CURRENTLY_ON(BrowserThread::IO);
674 if (rtp_dump_handler_) {
675 BrowserThread::PostTask(
676 BrowserThread::UI,
677 FROM_HERE,
678 base::Bind(stop_rtp_dump_callback_, true, true));
680 rtp_dump_handler_->StopOngoingDumps(
681 base::Bind(&WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps,
682 this,
683 log_directory,
684 callback));
685 return;
688 DoUploadLogAndRtpDumps(log_directory, callback);
691 void WebRtcLoggingHandlerHost::StoreLogInDirectory(
692 const std::string& log_id,
693 scoped_ptr<WebRtcLogPaths> log_paths,
694 const GenericDoneCallback& done_callback,
695 const base::FilePath& directory) {
696 DCHECK_CURRENTLY_ON(BrowserThread::IO);
697 log_paths->log_path = directory;
699 log_buffer_->SetComplete();
700 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
701 base::Bind(&WebRtcLogUploader::LoggingStoppedDoStore,
702 base::Unretained(g_browser_process->webrtc_log_uploader()),
703 *log_paths.get(), log_id, Passed(&log_buffer_), Passed(&meta_data_),
704 done_callback));
706 logging_state_ = CLOSED;
709 void WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps(
710 const base::FilePath& log_directory,
711 const UploadDoneCallback& callback) {
712 DCHECK_CURRENTLY_ON(BrowserThread::IO);
714 WebRtcLogUploadDoneData upload_done_data;
715 upload_done_data.log_path = log_directory;
716 upload_done_data.callback = callback;
717 upload_done_data.host = this;
718 ReleaseRtpDumps(&upload_done_data);
720 log_buffer_->SetComplete();
721 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
722 &WebRtcLogUploader::LoggingStoppedDoUpload,
723 base::Unretained(g_browser_process->webrtc_log_uploader()),
724 Passed(&log_buffer_),
725 Passed(&meta_data_),
726 upload_done_data));
728 logging_state_ = CLOSED;
731 void WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart(
732 RtpDumpType type,
733 const GenericDoneCallback& callback,
734 const base::FilePath& dump_dir) {
735 DCHECK_CURRENTLY_ON(BrowserThread::IO);
737 // |rtp_dump_handler_| may be non-NULL if StartRtpDump is called again before
738 // GetLogDirectoryAndEnsureExists returns on the FILE thread for a previous
739 // StartRtpDump.
740 if (!rtp_dump_handler_)
741 rtp_dump_handler_.reset(new WebRtcRtpDumpHandler(dump_dir));
743 DoStartRtpDump(type, callback);
746 void WebRtcLoggingHandlerHost::DoStartRtpDump(
747 RtpDumpType type, const GenericDoneCallback& callback) {
748 DCHECK_CURRENTLY_ON(BrowserThread::IO);
749 DCHECK(rtp_dump_handler_);
751 std::string error;
752 bool result = rtp_dump_handler_->StartDump(type, &error);
753 FireGenericDoneCallback(callback, result, error);
756 bool WebRtcLoggingHandlerHost::ReleaseRtpDumps(WebRtcLogPaths* log_paths) {
757 DCHECK_CURRENTLY_ON(BrowserThread::IO);
758 DCHECK(log_paths);
760 if (!rtp_dump_handler_)
761 return false;
763 WebRtcRtpDumpHandler::ReleasedDumps rtp_dumps(
764 rtp_dump_handler_->ReleaseDumps());
765 log_paths->incoming_rtp_dump = rtp_dumps.incoming_dump_path;
766 log_paths->outgoing_rtp_dump = rtp_dumps.outgoing_dump_path;
768 rtp_dump_handler_.reset();
769 stop_rtp_dump_callback_.Reset();
771 return true;