OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/media/webrtc_logging_handler_host.h" | 5 #include "chrome/browser/media/webrtc_logging_handler_host.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 const MetaDataMap& meta_data, | 98 const MetaDataMap& meta_data, |
99 std::string* message) { | 99 std::string* message) { |
100 for (MetaDataMap::const_iterator it = meta_data.begin(); | 100 for (MetaDataMap::const_iterator it = meta_data.begin(); |
101 it != meta_data.end(); ++it) { | 101 it != meta_data.end(); ++it) { |
102 *message += it->first + ": " + it->second + '\n'; | 102 *message += it->first + ": " + it->second + '\n'; |
103 } | 103 } |
104 // Remove last '\n'. | 104 // Remove last '\n'. |
105 message->resize(message->size() - 1); | 105 message->resize(message->size() - 1); |
106 } | 106 } |
107 | 107 |
| 108 // Returns a path name to be used as prefix for audio debug recordings files. |
| 109 base::FilePath GetAudioDebugRecordingsPrefixPath( |
| 110 const base::FilePath& directory, |
| 111 uint64_t audio_debug_recordings_id) { |
| 112 static const char kAudioDebugRecordingsFilePrefix[] = "AudioDebugRecordings."; |
| 113 return directory.AppendASCII(kAudioDebugRecordingsFilePrefix + |
| 114 base::Int64ToString(audio_debug_recordings_id)); |
| 115 } |
| 116 |
108 } // namespace | 117 } // namespace |
109 | 118 |
110 WebRtcLogBuffer::WebRtcLogBuffer() | 119 WebRtcLogBuffer::WebRtcLogBuffer() |
111 : buffer_(), | 120 : buffer_(), |
112 circular_(&buffer_[0], sizeof(buffer_), sizeof(buffer_) / 2, false), | 121 circular_(&buffer_[0], sizeof(buffer_), sizeof(buffer_) / 2, false), |
113 read_only_(false) { | 122 read_only_(false) { |
114 } | 123 } |
115 | 124 |
116 WebRtcLogBuffer::~WebRtcLogBuffer() { | 125 WebRtcLogBuffer::~WebRtcLogBuffer() { |
117 DCHECK(read_only_ || thread_checker_.CalledOnValidThread()); | 126 DCHECK(read_only_ || thread_checker_.CalledOnValidThread()); |
(...skipping 16 matching lines...) Expand all Loading... |
134 void WebRtcLogBuffer::SetComplete() { | 143 void WebRtcLogBuffer::SetComplete() { |
135 DCHECK(thread_checker_.CalledOnValidThread()); | 144 DCHECK(thread_checker_.CalledOnValidThread()); |
136 DCHECK(!read_only_) << "Already set? (programmer error)"; | 145 DCHECK(!read_only_) << "Already set? (programmer error)"; |
137 read_only_ = true; | 146 read_only_ = true; |
138 // Detach from the current thread so that we can check reads on a different | 147 // Detach from the current thread so that we can check reads on a different |
139 // thread. This is to make sure that Read()s still happen on one thread only. | 148 // thread. This is to make sure that Read()s still happen on one thread only. |
140 thread_checker_.DetachFromThread(); | 149 thread_checker_.DetachFromThread(); |
141 } | 150 } |
142 | 151 |
143 WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost( | 152 WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost( |
144 Profile* profile, WebRtcLogUploader* log_uploader) | 153 Profile* profile, |
| 154 WebRtcLogUploader* log_uploader) |
145 : BrowserMessageFilter(WebRtcLoggingMsgStart), | 155 : BrowserMessageFilter(WebRtcLoggingMsgStart), |
146 profile_(profile), | 156 profile_(profile), |
147 logging_state_(CLOSED), | 157 logging_state_(CLOSED), |
148 upload_log_on_render_close_(false), | 158 upload_log_on_render_close_(false), |
149 log_uploader_(log_uploader) { | 159 log_uploader_(log_uploader), |
| 160 is_audio_debug_recordings_in_progress_(false), |
| 161 current_audio_debug_recordings_id_(0) { |
150 DCHECK(profile_); | 162 DCHECK(profile_); |
151 DCHECK(log_uploader_); | 163 DCHECK(log_uploader_); |
152 } | 164 } |
153 | 165 |
154 WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() { | 166 WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() { |
155 // If we hit this, then we might be leaking a log reference count (see | 167 // If we hit this, then we might be leaking a log reference count (see |
156 // ApplyForStartLogging). | 168 // ApplyForStartLogging). |
157 DCHECK_EQ(CLOSED, logging_state_); | 169 DCHECK_EQ(CLOSED, logging_state_); |
158 } | 170 } |
159 | 171 |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 434 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
423 | 435 |
424 // |rtp_dump_handler_| could be NULL if we are waiting for the FILE thread to | 436 // |rtp_dump_handler_| could be NULL if we are waiting for the FILE thread to |
425 // create/ensure the log directory. | 437 // create/ensure the log directory. |
426 if (rtp_dump_handler_) { | 438 if (rtp_dump_handler_) { |
427 rtp_dump_handler_->OnRtpPacket( | 439 rtp_dump_handler_->OnRtpPacket( |
428 packet_header.get(), header_length, packet_length, incoming); | 440 packet_header.get(), header_length, packet_length, incoming); |
429 } | 441 } |
430 } | 442 } |
431 | 443 |
| 444 void WebRtcLoggingHandlerHost::StartAudioDebugRecordings( |
| 445 content::RenderProcessHost* host, |
| 446 base::TimeDelta delay, |
| 447 const AudioDebugRecordingsCallback& callback, |
| 448 const AudioDebugRecordingsErrorCallback& error_callback) { |
| 449 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 450 |
| 451 BrowserThread::PostTaskAndReplyWithResult( |
| 452 BrowserThread::FILE, FROM_HERE, |
| 453 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, |
| 454 this), |
| 455 base::Bind(&WebRtcLoggingHandlerHost::DoStartAudioDebugRecordings, this, |
| 456 host, delay, callback, error_callback)); |
| 457 } |
| 458 |
| 459 void WebRtcLoggingHandlerHost::StopAudioDebugRecordings( |
| 460 content::RenderProcessHost* host, |
| 461 const AudioDebugRecordingsCallback& callback, |
| 462 const AudioDebugRecordingsErrorCallback& error_callback) { |
| 463 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 464 BrowserThread::PostTaskAndReplyWithResult( |
| 465 BrowserThread::FILE, FROM_HERE, |
| 466 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, |
| 467 this), |
| 468 base::Bind(&WebRtcLoggingHandlerHost::DoStopAudioDebugRecordings, this, |
| 469 host, true /* manual stop */, |
| 470 current_audio_debug_recordings_id_, callback, error_callback)); |
| 471 } |
| 472 |
432 void WebRtcLoggingHandlerHost::OnChannelClosing() { | 473 void WebRtcLoggingHandlerHost::OnChannelClosing() { |
433 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 474 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
434 if (logging_state_ == STARTED || logging_state_ == STOPPED) { | 475 if (logging_state_ == STARTED || logging_state_ == STOPPED) { |
435 if (upload_log_on_render_close_) { | 476 if (upload_log_on_render_close_) { |
436 logging_started_time_ = base::Time(); | 477 logging_started_time_ = base::Time(); |
437 | 478 |
438 content::BrowserThread::PostTaskAndReplyWithResult( | 479 content::BrowserThread::PostTaskAndReplyWithResult( |
439 content::BrowserThread::FILE, | 480 content::BrowserThread::FILE, |
440 FROM_HERE, | 481 FROM_HERE, |
441 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, | 482 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
758 case STOPPED: | 799 case STOPPED: |
759 error_message_with_state += " State=stopped."; | 800 error_message_with_state += " State=stopped."; |
760 break; | 801 break; |
761 } | 802 } |
762 | 803 |
763 content::BrowserThread::PostTask( | 804 content::BrowserThread::PostTask( |
764 content::BrowserThread::UI, | 805 content::BrowserThread::UI, |
765 FROM_HERE, | 806 FROM_HERE, |
766 base::Bind(callback, success, error_message_with_state)); | 807 base::Bind(callback, success, error_message_with_state)); |
767 } | 808 } |
| 809 |
| 810 void WebRtcLoggingHandlerHost::DoStartAudioDebugRecordings( |
| 811 content::RenderProcessHost* host, |
| 812 base::TimeDelta delay, |
| 813 const AudioDebugRecordingsCallback& callback, |
| 814 const AudioDebugRecordingsErrorCallback& error_callback, |
| 815 const base::FilePath& log_directory) { |
| 816 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 817 |
| 818 if (is_audio_debug_recordings_in_progress_) { |
| 819 error_callback.Run("Audio debug recordings already in progress"); |
| 820 return; |
| 821 } |
| 822 |
| 823 is_audio_debug_recordings_in_progress_ = true; |
| 824 base::FilePath prefix_path = GetAudioDebugRecordingsPrefixPath( |
| 825 log_directory, ++current_audio_debug_recordings_id_); |
| 826 host->EnableAudioDebugRecordings(prefix_path); |
| 827 |
| 828 if (delay.is_zero()) { |
| 829 callback.Run(prefix_path.AsUTF8Unsafe(), false /* not stopped */, |
| 830 false /* not manually stopped */); |
| 831 return; |
| 832 } |
| 833 |
| 834 BrowserThread::PostTask( |
| 835 BrowserThread::UI, FROM_HERE, |
| 836 base::Bind(&WebRtcLoggingHandlerHost::DoStopAudioDebugRecordings, this, |
| 837 host, false /* no manual stop */, |
| 838 current_audio_debug_recordings_id_, callback, error_callback, |
| 839 prefix_path)); |
| 840 } |
| 841 |
| 842 void WebRtcLoggingHandlerHost::DoStopAudioDebugRecordings( |
| 843 content::RenderProcessHost* host, |
| 844 bool is_manual_stop, |
| 845 uint64_t audio_debug_recordings_id, |
| 846 const AudioDebugRecordingsCallback& callback, |
| 847 const AudioDebugRecordingsErrorCallback& error_callback, |
| 848 const base::FilePath& log_directory) { |
| 849 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 850 DCHECK_LE(audio_debug_recordings_id, current_audio_debug_recordings_id_); |
| 851 |
| 852 base::FilePath prefix_path = GetAudioDebugRecordingsPrefixPath( |
| 853 log_directory, audio_debug_recordings_id); |
| 854 // Prevent an old posted StopAudioDebugRecordings() call to stop a newer dump. |
| 855 // This could happen in a sequence like: |
| 856 // Start(10); //Start dump 1. Post Stop() to run after 10 seconds. |
| 857 // Stop(); // Manually stop dump 1 before 10 seconds; |
| 858 // Start(20); // Start dump 2. Posted Stop() for 1 should not stop dump 2. |
| 859 if (audio_debug_recordings_id < current_audio_debug_recordings_id_) { |
| 860 callback.Run(prefix_path.AsUTF8Unsafe(), false /* not stopped */, |
| 861 is_manual_stop); |
| 862 return; |
| 863 } |
| 864 |
| 865 if (!is_audio_debug_recordings_in_progress_) { |
| 866 error_callback.Run("No audio debug recording in progress"); |
| 867 return; |
| 868 } |
| 869 |
| 870 host->DisableAudioDebugRecordings(); |
| 871 is_audio_debug_recordings_in_progress_ = false; |
| 872 callback.Run(prefix_path.AsUTF8Unsafe(), true /* stopped */, is_manual_stop); |
| 873 } |
OLD | NEW |