diff options
author | grunell@chromium.org <grunell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-31 23:58:31 +0000 |
---|---|---|
committer | grunell@chromium.org <grunell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-31 23:58:31 +0000 |
commit | 6ef98b5a0dabccfe9271697efee657316693cbee (patch) | |
tree | 7e219b96acacdbaab8c6e7d84e136a36df0a0362 /chrome | |
parent | 66d5ac0c4ff1e95e240d076c798300435891b58b (diff) | |
download | chromium_src-6ef98b5a0dabccfe9271697efee657316693cbee.zip chromium_src-6ef98b5a0dabccfe9271697efee657316693cbee.tar.gz chromium_src-6ef98b5a0dabccfe9271697efee657316693cbee.tar.bz2 |
Moving WebRTC logging related files from content to chrome.
BUG=229829
Review URL: https://chromiumcodereview.appspot.com/15741003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203516 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
19 files changed, 887 insertions, 5 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 568351e..393fec0 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -181,6 +181,10 @@ #include "chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h" #endif +#if defined(ENABLE_WEBRTC) +#include "chrome/browser/media/webrtc_logging_handler_host.h" +#endif + using base::FileDescriptor; using content::AccessTokenStore; using content::BrowserChildProcessHostIterator; @@ -723,6 +727,9 @@ void ChromeContentBrowserClient::RenderProcessHostCreated( new prerender::PrerenderMessageFilter(id, profile)); host->GetChannel()->AddFilter(new ValidationMessageMessageFilter(id)); host->GetChannel()->AddFilter(new TtsMessageFilter(id, profile)); +#if defined(ENABLE_WEBRTC) + host->GetChannel()->AddFilter(new WebRtcLoggingHandlerHost()); +#endif host->Send(new ChromeViewMsg_SetIsIncognitoProcess( profile->IsOffTheRecord())); diff --git a/chrome/browser/media/webrtc_logging_handler_host.cc b/chrome/browser/media/webrtc_logging_handler_host.cc new file mode 100644 index 0000000..c04a28a --- /dev/null +++ b/chrome/browser/media/webrtc_logging_handler_host.cc @@ -0,0 +1,66 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media/webrtc_logging_handler_host.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "chrome/common/media/webrtc_logging_messages.h" + +using content::BrowserThread; + +#if defined(OS_ANDROID) +const size_t kWebRtcLogSize = 1 * 1024 * 1024; // 1 MB +#else +const size_t kWebRtcLogSize = 6 * 1024 * 1024; // 6 MB +#endif + +WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost() { +} + +WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() { +} + +void WebRtcLoggingHandlerHost::OnChannelClosing() { + content::BrowserMessageFilter::OnChannelClosing(); +} + +void WebRtcLoggingHandlerHost::OnDestruct() const { + BrowserThread::DeleteOnIOThread::Destruct(this); +} + +bool WebRtcLoggingHandlerHost::OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(WebRtcLoggingHandlerHost, message, *message_was_ok) + IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_OpenLog, OnOpenLog) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() + + return handled; +} + +void WebRtcLoggingHandlerHost::OnOpenLog(const std::string& app_session_id, + const std::string& app_url) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK(!base::SharedMemory::IsHandleValid(shared_memory_.handle())); + + if (!shared_memory_.CreateAndMapAnonymous(kWebRtcLogSize)) { + DLOG(ERROR) << "Failed to create shared memory."; + Send(new WebRtcLoggingMsg_OpenLogFailed()); + return; + } + + base::SharedMemoryHandle foreign_memory_handle; + if (!shared_memory_.ShareToProcess(peer_handle(), + &foreign_memory_handle)) { + Send(new WebRtcLoggingMsg_OpenLogFailed()); + return; + } + + app_session_id_ = app_session_id; + app_url_ = app_url; + Send(new WebRtcLoggingMsg_LogOpened(foreign_memory_handle, kWebRtcLogSize)); +} diff --git a/chrome/browser/media/webrtc_logging_handler_host.h b/chrome/browser/media/webrtc_logging_handler_host.h new file mode 100644 index 0000000..2b735a8 --- /dev/null +++ b/chrome/browser/media/webrtc_logging_handler_host.h @@ -0,0 +1,40 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MEDIA_WEBRTC_LOGGING_HANDLER_HOST_H_ +#define CHROME_BROWSER_MEDIA_WEBRTC_LOGGING_HANDLER_HOST_H_ + +#include "base/basictypes.h" +#include "base/shared_memory.h" +#include "content/public/browser/browser_message_filter.h" + +// WebRtcLoggingHandlerHost handles operations regarding the WebRTC logging: +// opening and closing shared memory buffer that the handler in the renderer +// process writes to. +class WebRtcLoggingHandlerHost : public content::BrowserMessageFilter { + public: + WebRtcLoggingHandlerHost(); + + private: + // BrowserMessageFilter implementation. + virtual void OnChannelClosing() OVERRIDE; + virtual void OnDestruct() const OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) OVERRIDE; + + friend class content::BrowserThread; + friend class base::DeleteHelper<WebRtcLoggingHandlerHost>; + + virtual ~WebRtcLoggingHandlerHost(); + + void OnOpenLog(const std::string& app_session_id, const std::string& app_url); + + base::SharedMemory shared_memory_; + std::string app_session_id_; + std::string app_url_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcLoggingHandlerHost); +}; + +#endif // CHROME_BROWSER_MEDIA_WEBRTC_LOGGING_HANDLER_HOST_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index f6a3b1d..2c1fa67 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -973,6 +973,8 @@ 'browser/media/media_stream_devices_controller.h', 'browser/media/media_stream_infobar_delegate.cc', 'browser/media/media_stream_infobar_delegate.h', + 'browser/media/webrtc_logging_handler_host.cc', + 'browser/media/webrtc_logging_handler_host.h', 'browser/media_galleries/fileapi/filtering_file_enumerator.cc', 'browser/media_galleries/fileapi/filtering_file_enumerator.h', 'browser/media_galleries/fileapi/itunes_finder.cc', @@ -3068,11 +3070,11 @@ ['exclude', '^browser/managed_mode/'], ] }], - ['enable_webrtc==1', { - 'dependencies': [ - '../third_party/libjingle/libjingle.gyp:libjingle_webrtc', - '../third_party/libjingle/libjingle.gyp:libpeerconnection', - ], + ['enable_webrtc==0', { + 'sources!': [ + 'browser/media/webrtc_logging_handler_host.cc', + 'browser/media/webrtc_logging_handler_host.h', + ] }], ], 'target_conditions': [ diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 58c0057..429cc9c 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -352,6 +352,7 @@ 'common/mac/objc_method_swizzle.mm', 'common/mac/objc_zombie.h', 'common/mac/objc_zombie.mm', + 'common/media/webrtc_logging_messages.h', 'common/metrics/entropy_provider.cc', 'common/metrics/entropy_provider.h', 'common/metrics/metrics_log_base.cc', @@ -380,6 +381,8 @@ 'common/omaha_query_params/omaha_query_params.h', 'common/omnibox_focus_state.h', 'common/one_click_signin_messages.h', + 'common/partial_circular_buffer.cc', + 'common/partial_circular_buffer.h', 'common/pepper_flash.cc', 'common/pepper_flash.h', 'common/pref_names_util.cc', @@ -573,6 +576,11 @@ '<(DEPTH)/base/third_party/nspr/nspr.gyp:nspr', ], }], + ['enable_webrtc==0', { + 'sources!': [ + 'common/media/webrtc_logging_messages.h', + ] + }], ], 'target_conditions': [ ['OS == "ios"', { diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index 032f414..653c1e1 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi @@ -145,6 +145,10 @@ 'renderer/isolated_world_ids.h', 'renderer/loadtimes_extension_bindings.cc', 'renderer/loadtimes_extension_bindings.h', + 'renderer/media/webrtc_logging_handler_impl.cc', + 'renderer/media/webrtc_logging_handler_impl.h', + 'renderer/media/webrtc_logging_message_filter.cc', + 'renderer/media/webrtc_logging_message_filter.h', 'renderer/net/net_error_helper.cc', 'renderer/net/net_error_helper.h', 'renderer/net/predictor_queue.cc', @@ -348,6 +352,14 @@ ['exclude', '^renderer/safe_browsing/'], ], }], + ['enable_webrtc==0', { + 'sources!': [ + 'renderer/media/webrtc_logging_handler_impl.cc', + 'renderer/media/webrtc_logging_handler_impl.h', + 'renderer/media/webrtc_logging_message_filter.cc', + 'renderer/media/webrtc_logging_message_filter.h', + ], + }], ['OS=="mac"', { 'dependencies': [ '../third_party/mach_override/mach_override.gyp:mach_override', diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 915cb64..b98e7c8 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -1671,6 +1671,7 @@ 'common/multi_process_lock_unittest.cc', 'common/net/net_error_tracker_unittest.cc', 'common/net/x509_certificate_model_unittest.cc', + 'common/partial_circular_buffer_unittest.cc', 'common/pref_names_util_unittest.cc', 'common/service_process_util_unittest.cc', 'common/switch_utils_unittest.cc', @@ -1687,6 +1688,7 @@ 'renderer/extensions/json_schema_unittest.cc', 'renderer/extensions/module_system_unittest.cc', 'renderer/extensions/renderer_permissions_policy_delegate_unittest.cc', + 'renderer/media/webrtc_logging_handler_impl_unittest.cc', 'renderer/net/predictor_queue_unittest.cc', 'renderer/net/renderer_predictor_unittest.cc', 'renderer/plugins/plugin_uma_unittest.cc', @@ -2049,6 +2051,11 @@ 'browser/ui/startup/session_crashed_infobar_delegate_unittest.cc', ], }], + ['enable_webrtc==0', { + 'sources!': [ + 'renderer/media/webrtc_logging_handler_impl_unittest.cc', + ], + }], ['chromeos==1', { 'sources!': [ 'browser/password_manager/native_backend_gnome_x_unittest.cc', diff --git a/chrome/common/common_message_generator.h b/chrome/common/common_message_generator.h index de8ab77..dce23eb 100644 --- a/chrome/common/common_message_generator.h +++ b/chrome/common/common_message_generator.h @@ -17,3 +17,7 @@ #include "chrome/common/spellcheck_messages.h" #include "chrome/common/tts_messages.h" #include "chrome/common/validation_message_messages.h" + +#if defined(ENABLE_WEBRTC) +#include "chrome/common/media/webrtc_logging_messages.h" +#endif diff --git a/chrome/common/media/webrtc_logging_messages.h b/chrome/common/media/webrtc_logging_messages.h new file mode 100644 index 0000000..5bcf8f9 --- /dev/null +++ b/chrome/common/media/webrtc_logging_messages.h @@ -0,0 +1,28 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// IPC messages for WebRTC logging. +// Multiply-included message file, hence no include guard. + +#include "base/shared_memory.h" +#include "ipc/ipc_message_macros.h" + +#define IPC_MESSAGE_START WebRtcLoggingMsgStart + +// Messages sent from the renderer to the browser. + +// Request to open a log. +IPC_MESSAGE_CONTROL2(WebRtcLoggingMsg_OpenLog, + std::string /* app_session_id */, + std::string /* app_url */) + +// Messages sent from the browser to the renderer. + +// Notification that a log could not be opened. +IPC_MESSAGE_CONTROL0(WebRtcLoggingMsg_OpenLogFailed) + +// Notification that a log has been opened. +IPC_MESSAGE_CONTROL2(WebRtcLoggingMsg_LogOpened, + base::SharedMemoryHandle /* handle */, + uint32 /* length */) diff --git a/chrome/common/partial_circular_buffer.cc b/chrome/common/partial_circular_buffer.cc new file mode 100644 index 0000000..f6e0b70 --- /dev/null +++ b/chrome/common/partial_circular_buffer.cc @@ -0,0 +1,162 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/partial_circular_buffer.h" + +#include <algorithm> + +#include "base/logging.h" + +namespace { + +inline uint32 Min3(uint32 a, uint32 b, uint32 c) { + return std::min(a, std::min(b, c)); +} + +} // namespace + +PartialCircularBuffer::PartialCircularBuffer(void* buffer, + uint32 buffer_size) + : buffer_data_(reinterpret_cast<BufferData*>(buffer)), + memory_buffer_size_(buffer_size), + data_size_(0), + position_(0), + total_read_(0) { + uint32 header_size = + buffer_data_->data - reinterpret_cast<uint8*>(buffer_data_); + data_size_ = memory_buffer_size_ - header_size; + + DCHECK(buffer_data_); + DCHECK_GE(memory_buffer_size_, header_size); + DCHECK_LE(buffer_data_->total_written, data_size_); + DCHECK_LT(buffer_data_->wrap_position, data_size_); + DCHECK_LT(buffer_data_->end_position, data_size_); +} + +PartialCircularBuffer::PartialCircularBuffer(void* buffer, + uint32 buffer_size, + uint32 wrap_position) + : buffer_data_(reinterpret_cast<BufferData*>(buffer)), + memory_buffer_size_(buffer_size), + data_size_(0), + position_(0), + total_read_(0) { + uint32 header_size = + buffer_data_->data - reinterpret_cast<uint8*>(buffer_data_); + data_size_ = memory_buffer_size_ - header_size; + + DCHECK(buffer_data_); + DCHECK_GE(memory_buffer_size_, header_size); + DCHECK_LT(wrap_position, data_size_); + + buffer_data_->total_written = 0; + buffer_data_->wrap_position = wrap_position; + buffer_data_->end_position = 0; +} + +uint32 PartialCircularBuffer::Read(void* buffer, uint32 buffer_size) { + DCHECK(buffer_data_); + if (total_read_ >= buffer_data_->total_written) + return 0; + + uint8* buffer_uint8 = reinterpret_cast<uint8*>(buffer); + uint32 read = 0; + + // Read from beginning part. + if (position_ < buffer_data_->wrap_position) { + uint32 to_wrap_pos = buffer_data_->wrap_position - position_; + uint32 to_eow = buffer_data_->total_written - total_read_; + uint32 to_read = Min3(buffer_size, to_wrap_pos, to_eow); + memcpy(buffer_uint8, buffer_data_->data + position_, to_read); + position_ += to_read; + total_read_ += to_read; + read += to_read; + if (position_ == buffer_data_->wrap_position && + buffer_data_->total_written == data_size_) { + // We've read all the beginning part, set the position to the middle part. + // (The second condition above checks if the wrapping part is filled, i.e. + // writing has wrapped.) + position_ = buffer_data_->end_position; + } + if (read >= buffer_size) { + DCHECK_EQ(read, buffer_size); + return read; + } + if (read >= to_eow) { + DCHECK_EQ(read, to_eow); + DCHECK_EQ(total_read_, buffer_data_->total_written); + return read; + } + } + + // Read from middle part. + DCHECK_GE(position_, buffer_data_->wrap_position); + if (position_ >= buffer_data_->end_position) { + uint32 remaining_buffer_size = buffer_size - read; + uint32 to_eof = data_size_ - position_; + uint32 to_eow = buffer_data_->total_written - total_read_; + uint32 to_read = Min3(remaining_buffer_size, to_eof, to_eow); + memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read); + position_ += to_read; + total_read_ += to_read; + read += to_read; + if (position_ == data_size_) { + // We've read all the middle part, set position to the end part. + position_ = buffer_data_->wrap_position; + } + if (read >= buffer_size) { + DCHECK_EQ(read, buffer_size); + return read; + } + if (total_read_ >= buffer_data_->total_written) { + DCHECK_EQ(total_read_, buffer_data_->total_written); + return read; + } + } + + // Read from end part. + DCHECK_GE(position_, buffer_data_->wrap_position); + DCHECK_LT(position_, buffer_data_->end_position); + uint32 remaining_buffer_size = buffer_size - read; + uint32 to_eob = buffer_data_->end_position - position_; + uint32 to_eow = buffer_data_->total_written - total_read_; + uint32 to_read = Min3(remaining_buffer_size, to_eob, to_eow); + memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read); + position_ += to_read; + total_read_ += to_read; + read += to_read; + DCHECK_LE(read, buffer_size); + DCHECK_LE(total_read_, buffer_data_->total_written); + return read; +} + +void PartialCircularBuffer::Write(const void* buffer, uint32 buffer_size) { + DCHECK(buffer_data_); + uint32 position_before_write = position_; + + uint32 to_eof = data_size_ - position_; + uint32 to_write = std::min(buffer_size, to_eof); + DoWrite(buffer_data_->data + position_, buffer, to_write); + if (position_ >= data_size_) { + DCHECK_EQ(position_, data_size_); + position_ = buffer_data_->wrap_position; + } + + if (to_write < buffer_size) { + uint32 remainder_to_write = buffer_size - to_write; + DCHECK_LT(position_, position_before_write); + DCHECK_LE(position_ + remainder_to_write, position_before_write); + DoWrite(buffer_data_->data + position_, + reinterpret_cast<const uint8*>(buffer) + to_write, + remainder_to_write); + } +} + +void PartialCircularBuffer::DoWrite(void* dest, const void* src, uint32 num) { + memcpy(dest, src, num); + position_ += num; + buffer_data_->total_written = + std::min(buffer_data_->total_written + num, data_size_); + buffer_data_->end_position = position_; +} diff --git a/chrome/common/partial_circular_buffer.h b/chrome/common/partial_circular_buffer.h new file mode 100644 index 0000000..582487c --- /dev/null +++ b/chrome/common/partial_circular_buffer.h @@ -0,0 +1,65 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_COMMON_PARTIAL_CIRCULAR_BUFFER_H_ +#define CHROME_COMMON_PARTIAL_CIRCULAR_BUFFER_H_ + +#include "base/basictypes.h" +#include "base/gtest_prod_util.h" + +// A wrapper around a memory buffer that allows circular read and write with a +// selectable wrapping position. Buffer layout (after wrap; H is header): +// ----------------------------------------------------------- +// | H | Beginning | End | Middle | +// ----------------------------------------------------------- +// ^---- Non-wrapping -----^ ^--------- Wrapping ----------^ +// The non-wrapping part is never overwritten. The wrapping part will be +// circular. The very first part is the header (see the BufferData struct +// below). It consists of the following information: +// - Length written to the buffer (not including header). +// - Wrapping position. +// - End position of buffer. (If the last byte is at x, this will be x + 1.) +// Users of wrappers around the same underlying buffer must ensure that writing +// is finished before reading is started. +class PartialCircularBuffer { + public: + // Use for reading. |buffer_size| is in bytes and must be larger than the + // header size (see above). + PartialCircularBuffer(void* buffer, uint32 buffer_size); + + // Use for writing. |buffer_size| is in bytes and must be larger than the + // header size (see above). + PartialCircularBuffer(void* buffer, + uint32 buffer_size, + uint32 wrap_position); + + uint32 Read(void* buffer, uint32 buffer_size); + void Write(const void* buffer, uint32 buffer_size); + + private: + friend class PartialCircularBufferTest; + +#pragma pack(push) +#pragma pack(4) + struct BufferData { + uint32 total_written; + uint32 wrap_position; + uint32 end_position; + uint8 data[1]; + }; +#pragma pack(pop) + + void DoWrite(void* dest, const void* src, uint32 num); + + // Used for reading and writing. + BufferData* buffer_data_; + uint32 memory_buffer_size_; + uint32 data_size_; + uint32 position_; + + // Used for reading. + uint32 total_read_; +}; + +#endif // CHROME_COMMON_PARTIAL_CIRCULAR_BUFFER_H_ diff --git a/chrome/common/partial_circular_buffer_unittest.cc b/chrome/common/partial_circular_buffer_unittest.cc new file mode 100644 index 0000000..f176e82 --- /dev/null +++ b/chrome/common/partial_circular_buffer_unittest.cc @@ -0,0 +1,134 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// The test buffer data is 52 bytes, wrap position is set to 20 (this is +// arbitrarily chosen). The total buffer size is allocated dynamically based on +// the actual header size. This gives: +// Header of some size, non-wrapping part 20 bytes, wrapping part 32 bytes. +// As input data, a 14 byte array is used and repeatedly written. It's chosen +// not to be an integer factor smaller than the wrapping part. This ensures that +// the wrapped data isn't repeated at the same position. +// Note that desipte the number of wraps (if one or more), the reference output +// data is the same since the offset at each wrap is always the same. + +#include "base/memory/scoped_ptr.h" +#include "chrome/common/partial_circular_buffer.h" +#include "testing/gtest/include/gtest/gtest.h" + +const uint32 kWrapPosition = 20; +const uint8 kInputData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; +const uint8 kOutputRefDataWrap[] = + // The 20 bytes in the non-wrapping part. + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6, + // The 32 bytes in wrapping part. + 11, 12, 13, 14, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + +class PartialCircularBufferTest : public testing::Test { + public: + PartialCircularBufferTest() { + PartialCircularBuffer::BufferData test_struct; + buffer_header_size_ = + &test_struct.data[0] - reinterpret_cast<uint8*>(&test_struct); + + buffer_.reset(new uint8[buffer_header_size_ + sizeof(kOutputRefDataWrap)]); + pcb_write_.reset(new PartialCircularBuffer( + buffer_.get(), + buffer_header_size_ + sizeof(kOutputRefDataWrap), + kWrapPosition)); + } + + void WriteToBuffer(int num) { + for (int i = 0; i < num; ++i) + pcb_write_->Write(kInputData, sizeof(kInputData)); + } + + void InitReadBuffer() { + pcb_read_.reset(new PartialCircularBuffer( + buffer_.get(), buffer_header_size_ + sizeof(kOutputRefDataWrap))); + } + + protected: + scoped_ptr<PartialCircularBuffer> pcb_write_; + scoped_ptr<PartialCircularBuffer> pcb_read_; + scoped_ptr<uint8[]> buffer_; + uint32 buffer_header_size_; + + DISALLOW_COPY_AND_ASSIGN(PartialCircularBufferTest); +}; + +TEST_F(PartialCircularBufferTest, NoWrapBeginningPartOnly) { + WriteToBuffer(1); + InitReadBuffer(); + + uint8 output_data[sizeof(kInputData)] = {0}; + EXPECT_EQ(sizeof(output_data), + pcb_read_->Read(output_data, sizeof(output_data))); + + EXPECT_EQ(0, memcmp(kInputData, output_data, sizeof(kInputData))); + + EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data))); +} + +TEST_F(PartialCircularBufferTest, NoWrapBeginningAndEndParts) { + WriteToBuffer(2); + InitReadBuffer(); + + uint8 output_data[2 * sizeof(kInputData)] = {0}; + EXPECT_EQ(sizeof(output_data), + pcb_read_->Read(output_data, sizeof(output_data))); + + const uint8 output_ref_data[2 * sizeof(kInputData)] = + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + EXPECT_EQ(0, memcmp(output_ref_data, output_data, sizeof(output_data))); + + EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data))); +} + +TEST_F(PartialCircularBufferTest, WrapOnce) { + WriteToBuffer(4); + InitReadBuffer(); + + uint8 output_data[sizeof(kOutputRefDataWrap)] = {0}; + EXPECT_EQ(sizeof(output_data), + pcb_read_->Read(output_data, sizeof(output_data))); + + EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data))); + + EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data))); +} + +TEST_F(PartialCircularBufferTest, WrapTwice) { + WriteToBuffer(7); + InitReadBuffer(); + + uint8 output_data[sizeof(kOutputRefDataWrap)] = {0}; + EXPECT_EQ(sizeof(output_data), + pcb_read_->Read(output_data, sizeof(output_data))); + + EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data))); + + EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data))); +} + +TEST_F(PartialCircularBufferTest, WrapOnceSmallerOutputBuffer) { + WriteToBuffer(4); + InitReadBuffer(); + + uint8 output_data[sizeof(kOutputRefDataWrap)] = {0}; + const uint32 size_per_read = 16; + uint32 read = 0; + for (; read + size_per_read <= sizeof(output_data); read += size_per_read) { + EXPECT_EQ(size_per_read, + pcb_read_->Read(output_data + read, size_per_read)); + } + EXPECT_EQ(sizeof(output_data) - read, + pcb_read_->Read(output_data + read, size_per_read)); + + EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data))); + + EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data))); +} diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 14c0cd0..092b48f 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -100,6 +100,10 @@ #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. +#if defined(ENABLE_WEBRTC) +#include "chrome/renderer/media/webrtc_logging_message_filter.h" +#endif + using autofill::AutofillAgent; using autofill::PasswordAutofillAgent; using autofill::PasswordGenerationManager; @@ -223,6 +227,10 @@ void ChromeContentRendererClient::RenderThreadStarted() { phishing_classifier_.reset(safe_browsing::PhishingClassifierFilter::Create()); #endif prerender_dispatcher_.reset(new prerender::PrerenderDispatcher()); +#if defined(ENABLE_WEBRTC) + webrtc_logging_message_filter_ = new WebRtcLoggingMessageFilter( + content::RenderThread::Get()->GetIOMessageLoopProxy()); +#endif RenderThread* thread = RenderThread::Get(); @@ -235,6 +243,10 @@ void ChromeContentRendererClient::RenderThreadStarted() { thread->AddObserver(visited_link_slave_.get()); thread->AddObserver(prerender_dispatcher_.get()); +#if defined(ENABLE_WEBRTC) + thread->AddFilter(webrtc_logging_message_filter_.get()); +#endif + thread->RegisterExtension(extensions_v8::ExternalExtension::Get()); thread->RegisterExtension(extensions_v8::LoadTimesExtension::Get()); diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index 02f620b..4edcfb8 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h @@ -48,6 +48,10 @@ namespace WebKit { class WebSecurityOrigin; } +#if defined(ENABLE_WEBRTC) +class WebRtcLoggingMessageFilter; +#endif + namespace chrome { class ChromeContentRendererClient : public content::ContentRendererClient { @@ -184,6 +188,9 @@ class ChromeContentRendererClient : public content::ContentRendererClient { scoped_ptr<visitedlink::VisitedLinkSlave> visited_link_slave_; scoped_ptr<safe_browsing::PhishingClassifierFilter> phishing_classifier_; scoped_ptr<prerender::PrerenderDispatcher> prerender_dispatcher_; +#if defined(ENABLE_WEBRTC) + scoped_refptr<WebRtcLoggingMessageFilter> webrtc_logging_message_filter_; +#endif }; } // namespace chrome diff --git a/chrome/renderer/media/webrtc_logging_handler_impl.cc b/chrome/renderer/media/webrtc_logging_handler_impl.cc new file mode 100644 index 0000000..b46ec73 --- /dev/null +++ b/chrome/renderer/media/webrtc_logging_handler_impl.cc @@ -0,0 +1,75 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/media/webrtc_logging_handler_impl.h" + +#include "base/logging.h" +#include "base/message_loop_proxy.h" +#include "chrome/common/partial_circular_buffer.h" +#include "chrome/renderer/media/webrtc_logging_message_filter.h" + +WebRtcLoggingHandlerImpl::WebRtcLoggingHandlerImpl( + const scoped_refptr<base::MessageLoopProxy>& io_message_loop, + WebRtcLoggingMessageFilter* message_filter) + : io_message_loop_(io_message_loop), + message_filter_(message_filter), + log_initialized_(false) { + content::InitWebRtcLoggingDelegate(this); +} + +WebRtcLoggingHandlerImpl::~WebRtcLoggingHandlerImpl() { + DCHECK(CalledOnValidThread()); +} + +void WebRtcLoggingHandlerImpl::InitLogging(const std::string& app_session_id, + const std::string& app_url) { + DCHECK(CalledOnValidThread()); + + if (!log_initialized_) { + log_initialized_ = true; + message_filter_->InitLogging(app_session_id, app_url); + } +} + +void WebRtcLoggingHandlerImpl::LogMessage(const std::string& message) { + if (!CalledOnValidThread()) { + io_message_loop_->PostTask( + FROM_HERE, base::Bind( + &WebRtcLoggingHandlerImpl::LogMessage, + base::Unretained(this), + message)); + return; + } + + if (circular_buffer_) { + circular_buffer_->Write(message.c_str(), message.length()); + const char eol = '\n'; + circular_buffer_->Write(&eol, 1); + } +} + +void WebRtcLoggingHandlerImpl::OnFilterRemoved() { + DCHECK(CalledOnValidThread()); + message_filter_ = NULL; +} + +void WebRtcLoggingHandlerImpl::OnLogOpened( + base::SharedMemoryHandle handle, + uint32 length) { + DCHECK(CalledOnValidThread()); + + shared_memory_.reset(new base::SharedMemory(handle, false)); + CHECK(shared_memory_->Map(length)); + circular_buffer_.reset( + new PartialCircularBuffer(shared_memory_->memory(), + length, + length / 2)); +} + +void WebRtcLoggingHandlerImpl::OnOpenLogFailed() { + DCHECK(CalledOnValidThread()); + DLOG(ERROR) << "Could not open log."; + // TODO(grunell): Implement. + NOTIMPLEMENTED(); +} diff --git a/chrome/renderer/media/webrtc_logging_handler_impl.h b/chrome/renderer/media/webrtc_logging_handler_impl.h new file mode 100644 index 0000000..5a98143 --- /dev/null +++ b/chrome/renderer/media/webrtc_logging_handler_impl.h @@ -0,0 +1,56 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_MEDIA_WEBRTC_LOGGING_HANDLER_IMPL_H_ +#define CHROME_RENDERER_MEDIA_WEBRTC_LOGGING_HANDLER_IMPL_H_ + +#include <string> + +#include "base/shared_memory.h" +#include "content/public/renderer/webrtc_log_message_delegate.h" +#include "ipc/ipc_channel_proxy.h" + +namespace base { +class MessageLoopProxy; +} + +class PartialCircularBuffer; +class WebRtcLoggingMessageFilter; + +// WebRtcLoggingHandlerImpl handles WebRTC logging. There is one object per +// render process, owned by WebRtcLoggingMessageFilter. It communicates with +// WebRtcLoggingHandlerHost and receives logging messages from libjingle and +// writes them to a shared memory buffer. +class WebRtcLoggingHandlerImpl + : public content::WebRtcLogMessageDelegate, + public base::NonThreadSafe { + public: + WebRtcLoggingHandlerImpl( + const scoped_refptr<base::MessageLoopProxy>& io_message_loop, + WebRtcLoggingMessageFilter* message_filter); + + virtual ~WebRtcLoggingHandlerImpl(); + + // content::WebRtcLogMessageDelegate implementation. + virtual void InitLogging(const std::string& app_session_id, + const std::string& app_url) OVERRIDE; + virtual void LogMessage(const std::string& message) OVERRIDE; + + void OnFilterRemoved(); + + void OnLogOpened(base::SharedMemoryHandle handle, uint32 length); + void OnOpenLogFailed(); + + private: + scoped_refptr<base::MessageLoopProxy> io_message_loop_; + scoped_ptr<base::SharedMemory> shared_memory_; + scoped_ptr<PartialCircularBuffer> circular_buffer_; + + WebRtcLoggingMessageFilter* message_filter_; + bool log_initialized_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcLoggingHandlerImpl); +}; + +#endif // CHROME_RENDERER_MEDIA_WEBRTC_LOGGING_HANDLER_IMPL_H_ diff --git a/chrome/renderer/media/webrtc_logging_handler_impl_unittest.cc b/chrome/renderer/media/webrtc_logging_handler_impl_unittest.cc new file mode 100644 index 0000000..b12f622 --- /dev/null +++ b/chrome/renderer/media/webrtc_logging_handler_impl_unittest.cc @@ -0,0 +1,46 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "base/process_util.h" +#include "chrome/common/partial_circular_buffer.h" +#include "chrome/renderer/media/webrtc_logging_handler_impl.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(WebRtcLoggingHandlerImplTest, Basic) { + const uint32 kTestLogSize = 1024; // 1 KB + const char kTestString[] = "abcdefghijklmnopqrstuvwxyz"; + + base::MessageLoop message_loop(base::MessageLoop::TYPE_IO); + + scoped_ptr<WebRtcLoggingHandlerImpl> logging_handler( + new WebRtcLoggingHandlerImpl(message_loop.message_loop_proxy(), NULL)); + + base::SharedMemory shared_memory; + ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kTestLogSize)); + base::SharedMemoryHandle new_handle; + ASSERT_TRUE(shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), + &new_handle)); + logging_handler->OnLogOpened(new_handle, kTestLogSize); + + logging_handler->LogMessage(kTestString); + logging_handler->LogMessage(kTestString); + + PartialCircularBuffer read_pcb( + reinterpret_cast<uint8*>(shared_memory.memory()), kTestLogSize); + + // Size is calculated as (sizeof(kTestString) - 1 for terminating null + // + 1 for eol added for each log message in LogMessage) * 2 + 1 for + // terminating null. + char read_buffer[sizeof(kTestString) * 2 + 1] = {0}; + + uint32 read = read_pcb.Read(read_buffer, sizeof(read_buffer)); + EXPECT_EQ(sizeof(read_buffer) - 1, read); + std::string ref_output = kTestString; + ref_output.append("\n"); + ref_output.append(kTestString); + ref_output.append("\n"); + EXPECT_STREQ(ref_output.c_str(), read_buffer); +} diff --git a/chrome/renderer/media/webrtc_logging_message_filter.cc b/chrome/renderer/media/webrtc_logging_message_filter.cc new file mode 100644 index 0000000..f12c695 --- /dev/null +++ b/chrome/renderer/media/webrtc_logging_message_filter.cc @@ -0,0 +1,88 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/media/webrtc_logging_message_filter.h" + +#include "base/logging.h" +#include "base/message_loop_proxy.h" +#include "chrome/common/media/webrtc_logging_messages.h" +#include "chrome/renderer/media/webrtc_logging_handler_impl.h" +#include "ipc/ipc_logging.h" + +WebRtcLoggingMessageFilter::WebRtcLoggingMessageFilter( + const scoped_refptr<base::MessageLoopProxy>& io_message_loop) + : logging_handler_(NULL), + io_message_loop_(io_message_loop), + channel_(NULL) { + io_message_loop_->PostTask( + FROM_HERE, base::Bind( + &WebRtcLoggingMessageFilter::CreateLoggingHandler, + base::Unretained(this))); +} + +WebRtcLoggingMessageFilter::~WebRtcLoggingMessageFilter() { +} + +bool WebRtcLoggingMessageFilter::OnMessageReceived( + const IPC::Message& message) { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(WebRtcLoggingMessageFilter, message) + IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_LogOpened, OnLogOpened) + IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_OpenLogFailed, OnOpenLogFailed) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void WebRtcLoggingMessageFilter::OnFilterAdded(IPC::Channel* channel) { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + channel_ = channel; +} + +void WebRtcLoggingMessageFilter::OnFilterRemoved() { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + channel_ = NULL; + logging_handler_->OnFilterRemoved(); +} + +void WebRtcLoggingMessageFilter::OnChannelClosing() { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + channel_ = NULL; + logging_handler_->OnFilterRemoved(); +} + +void WebRtcLoggingMessageFilter::InitLogging( + const std::string& app_session_id, + const std::string& app_url) { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + Send(new WebRtcLoggingMsg_OpenLog(app_session_id, app_url)); +} + +void WebRtcLoggingMessageFilter::CreateLoggingHandler() { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + logging_handler_ = new WebRtcLoggingHandlerImpl(io_message_loop_, this); +} + +void WebRtcLoggingMessageFilter::OnLogOpened( + base::SharedMemoryHandle handle, + uint32 length) { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + logging_handler_->OnLogOpened(handle, length); +} + +void WebRtcLoggingMessageFilter::OnOpenLogFailed() { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + logging_handler_->OnOpenLogFailed(); +} + +void WebRtcLoggingMessageFilter::Send(IPC::Message* message) { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + if (!channel_) { + DLOG(ERROR) << "IPC channel not available."; + delete message; + } else { + channel_->Send(message); + } +} diff --git a/chrome/renderer/media/webrtc_logging_message_filter.h b/chrome/renderer/media/webrtc_logging_message_filter.h new file mode 100644 index 0000000..4466a1cd --- /dev/null +++ b/chrome/renderer/media/webrtc_logging_message_filter.h @@ -0,0 +1,63 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_MEDIA_WEBRTC_LOGGING_MESSAGE_FILTER_H_ +#define CHROME_RENDERER_MEDIA_WEBRTC_LOGGING_MESSAGE_FILTER_H_ + +#include "base/shared_memory.h" +#include "ipc/ipc_channel_proxy.h" + +namespace base { +class MessageLoopProxy; +} + +class WebRtcLoggingHandlerImpl; + +// Filter for WebRTC logging messages. Sits between WebRtcLoggingHandlerImpl +// (renderer process) and WebRtcLoggingHandlerHost (browser process). Must be +// called on the IO thread. +class WebRtcLoggingMessageFilter + : public IPC::ChannelProxy::MessageFilter { + public: + explicit WebRtcLoggingMessageFilter( + const scoped_refptr<base::MessageLoopProxy>& io_message_loop); + + virtual void InitLogging(const std::string& app_session_id, + const std::string& app_url); + + const scoped_refptr<base::MessageLoopProxy>& io_message_loop() { + return io_message_loop_; + } + + protected: + virtual ~WebRtcLoggingMessageFilter(); + + private: + // IPC::ChannelProxy::MessageFilter implementation. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE; + virtual void OnFilterRemoved() OVERRIDE; + virtual void OnChannelClosing() OVERRIDE; + + void CreateLoggingHandler(); + + void OnLogOpened(base::SharedMemoryHandle handle, uint32 length); + void OnOpenLogFailed(); + + void Send(IPC::Message* message); + + // Owned by this class. The only other pointer to it is in libjingle's logging + // file. That's a global pointer used on different threads, so we will leak + // this object when we go away to ensure that it outlives any log messages + // coming from libjingle. + WebRtcLoggingHandlerImpl* logging_handler_; + + scoped_refptr<base::MessageLoopProxy> io_message_loop_; + + IPC::Channel* channel_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcLoggingMessageFilter); +}; + +#endif // CHROME_RENDERER_MEDIA_WEBRTC_LOGGING_MESSAGE_FILTER_H_ |