| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/renderer_host/media/audio_input_renderer_host.h" | 5 #include "content/browser/renderer_host/media/audio_input_renderer_host.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/files/file.h" |
| 9 #include "base/memory/ref_counted.h" |
| 8 #include "base/memory/shared_memory.h" | 10 #include "base/memory/shared_memory.h" |
| 9 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 10 #include "base/numerics/safe_math.h" | 12 #include "base/numerics/safe_math.h" |
| 11 #include "base/process/process.h" | 13 #include "base/process/process.h" |
| 14 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 13 #include "content/browser/media/capture/web_contents_audio_input_stream.h" | 16 #include "content/browser/media/capture/web_contents_audio_input_stream.h" |
| 14 #include "content/browser/media/capture/web_contents_capture_util.h" | 17 #include "content/browser/media/capture/web_contents_capture_util.h" |
| 15 #include "content/browser/media/media_internals.h" | 18 #include "content/browser/media/media_internals.h" |
| 19 #include "content/browser/media/webrtc_internals.h" |
| 20 #include "content/browser/renderer_host/media/audio_input_debug_writer.h" |
| 16 #include "content/browser/renderer_host/media/audio_input_device_manager.h" | 21 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
| 17 #include "content/browser/renderer_host/media/audio_input_sync_writer.h" | 22 #include "content/browser/renderer_host/media/audio_input_sync_writer.h" |
| 18 #include "content/browser/renderer_host/media/media_stream_manager.h" | 23 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 19 #include "media/audio/audio_manager_base.h" | 24 #include "media/audio/audio_manager_base.h" |
| 20 #include "media/base/audio_bus.h" | 25 #include "media/base/audio_bus.h" |
| 21 | 26 |
| 27 namespace content { |
| 28 |
| 22 namespace { | 29 namespace { |
| 23 | 30 |
| 31 #ifdef ENABLE_WEBRTC |
| 32 const base::FilePath::CharType kDebugRecordingFileNameAddition[] = |
| 33 FILE_PATH_LITERAL("source_input"); |
| 34 const base::FilePath::CharType kDebugRecordingFileNameExtension[] = |
| 35 FILE_PATH_LITERAL("pcm"); |
| 36 #endif |
| 37 |
| 24 void LogMessage(int stream_id, const std::string& msg, bool add_prefix) { | 38 void LogMessage(int stream_id, const std::string& msg, bool add_prefix) { |
| 25 std::ostringstream oss; | 39 std::ostringstream oss; |
| 26 oss << "[stream_id=" << stream_id << "] "; | 40 oss << "[stream_id=" << stream_id << "] "; |
| 27 if (add_prefix) | 41 if (add_prefix) |
| 28 oss << "AIRH::"; | 42 oss << "AIRH::"; |
| 29 oss << msg; | 43 oss << msg; |
| 30 content::MediaStreamManager::SendMessageToNativeLog(oss.str()); | 44 content::MediaStreamManager::SendMessageToNativeLog(oss.str()); |
| 31 DVLOG(1) << oss.str(); | 45 DVLOG(1) << oss.str(); |
| 32 } | 46 } |
| 33 | 47 |
| 48 #ifdef ENABLE_WEBRTC |
| 49 base::File CreateDebugRecordingFile(base::FilePath file_path) { |
| 50 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 51 base::File recording_file( |
| 52 file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND); |
| 53 PLOG_IF(ERROR, !recording_file.IsValid()) |
| 54 << "Could not open debug recording file, error=" |
| 55 << recording_file.error_details(); |
| 56 return recording_file.Pass(); |
| 57 } |
| 58 |
| 59 void CloseFile(base::File file) { |
| 60 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 61 // |file| must be closed and destroyed on FILE thread. |
| 62 } |
| 63 |
| 64 void DeleteInputDebugWriterOnFileThread( |
| 65 scoped_ptr<AudioInputDebugWriter> writer) { |
| 66 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 67 // |writer| must be closed and destroyed on FILE thread. |
| 68 } |
| 69 #endif // ENABLE_WEBRTC |
| 70 |
| 34 } // namespace | 71 } // namespace |
| 35 | 72 |
| 36 namespace content { | |
| 37 | |
| 38 struct AudioInputRendererHost::AudioEntry { | 73 struct AudioInputRendererHost::AudioEntry { |
| 39 AudioEntry(); | 74 AudioEntry(); |
| 40 ~AudioEntry(); | 75 ~AudioEntry(); |
| 41 | 76 |
| 42 // The AudioInputController that manages the audio input stream. | 77 // The AudioInputController that manages the audio input stream. |
| 43 scoped_refptr<media::AudioInputController> controller; | 78 scoped_refptr<media::AudioInputController> controller; |
| 44 | 79 |
| 45 // The audio input stream ID in the render view. | 80 // The audio input stream ID in the render view. |
| 46 int stream_id; | 81 int stream_id; |
| 47 | 82 |
| 48 // Shared memory for transmission of the audio data. It has | 83 // Shared memory for transmission of the audio data. It has |
| 49 // |shared_memory_segment_count| equal lengthed segments. | 84 // |shared_memory_segment_count| equal lengthed segments. |
| 50 base::SharedMemory shared_memory; | 85 base::SharedMemory shared_memory; |
| 51 int shared_memory_segment_count; | 86 int shared_memory_segment_count; |
| 52 | 87 |
| 53 // The synchronous writer to be used by the controller. We have the | 88 // The synchronous writer to be used by the controller. We have the |
| 54 // ownership of the writer. | 89 // ownership of the writer. |
| 55 scoped_ptr<media::AudioInputController::SyncWriter> writer; | 90 scoped_ptr<media::AudioInputController::SyncWriter> writer; |
| 56 | 91 |
| 92 // Must be deleted on the file thread. Must be posted for deletion and nulled |
| 93 // before the AudioEntry is deleted. |
| 94 scoped_ptr<AudioInputDebugWriter> input_debug_writer; |
| 95 |
| 57 // Set to true after we called Close() for the controller. | 96 // Set to true after we called Close() for the controller. |
| 58 bool pending_close; | 97 bool pending_close; |
| 59 | 98 |
| 60 // If this entry's layout has a keyboard mic channel. | 99 // If this entry's layout has a keyboard mic channel. |
| 61 bool has_keyboard_mic_; | 100 bool has_keyboard_mic; |
| 62 }; | 101 }; |
| 63 | 102 |
| 64 AudioInputRendererHost::AudioEntry::AudioEntry() | 103 AudioInputRendererHost::AudioEntry::AudioEntry() |
| 65 : stream_id(0), | 104 : stream_id(0), |
| 66 shared_memory_segment_count(0), | 105 shared_memory_segment_count(0), |
| 67 pending_close(false), | 106 pending_close(false), |
| 68 has_keyboard_mic_(false) { | 107 has_keyboard_mic(false) { |
| 69 } | 108 } |
| 70 | 109 |
| 71 AudioInputRendererHost::AudioEntry::~AudioEntry() {} | 110 AudioInputRendererHost::AudioEntry::~AudioEntry() { |
| 111 DCHECK(!input_debug_writer.get()); |
| 112 } |
| 72 | 113 |
| 73 AudioInputRendererHost::AudioInputRendererHost( | 114 AudioInputRendererHost::AudioInputRendererHost( |
| 74 int render_process_id, | 115 int render_process_id, |
| 116 int32 renderer_pid, |
| 75 media::AudioManager* audio_manager, | 117 media::AudioManager* audio_manager, |
| 76 MediaStreamManager* media_stream_manager, | 118 MediaStreamManager* media_stream_manager, |
| 77 AudioMirroringManager* audio_mirroring_manager, | 119 AudioMirroringManager* audio_mirroring_manager, |
| 78 media::UserInputMonitor* user_input_monitor) | 120 media::UserInputMonitor* user_input_monitor) |
| 79 : BrowserMessageFilter(AudioMsgStart), | 121 : BrowserMessageFilter(AudioMsgStart), |
| 80 render_process_id_(render_process_id), | 122 render_process_id_(render_process_id), |
| 123 renderer_pid_(renderer_pid), |
| 81 audio_manager_(audio_manager), | 124 audio_manager_(audio_manager), |
| 82 media_stream_manager_(media_stream_manager), | 125 media_stream_manager_(media_stream_manager), |
| 83 audio_mirroring_manager_(audio_mirroring_manager), | 126 audio_mirroring_manager_(audio_mirroring_manager), |
| 84 user_input_monitor_(user_input_monitor), | 127 user_input_monitor_(user_input_monitor), |
| 85 audio_log_(MediaInternals::GetInstance()->CreateAudioLog( | 128 audio_log_(MediaInternals::GetInstance()->CreateAudioLog( |
| 86 media::AudioLogFactory::AUDIO_INPUT_CONTROLLER)) {} | 129 media::AudioLogFactory::AUDIO_INPUT_CONTROLLER)), |
| 130 weak_factory_(this) {} |
| 87 | 131 |
| 88 AudioInputRendererHost::~AudioInputRendererHost() { | 132 AudioInputRendererHost::~AudioInputRendererHost() { |
| 89 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 133 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 90 DCHECK(audio_entries_.empty()); | 134 DCHECK(audio_entries_.empty()); |
| 91 } | 135 } |
| 92 | 136 |
| 137 #ifdef ENABLE_WEBRTC |
| 138 void AudioInputRendererHost::EnableDebugRecording(const base::FilePath& file) { |
| 139 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 140 base::FilePath file_with_extensions = |
| 141 GetDebugRecordingFilePathWithExtensions(file); |
| 142 for (const auto& entry : audio_entries_) |
| 143 EnableDebugRecordingForId(file_with_extensions, entry.first); |
| 144 } |
| 145 |
| 146 void AudioInputRendererHost::DisableDebugRecording() { |
| 147 for (const auto& entry : audio_entries_) { |
| 148 entry.second->controller->DisableDebugRecording( |
| 149 base::Bind(&AudioInputRendererHost::DeleteDebugWriter, |
| 150 this, |
| 151 entry.first)); |
| 152 } |
| 153 } |
| 154 #endif // ENABLE_WEBRTC |
| 155 |
| 93 void AudioInputRendererHost::OnChannelClosing() { | 156 void AudioInputRendererHost::OnChannelClosing() { |
| 94 // Since the IPC sender is gone, close all requested audio streams. | 157 // Since the IPC sender is gone, close all requested audio streams. |
| 95 DeleteEntries(); | 158 DeleteEntries(); |
| 96 } | 159 } |
| 97 | 160 |
| 98 void AudioInputRendererHost::OnDestruct() const { | 161 void AudioInputRendererHost::OnDestruct() const { |
| 99 BrowserThread::DeleteOnIOThread::Destruct(this); | 162 BrowserThread::DeleteOnIOThread::Destruct(this); |
| 100 } | 163 } |
| 101 | 164 |
| 102 void AudioInputRendererHost::OnCreated( | 165 void AudioInputRendererHost::OnCreated( |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 void AudioInputRendererHost::OnLog(media::AudioInputController* controller, | 204 void AudioInputRendererHost::OnLog(media::AudioInputController* controller, |
| 142 const std::string& message) { | 205 const std::string& message) { |
| 143 BrowserThread::PostTask(BrowserThread::IO, | 206 BrowserThread::PostTask(BrowserThread::IO, |
| 144 FROM_HERE, | 207 FROM_HERE, |
| 145 base::Bind(&AudioInputRendererHost::DoLog, | 208 base::Bind(&AudioInputRendererHost::DoLog, |
| 146 this, | 209 this, |
| 147 make_scoped_refptr(controller), | 210 make_scoped_refptr(controller), |
| 148 message)); | 211 message)); |
| 149 } | 212 } |
| 150 | 213 |
| 214 void AudioInputRendererHost::set_renderer_pid(int32 renderer_pid) { |
| 215 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 216 renderer_pid_ = renderer_pid; |
| 217 } |
| 218 |
| 151 void AudioInputRendererHost::DoCompleteCreation( | 219 void AudioInputRendererHost::DoCompleteCreation( |
| 152 media::AudioInputController* controller) { | 220 media::AudioInputController* controller) { |
| 153 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 221 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 154 | 222 |
| 155 AudioEntry* entry = LookupByController(controller); | 223 AudioEntry* entry = LookupByController(controller); |
| 156 if (!entry) { | 224 if (!entry) { |
| 157 NOTREACHED() << "AudioInputController is invalid."; | 225 NOTREACHED() << "AudioInputController is invalid."; |
| 158 return; | 226 return; |
| 159 } | 227 } |
| 160 | 228 |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 | 470 |
| 403 if (!entry->controller.get()) { | 471 if (!entry->controller.get()) { |
| 404 SendErrorMessage(stream_id, STREAM_CREATE_ERROR); | 472 SendErrorMessage(stream_id, STREAM_CREATE_ERROR); |
| 405 MaybeUnregisterKeyboardMicStream(config); | 473 MaybeUnregisterKeyboardMicStream(config); |
| 406 return; | 474 return; |
| 407 } | 475 } |
| 408 | 476 |
| 409 #if defined(OS_CHROMEOS) | 477 #if defined(OS_CHROMEOS) |
| 410 if (config.params.channel_layout() == | 478 if (config.params.channel_layout() == |
| 411 media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { | 479 media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { |
| 412 entry->has_keyboard_mic_ = true; | 480 entry->has_keyboard_mic = true; |
| 413 } | 481 } |
| 414 #endif | 482 #endif |
| 415 | 483 |
| 416 MediaStreamManager::SendMessageToNativeLog(oss.str()); | 484 MediaStreamManager::SendMessageToNativeLog(oss.str()); |
| 417 DVLOG(1) << oss.str(); | 485 DVLOG(1) << oss.str(); |
| 418 | 486 |
| 419 // Since the controller was created successfully, create an entry and add it | 487 // Since the controller was created successfully, create an entry and add it |
| 420 // to the map. | 488 // to the map. |
| 421 entry->stream_id = stream_id; | 489 entry->stream_id = stream_id; |
| 422 audio_entries_.insert(std::make_pair(stream_id, entry.release())); | 490 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
| 423 audio_log_->OnCreated(stream_id, audio_params, device_id); | 491 audio_log_->OnCreated(stream_id, audio_params, device_id); |
| 424 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( | 492 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( |
| 425 stream_id, render_process_id_, render_frame_id, audio_log_.get()); | 493 stream_id, render_process_id_, render_frame_id, audio_log_.get()); |
| 494 |
| 495 #if defined(ENABLE_WEBRTC) |
| 496 BrowserThread::PostTask( |
| 497 BrowserThread::UI, |
| 498 FROM_HERE, |
| 499 base::Bind( |
| 500 &AudioInputRendererHost::MaybeEnableDebugRecordingForId, |
| 501 this, |
| 502 stream_id)); |
| 503 #endif |
| 426 } | 504 } |
| 427 | 505 |
| 428 void AudioInputRendererHost::OnRecordStream(int stream_id) { | 506 void AudioInputRendererHost::OnRecordStream(int stream_id) { |
| 429 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 507 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 430 LogMessage(stream_id, "OnRecordStream", true); | 508 LogMessage(stream_id, "OnRecordStream", true); |
| 431 | 509 |
| 432 AudioEntry* entry = LookupById(stream_id); | 510 AudioEntry* entry = LookupById(stream_id); |
| 433 if (!entry) { | 511 if (!entry) { |
| 434 SendErrorMessage(stream_id, INVALID_AUDIO_ENTRY); | 512 SendErrorMessage(stream_id, INVALID_AUDIO_ENTRY); |
| 435 return; | 513 return; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 entry->pending_close = true; | 569 entry->pending_close = true; |
| 492 audio_log_->OnClosed(entry->stream_id); | 570 audio_log_->OnClosed(entry->stream_id); |
| 493 } | 571 } |
| 494 } | 572 } |
| 495 | 573 |
| 496 void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) { | 574 void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) { |
| 497 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 575 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 498 LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true); | 576 LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true); |
| 499 | 577 |
| 500 #if defined(OS_CHROMEOS) | 578 #if defined(OS_CHROMEOS) |
| 501 if (entry->has_keyboard_mic_) { | 579 if (entry->has_keyboard_mic) { |
| 502 media_stream_manager_->audio_input_device_manager() | 580 media_stream_manager_->audio_input_device_manager() |
| 503 ->UnregisterKeyboardMicStream(); | 581 ->UnregisterKeyboardMicStream(); |
| 504 } | 582 } |
| 505 #endif | 583 #endif |
| 506 | 584 |
| 585 #if defined(ENABLE_WEBRTC) |
| 586 if (entry->input_debug_writer.get()) { |
| 587 BrowserThread::PostTask( |
| 588 BrowserThread::FILE, |
| 589 FROM_HERE, |
| 590 base::Bind(&DeleteInputDebugWriterOnFileThread, |
| 591 base::Passed(entry->input_debug_writer.Pass()))); |
| 592 } |
| 593 #endif |
| 594 |
| 507 // Delete the entry when this method goes out of scope. | 595 // Delete the entry when this method goes out of scope. |
| 508 scoped_ptr<AudioEntry> entry_deleter(entry); | 596 scoped_ptr<AudioEntry> entry_deleter(entry); |
| 509 | 597 |
| 510 // Erase the entry from the map. | 598 // Erase the entry from the map. |
| 511 audio_entries_.erase(entry->stream_id); | 599 audio_entries_.erase(entry->stream_id); |
| 512 } | 600 } |
| 513 | 601 |
| 514 void AudioInputRendererHost::DeleteEntryOnError(AudioEntry* entry, | 602 void AudioInputRendererHost::DeleteEntryOnError(AudioEntry* entry, |
| 515 ErrorCode error_code) { | 603 ErrorCode error_code) { |
| 516 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 604 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 const AudioInputHostMsg_CreateStream_Config& config) { | 637 const AudioInputHostMsg_CreateStream_Config& config) { |
| 550 #if defined(OS_CHROMEOS) | 638 #if defined(OS_CHROMEOS) |
| 551 if (config.params.channel_layout() == | 639 if (config.params.channel_layout() == |
| 552 media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { | 640 media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { |
| 553 media_stream_manager_->audio_input_device_manager() | 641 media_stream_manager_->audio_input_device_manager() |
| 554 ->UnregisterKeyboardMicStream(); | 642 ->UnregisterKeyboardMicStream(); |
| 555 } | 643 } |
| 556 #endif | 644 #endif |
| 557 } | 645 } |
| 558 | 646 |
| 647 #if defined(ENABLE_WEBRTC) |
| 648 void AudioInputRendererHost::MaybeEnableDebugRecordingForId(int stream_id) { |
| 649 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 650 if (WebRTCInternals::GetInstance()->IsAudioDebugRecordingsEnabled()) { |
| 651 BrowserThread::PostTask( |
| 652 BrowserThread::IO, |
| 653 FROM_HERE, |
| 654 base::Bind( |
| 655 &AudioInputRendererHost::EnableDebugRecordingForId, |
| 656 this, |
| 657 GetDebugRecordingFilePathWithExtensions( |
| 658 WebRTCInternals::GetInstance()-> |
| 659 GetAudioDebugRecordingsFilePath()), |
| 660 stream_id)); |
| 661 } |
| 662 } |
| 663 |
| 664 #if defined(OS_WIN) |
| 665 #define IntToStringType base::IntToString16 |
| 666 #else |
| 667 #define IntToStringType base::IntToString |
| 668 #endif |
| 669 |
| 670 base::FilePath AudioInputRendererHost::GetDebugRecordingFilePathWithExtensions( |
| 671 const base::FilePath& file) { |
| 672 return file.AddExtension(IntToStringType(renderer_pid_)) |
| 673 .AddExtension(kDebugRecordingFileNameAddition); |
| 674 } |
| 675 |
| 676 void AudioInputRendererHost::EnableDebugRecordingForId( |
| 677 const base::FilePath& file, |
| 678 int stream_id) { |
| 679 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 680 BrowserThread::PostTaskAndReplyWithResult( |
| 681 BrowserThread::FILE, |
| 682 FROM_HERE, |
| 683 base::Bind( |
| 684 &CreateDebugRecordingFile, |
| 685 file.AddExtension(IntToStringType(stream_id)) |
| 686 .AddExtension(kDebugRecordingFileNameExtension)), |
| 687 base::Bind( |
| 688 &AudioInputRendererHost::DoEnableDebugRecording, |
| 689 weak_factory_.GetWeakPtr(), |
| 690 stream_id)); |
| 691 } |
| 692 |
| 693 #undef IntToStringType |
| 694 |
| 695 void AudioInputRendererHost::DoEnableDebugRecording( |
| 696 int stream_id, |
| 697 base::File file) { |
| 698 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 699 if (!file.IsValid()) |
| 700 return; |
| 701 AudioEntry* entry = LookupById(stream_id); |
| 702 if (!entry) { |
| 703 BrowserThread::PostTask( |
| 704 BrowserThread::FILE, |
| 705 FROM_HERE, |
| 706 base::Bind( |
| 707 &CloseFile, |
| 708 Passed(file.Pass()))); |
| 709 return; |
| 710 } |
| 711 entry->input_debug_writer.reset(new AudioInputDebugWriter(file.Pass())); |
| 712 entry->controller->EnableDebugRecording(entry->input_debug_writer.get()); |
| 713 } |
| 714 |
| 715 void AudioInputRendererHost::DeleteDebugWriter(int stream_id) { |
| 716 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 717 AudioEntry* entry = LookupById(stream_id); |
| 718 if (!entry) { |
| 719 // This happens if DisableDebugRecording is called right after |
| 720 // DeleteEntries. |
| 721 return; |
| 722 } |
| 723 |
| 724 if (entry->input_debug_writer.get()) { |
| 725 BrowserThread::PostTask( |
| 726 BrowserThread::FILE, |
| 727 FROM_HERE, |
| 728 base::Bind(&DeleteInputDebugWriterOnFileThread, |
| 729 base::Passed(entry->input_debug_writer.Pass()))); |
| 730 } |
| 731 } |
| 732 #endif // defined(ENABLE_WEBRTC) |
| 733 |
| 559 } // namespace content | 734 } // namespace content |
| OLD | NEW |