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/renderer/media/rtc_data_channel_handler.h" | 5 #include "content/renderer/media/rtc_data_channel_handler.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | |
11 #include "base/location.h" | |
12 #include "base/logging.h" | 10 #include "base/logging.h" |
13 #include "base/message_loop/message_loop.h" | |
14 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
15 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
16 #include "base/thread_task_runner_handle.h" | |
17 | 13 |
18 namespace content { | 14 namespace content { |
19 | 15 |
20 namespace { | 16 namespace { |
21 | 17 |
22 enum DataChannelCounters { | 18 enum DataChannelCounters { |
23 CHANNEL_CREATED, | 19 CHANNEL_CREATED, |
24 CHANNEL_OPENED, | 20 CHANNEL_OPENED, |
25 CHANNEL_RELIABLE, | 21 CHANNEL_RELIABLE, |
26 CHANNEL_ORDERED, | 22 CHANNEL_ORDERED, |
27 CHANNEL_NEGOTIATED, | 23 CHANNEL_NEGOTIATED, |
28 CHANNEL_BOUNDARY | 24 CHANNEL_BOUNDARY |
29 }; | 25 }; |
30 | 26 |
31 void IncrementCounter(DataChannelCounters counter) { | 27 void IncrementCounter(DataChannelCounters counter) { |
32 UMA_HISTOGRAM_ENUMERATION("WebRTC.DataChannelCounters", | 28 UMA_HISTOGRAM_ENUMERATION("WebRTC.DataChannelCounters", |
33 counter, | 29 counter, |
34 CHANNEL_BOUNDARY); | 30 CHANNEL_BOUNDARY); |
35 } | 31 } |
36 | 32 |
37 } // namespace | 33 } // namespace |
38 | 34 |
39 // Implementation of DataChannelObserver that receives events on libjingle's | 35 RtcDataChannelHandler::RtcDataChannelHandler( |
40 // signaling thread and forwards them over to the main thread for handling. | |
41 // Since the handler's lifetime is scoped potentially narrower than what | |
42 // the callbacks allow for, we use reference counting here to make sure | |
43 // all callbacks have a valid pointer but won't do anything if the handler | |
44 // has gone away. | |
45 RtcDataChannelHandler::Observer::Observer( | |
46 RtcDataChannelHandler* handler, | |
47 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | |
48 webrtc::DataChannelInterface* channel) | 36 webrtc::DataChannelInterface* channel) |
49 : handler_(handler), main_thread_(main_thread), channel_(channel) { | 37 : channel_(channel), |
| 38 webkit_client_(NULL) { |
| 39 DVLOG(1) << "::ctor"; |
50 channel_->RegisterObserver(this); | 40 channel_->RegisterObserver(this); |
51 } | |
52 | |
53 RtcDataChannelHandler::Observer::~Observer() {} | |
54 | |
55 const scoped_refptr<base::SingleThreadTaskRunner>& | |
56 RtcDataChannelHandler::Observer::main_thread() const { | |
57 return main_thread_; | |
58 } | |
59 | |
60 const scoped_refptr<webrtc::DataChannelInterface>& | |
61 RtcDataChannelHandler::Observer::channel() const { | |
62 return channel_; | |
63 } | |
64 | |
65 void RtcDataChannelHandler::Observer::ClearHandler() { | |
66 DCHECK(main_thread_->BelongsToCurrentThread()); | |
67 handler_ = nullptr; | |
68 } | |
69 | |
70 void RtcDataChannelHandler::Observer::OnStateChange() { | |
71 main_thread_->PostTask(FROM_HERE, base::Bind( | |
72 &RtcDataChannelHandler::Observer::OnStateChangeImpl, this, | |
73 channel_->state())); | |
74 } | |
75 | |
76 void RtcDataChannelHandler::Observer::OnMessage( | |
77 const webrtc::DataBuffer& buffer) { | |
78 // TODO(tommi): Figure out a way to transfer ownership of the buffer without | |
79 // having to create a copy. See webrtc bug 3967. | |
80 scoped_ptr<webrtc::DataBuffer> new_buffer(new webrtc::DataBuffer(buffer)); | |
81 main_thread_->PostTask(FROM_HERE, | |
82 base::Bind(&RtcDataChannelHandler::Observer::OnMessageImpl, this, | |
83 base::Passed(&new_buffer))); | |
84 } | |
85 | |
86 void RtcDataChannelHandler::Observer::OnStateChangeImpl( | |
87 webrtc::DataChannelInterface::DataState state) { | |
88 DCHECK(main_thread_->BelongsToCurrentThread()); | |
89 if (handler_) | |
90 handler_->OnStateChange(state); | |
91 } | |
92 | |
93 void RtcDataChannelHandler::Observer::OnMessageImpl( | |
94 scoped_ptr<webrtc::DataBuffer> buffer) { | |
95 DCHECK(main_thread_->BelongsToCurrentThread()); | |
96 if (handler_) | |
97 handler_->OnMessage(buffer.Pass()); | |
98 } | |
99 | |
100 RtcDataChannelHandler::RtcDataChannelHandler( | |
101 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | |
102 webrtc::DataChannelInterface* channel) | |
103 : observer_(new Observer(this, main_thread, channel)), | |
104 webkit_client_(NULL) { | |
105 DVLOG(1) << "RtcDataChannelHandler " << channel->label(); | |
106 | |
107 // Detach from the ctor thread since we can be constructed on either the main | |
108 // or signaling threads. | |
109 thread_checker_.DetachFromThread(); | |
110 | 41 |
111 IncrementCounter(CHANNEL_CREATED); | 42 IncrementCounter(CHANNEL_CREATED); |
112 if (channel->reliable()) | 43 if (isReliable()) |
113 IncrementCounter(CHANNEL_RELIABLE); | 44 IncrementCounter(CHANNEL_RELIABLE); |
114 if (channel->ordered()) | 45 if (ordered()) |
115 IncrementCounter(CHANNEL_ORDERED); | 46 IncrementCounter(CHANNEL_ORDERED); |
116 if (channel->negotiated()) | 47 if (negotiated()) |
117 IncrementCounter(CHANNEL_NEGOTIATED); | 48 IncrementCounter(CHANNEL_NEGOTIATED); |
118 | 49 |
119 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmits", | 50 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmits", |
120 channel->maxRetransmits(), 0, | 51 maxRetransmits(), 0, |
121 std::numeric_limits<unsigned short>::max(), 50); | 52 std::numeric_limits<unsigned short>::max(), 50); |
122 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmitTime", | 53 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmitTime", |
123 channel->maxRetransmitTime(), 0, | 54 maxRetransmitTime(), 0, |
124 std::numeric_limits<unsigned short>::max(), 50); | 55 std::numeric_limits<unsigned short>::max(), 50); |
125 } | 56 } |
126 | 57 |
127 RtcDataChannelHandler::~RtcDataChannelHandler() { | 58 RtcDataChannelHandler::~RtcDataChannelHandler() { |
128 DCHECK(thread_checker_.CalledOnValidThread()); | |
129 DVLOG(1) << "::dtor"; | 59 DVLOG(1) << "::dtor"; |
130 observer_->ClearHandler(); | 60 channel_->UnregisterObserver(); |
131 } | 61 } |
132 | 62 |
133 void RtcDataChannelHandler::setClient( | 63 void RtcDataChannelHandler::setClient( |
134 blink::WebRTCDataChannelHandlerClient* client) { | 64 blink::WebRTCDataChannelHandlerClient* client) { |
135 DCHECK(thread_checker_.CalledOnValidThread()); | |
136 webkit_client_ = client; | 65 webkit_client_ = client; |
137 } | 66 } |
138 | 67 |
139 blink::WebString RtcDataChannelHandler::label() { | 68 blink::WebString RtcDataChannelHandler::label() { |
140 DCHECK(thread_checker_.CalledOnValidThread()); | 69 return base::UTF8ToUTF16(channel_->label()); |
141 return base::UTF8ToUTF16(channel()->label()); | |
142 } | 70 } |
143 | 71 |
144 bool RtcDataChannelHandler::isReliable() { | 72 bool RtcDataChannelHandler::isReliable() { |
145 DCHECK(thread_checker_.CalledOnValidThread()); | 73 return channel_->reliable(); |
146 return channel()->reliable(); | |
147 } | 74 } |
148 | 75 |
149 bool RtcDataChannelHandler::ordered() const { | 76 bool RtcDataChannelHandler::ordered() const { |
150 DCHECK(thread_checker_.CalledOnValidThread()); | 77 return channel_->ordered(); |
151 return channel()->ordered(); | |
152 } | 78 } |
153 | 79 |
154 unsigned short RtcDataChannelHandler::maxRetransmitTime() const { | 80 unsigned short RtcDataChannelHandler::maxRetransmitTime() const { |
155 DCHECK(thread_checker_.CalledOnValidThread()); | 81 return channel_->maxRetransmitTime(); |
156 return channel()->maxRetransmitTime(); | |
157 } | 82 } |
158 | 83 |
159 unsigned short RtcDataChannelHandler::maxRetransmits() const { | 84 unsigned short RtcDataChannelHandler::maxRetransmits() const { |
160 DCHECK(thread_checker_.CalledOnValidThread()); | 85 return channel_->maxRetransmits(); |
161 return channel()->maxRetransmits(); | |
162 } | 86 } |
163 | 87 |
164 blink::WebString RtcDataChannelHandler::protocol() const { | 88 blink::WebString RtcDataChannelHandler::protocol() const { |
165 DCHECK(thread_checker_.CalledOnValidThread()); | 89 return base::UTF8ToUTF16(channel_->protocol()); |
166 return base::UTF8ToUTF16(channel()->protocol()); | |
167 } | 90 } |
168 | 91 |
169 bool RtcDataChannelHandler::negotiated() const { | 92 bool RtcDataChannelHandler::negotiated() const { |
170 DCHECK(thread_checker_.CalledOnValidThread()); | 93 return channel_->negotiated(); |
171 return channel()->negotiated(); | |
172 } | 94 } |
173 | 95 |
174 unsigned short RtcDataChannelHandler::id() const { | 96 unsigned short RtcDataChannelHandler::id() const { |
175 DCHECK(thread_checker_.CalledOnValidThread()); | 97 return channel_->id(); |
176 return channel()->id(); | |
177 } | 98 } |
178 | 99 |
179 unsigned long RtcDataChannelHandler::bufferedAmount() { | 100 unsigned long RtcDataChannelHandler::bufferedAmount() { |
180 DCHECK(thread_checker_.CalledOnValidThread()); | 101 return channel_->buffered_amount(); |
181 return channel()->buffered_amount(); | |
182 } | 102 } |
183 | 103 |
184 bool RtcDataChannelHandler::sendStringData(const blink::WebString& data) { | 104 bool RtcDataChannelHandler::sendStringData(const blink::WebString& data) { |
185 DCHECK(thread_checker_.CalledOnValidThread()); | |
186 std::string utf8_buffer = base::UTF16ToUTF8(data); | 105 std::string utf8_buffer = base::UTF16ToUTF8(data); |
187 rtc::Buffer buffer(utf8_buffer.c_str(), utf8_buffer.length()); | 106 rtc::Buffer buffer(utf8_buffer.c_str(), utf8_buffer.length()); |
188 webrtc::DataBuffer data_buffer(buffer, false); | 107 webrtc::DataBuffer data_buffer(buffer, false); |
189 RecordMessageSent(data_buffer.size()); | 108 RecordMessageSent(data_buffer.size()); |
190 return channel()->Send(data_buffer); | 109 return channel_->Send(data_buffer); |
191 } | 110 } |
192 | 111 |
193 bool RtcDataChannelHandler::sendRawData(const char* data, size_t length) { | 112 bool RtcDataChannelHandler::sendRawData(const char* data, size_t length) { |
194 DCHECK(thread_checker_.CalledOnValidThread()); | |
195 rtc::Buffer buffer(data, length); | 113 rtc::Buffer buffer(data, length); |
196 webrtc::DataBuffer data_buffer(buffer, true); | 114 webrtc::DataBuffer data_buffer(buffer, true); |
197 RecordMessageSent(data_buffer.size()); | 115 RecordMessageSent(data_buffer.size()); |
198 return channel()->Send(data_buffer); | 116 return channel_->Send(data_buffer); |
199 } | 117 } |
200 | 118 |
201 void RtcDataChannelHandler::close() { | 119 void RtcDataChannelHandler::close() { |
202 DCHECK(thread_checker_.CalledOnValidThread()); | 120 channel_->Close(); |
203 channel()->Close(); | |
204 // Note that even though Close() will run synchronously, the readyState has | |
205 // not changed yet since the state changes that occured on the signaling | |
206 // thread have been posted to this thread and will be delivered later. | |
207 // To work around this, we could have a nested loop here and deliver the | |
208 // callbacks before running from this function, but doing so can cause | |
209 // undesired side effects in webkit, so we don't, and instead rely on the | |
210 // user of the API handling readyState notifications. | |
211 } | 121 } |
212 | 122 |
213 const scoped_refptr<webrtc::DataChannelInterface>& | 123 void RtcDataChannelHandler::OnStateChange() { |
214 RtcDataChannelHandler::channel() const { | |
215 return observer_->channel(); | |
216 } | |
217 | |
218 void RtcDataChannelHandler::OnStateChange( | |
219 webrtc::DataChannelInterface::DataState state) { | |
220 DCHECK(thread_checker_.CalledOnValidThread()); | |
221 DVLOG(1) << "OnStateChange " << state; | |
222 | |
223 if (!webkit_client_) { | 124 if (!webkit_client_) { |
224 // If this happens, the web application will not get notified of changes. | 125 LOG(ERROR) << "WebRTCDataChannelHandlerClient not set."; |
225 NOTREACHED() << "WebRTCDataChannelHandlerClient not set."; | |
226 return; | 126 return; |
227 } | 127 } |
228 | 128 DVLOG(1) << "OnStateChange " << channel_->state(); |
229 switch (state) { | 129 switch (channel_->state()) { |
230 case webrtc::DataChannelInterface::kConnecting: | 130 case webrtc::DataChannelInterface::kConnecting: |
231 webkit_client_->didChangeReadyState( | 131 webkit_client_->didChangeReadyState( |
232 blink::WebRTCDataChannelHandlerClient::ReadyStateConnecting); | 132 blink::WebRTCDataChannelHandlerClient::ReadyStateConnecting); |
233 break; | 133 break; |
234 case webrtc::DataChannelInterface::kOpen: | 134 case webrtc::DataChannelInterface::kOpen: |
235 IncrementCounter(CHANNEL_OPENED); | 135 IncrementCounter(CHANNEL_OPENED); |
236 webkit_client_->didChangeReadyState( | 136 webkit_client_->didChangeReadyState( |
237 blink::WebRTCDataChannelHandlerClient::ReadyStateOpen); | 137 blink::WebRTCDataChannelHandlerClient::ReadyStateOpen); |
238 break; | 138 break; |
239 case webrtc::DataChannelInterface::kClosing: | 139 case webrtc::DataChannelInterface::kClosing: |
240 webkit_client_->didChangeReadyState( | 140 webkit_client_->didChangeReadyState( |
241 blink::WebRTCDataChannelHandlerClient::ReadyStateClosing); | 141 blink::WebRTCDataChannelHandlerClient::ReadyStateClosing); |
242 break; | 142 break; |
243 case webrtc::DataChannelInterface::kClosed: | 143 case webrtc::DataChannelInterface::kClosed: |
244 webkit_client_->didChangeReadyState( | 144 webkit_client_->didChangeReadyState( |
245 blink::WebRTCDataChannelHandlerClient::ReadyStateClosed); | 145 blink::WebRTCDataChannelHandlerClient::ReadyStateClosed); |
246 break; | 146 break; |
247 default: | 147 default: |
248 NOTREACHED(); | 148 NOTREACHED(); |
249 break; | 149 break; |
250 } | 150 } |
251 } | 151 } |
252 | 152 |
253 void RtcDataChannelHandler::OnMessage(scoped_ptr<webrtc::DataBuffer> buffer) { | 153 void RtcDataChannelHandler::OnMessage(const webrtc::DataBuffer& buffer) { |
254 DCHECK(thread_checker_.CalledOnValidThread()); | |
255 if (!webkit_client_) { | 154 if (!webkit_client_) { |
256 // If this happens, the web application will not get notified of changes. | 155 LOG(ERROR) << "WebRTCDataChannelHandlerClient not set."; |
257 NOTREACHED() << "WebRTCDataChannelHandlerClient not set."; | |
258 return; | 156 return; |
259 } | 157 } |
260 | 158 |
261 if (buffer->binary) { | 159 if (buffer.binary) { |
262 webkit_client_->didReceiveRawData(buffer->data.data(), | 160 webkit_client_->didReceiveRawData(buffer.data.data(), buffer.data.length()); |
263 buffer->data.length()); | |
264 } else { | 161 } else { |
265 base::string16 utf16; | 162 base::string16 utf16; |
266 if (!base::UTF8ToUTF16(buffer->data.data(), buffer->data.length(), | 163 if (!base::UTF8ToUTF16(buffer.data.data(), buffer.data.length(), &utf16)) { |
267 &utf16)) { | |
268 LOG(ERROR) << "Failed convert received data to UTF16"; | 164 LOG(ERROR) << "Failed convert received data to UTF16"; |
269 return; | 165 return; |
270 } | 166 } |
271 webkit_client_->didReceiveStringData(utf16); | 167 webkit_client_->didReceiveStringData(utf16); |
272 } | 168 } |
273 } | 169 } |
274 | 170 |
275 void RtcDataChannelHandler::RecordMessageSent(size_t num_bytes) { | 171 void RtcDataChannelHandler::RecordMessageSent(size_t num_bytes) { |
276 // Currently, messages are capped at some fairly low limit (16 Kb?) | 172 // Currently, messages are capped at some fairly low limit (16 Kb?) |
277 // but we may allow unlimited-size messages at some point, so making | 173 // but we may allow unlimited-size messages at some point, so making |
278 // the histogram maximum quite large (100 Mb) to have some | 174 // the histogram maximum quite large (100 Mb) to have some |
279 // granularity at the higher end in that eventuality. The histogram | 175 // granularity at the higher end in that eventuality. The histogram |
280 // buckets are exponentially growing in size, so we'll still have | 176 // buckets are exponentially growing in size, so we'll still have |
281 // good granularity at the low end. | 177 // good granularity at the low end. |
282 | 178 |
283 // This makes the last bucket in the histogram count messages from | 179 // This makes the last bucket in the histogram count messages from |
284 // 100 Mb to infinity. | 180 // 100 Mb to infinity. |
285 const int kMaxBucketSize = 100 * 1024 * 1024; | 181 const int kMaxBucketSize = 100 * 1024 * 1024; |
286 const int kNumBuckets = 50; | 182 const int kNumBuckets = 50; |
287 | 183 |
288 if (channel()->reliable()) { | 184 if (isReliable()) { |
289 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.ReliableDataChannelMessageSize", | 185 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.ReliableDataChannelMessageSize", |
290 num_bytes, | 186 num_bytes, |
291 1, kMaxBucketSize, kNumBuckets); | 187 1, kMaxBucketSize, kNumBuckets); |
292 } else { | 188 } else { |
293 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.UnreliableDataChannelMessageSize", | 189 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.UnreliableDataChannelMessageSize", |
294 num_bytes, | 190 num_bytes, |
295 1, kMaxBucketSize, kNumBuckets); | 191 1, kMaxBucketSize, kNumBuckets); |
296 } | 192 } |
297 } | 193 } |
298 | 194 |
299 } // namespace content | 195 } // namespace content |
OLD | NEW |