Skip to content

Commit

Permalink
Data collection part of webrtc-internals implementation
Browse files Browse the repository at this point in the history
This change implements the data collection part of webrtc-internals. 
RTCPeerConnectionHandler is an existing class living in the main renderer thread and knows about the status of a peer connection. With this CL, it reports every peer connection creation to PeerConnectionTracker.

PeerConnectionTracker is also running in the renderer process. It assigns an integer ID to each peer connectionstore and sends the basic peer connection info to PeerConnectionTrackerHost along with the ID.

PeerConnectionTrackerHost is running in the browser process in the IO thread. It simply passes anything it receives from PeerConnectionTracker to WebRTCInternals.

WebRTCInternals is a singlton running in the browser process. It sends the data received from PeerConnectionTrackerHost to every observer, i.e. webrtc-internals page. WebRTCInternalsUIObserver will be implemented in another change list.


BUG=168232


Review URL: https://chromiumcodereview.appspot.com/11753020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176012 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
jiayl@chromium.org committed Jan 10, 2013
1 parent 4596925 commit af08997
Show file tree
Hide file tree
Showing 19 changed files with 555 additions and 2 deletions.
84 changes: 84 additions & 0 deletions content/browser/media/webrtc_internals.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) 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 "content/browser/media/webrtc_internals.h"

#include "content/browser/media/webrtc_internals_ui_observer.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/public/browser/browser_thread.h"

using base::DictionaryValue;
using base::ProcessId;

namespace content{

WebRTCInternals::WebRTCInternals() {
}

WebRTCInternals::~WebRTCInternals() {
}

WebRTCInternals* WebRTCInternals::GetInstance() {
return Singleton<WebRTCInternals>::get();
}

void WebRTCInternals::AddPeerConnection(ProcessId pid,
const PeerConnectionInfo& info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (observers_.size()) {
DictionaryValue* dict = new DictionaryValue();
if (dict != NULL) {
dict->SetInteger("pid", static_cast<int>(pid));
dict->SetInteger("lid", info.lid);
dict->SetString("servers", info.servers);
dict->SetString("constraints", info.constraints);
dict->SetString("url", info.url);

SendUpdate("updatePeerConnectionAdded", dict);
peer_connection_data_.Append(dict);
}
}
}

void WebRTCInternals::RemovePeerConnection(ProcessId pid, int lid) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (observers_.size()) {
DictionaryValue dict;
dict.SetInteger("pid", static_cast<int>(pid));
dict.SetInteger("lid", lid);
SendUpdate("updatePeerConnectionRemoved", &dict);

for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) {
DictionaryValue* dict = NULL;
peer_connection_data_.GetDictionary(i, &dict);

int this_pid = 0;
int this_lid = 0;
dict->GetInteger("pid", &this_pid);
dict->GetInteger("lid", &this_lid);
if (this_pid == static_cast<int>(pid) && this_lid == lid)
peer_connection_data_.Remove(i, NULL);
}
}
}

void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver *observer) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
observers_.AddObserver(observer);
}

void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver *observer) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
observers_.RemoveObserver(observer);
}

void WebRTCInternals::SendUpdate(const std::string& command, Value* value) {
DCHECK(observers_.size());

FOR_EACH_OBSERVER(WebRTCInternalsUIObserver,
observers_,
OnUpdate(command, value));
}

} // namespace content
52 changes: 52 additions & 0 deletions content/browser/media/webrtc_internals.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) 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 CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_H_
#define CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_H_

#include "base/memory/singleton.h"
#include "base/observer_list.h"
#include "base/process.h"
#include "base/values.h"
#include "content/common/content_export.h"

struct PeerConnectionInfo;

