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/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"
39 #include "base/linux_util.h"
42 #if defined(OS_MACOSX)
43 #include "base/mac/mac_util.h"
46 #if defined(OS_CHROMEOS)
47 #include "chromeos/system/statistics_provider.h"
50 using base::IntToString
;
51 using content::BrowserThread
;
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
63 std::string
IPAddressToSensitiveString(const net::IPAddressNumber
& address
) {
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
)
72 sensitive_address
.resize(find_pos
);
73 sensitive_address
+= ".x";
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
);
85 case net::ADDRESS_FAMILY_UNSPECIFIED
: {
89 return sensitive_address
;
91 return net::IPAddressToString(address
);
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';
103 message
->resize(message
->size() - 1);
106 void FireGenericDoneCallback(
107 const WebRtcLoggingHandlerHost::GenericDoneCallback
& callback
,
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
,
115 base::Bind(callback
, success
, error_message
));
118 void FireAndResetGenericDoneCallback(
119 WebRtcLoggingHandlerHost::GenericDoneCallback
* callback
,
121 const std::string
& error_message
) {
122 FireGenericDoneCallback(*callback
, success
, error_message
);
128 WebRtcLogBuffer::WebRtcLogBuffer()
130 circular_(&buffer_
[0], sizeof(buffer_
), sizeof(buffer_
) / 2, false),
134 WebRtcLogBuffer::~WebRtcLogBuffer() {
135 DCHECK(read_only_
|| thread_checker_
.CalledOnValidThread());
138 void WebRtcLogBuffer::Log(const std::string
& message
) {
139 DCHECK(thread_checker_
.CalledOnValidThread());
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());
149 return PartialCircularBuffer(&buffer_
[0], sizeof(buffer_
));
152 void WebRtcLogBuffer::SetComplete() {
153 DCHECK(thread_checker_
.CalledOnValidThread());
154 DCHECK(!read_only_
) << "Already set? (programmer error)";
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
),
164 logging_state_(CLOSED
),
165 upload_log_on_render_close_(false) {
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
);
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");
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");
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
));
240 content::BrowserThread::PostTaskAndReplyWithResult(
241 content::BrowserThread::FILE,
243 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists
,
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,
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
);
287 g_browser_process
->webrtc_log_uploader()->LoggingStoppedDontUpload();
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
);
308 if (rtp_dump_handler_
) {
309 BrowserThread::PostTask(
312 base::Bind(stop_rtp_dump_callback_
, true, true));
314 rtp_dump_handler_
->StopOngoingDumps(
315 base::Bind(&WebRtcLoggingHandlerHost::StoreLogContinue
,
316 this, log_id
, callback
));
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,
335 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists
,
337 base::Bind(&WebRtcLoggingHandlerHost::StoreLogInDirectory
, this, log_id
,
338 Passed(&log_paths
), callback
));
341 void WebRtcLoggingHandlerHost::LogMessage(const std::string
& message
) {
342 BrowserThread::PostTask(
346 &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser
,
348 WebRtcLoggingMessageData(base::Time::Now(), message
)));
351 void WebRtcLoggingHandlerHost::StartRtpDump(
353 const GenericDoneCallback
& callback
,
354 const content::RenderProcessHost::WebRtcStopRtpDumpCallback
&
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,
366 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists
,
368 base::Bind(&WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart
,
375 DoStartRtpDump(type
, callback
);
378 void WebRtcLoggingHandlerHost::StopRtpDump(
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.");
389 if (!stop_rtp_dump_callback_
.is_null()) {
390 BrowserThread::PostTask(
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
,
405 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
407 BrowserThread::PostTask(
410 base::Bind(&WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread
,
412 base::Passed(&packet_header
),
418 void WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread(
419 scoped_ptr
<uint8
[]> packet_header
,
420 size_t header_length
,
421 size_t packet_length
,
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,
442 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists
,
444 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload
, this,
445 UploadDoneCallback()));
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
);
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()
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 "
494 bad_message::ReceivedBadMessage(
495 this, bad_message::WRLHH_LOGGING_STOPPED_BAD_STATE
);
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(),
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.");
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.");
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
,
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.");
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()) {
571 FormatMetaDataAsLogMessage(*meta_data_
.get(), &info
);
572 LogToCircularBuffer(info
);
576 chrome::VersionInfo version_info
;
577 LogToCircularBuffer("Chrome version: " + version_info
.Version() + " " +
578 chrome::VersionInfo::GetVersionStringModifier());
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();