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"
10 #include "base/command_line.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"
40 #include "base/linux_util.h"
43 #if defined(OS_MACOSX)
44 #include "base/mac/mac_util.h"
47 #if defined(OS_CHROMEOS)
48 #include "chromeos/system/statistics_provider.h"
51 using base::IntToString
;
52 using content::BrowserThread
;
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
64 std::string
IPAddressToSensitiveString(const net::IPAddressNumber
& address
) {
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
)
73 sensitive_address
.resize(find_pos
);
74 sensitive_address
+= ".x";
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
);
86 case net::ADDRESS_FAMILY_UNSPECIFIED
: {
90 return sensitive_address
;
92 return net::IPAddressToString(address
);
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';
104 message
->resize(message
->size() - 1);
107 void FireGenericDoneCallback(
108 const WebRtcLoggingHandlerHost::GenericDoneCallback
& callback
,
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
,
116 base::Bind(callback
, success
, error_message
));
119 void FireAndResetGenericDoneCallback(
120 WebRtcLoggingHandlerHost::GenericDoneCallback
* callback
,
122 const std::string
& error_message
) {
123 FireGenericDoneCallback(*callback
, success
, error_message
);
129 WebRtcLogBuffer::WebRtcLogBuffer()
131 circular_(&buffer_
[0], sizeof(buffer_
), sizeof(buffer_
) / 2, false),
135 WebRtcLogBuffer::~WebRtcLogBuffer() {
136 DCHECK(read_only_
|| thread_checker_
.CalledOnValidThread());
139 void WebRtcLogBuffer::Log(const std::string
& message
) {
140 DCHECK(thread_checker_
.CalledOnValidThread());
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());
150 return PartialCircularBuffer(&buffer_
[0], sizeof(buffer_
));
153 void WebRtcLogBuffer::SetComplete() {
154 DCHECK(thread_checker_
.CalledOnValidThread());
155 DCHECK(!read_only_
) << "Already set? (programmer error)";
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
),
165 logging_state_(CLOSED
),
166 upload_log_on_render_close_(false) {
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
);
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");
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");
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
));
241 content::BrowserThread::PostTaskAndReplyWithResult(
242 content::BrowserThread::FILE,
244 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists
,
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,
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
);
288 g_browser_process
->webrtc_log_uploader()->LoggingStoppedDontUpload();
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
);
309 if (rtp_dump_handler_
) {
310 BrowserThread::PostTask(
313 base::Bind(stop_rtp_dump_callback_
, true, true));
315 rtp_dump_handler_
->StopOngoingDumps(
316 base::Bind(&WebRtcLoggingHandlerHost::StoreLogContinue
,
317 this, log_id
, callback
));
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,
336 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists
,
338 base::Bind(&WebRtcLoggingHandlerHost::StoreLogInDirectory
, this, log_id
,
339 Passed(&log_paths
), callback
));
342 void WebRtcLoggingHandlerHost::LogMessage(const std::string
& message
) {
343 BrowserThread::PostTask(
347 &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser
,
349 WebRtcLoggingMessageData(base::Time::Now(), message
)));
352 void WebRtcLoggingHandlerHost::StartRtpDump(
354 const GenericDoneCallback
& callback
,
355 const content::RenderProcessHost::WebRtcStopRtpDumpCallback
&
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,
367 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists
,
369 base::Bind(&WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart
,
376 DoStartRtpDump(type
, callback
);
379 void WebRtcLoggingHandlerHost::StopRtpDump(
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.");
390 if (!stop_rtp_dump_callback_
.is_null()) {
391 BrowserThread::PostTask(
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
,
406 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
408 BrowserThread::PostTask(
411 base::Bind(&WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread
,
413 base::Passed(&packet_header
),
419 void WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread(
420 scoped_ptr
<uint8
[]> packet_header
,
421 size_t header_length
,
422 size_t packet_length
,
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,
443 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists
,
445 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload
, this,
446 UploadDoneCallback()));
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
);
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()
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 "
495 bad_message::ReceivedBadMessage(
496 this, bad_message::WRLHH_LOGGING_STOPPED_BAD_STATE
);
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(),
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.");
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.");
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
,
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.");
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()) {
572 FormatMetaDataAsLogMessage(*meta_data_
.get(), &info
);
573 LogToCircularBuffer(info
);
577 LogToCircularBuffer("Chrome version: " + version_info::GetVersionNumber() +
578 " " + chrome::GetChannelString());
581 LogToCircularBuffer(base::SysInfo::OperatingSystemName() + " " +
582 base::SysInfo::OperatingSystemVersion() + " " +
583 base::SysInfo::OperatingSystemArchitecture());
584 #if defined(OS_LINUX)
585 LogToCircularBuffer("Linux distribution: " + base::GetLinuxDistro());
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
);
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
);
611 LogToCircularBuffer("Computer model: " + computer_model
);
614 gpu::GPUInfo gpu_info
= content::GpuDataManager::GetInstance()->GetGPUInfo();
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
);
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
) {
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();
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(
678 base::Bind(stop_rtp_dump_callback_
, true, true));
680 rtp_dump_handler_
->StopOngoingDumps(
681 base::Bind(&WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps
,
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_
),
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_
),
728 logging_state_
= CLOSED
;
731 void WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart(
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
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_
);
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
);
760 if (!rtp_dump_handler_
)
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();