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 3 // found in the LICENSE file. 4 5 #include "content/renderer/media/rtc_data_channel_handler.h" 6 7 #include <limits> 8 #include <string> 9 10 #include "base/logging.h" 11 #include "base/metrics/histogram.h" 12 #include "base/strings/utf_string_conversions.h" 13 14 namespace content { 15 16 namespace { 17 18 enum DataChannelCounters { 19 CHANNEL_CREATED, 20 CHANNEL_OPENED, 21 CHANNEL_RELIABLE, 22 CHANNEL_ORDERED, 23 CHANNEL_NEGOTIATED, 24 CHANNEL_BOUNDARY 25 }; 26 27 void IncrementCounter(DataChannelCounters counter) { 28 UMA_HISTOGRAM_ENUMERATION("WebRTC.DataChannelCounters", 29 counter, 30 CHANNEL_BOUNDARY); 31 } 32 33 } // namespace 34 35 RtcDataChannelHandler::RtcDataChannelHandler( 36 webrtc::DataChannelInterface* channel) 37 : channel_(channel), 38 webkit_client_(NULL) { 39 DVLOG(1) << "::ctor"; 40 channel_->RegisterObserver(this); 41 42 IncrementCounter(CHANNEL_CREATED); 43 if (isReliable()) 44 IncrementCounter(CHANNEL_RELIABLE); 45 if (ordered()) 46 IncrementCounter(CHANNEL_ORDERED); 47 if (negotiated()) 48 IncrementCounter(CHANNEL_NEGOTIATED); 49 50 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmits", 51 maxRetransmits(), 0, 52 std::numeric_limits<unsigned short>::max(), 50); 53 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmitTime", 54 maxRetransmitTime(), 0, 55 std::numeric_limits<unsigned short>::max(), 50); 56 } 57 58 RtcDataChannelHandler::~RtcDataChannelHandler() { 59 DVLOG(1) << "::dtor"; 60 channel_->UnregisterObserver(); 61 } 62 63 void RtcDataChannelHandler::setClient( 64 blink::WebRTCDataChannelHandlerClient* client) { 65 webkit_client_ = client; 66 } 67 68 blink::WebString RtcDataChannelHandler::label() { 69 return base::UTF8ToUTF16(channel_->label()); 70 } 71 72 bool RtcDataChannelHandler::isReliable() { 73 return channel_->reliable(); 74 } 75 76 bool RtcDataChannelHandler::ordered() const { 77 return channel_->ordered(); 78 } 79 80 unsigned short RtcDataChannelHandler::maxRetransmitTime() const { 81 return channel_->maxRetransmitTime(); 82 } 83 84 unsigned short RtcDataChannelHandler::maxRetransmits() const { 85 return channel_->maxRetransmits(); 86 } 87 88 blink::WebString RtcDataChannelHandler::protocol() const { 89 return base::UTF8ToUTF16(channel_->protocol()); 90 } 91 92 bool RtcDataChannelHandler::negotiated() const { 93 return channel_->negotiated(); 94 } 95 96 unsigned short RtcDataChannelHandler::id() const { 97 return channel_->id(); 98 } 99 100 unsigned long RtcDataChannelHandler::bufferedAmount() { 101 return channel_->buffered_amount(); 102 } 103 104 bool RtcDataChannelHandler::sendStringData(const blink::WebString& data) { 105 std::string utf8_buffer = base::UTF16ToUTF8(data); 106 talk_base::Buffer buffer(utf8_buffer.c_str(), utf8_buffer.length()); 107 webrtc::DataBuffer data_buffer(buffer, false); 108 RecordMessageSent(data_buffer.size()); 109 return channel_->Send(data_buffer); 110 } 111 112 bool RtcDataChannelHandler::sendRawData(const char* data, size_t length) { 113 talk_base::Buffer buffer(data, length); 114 webrtc::DataBuffer data_buffer(buffer, true); 115 RecordMessageSent(data_buffer.size()); 116 return channel_->Send(data_buffer); 117 } 118 119 void RtcDataChannelHandler::close() { 120 channel_->Close(); 121 } 122 123 void RtcDataChannelHandler::OnStateChange() { 124 if (!webkit_client_) { 125 LOG(ERROR) << "WebRTCDataChannelHandlerClient not set."; 126 return; 127 } 128 DVLOG(1) << "OnStateChange " << channel_->state(); 129 switch (channel_->state()) { 130 case webrtc::DataChannelInterface::kConnecting: 131 webkit_client_->didChangeReadyState( 132 blink::WebRTCDataChannelHandlerClient::ReadyStateConnecting); 133 break; 134 case webrtc::DataChannelInterface::kOpen: 135 IncrementCounter(CHANNEL_OPENED); 136 webkit_client_->didChangeReadyState( 137 blink::WebRTCDataChannelHandlerClient::ReadyStateOpen); 138 break; 139 case webrtc::DataChannelInterface::kClosing: 140 webkit_client_->didChangeReadyState( 141 blink::WebRTCDataChannelHandlerClient::ReadyStateClosing); 142 break; 143 case webrtc::DataChannelInterface::kClosed: 144 webkit_client_->didChangeReadyState( 145 blink::WebRTCDataChannelHandlerClient::ReadyStateClosed); 146 break; 147 default: 148 NOTREACHED(); 149 break; 150 } 151 } 152 153 void RtcDataChannelHandler::OnMessage(const webrtc::DataBuffer& buffer) { 154 if (!webkit_client_) { 155 LOG(ERROR) << "WebRTCDataChannelHandlerClient not set."; 156 return; 157 } 158 159 if (buffer.binary) { 160 webkit_client_->didReceiveRawData(buffer.data.data(), buffer.data.length()); 161 } else { 162 base::string16 utf16; 163 if (!base::UTF8ToUTF16(buffer.data.data(), buffer.data.length(), &utf16)) { 164 LOG(ERROR) << "Failed convert received data to UTF16"; 165 return; 166 } 167 webkit_client_->didReceiveStringData(utf16); 168 } 169 } 170 171 void RtcDataChannelHandler::RecordMessageSent(size_t num_bytes) { 172 // Currently, messages are capped at some fairly low limit (16 Kb?) 173 // but we may allow unlimited-size messages at some point, so making 174 // the histogram maximum quite large (100 Mb) to have some 175 // granularity at the higher end in that eventuality. The histogram 176 // buckets are exponentially growing in size, so we'll still have 177 // good granularity at the low end. 178 179 // This makes the last bucket in the histogram count messages from 180 // 100 Mb to infinity. 181 const int kMaxBucketSize = 100 * 1024 * 1024; 182 const int kNumBuckets = 50; 183 184 if (isReliable()) { 185 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.ReliableDataChannelMessageSize", 186 num_bytes, 187 1, kMaxBucketSize, kNumBuckets); 188 } else { 189 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.UnreliableDataChannelMessageSize", 190 num_bytes, 191 1, kMaxBucketSize, kNumBuckets); 192 } 193 } 194 195 } // namespace content 196