Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / media / webrtc_logging_handler_host.cc
blobc1180173cd58657a8f409f7444e8892683db0e30
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/browser_process.h"
19 #include "chrome/browser/chromeos/settings/cros_settings.h"
20 #include "chrome/browser/media/webrtc_log_list.h"
21 #include "chrome/browser/media/webrtc_log_uploader.h"
22 #include "chrome/browser/media/webrtc_rtp_dump_handler.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/chrome_version_info.h"
26 #include "chrome/common/media/webrtc_logging_messages.h"
27 #include "chromeos/settings/cros_settings_names.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/content_browser_client.h"
30 #include "content/public/browser/gpu_data_manager.h"
31 #include "content/public/browser/render_process_host.h"
32 #include "gpu/config/gpu_info.h"
33 #include "net/base/address_family.h"
34 #include "net/url_request/url_request_context_getter.h"
36 #if defined(OS_LINUX)
37 #include "base/linux_util.h"
38 #endif
40 #if defined(OS_MACOSX)
41 #include "base/mac/mac_util.h"
42 #endif
44 #if defined(OS_CHROMEOS)
45 #include "chromeos/system/statistics_provider.h"
46 #endif
48 using base::IntToString;
49 using content::BrowserThread;
51 namespace {
53 const char kLogNotStoppedOrNoLogOpen[] =
54 "Logging not stopped or no log open.";
56 // For privacy reasons when logging IP addresses. The returned "sensitive
57 // string" is for release builds a string with the end stripped away. Last
58 // octet for IPv4 and last 80 bits (5 groups) for IPv6. String will be
59 // "1.2.3.x" and "1.2.3::" respectively. For debug builds, the string is
60 // not stripped.
61 std::string IPAddressToSensitiveString(const net::IPAddressNumber& address) {
62 #if defined(NDEBUG)
63 std::string sensitive_address;
64 switch (net::GetAddressFamily(address)) {
65 case net::ADDRESS_FAMILY_IPV4: {
66 sensitive_address = net::IPAddressToString(address);
67 size_t find_pos = sensitive_address.rfind('.');
68 if (find_pos == std::string::npos)
69 return std::string();
70 sensitive_address.resize(find_pos);
71 sensitive_address += ".x";
72 break;
74 case net::ADDRESS_FAMILY_IPV6: {
75 // TODO(grunell): Create a string of format "1:2:3:x:x:x:x:x" to clarify
76 // that the end has been stripped out.
77 net::IPAddressNumber sensitive_address_number = address;
78 sensitive_address_number.resize(net::kIPv6AddressSize - 10);
79 sensitive_address_number.resize(net::kIPv6AddressSize, 0);
80 sensitive_address = net::IPAddressToString(sensitive_address_number);
81 break;
83 case net::ADDRESS_FAMILY_UNSPECIFIED: {
84 break;
87 return sensitive_address;
88 #else
89 return net::IPAddressToString(address);
90 #endif
93 void FormatMetaDataAsLogMessage(
94 const MetaDataMap& meta_data,
95 std::string* message) {
96 for (MetaDataMap::const_iterator it = meta_data.begin();
97 it != meta_data.end(); ++it) {
98 *message += it->first + ": " + it->second + '\n';
100 // Remove last '\n'.
101 message->resize(message->size() - 1);
104 void FireGenericDoneCallback(
105 const WebRtcLoggingHandlerHost::GenericDoneCallback& callback,
106 bool success,
107 const std::string& error_message) {
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
109 DCHECK(!callback.is_null());
110 content::BrowserThread::PostTask(
111 content::BrowserThread::UI,
112 FROM_HERE,
113 base::Bind(callback, success, error_message));
116 void FireAndResetGenericDoneCallback(
117 WebRtcLoggingHandlerHost::GenericDoneCallback* callback,
118 bool success,
119 const std::string& error_message) {
120 FireGenericDoneCallback(*callback, success, error_message);
121 callback->Reset();
124 } // namespace
126 WebRtcLogBuffer::WebRtcLogBuffer()
127 : buffer_(),
128 circular_(&buffer_[0], sizeof(buffer_), sizeof(buffer_) / 2, false),
129 read_only_(false) {
132 WebRtcLogBuffer::~WebRtcLogBuffer() {
133 DCHECK(read_only_ || thread_checker_.CalledOnValidThread());
136 void WebRtcLogBuffer::Log(const std::string& message) {
137 DCHECK(thread_checker_.CalledOnValidThread());
138 DCHECK(!read_only_);
139 circular_.Write(message.c_str(), message.length());
140 const char eol = '\n';
141 circular_.Write(&eol, 1);
144 PartialCircularBuffer WebRtcLogBuffer::Read() {
145 DCHECK(thread_checker_.CalledOnValidThread());
146 DCHECK(read_only_);
147 return PartialCircularBuffer(&buffer_[0], sizeof(buffer_));
150 void WebRtcLogBuffer::SetComplete() {
151 DCHECK(thread_checker_.CalledOnValidThread());
152 DCHECK(!read_only_) << "Already set? (programmer error)";
153 read_only_ = true;
154 // Detach from the current thread so that we can check reads on a different
155 // thread. This is to make sure that Read()s still happen on one thread only.
156 thread_checker_.DetachFromThread();
159 WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost(Profile* profile)
160 : BrowserMessageFilter(WebRtcLoggingMsgStart),
161 profile_(profile),
162 logging_state_(CLOSED),
163 upload_log_on_render_close_(false) {
164 DCHECK(profile_);
167 WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() {}
169 void WebRtcLoggingHandlerHost::SetMetaData(
170 scoped_ptr<MetaDataMap> meta_data,
171 const GenericDoneCallback& callback) {
172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
173 DCHECK(!callback.is_null());
175 std::string error_message;
176 if (logging_state_ == CLOSED) {
177 if (!meta_data_.get())
178 meta_data_ = meta_data.Pass();
179 } else if (logging_state_ == STARTED) {
180 std::string meta_data_message;
181 FormatMetaDataAsLogMessage(*meta_data.get(), &meta_data_message);
182 LogToCircularBuffer(meta_data_message);
183 } else {
184 error_message = "Meta data must be set before stop or upload.";
187 if (error_message.empty() && meta_data.get()) {
188 // Keep the meta data around for uploading separately from the log.
189 for (const auto& it : *meta_data.get())
190 (*meta_data_.get())[it.first] = it.second;
193 FireGenericDoneCallback(callback, error_message.empty(), error_message);
196 void WebRtcLoggingHandlerHost::StartLogging(
197 const GenericDoneCallback& callback) {
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
199 DCHECK(!callback.is_null());
201 if (logging_state_ != CLOSED) {
202 FireGenericDoneCallback(callback, false, "A log is already open");
203 return;
206 logging_state_ = STARTING;
207 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
208 &WebRtcLoggingHandlerHost::StartLoggingIfAllowed, this, callback));
211 void WebRtcLoggingHandlerHost::StopLogging(
212 const GenericDoneCallback& callback) {
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
214 DCHECK(!callback.is_null());
216 if (logging_state_ != STARTED) {
217 FireGenericDoneCallback(callback, false, "Logging not started");
218 return;
221 stop_callback_ = callback;
222 logging_state_ = STOPPING;
223 Send(new WebRtcLoggingMsg_StopLogging());
226 void WebRtcLoggingHandlerHost::UploadLog(const UploadDoneCallback& callback) {
227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
228 DCHECK(!callback.is_null());
230 if (logging_state_ != STOPPED) {
231 if (!callback.is_null()) {
232 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
233 base::Bind(callback, false, "", kLogNotStoppedOrNoLogOpen));
235 return;
238 content::BrowserThread::PostTaskAndReplyWithResult(
239 content::BrowserThread::FILE,
240 FROM_HERE,
241 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
242 this),
243 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this, callback));
246 void WebRtcLoggingHandlerHost::UploadStoredLog(
247 const std::string& log_id,
248 const UploadDoneCallback& callback) {
249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
250 DCHECK(!callback.is_null());
252 content::BrowserThread::PostTask(content::BrowserThread::FILE,
253 FROM_HERE,
254 base::Bind(&WebRtcLoggingHandlerHost::UploadStoredLogOnFileThread,
255 this, log_id, callback));
258 void WebRtcLoggingHandlerHost::UploadStoredLogOnFileThread(
259 const std::string& log_id,
260 const UploadDoneCallback& callback) {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
263 WebRtcLogUploadDoneData upload_data;
264 upload_data.log_path = GetLogDirectoryAndEnsureExists();
265 upload_data.callback = callback;
266 upload_data.host = this;
267 upload_data.local_log_id = log_id;
269 g_browser_process->webrtc_log_uploader()->UploadStoredLog(upload_data);
272 void WebRtcLoggingHandlerHost::UploadLogDone() {
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
274 logging_state_ = CLOSED;
277 void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
279 DCHECK(!callback.is_null());
281 if (logging_state_ != STOPPED) {
282 FireGenericDoneCallback(callback, false, kLogNotStoppedOrNoLogOpen);
283 return;
285 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
286 log_buffer_.reset();
287 meta_data_.reset();
288 logging_state_ = CLOSED;
289 rtp_dump_handler_.reset();
290 stop_rtp_dump_callback_.Reset();
291 FireGenericDoneCallback(callback, true, "");
294 // Stores the log locally using a hash of log_id + security origin.
295 void WebRtcLoggingHandlerHost::StoreLog(
296 const std::string& log_id,
297 const GenericDoneCallback& callback) {
298 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
299 DCHECK(!callback.is_null());
301 if (logging_state_ != STOPPED) {
302 FireGenericDoneCallback(callback, false, kLogNotStoppedOrNoLogOpen);
303 return;
306 if (rtp_dump_handler_) {
307 BrowserThread::PostTask(
308 BrowserThread::UI,
309 FROM_HERE,
310 base::Bind(stop_rtp_dump_callback_, true, true));
312 rtp_dump_handler_->StopOngoingDumps(
313 base::Bind(&WebRtcLoggingHandlerHost::StoreLogContinue,
314 this, log_id, callback));
315 return;
318 StoreLogContinue(log_id, callback);
321 void WebRtcLoggingHandlerHost::StoreLogContinue(
322 const std::string& log_id,
323 const GenericDoneCallback& callback) {
324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
325 DCHECK(!callback.is_null());
327 scoped_ptr<WebRtcLogPaths> log_paths(new WebRtcLogPaths());
328 ReleaseRtpDumps(log_paths.get());
330 content::BrowserThread::PostTaskAndReplyWithResult(
331 content::BrowserThread::FILE,
332 FROM_HERE,
333 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
334 this),
335 base::Bind(&WebRtcLoggingHandlerHost::StoreLogInDirectory, this, log_id,
336 Passed(&log_paths), callback));
339 void WebRtcLoggingHandlerHost::LogMessage(const std::string& message) {
340 BrowserThread::PostTask(
341 BrowserThread::IO,
342 FROM_HERE,
343 base::Bind(
344 &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser,
345 this,
346 WebRtcLoggingMessageData(base::Time::Now(), message)));
349 void WebRtcLoggingHandlerHost::StartRtpDump(
350 RtpDumpType type,
351 const GenericDoneCallback& callback,
352 const content::RenderProcessHost::WebRtcStopRtpDumpCallback&
353 stop_callback) {
354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
355 DCHECK(stop_rtp_dump_callback_.is_null() ||
356 stop_rtp_dump_callback_.Equals(stop_callback));
358 stop_rtp_dump_callback_ = stop_callback;
360 if (!rtp_dump_handler_) {
361 content::BrowserThread::PostTaskAndReplyWithResult(
362 content::BrowserThread::FILE,
363 FROM_HERE,
364 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
365 this),
366 base::Bind(&WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart,
367 this,
368 type,
369 callback));
370 return;
373 DoStartRtpDump(type, callback);
376 void WebRtcLoggingHandlerHost::StopRtpDump(
377 RtpDumpType type,
378 const GenericDoneCallback& callback) {
379 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
380 DCHECK(!callback.is_null());
382 if (!rtp_dump_handler_) {
383 FireGenericDoneCallback(callback, false, "RTP dump has not been started.");
384 return;
387 if (!stop_rtp_dump_callback_.is_null()) {
388 BrowserThread::PostTask(
389 BrowserThread::UI,
390 FROM_HERE,
391 base::Bind(stop_rtp_dump_callback_,
392 type == RTP_DUMP_INCOMING || type == RTP_DUMP_BOTH,
393 type == RTP_DUMP_OUTGOING || type == RTP_DUMP_BOTH));
396 rtp_dump_handler_->StopDump(type, callback);
399 void WebRtcLoggingHandlerHost::OnRtpPacket(scoped_ptr<uint8[]> packet_header,
400 size_t header_length,
401 size_t packet_length,
402 bool incoming) {
403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
405 BrowserThread::PostTask(
406 BrowserThread::IO,
407 FROM_HERE,
408 base::Bind(&WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread,
409 this,
410 base::Passed(&packet_header),
411 header_length,
412 packet_length,
413 incoming));
416 void WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread(
417 scoped_ptr<uint8[]> packet_header,
418 size_t header_length,
419 size_t packet_length,
420 bool incoming) {
421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
423 // |rtp_dump_handler_| could be NULL if we are waiting for the FILE thread to
424 // create/ensure the log directory.
425 if (rtp_dump_handler_) {
426 rtp_dump_handler_->OnRtpPacket(
427 packet_header.get(), header_length, packet_length, incoming);
431 void WebRtcLoggingHandlerHost::OnChannelClosing() {
432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
433 if (logging_state_ == STARTED || logging_state_ == STOPPED) {
434 if (upload_log_on_render_close_) {
435 logging_started_time_ = base::Time();
437 content::BrowserThread::PostTaskAndReplyWithResult(
438 content::BrowserThread::FILE,
439 FROM_HERE,
440 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
441 this),
442 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this,
443 UploadDoneCallback()));
444 } else {
445 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
448 content::BrowserMessageFilter::OnChannelClosing();
451 void WebRtcLoggingHandlerHost::OnDestruct() const {
452 BrowserThread::DeleteOnIOThread::Destruct(this);
455 bool WebRtcLoggingHandlerHost::OnMessageReceived(const IPC::Message& message) {
456 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
457 bool handled = true;
458 IPC_BEGIN_MESSAGE_MAP(WebRtcLoggingHandlerHost, message)
459 IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_AddLogMessages, OnAddLogMessages)
460 IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_LoggingStopped,
461 OnLoggingStoppedInRenderer)
462 IPC_MESSAGE_UNHANDLED(handled = false)
463 IPC_END_MESSAGE_MAP()
465 return handled;
468 void WebRtcLoggingHandlerHost::AddLogMessageFromBrowser(
469 const WebRtcLoggingMessageData& message) {
470 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
471 if (logging_state_ == STARTED)
472 LogToCircularBuffer(message.Format(logging_started_time_));
475 void WebRtcLoggingHandlerHost::OnAddLogMessages(
476 const std::vector<WebRtcLoggingMessageData>& messages) {
477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
478 if (logging_state_ == STARTED || logging_state_ == STOPPING) {
479 for (size_t i = 0; i < messages.size(); ++i) {
480 LogToCircularBuffer(messages[i].Format(logging_started_time_));
485 void WebRtcLoggingHandlerHost::OnLoggingStoppedInRenderer() {
486 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
487 if (logging_state_ != STOPPING) {
488 // If an out-of-order response is received, stop_callback_ may be invalid,
489 // and must not be invoked.
490 DLOG(ERROR) << "OnLoggingStoppedInRenderer invoked in state "
491 << logging_state_;
492 BadMessageReceived();
493 return;
495 logging_started_time_ = base::Time();
496 logging_state_ = STOPPED;
497 FireAndResetGenericDoneCallback(&stop_callback_, true, "");
500 void WebRtcLoggingHandlerHost::StartLoggingIfAllowed(
501 const GenericDoneCallback& callback) {
502 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
503 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
504 &WebRtcLoggingHandlerHost::DoStartLogging, this,
505 g_browser_process->webrtc_log_uploader()->ApplyForStartLogging(),
506 callback));
509 void WebRtcLoggingHandlerHost::DoStartLogging(
510 bool permissions_granted,
511 const GenericDoneCallback& callback) {
512 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
513 if (logging_state_ != STARTING) {
514 FireGenericDoneCallback(callback, false, "Logging cancelled.");
515 return;
518 if (!permissions_granted) {
519 logging_state_ = CLOSED;
520 FireGenericDoneCallback(callback, false,
521 "Cannot start, maybe the maximum number of "
522 "simultaneuos logs has been reached.");
523 return;
526 DCHECK(!log_buffer_.get());
527 log_buffer_.reset(new WebRtcLogBuffer());
528 if (!meta_data_.get())
529 meta_data_.reset(new MetaDataMap());
531 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
532 &WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread, this, callback));
535 void WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread(
536 const GenericDoneCallback& callback) {
537 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
539 net::NetworkInterfaceList network_list;
540 net::GetNetworkList(&network_list,
541 net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
543 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
544 &WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread, this, network_list,
545 callback));
548 void WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread(
549 const net::NetworkInterfaceList& network_list,
550 const GenericDoneCallback& callback) {
551 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
552 if (logging_state_ != STARTING) {
553 FireGenericDoneCallback(callback, false, "Logging cancelled.");
554 return;
557 // Log start time (current time). We don't use base/i18n/time_formatting.h
558 // here because we don't want the format of the current locale.
559 base::Time::Exploded now = {0};
560 base::Time::Now().LocalExplode(&now);
561 LogToCircularBuffer(base::StringPrintf(
562 "Start %d-%02d-%02d %02d:%02d:%02d", now.year, now.month,
563 now.day_of_month, now.hour, now.minute, now.second));
565 // Write metadata if received before logging started.
566 if (meta_data_.get() && !meta_data_->empty()) {
567 std::string info;
568 FormatMetaDataAsLogMessage(*meta_data_.get(), &info);
569 LogToCircularBuffer(info);
572 // Chrome version
573 chrome::VersionInfo version_info;
574 LogToCircularBuffer("Chrome version: " + version_info.Version() + " " +
575 chrome::VersionInfo::GetVersionStringModifier());
577 // OS
578 LogToCircularBuffer(base::SysInfo::OperatingSystemName() + " " +
579 base::SysInfo::OperatingSystemVersion() + " " +
580 base::SysInfo::OperatingSystemArchitecture());
581 #if defined(OS_LINUX)
582 LogToCircularBuffer("Linux distribution: " + base::GetLinuxDistro());
583 #endif
585 // CPU
586 base::CPU cpu;
587 LogToCircularBuffer(
588 "Cpu: " + IntToString(cpu.family()) + "." + IntToString(cpu.model()) +
589 "." + IntToString(cpu.stepping()) + ", x" +
590 IntToString(base::SysInfo::NumberOfProcessors()) + ", " +
591 IntToString(base::SysInfo::AmountOfPhysicalMemoryMB()) + "MB");
592 std::string cpu_brand = cpu.cpu_brand();
593 // Workaround for crbug.com/249713.
594 // TODO(grunell): Remove workaround when bug is fixed.
595 size_t null_pos = cpu_brand.find('\0');
596 if (null_pos != std::string::npos)
597 cpu_brand.erase(null_pos);
598 LogToCircularBuffer("Cpu brand: " + cpu_brand);
600 // Computer model
601 std::string computer_model = "Not available";
602 #if defined(OS_MACOSX)
603 computer_model = base::mac::GetModelIdentifier();
604 #elif defined(OS_CHROMEOS)
605 chromeos::system::StatisticsProvider::GetInstance()->
606 GetMachineStatistic(chromeos::system::kHardwareClassKey, &computer_model);
607 #endif
608 LogToCircularBuffer("Computer model: " + computer_model);
610 // GPU
611 gpu::GPUInfo gpu_info = content::GpuDataManager::GetInstance()->GetGPUInfo();
612 LogToCircularBuffer(
613 "Gpu: machine-model-name=" + gpu_info.machine_model_name +
614 ", machine-model-version=" + gpu_info.machine_model_version +
615 ", vendor-id=" + IntToString(gpu_info.gpu.vendor_id) +
616 ", device-id=" + IntToString(gpu_info.gpu.device_id) +
617 ", driver-vendor=" + gpu_info.driver_vendor +
618 ", driver-version=" + gpu_info.driver_version);
619 LogToCircularBuffer(
620 "OpenGL: gl-vendor=" + gpu_info.gl_vendor +
621 ", gl-renderer=" + gpu_info.gl_renderer +
622 ", gl-version=" + gpu_info.gl_version);
624 // Network interfaces
625 LogToCircularBuffer("Discovered " + IntToString(network_list.size()) +
626 " network interfaces:");
627 for (net::NetworkInterfaceList::const_iterator it = network_list.begin();
628 it != network_list.end(); ++it) {
629 LogToCircularBuffer(
630 "Name: " + it->friendly_name + ", Address: " +
631 IPAddressToSensitiveString(it->address) + ", Type: " +
632 net::NetworkChangeNotifier::ConnectionTypeToString(it->type));
635 NotifyLoggingStarted(callback);
638 void WebRtcLoggingHandlerHost::NotifyLoggingStarted(
639 const GenericDoneCallback& callback) {
640 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
641 DCHECK_EQ(logging_state_, STARTING);
642 Send(new WebRtcLoggingMsg_StartLogging());
643 logging_started_time_ = base::Time::Now();
644 logging_state_ = STARTED;
645 FireGenericDoneCallback(callback, true, "");
648 void WebRtcLoggingHandlerHost::LogToCircularBuffer(const std::string& message) {
649 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
650 DCHECK_NE(logging_state_, CLOSED);
651 log_buffer_->Log(message);
654 base::FilePath WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists() {
655 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
656 base::FilePath log_dir_path =
657 WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath());
658 base::File::Error error;
659 if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) {
660 DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error;
661 return base::FilePath();
663 return log_dir_path;
666 void WebRtcLoggingHandlerHost::TriggerUpload(
667 const UploadDoneCallback& callback,
668 const base::FilePath& log_directory) {
669 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
671 if (rtp_dump_handler_) {
672 BrowserThread::PostTask(
673 BrowserThread::UI,
674 FROM_HERE,
675 base::Bind(stop_rtp_dump_callback_, true, true));
677 rtp_dump_handler_->StopOngoingDumps(
678 base::Bind(&WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps,
679 this,
680 log_directory,
681 callback));
682 return;
685 DoUploadLogAndRtpDumps(log_directory, callback);
688 void WebRtcLoggingHandlerHost::StoreLogInDirectory(
689 const std::string& log_id,
690 scoped_ptr<WebRtcLogPaths> log_paths,
691 const GenericDoneCallback& done_callback,
692 const base::FilePath& directory) {
693 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
694 log_paths->log_path = directory;
696 log_buffer_->SetComplete();
697 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
698 base::Bind(&WebRtcLogUploader::LoggingStoppedDoStore,
699 base::Unretained(g_browser_process->webrtc_log_uploader()),
700 *log_paths.get(), log_id, Passed(&log_buffer_), Passed(&meta_data_),
701 done_callback));
703 logging_state_ = CLOSED;
706 void WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps(
707 const base::FilePath& log_directory,
708 const UploadDoneCallback& callback) {
709 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
711 WebRtcLogUploadDoneData upload_done_data;
712 upload_done_data.log_path = log_directory;
713 upload_done_data.callback = callback;
714 upload_done_data.host = this;
715 ReleaseRtpDumps(&upload_done_data);
717 log_buffer_->SetComplete();
718 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
719 &WebRtcLogUploader::LoggingStoppedDoUpload,
720 base::Unretained(g_browser_process->webrtc_log_uploader()),
721 Passed(&log_buffer_),
722 Passed(&meta_data_),
723 upload_done_data));
725 logging_state_ = CLOSED;
728 void WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart(
729 RtpDumpType type,
730 const GenericDoneCallback& callback,
731 const base::FilePath& dump_dir) {
732 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
734 // |rtp_dump_handler_| may be non-NULL if StartRtpDump is called again before
735 // GetLogDirectoryAndEnsureExists returns on the FILE thread for a previous
736 // StartRtpDump.
737 if (!rtp_dump_handler_)
738 rtp_dump_handler_.reset(new WebRtcRtpDumpHandler(dump_dir));
740 DoStartRtpDump(type, callback);
743 void WebRtcLoggingHandlerHost::DoStartRtpDump(
744 RtpDumpType type, const GenericDoneCallback& callback) {
745 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
746 DCHECK(rtp_dump_handler_);
748 std::string error;
749 bool result = rtp_dump_handler_->StartDump(type, &error);
750 FireGenericDoneCallback(callback, result, error);
753 bool WebRtcLoggingHandlerHost::ReleaseRtpDumps(WebRtcLogPaths* log_paths) {
754 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
755 DCHECK(log_paths);
757 if (!rtp_dump_handler_)
758 return false;
760 WebRtcRtpDumpHandler::ReleasedDumps rtp_dumps(
761 rtp_dump_handler_->ReleaseDumps());
762 log_paths->incoming_rtp_dump = rtp_dumps.incoming_dump_path;
763 log_paths->outgoing_rtp_dump = rtp_dumps.outgoing_dump_path;
765 rtp_dump_handler_.reset();
766 stop_rtp_dump_callback_.Reset();
768 return true;