namespace content {

class WebRTCInternalsUIObserver;

// This is a singleton class running in the browser process.
// It collects peer connection infomation from the renderers,
// forwards the data to WebRTCInternalsUIObserver and
// sends data collecting commands to the renderers.
class CONTENT_EXPORT WebRTCInternals {
public:
static WebRTCInternals* GetInstance();

// Methods called when peer connection status changes.
void AddPeerConnection(base::ProcessId pid, const PeerConnectionInfo& info);
void RemovePeerConnection(base::ProcessId pid, int lid);

// Methods for adding or removing WebRTCInternalsUIObserver.
void AddObserver(WebRTCInternalsUIObserver *observer);
void RemoveObserver(WebRTCInternalsUIObserver *observer);

private:
friend struct DefaultSingletonTraits<WebRTCInternals>;

WebRTCInternals();
virtual ~WebRTCInternals();

// Send updates to observers on UI thread.
void SendUpdate(const std::string& command, base::Value* value);

// Only the IO thread should access these fields.
ObserverList<WebRTCInternalsUIObserver> observers_;
base::ListValue peer_connection_data_;
};

} // namespace content

#endif // CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_H_
26 changes: 26 additions & 0 deletions content/browser/media/webrtc_internals_ui_observer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 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 CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_UI_OBSERVER_H_
#define CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_UI_OBSERVER_H_

namespace base {
class Value;
} // namespace base

namespace content {

// Implement this interface to receive WebRTCInternals updates.
class WebRTCInternalsUIObserver {
public:
virtual ~WebRTCInternalsUIObserver() {}

// This is called on the browser IO thread.
virtual void OnUpdate(const std::string& command,
const base::Value* args) = 0;
};

} // namespace content

#endif // CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_UI_OBSERVER_H_
99 changes: 99 additions & 0 deletions content/browser/media/webrtc_internals_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) 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 "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/values.h"
#include "content/browser/media/webrtc_internals.h"
#include "content/browser/media/webrtc_internals_ui_observer.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {
class MockWebRTCInternalsProxy : public content::WebRTCInternalsUIObserver {
public:
void OnUpdate(const std::string& command, const Value* value) OVERRIDE {
data_ = command;
}

std::string data() {
return data_;
}

private:
std::string data_;
};

class WebRTCInternalsTest : public testing::Test {
public:
WebRTCInternalsTest()
: io_thread_(content::BrowserThread::IO, &io_loop_) {}

protected:
virtual void SetUp() {
webrtc_internals_ = WebRTCInternals::GetInstance();
}

PeerConnectionInfo GetPeerConnectionInfo(uintptr_t lid) {
PeerConnectionInfo info;
info.lid = lid;
info.servers = "s";
info.constraints = "c";
info.url = "u";
return info;
}
std::string ExpectedInfo(std::string prefix,
std::string id,
std::string suffix) {
static const std::string kstatic_part1 = std::string(
"{\"constraints\":\"c\",");
static const std::string kstatic_part2 = std::string(
",\"servers\":\"s\",\"url\":\"u\"}");
return prefix + kstatic_part1 + id + kstatic_part2 + suffix;
}

MessageLoop io_loop_;
content::TestBrowserThread io_thread_;
WebRTCInternals *webrtc_internals_;
};

TEST_F(WebRTCInternalsTest, GetInstance) {
EXPECT_TRUE(webrtc_internals_);
}

TEST_F(WebRTCInternalsTest, AddRemoveObserver) {
scoped_ptr<MockWebRTCInternalsProxy> observer(
new MockWebRTCInternalsProxy());
webrtc_internals_->AddObserver(observer.get());
webrtc_internals_->RemoveObserver(observer.get());
webrtc_internals_->AddPeerConnection(3, GetPeerConnectionInfo(4));
EXPECT_EQ("", observer->data());

webrtc_internals_->RemovePeerConnection(3, 4);
}

TEST_F(WebRTCInternalsTest, SendAddPeerConnectionUpdate) {
scoped_ptr<MockWebRTCInternalsProxy> observer(
new MockWebRTCInternalsProxy());
webrtc_internals_->AddObserver(observer.get());
webrtc_internals_->AddPeerConnection(1, GetPeerConnectionInfo(2));
EXPECT_EQ("updatePeerConnectionAdded", observer->data());

webrtc_internals_->RemoveObserver(observer.get());
webrtc_internals_->RemovePeerConnection(1, 2);
}

TEST_F(WebRTCInternalsTest, SendRemovePeerConnectionUpdate) {
scoped_ptr<MockWebRTCInternalsProxy> observer(
new MockWebRTCInternalsProxy());
webrtc_internals_->AddObserver(observer.get());
webrtc_internals_->AddPeerConnection(1, GetPeerConnectionInfo(2));
webrtc_internals_->RemovePeerConnection(1, 2);
EXPECT_EQ("updatePeerConnectionRemoved", observer->data());

webrtc_internals_->RemoveObserver(observer.get());
}

} // namespace content
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) 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 "content/browser/renderer_host/media/peer_connection_tracker_host.h"

