Refactor WebsiteSettings to operate on a SecurityInfo
[chromium-blink-merge.git] / chrome / browser / media / webrtc_logging_handler_host.cc
blob1a354c3ae8f9ea03bea7fc30baf40b82b11a0427
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/channel_info.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/media/webrtc_logging_messages.h"
28 #include "chromeos/settings/cros_settings_names.h"
29 #include "components/version_info/version_info.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "content/public/browser/content_browser_client.h"
32 #include "content/public/browser/gpu_data_manager.h"
33 #include "content/public/browser/render_process_host.h"
34 #include "gpu/config/gpu_info.h"
35 #include "net/base/address_family.h"
36 #include "net/base/ip_address_number.h"
37 #include "net/url_request/url_request_context_getter.h"
39 #if defined(OS_LINUX)
40 #include "base/linux_util.h"
41 #endif
43 #if defined(OS_MACOSX)
44 #include "base/mac/mac_util.h"
45 #endif
47 #if defined(OS_CHROMEOS)
48 #include "chromeos/system/statistics_provider.h"
49 #endif
51 using base::IntToString;
52 using content::BrowserThread;
54 namespace {
56 const char kLogNotStoppedOrNoLogOpen[] =
57 "Logging not stopped or no log open.";
59 // For privacy reasons when logging IP addresses. The returned "sensitive
60 // string" is for release builds a string with the end stripped away. Last
61 // octet for IPv4 and last 80 bits (5 groups) for IPv6. String will be
62 // "1.2.3.x" and "1.2.3::" respectively. For debug builds, the string is
63 // not stripped.
64 std::string IPAddressToSensitiveString(const net::IPAddressNumber& address) {
65 #if defined(NDEBUG)
66 std::string sensitive_address;
67 switch (net::GetAddressFamily(address)) {
68 case net::ADDRESS_FAMILY_IPV4: {
69 sensitive_address = net::IPAddressToString(address);
70 size_t find_pos = sensitive_address.rfind('.');
71 if (find_pos == std::string::npos)
72 return std::string();
73 sensitive_address.resize(find_pos);
74 sensitive_address += ".x";
75 break;
77 case net::ADDRESS_FAMILY_IPV6: {
78 // TODO(grunell): Create a string of format "1:2:3:x:x:x:x:x" to clarify
79 // that the end has been stripped out.
80 net::IPAddressNumber sensitive_address_number = address;
81 sensitive_address_number.resize(net::kIPv6AddressSize - 10);
82 sensitive_address_number.resize(net::kIPv6AddressSize, 0);
83 sensitive_address = net::IPAddressToString(sensitive_address_number);
84 break;
86 case net::ADDRESS_FAMILY_UNSPECIFIED: {
87 break;
90 return sensitive_address;
91 #else
92 return net::IPAddressToString(address);
93 #endif
96 void FormatMetaDataAsLogMessage(
97 const MetaDataMap& meta_data,
98 std::string* message) {
99 for (MetaDataMap::const_iterator it = meta_data.begin();
100 it != meta_data.end(); ++it) {
101 *message += it->first + ": " + it->second + '\n';
103 // Remove last '\n'.
104 message->resize(message->size() - 1);
107 void FireGenericDoneCallback(
108 const WebRtcLoggingHandlerHost::GenericDoneCallback& callback,
109 bool success,
110 const std::string& error_message) {
111 DCHECK_CURRENTLY_ON(BrowserThread::IO);
112 DCHECK(!callback.is_null());
113 content::BrowserThread::PostTask(
114 content::BrowserThread::UI,
115 FROM_HERE,
116 base::Bind(callback, success, error_message));
119 void FireAndResetGenericDoneCallback(
120 WebRtcLoggingHandlerHost::GenericDoneCallback* callback,
121 bool success,
122 const std::string& error_message) {
123 FireGenericDoneCallback(*callback, success, error_message);
124 callback->Reset();
127 } // namespace
129 WebRtcLogBuffer::WebRtcLogBuffer()
130 : buffer_(),
131 circular_(&buffer_[0], sizeof(buffer_), sizeof(buffer_) / 2, false),
132 read_only_(false) {
135 WebRtcLogBuffer::~WebRtcLogBuffer() {
136 DCHECK(read_only_ || thread_checker_.CalledOnValidThread());
139 void WebRtcLogBuffer::Log(const std::string& message) {
140 DCHECK(thread_checker_.CalledOnValidThread());
141 DCHECK(!read_only_);
142 circular_.Write(message.c_str(), message.length());
143 const char eol = '\n';
144 circular_.Write(&eol, 1);
147 PartialCircularBuffer WebRtcLogBuffer::Read() {
148 DCHECK(thread_checker_.CalledOnValidThread());
149 DCHECK(read_only_);
150 return PartialCircularBuffer(&buffer_[0], sizeof(buffer_));
153 void WebRtcLogBuffer::SetComplete() {
154 DCHECK(thread_checker_.CalledOnValidThread());
155 DCHECK(!read_only_) << "Already set? (programmer error)";
156 read_only_ = true;
157 // Detach from the current thread so that we can check reads on a different
158 // thread. This is to make sure that Read()s still happen on one thread only.
159 thread_checker_.DetachFromThread();
162 WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost(Profile* profile)
163 : BrowserMessageFilter(WebRtcLoggingMsgStart),
164 profile_(profile),
165 logging_state_(CLOSED),
166 upload_log_on_render_close_(false) {
167 DCHECK(profile_);
170 WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() {}
172 void WebRtcLoggingHandlerHost::SetMetaData(
173 scoped_ptr<MetaDataMap> meta_data,
174 const GenericDoneCallback& callback) {
175 DCHECK_CURRENTLY_ON(BrowserThread::IO);
176 DCHECK(!callback.is_null());
178 std::string error_message;
179 if (logging_state_ == CLOSED) {
180 if (!meta_data_.get())
181 meta_data_ = meta_data.Pass();
182 } else if (logging_state_ == STARTED) {
183 std::string meta_data_message;
184 FormatMetaDataAsLogMessage(*meta_data.get(), &meta_data_message);
185 LogToCircularBuffer(meta_data_message);
186 } else {
187 error_message = "Meta data must be set before stop or upload.";
190 if (error_message.empty() && meta_data.get()) {
191 // Keep the meta data around for uploading separately from the log.
192 for (const auto& it : *meta_data.get())
193 (*meta_data_.get())[it.first] = it.second;
196 FireGenericDoneCallback(callback, error_message.empty(), error_message);
199 void WebRtcLoggingHandlerHost::StartLogging(
200 const GenericDoneCallback& callback) {
201 DCHECK_CURRENTLY_ON(BrowserThread::IO);
202 DCHECK(!callback.is_null());
204 if (logging_state_ != CLOSED) {
205 FireGenericDoneCallback(callback, false, "A log is already open");
206 return;
209 logging_state_ = STARTING;
210 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
211 &WebRtcLoggingHandlerHost::StartLoggingIfAllowed, this, callback));
214 void WebRtcLoggingHandlerHost::StopLogging(
215 const GenericDoneCallback& callback) {
216 DCHECK_CURRENTLY_ON(BrowserThread::IO);
217 DCHECK(!callback.is_null());
219 if (logging_state_ != STARTED) {
220 FireGenericDoneCallback(callback, false, "Logging not started");
221 return;
224 stop_callback_ = callback;
225 logging_state_ = STOPPING;
226 Send(new WebRtcLoggingMsg_StopLogging());
229 void WebRtcLoggingHandlerHost::UploadLog(const UploadDoneCallback& callback) {
230 DCHECK_CURRENTLY_ON(BrowserThread::IO);
231 DCHECK(!callback.is_null());
233 if (logging_state_ != STOPPED) {
234 if (!callback.is_null()) {
235 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
236 base::Bind(callback, false, "", kLogNotStoppedOrNoLogOpen));
238 return;
241 content::BrowserThread::PostTaskAndReplyWithResult(
242 content::BrowserThread::FILE,
243 FROM_HERE,
244 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
245 this),
246 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this, callback));
249 void WebRtcLoggingHandlerHost::UploadStoredLog(
250 const std::string& log_id,
251 const UploadDoneCallback& callback) {
252 DCHECK_CURRENTLY_ON(BrowserThread::IO);
253 DCHECK(!callback.is_null());
255 content::BrowserThread::PostTask(content::BrowserThread::FILE,
256 FROM_HERE,
257 base::Bind(&WebRtcLoggingHandlerHost::UploadStoredLogOnFileThread,
258 this, log_id, callback));
261 void WebRtcLoggingHandlerHost::UploadStoredLogOnFileThread(
262 const std::string& log_id,
263 const UploadDoneCallback& callback) {
264 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
266 WebRtcLogUploadDoneData upload_data;
267 upload_data.log_path = GetLogDirectoryAndEnsureExists();
268 upload_data.callback = callback;
269 upload_data.host = this;
270 upload_data.local_log_id = log_id;
272 g_browser_process->webrtc_log_uploader()->UploadStoredLog(upload_data);
275 void WebRtcLoggingHandlerHost::UploadLogDone() {
276 DCHECK_CURRENTLY_ON(BrowserThread::IO);
277 logging_state_ = CLOSED;
280 void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) {
281 DCHECK_CURRENTLY_ON(BrowserThread::IO);
282 DCHECK(!callback.is_null());
284 if (logging_state_ != STOPPED) {
285 FireGenericDoneCallback(callback, false, kLogNotStoppedOrNoLogOpen);
286 return;
288 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
289 log_buffer_.reset();
290 meta_data_.reset();
291 logging_state_ = CLOSED;
292 rtp_dump_handler_.reset();
293 stop_rtp_dump_callback_.Reset();
294 FireGenericDoneCallback(callback, true, "");
297 // Stores the log locally using a hash of log_id + security origin.
298 void WebRtcLoggingHandlerHost::StoreLog(
299 const std::string& log_id,
300 const GenericDoneCallback& callback) {
301 DCHECK_CURRENTLY_ON(BrowserThread::IO);
302 DCHECK(!callback.is_null());
304 if (logging_state_ != STOPPED) {
305 FireGenericDoneCallback(callback, false, kLogNotStoppedOrNoLogOpen);
306 return;
309 if (rtp_dump_handler_) {
310 BrowserThread::PostTask(
311 BrowserThread::UI,
312 FROM_HERE,
313 base::Bind(stop_rtp_dump_callback_, true, true));
315 rtp_dump_handler_->StopOngoingDumps(
316 base::Bind(&WebRtcLoggingHandlerHost::StoreLogContinue,
317 this, log_id, callback));
318 return;
321 StoreLogContinue(log_id, callback);
324 void WebRtcLoggingHandlerHost::StoreLogContinue(
325 const std::string& log_id,
326 const GenericDoneCallback& callback) {
327 DCHECK_CURRENTLY_ON(BrowserThread::IO);
328 DCHECK(!callback.is_null());
330 scoped_ptr<WebRtcLogPaths> log_paths(new WebRtcLogPaths());
331 ReleaseRtpDumps(log_paths.get());
333 content::BrowserThread::PostTaskAndReplyWithResult(
334 content::BrowserThread::FILE,
335 FROM_HERE,
336 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
337 this),
338 base::Bind(&WebRtcLoggingHandlerHost::StoreLogInDirectory, this, log_id,
339 Passed(&log_paths), callback));
342 void WebRtcLoggingHandlerHost::LogMessage(const std::string& message) {
343 BrowserThread::PostTask(
344 BrowserThread::IO,
345 FROM_HERE,
346 base::Bind(
347 &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser,
348 this,
349 WebRtcLoggingMessageData(base::Time::Now(), message)));
352 void WebRtcLoggingHandlerHost::StartRtpDump(
353 RtpDumpType type,
354 const GenericDoneCallback& callback,
355 const content::RenderProcessHost::WebRtcStopRtpDumpCallback&
356 stop_callback) {
357 DCHECK_CURRENTLY_ON(BrowserThread::IO);
358 DCHECK(stop_rtp_dump_callback_.is_null() ||
359 stop_rtp_dump_callback_.Equals(stop_callback));
361 stop_rtp_dump_callback_ = stop_callback;
363 if (!rtp_dump_handler_) {
364 content::BrowserThread::PostTaskAndReplyWithResult(
365 content::BrowserThread::FILE,
366 FROM_HERE,
367 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
368 this),
369 base::Bind(&WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart,
370 this,
371 type,
372 callback));
373 return;
376 DoStartRtpDump(type, callback);
379 void WebRtcLoggingHandlerHost::StopRtpDump(
380 RtpDumpType type,
381 const GenericDoneCallback& callback) {
382 DCHECK_CURRENTLY_ON(BrowserThread::IO);
383 DCHECK(!callback.is_null());
385 if (!rtp_dump_handler_) {
386 FireGenericDoneCallback(callback, false, "RTP dump has not been started.");
387 return;
390 if (!stop_rtp_dump_callback_.is_null()) {
391 BrowserThread::PostTask(
392 BrowserThread::UI,
393 FROM_HERE,
394 base::Bind(stop_rtp_dump_callback_,
395 type == RTP_DUMP_INCOMING || type == RTP_DUMP_BOTH,
396 type == RTP_DUMP_OUTGOING || type == RTP_DUMP_BOTH));
399 rtp_dump_handler_->StopDump(type, callback);
402 void WebRtcLoggingHandlerHost::OnRtpPacket(scoped_ptr<uint8[]> packet_header,
403 size_t header_length,
404 size_t packet_length,
405 bool incoming) {
406 DCHECK_CURRENTLY_ON(BrowserThread::UI);
408 BrowserThread::PostTask(
409 BrowserThread::IO,
410 FROM_HERE,
411 base::Bind(&WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread,
412 this,
413 base::Passed(&packet_header),
414 header_length,
415 packet_length,
416 incoming));
419 void WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread(
420 scoped_ptr<uint8[]> packet_header,
421 size_t header_length,
422 size_t packet_length,
423 bool incoming) {
424 DCHECK_CURRENTLY_ON(BrowserThread::IO);
426 // |rtp_dump_handler_| could be NULL if we are waiting for the FILE thread to
427 // create/ensure the log directory.
428 if (rtp_dump_handler_) {
429 rtp_dump_handler_->OnRtpPacket(
430 packet_header.get(), header_length, packet_length, incoming);
434 void WebRtcLoggingHandlerHost::OnChannelClosing() {
435 DCHECK_CURRENTLY_ON(BrowserThread::IO);
436 if (logging_state_ == STARTED || logging_state_ == STOPPED) {
437 if (upload_log_on_render_close_) {
438 logging_started_time_ = base::Time();
440 content::BrowserThread::PostTaskAndReplyWithResult(
441 content::BrowserThread::FILE,
442 FROM_HERE,
443 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
444 this),
445 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this,
446 UploadDoneCallback()));
447 } else {
448 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
451 content::BrowserMessageFilter::OnChannelClosing();
454 void WebRtcLoggingHandlerHost::OnDestruct() const {
455 BrowserThread::DeleteOnIOThread::Destruct(this);
458 bool WebRtcLoggingHandlerHost::OnMessageReceived(const IPC::Message& message) {
459 DCHECK_CURRENTLY_ON(BrowserThread::IO);
460 bool handled = true;
461 IPC_BEGIN_MESSAGE_MAP(WebRtcLoggingHandlerHost, message)
462 IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_AddLogMessages, OnAddLogMessages)
463 IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_LoggingStopped,
464 OnLoggingStoppedInRenderer)
465 IPC_MESSAGE_UNHANDLED(handled = false)
466 IPC_END_MESSAGE_MAP()
468 return handled;
471 void WebRtcLoggingHandlerHost::AddLogMessageFromBrowser(
472 const WebRtcLoggingMessageData& message) {
473 DCHECK_CURRENTLY_ON(BrowserThread::IO);
474 if (logging_state_ == STARTED)
475 LogToCircularBuffer(message.Format(logging_started_time_));
478 void WebRtcLoggingHandlerHost::OnAddLogMessages(
479 const std::vector<WebRtcLoggingMessageData>& messages) {
480 DCHECK_CURRENTLY_ON(BrowserThread::IO);
481 if (logging_state_ == STARTED || logging_state_ == STOPPING) {
482 for (size_t i = 0; i < messages.size(); ++i) {
483 LogToCircularBuffer(messages[i].Format(logging_started_time_));
488 void WebRtcLoggingHandlerHost::OnLoggingStoppedInRenderer() {
489 DCHECK_CURRENTLY_ON(BrowserThread::IO);
490 if (logging_state_ != STOPPING) {
491 // If an out-of-order response is received, stop_callback_ may be invalid,
492 // and must not be invoked.
493 DLOG(ERROR) << "OnLoggingStoppedInRenderer invoked in state "
494 << logging_state_;
495 bad_message::ReceivedBadMessage(
496 this, bad_message::WRLHH_LOGGING_STOPPED_BAD_STATE);
497 return;
499 logging_started_time_ = base::Time();
500 logging_state_ = STOPPED;
501 FireAndResetGenericDoneCallback(&stop_callback_, true, "");
504 void WebRtcLoggingHandlerHost::StartLoggingIfAllowed(
505 const GenericDoneCallback& callback) {
506 DCHECK_CURRENTLY_ON(BrowserThread::UI);
507 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
508 &WebRtcLoggingHandlerHost::DoStartLogging, this,
509 g_browser_process->webrtc_log_uploader()->ApplyForStartLogging(),
510 callback));
513 void WebRtcLoggingHandlerHost::DoStartLogging(
514 bool permissions_granted,
515 const GenericDoneCallback& callback) {
516 DCHECK_CURRENTLY_ON(BrowserThread::IO);
517 if (logging_state_ != STARTING) {
518 FireGenericDoneCallback(callback, false, "Logging cancelled.");
519 return;
522 if (!permissions_granted) {
523 logging_state_ = CLOSED;
524 FireGenericDoneCallback(callback, false,
525 "Cannot start, maybe the maximum number of "
526 "simultaneuos logs has been reached.");
527 return;
530 DCHECK(!log_buffer_.get());
531 log_buffer_.reset(new WebRtcLogBuffer());
532 if (!meta_data_.get())
533 meta_data_.reset(new MetaDataMap());
535 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
536 &WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread, this, callback));
539 void WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread(
540 const GenericDoneCallback& callback) {
541 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
543 net::NetworkInterfaceList network_list;
544 net::GetNetworkList(&network_list,
545 net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
547 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
548 &WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread, this, network_list,
549 callback));
552 void WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread(
553 const net::NetworkInterfaceList& network_list,
554 const GenericDoneCallback& callback) {
555 DCHECK_CURRENTLY_ON(BrowserThread::IO);
556 if (logging_state_ != STARTING) {
557 FireGenericDoneCallback(callback, false, "Logging cancelled.");
558 return;
561 // Log start time (current time). We don't use base/i18n/time_formatting.h
562 // here because we don't want the format of the current locale.
563 base::Time::Exploded now = {0};
564 base::Time::Now().LocalExplode(&now);
565 LogToCircularBuffer(base::StringPrintf(
566 "Start %d-%02d-%02d %02d:%02d:%02d", now.year, now.month,
567 now.day_of_month, now.hour, now.minute, now.second));
569 // Write metadata if received before logging started.
570 if (meta_data_.get() && !meta_data_->empty()) {
571 std::string info;
572 FormatMetaDataAsLogMessage(*meta_data_.get(), &info);
573 LogToCircularBuffer(info);
576 // Chrome version
577 LogToCircularBuffer("Chrome version: " + version_info::GetVersionNumber() +
578 " " + chrome::GetChannelString());
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;