| 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 |