#include "base/process_util.h"
#include "content/browser/media/webrtc_internals.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/public/browser/content_browser_client.h"

namespace content {

PeerConnectionTrackerHost::PeerConnectionTrackerHost() {
}

bool PeerConnectionTrackerHost::OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(PeerConnectionTrackerHost, message, *message_was_ok)
IPC_MESSAGE_HANDLER(PeerConnectionTrackerHost_AddPeerConnection,
OnAddPeerConnection)
IPC_MESSAGE_HANDLER(PeerConnectionTrackerHost_RemovePeerConnection,
OnRemovePeerConnection)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
return handled;
}

PeerConnectionTrackerHost::~PeerConnectionTrackerHost() {
}

void PeerConnectionTrackerHost::OnAddPeerConnection(
const PeerConnectionInfo& info) {
WebRTCInternals::GetInstance()->AddPeerConnection(
base::GetProcId(peer_handle()), info);
}

void PeerConnectionTrackerHost::OnRemovePeerConnection(int lid) {
WebRTCInternals::GetInstance()->RemovePeerConnection(
base::GetProcId(peer_handle()), lid);
}

} // namespace content
39 changes: 39 additions & 0 deletions content/browser/renderer_host/media/peer_connection_tracker_host.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 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 CONTENT_BROWSER_RENDERER_HOST_MEDIA_PEER_CONNECTION_TRACKER_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_PEER_CONNECTION_TRACKER_HOST_H_

#include "content/public/browser/browser_message_filter.h"

struct PeerConnectionInfo;

namespace content {
class WebRTCInternals;

// This class is the host for PeerConnectionTracker in the browser process
// managed by RenderProcessHostImpl. It passes IPC messages between
// WebRTCInternals and PeerConnectionTracker.
class PeerConnectionTrackerHost : public BrowserMessageFilter {
public:
PeerConnectionTrackerHost();

// content::BrowserMessageFilter override.
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;

protected:
virtual ~PeerConnectionTrackerHost();

private:
// Handlers for peer connection messages coming from the renderer.
void OnAddPeerConnection(const PeerConnectionInfo& info);
void OnRemovePeerConnection(int lid);

DISALLOW_COPY_AND_ASSIGN(PeerConnectionTrackerHost);
};

} // namespace content

#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_PEER_CONNECTION_TRACKER_HOST_H_
3 changes: 3 additions & 0 deletions content/browser/renderer_host/render_process_host_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
#include "content/browser/renderer_host/media/video_capture_host.h"
#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
Expand Down Expand Up @@ -539,6 +540,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get());
channel_->AddFilter(gpu_message_filter_);
#if defined(ENABLE_WEBRTC)
peer_connection_tracker_host_ = new PeerConnectionTrackerHost();
channel_->AddFilter(peer_connection_tracker_host_);
channel_->AddFilter(new MediaStreamDispatcherHost(GetID()));
#endif
#if defined(ENABLE_PLUGINS)
Expand Down
5 changes: 5 additions & 0 deletions content/browser/renderer_host/render_process_host_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Size;

namespace content {
class GpuMessageFilter;
class PeerConnectionTrackerHost;
class RendererMainThread;
class RenderWidgetHelper;
class RenderWidgetHost;
Expand Down Expand Up @@ -308,6 +309,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
// renderer.
bool is_guest_;

// Forwards messages between WebRTCInternals in the browser process
// and PeerConnectionTracker in the renderer process.
scoped_refptr<PeerConnectionTrackerHost> peer_connection_tracker_host_;

DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
};

Expand Down
1 change: 1 addition & 0 deletions content/common/content_message_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "content/common/media/audio_messages.h"
#include "content/common/media/media_player_messages.h"
#include "content/common/media/media_stream_messages.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/common/media/video_capture_messages.h"
#include "content/common/mime_registry_messages.h"
#include "content/common/p2p_messages.h"
Expand Down
Loading

0 comments on commit af08997

Please sign in to comment.