Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Unified Diff: content/renderer/media/rtc_data_channel_handler.cc

Issue 689783002: Refactor RtcDataChannelHandler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/media/rtc_data_channel_handler.cc
diff --git a/content/renderer/media/rtc_data_channel_handler.cc b/content/renderer/media/rtc_data_channel_handler.cc
index 004cc46deb68c1a671c59eecdf2b8813aa01bd0d..084a02018cb9942a5c03e27193caade5a8351076 100644
--- a/content/renderer/media/rtc_data_channel_handler.cc
+++ b/content/renderer/media/rtc_data_channel_handler.cc
@@ -7,9 +7,13 @@
#include <limits>
#include <string>
+#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
namespace content {
@@ -32,101 +36,197 @@ void IncrementCounter(DataChannelCounters counter) {
} // namespace
+// Implementation of DataChannelObserver that receives events on libjingle's
+// signaling thread and forwards them over to the main thread for handling.
+// Since the handler's lifetime is scoped potentially narrower than what
+// the callbacks allow for, we use reference counting here to make sure
+// all callbacks have a valid pointer but won't do anything if the handler
+// has gone away.
+RtcDataChannelHandler::Observer::Observer(
+ RtcDataChannelHandler* handler,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::DataChannelInterface* channel)
+ : handler_(handler), main_thread_(main_thread), channel_(channel) {
+ channel_->RegisterObserver(this);
+}
+
+RtcDataChannelHandler::Observer::~Observer() {}
+
+const scoped_refptr<base::SingleThreadTaskRunner>&
+RtcDataChannelHandler::Observer::main_thread() const {
+ return main_thread_;
+}
+
+const scoped_refptr<webrtc::DataChannelInterface>&
+RtcDataChannelHandler::Observer::channel() const {
+ return channel_;
+}
+
+void RtcDataChannelHandler::Observer::ClearHandler() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ handler_ = nullptr;
+}
+
+void RtcDataChannelHandler::Observer::OnStateChange() {
+ main_thread_->PostTask(FROM_HERE, base::Bind(
+ &RtcDataChannelHandler::Observer::OnStateChangeImpl, this,
+ channel_->state()));
+}
+
+void RtcDataChannelHandler::Observer::OnMessage(
+ const webrtc::DataBuffer& buffer) {
+ // TODO(tommi): Figure out a way to transfer ownership of the buffer without
+ // having to create a copy. See webrtc bug 3967.
+ scoped_ptr<webrtc::DataBuffer> new_buffer(new webrtc::DataBuffer(buffer));
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RtcDataChannelHandler::Observer::OnMessageImpl, this,
+ base::Passed(&new_buffer)));
+}
+
+void RtcDataChannelHandler::Observer::OnStateChangeImpl(
+ webrtc::DataChannelInterface::DataState state) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (handler_)
+ handler_->OnStateChange(state);
+}
+
+void RtcDataChannelHandler::Observer::OnMessageImpl(
+ scoped_ptr<webrtc::DataBuffer> buffer) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (handler_)
+ handler_->OnMessage(buffer.Pass());
+}
+
RtcDataChannelHandler::RtcDataChannelHandler(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
webrtc::DataChannelInterface* channel)
- : channel_(channel),
+ : observer_(new Observer(this, main_thread, channel)),
webkit_client_(NULL) {
- DVLOG(1) << "::ctor";
- channel_->RegisterObserver(this);
+ DVLOG(1) << "RtcDataChannelHandler " << channel->label();
+
+ // Detach from the ctor thread since we can be constructed on either the main
+ // or signaling threads.
+ thread_checker_.DetachFromThread();
IncrementCounter(CHANNEL_CREATED);
- if (isReliable())
+ if (channel->reliable())
IncrementCounter(CHANNEL_RELIABLE);
- if (ordered())
+ if (channel->ordered())
IncrementCounter(CHANNEL_ORDERED);
- if (negotiated())
+ if (channel->negotiated())
IncrementCounter(CHANNEL_NEGOTIATED);
UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmits",
- maxRetransmits(), 0,
+ channel->maxRetransmits(), 0,
std::numeric_limits<unsigned short>::max(), 50);
UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmitTime",
- maxRetransmitTime(), 0,
+ channel->maxRetransmitTime(), 0,
std::numeric_limits<unsigned short>::max(), 50);
}
RtcDataChannelHandler::~RtcDataChannelHandler() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "::dtor";
- channel_->UnregisterObserver();
+ observer_->ClearHandler();
}
void RtcDataChannelHandler::setClient(
blink::WebRTCDataChannelHandlerClient* client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
webkit_client_ = client;
}
blink::WebString RtcDataChannelHandler::label() {
- return base::UTF8ToUTF16(channel_->label());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return base::UTF8ToUTF16(channel()->label());
}
bool RtcDataChannelHandler::isReliable() {
- return channel_->reliable();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->reliable();
}
bool RtcDataChannelHandler::ordered() const {
- return channel_->ordered();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->ordered();
}
unsigned short RtcDataChannelHandler::maxRetransmitTime() const {
- return channel_->maxRetransmitTime();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->maxRetransmitTime();
}
unsigned short RtcDataChannelHandler::maxRetransmits() const {
- return channel_->maxRetransmits();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->maxRetransmits();
}
blink::WebString RtcDataChannelHandler::protocol() const {
- return base::UTF8ToUTF16(channel_->protocol());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return base::UTF8ToUTF16(channel()->protocol());
}
bool RtcDataChannelHandler::negotiated() const {
- return channel_->negotiated();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->negotiated();
}
unsigned short RtcDataChannelHandler::id() const {
- return channel_->id();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->id();
}
unsigned long RtcDataChannelHandler::bufferedAmount() {
- return channel_->buffered_amount();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->buffered_amount();
}
bool RtcDataChannelHandler::sendStringData(const blink::WebString& data) {
+ DCHECK(thread_checker_.CalledOnValidThread());
std::string utf8_buffer = base::UTF16ToUTF8(data);
rtc::Buffer buffer(utf8_buffer.c_str(), utf8_buffer.length());
webrtc::DataBuffer data_buffer(buffer, false);
RecordMessageSent(data_buffer.size());
- return channel_->Send(data_buffer);
+ return channel()->Send(data_buffer);
}
bool RtcDataChannelHandler::sendRawData(const char* data, size_t length) {
+ DCHECK(thread_checker_.CalledOnValidThread());
rtc::Buffer buffer(data, length);
webrtc::DataBuffer data_buffer(buffer, true);
RecordMessageSent(data_buffer.size());
- return channel_->Send(data_buffer);
+ return channel()->Send(data_buffer);
}
void RtcDataChannelHandler::close() {
- channel_->Close();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ channel()->Close();
+ // Note that even though Close() will run synchronously, the readyState has
+ // not changed yet since the state changes that occured on the signaling
+ // thread have been posted to this thread and will be delivered later.
+ // To work around this, we could have a nested loop here and deliver the
+ // callbacks before running from this function, but doing so can cause
+ // undesired side effects in webkit, so we don't, and instead rely on the
+ // user of the API handling readyState notifications.
+}
+
+const scoped_refptr<webrtc::DataChannelInterface>&
+RtcDataChannelHandler::channel() const {
+ return observer_->channel();
}
-void RtcDataChannelHandler::OnStateChange() {
+void RtcDataChannelHandler::OnStateChange(
+ webrtc::DataChannelInterface::DataState state) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DVLOG(1) << "OnStateChange " << state;
+
if (!webkit_client_) {
- LOG(ERROR) << "WebRTCDataChannelHandlerClient not set.";
+ // If this happens, the web application will not get notified of changes.
+ NOTREACHED() << "WebRTCDataChannelHandlerClient not set.";
return;
}
- DVLOG(1) << "OnStateChange " << channel_->state();
- switch (channel_->state()) {
+
+ switch (state) {
case webrtc::DataChannelInterface::kConnecting:
webkit_client_->didChangeReadyState(
blink::WebRTCDataChannelHandlerClient::ReadyStateConnecting);
@@ -150,17 +250,21 @@ void RtcDataChannelHandler::OnStateChange() {
}
}
-void RtcDataChannelHandler::OnMessage(const webrtc::DataBuffer& buffer) {
+void RtcDataChannelHandler::OnMessage(scoped_ptr<webrtc::DataBuffer> buffer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!webkit_client_) {
- LOG(ERROR) << "WebRTCDataChannelHandlerClient not set.";
+ // If this happens, the web application will not get notified of changes.
+ NOTREACHED() << "WebRTCDataChannelHandlerClient not set.";
return;
}
- if (buffer.binary) {
- webkit_client_->didReceiveRawData(buffer.data.data(), buffer.data.length());
+ if (buffer->binary) {
+ webkit_client_->didReceiveRawData(buffer->data.data(),
+ buffer->data.length());
} else {
base::string16 utf16;
- if (!base::UTF8ToUTF16(buffer.data.data(), buffer.data.length(), &utf16)) {
+ if (!base::UTF8ToUTF16(buffer->data.data(), buffer->data.length(),
+ &utf16)) {
LOG(ERROR) << "Failed convert received data to UTF16";
return;
}
@@ -181,7 +285,7 @@ void RtcDataChannelHandler::RecordMessageSent(size_t num_bytes) {
const int kMaxBucketSize = 100 * 1024 * 1024;
const int kNumBuckets = 50;
- if (isReliable()) {
+ if (channel()->reliable()) {
UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.ReliableDataChannelMessageSize",
num_bytes,
1, kMaxBucketSize, kNumBuckets);
« no previous file with comments | « content/renderer/media/rtc_data_channel_handler.h ('k') | content/renderer/media/rtc_peer_connection_handler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698