1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/base/src/Dashboard.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,920 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http:mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "mozilla/dom/NetDashboardBinding.h" 1.9 +#include "mozilla/net/Dashboard.h" 1.10 +#include "mozilla/net/HttpInfo.h" 1.11 +#include "nsCxPusher.h" 1.12 +#include "nsHttp.h" 1.13 +#include "nsICancelable.h" 1.14 +#include "nsIDNSService.h" 1.15 +#include "nsIDNSRecord.h" 1.16 +#include "nsIInputStream.h" 1.17 +#include "nsISocketTransport.h" 1.18 +#include "nsIThread.h" 1.19 +#include "nsProxyRelease.h" 1.20 +#include "nsSocketTransportService2.h" 1.21 +#include "nsThreadUtils.h" 1.22 +#include "nsURLHelper.h" 1.23 + 1.24 +using mozilla::AutoSafeJSContext; 1.25 +using mozilla::dom::Sequence; 1.26 + 1.27 +namespace mozilla { 1.28 +namespace net { 1.29 + 1.30 +class SocketData 1.31 + : public nsISupports 1.32 +{ 1.33 +public: 1.34 + NS_DECL_THREADSAFE_ISUPPORTS 1.35 + 1.36 + SocketData() 1.37 + { 1.38 + mTotalSent = 0; 1.39 + mTotalRecv = 0; 1.40 + mThread = nullptr; 1.41 + } 1.42 + 1.43 + virtual ~SocketData() 1.44 + { 1.45 + } 1.46 + 1.47 + uint64_t mTotalSent; 1.48 + uint64_t mTotalRecv; 1.49 + nsTArray<SocketInfo> mData; 1.50 + nsMainThreadPtrHandle<NetDashboardCallback> mCallback; 1.51 + nsIThread *mThread; 1.52 +}; 1.53 + 1.54 +NS_IMPL_ISUPPORTS0(SocketData) 1.55 + 1.56 + 1.57 +class HttpData 1.58 + : public nsISupports 1.59 +{ 1.60 +public: 1.61 + NS_DECL_THREADSAFE_ISUPPORTS 1.62 + 1.63 + HttpData() 1.64 + { 1.65 + mThread = nullptr; 1.66 + } 1.67 + 1.68 + virtual ~HttpData() 1.69 + { 1.70 + } 1.71 + 1.72 + nsTArray<HttpRetParams> mData; 1.73 + nsMainThreadPtrHandle<NetDashboardCallback> mCallback; 1.74 + nsIThread *mThread; 1.75 +}; 1.76 + 1.77 +NS_IMPL_ISUPPORTS0(HttpData) 1.78 + 1.79 + 1.80 +class WebSocketRequest 1.81 + : public nsISupports 1.82 +{ 1.83 +public: 1.84 + NS_DECL_THREADSAFE_ISUPPORTS 1.85 + 1.86 + WebSocketRequest() 1.87 + { 1.88 + mThread = nullptr; 1.89 + } 1.90 + 1.91 + virtual ~WebSocketRequest() 1.92 + { 1.93 + } 1.94 + 1.95 + nsMainThreadPtrHandle<NetDashboardCallback> mCallback; 1.96 + nsIThread *mThread; 1.97 +}; 1.98 + 1.99 +NS_IMPL_ISUPPORTS0(WebSocketRequest) 1.100 + 1.101 + 1.102 +class DnsData 1.103 + : public nsISupports 1.104 +{ 1.105 +public: 1.106 + NS_DECL_THREADSAFE_ISUPPORTS 1.107 + 1.108 + DnsData() 1.109 + { 1.110 + mThread = nullptr; 1.111 + } 1.112 + 1.113 + virtual ~DnsData() 1.114 + { 1.115 + } 1.116 + 1.117 + nsTArray<DNSCacheEntries> mData; 1.118 + nsMainThreadPtrHandle<NetDashboardCallback> mCallback; 1.119 + nsIThread *mThread; 1.120 +}; 1.121 + 1.122 +NS_IMPL_ISUPPORTS0(DnsData) 1.123 + 1.124 + 1.125 +class ConnectionData 1.126 + : public nsITransportEventSink 1.127 + , public nsITimerCallback 1.128 +{ 1.129 +public: 1.130 + NS_DECL_THREADSAFE_ISUPPORTS 1.131 + NS_DECL_NSITRANSPORTEVENTSINK 1.132 + NS_DECL_NSITIMERCALLBACK 1.133 + 1.134 + void StartTimer(uint32_t aTimeout); 1.135 + void StopTimer(); 1.136 + 1.137 + ConnectionData(Dashboard *target) 1.138 + { 1.139 + mThread = nullptr; 1.140 + mDashboard = target; 1.141 + } 1.142 + 1.143 + virtual ~ConnectionData() 1.144 + { 1.145 + if (mTimer) { 1.146 + mTimer->Cancel(); 1.147 + } 1.148 + } 1.149 + 1.150 + nsCOMPtr<nsISocketTransport> mSocket; 1.151 + nsCOMPtr<nsIInputStream> mStreamIn; 1.152 + nsCOMPtr<nsITimer> mTimer; 1.153 + nsMainThreadPtrHandle<NetDashboardCallback> mCallback; 1.154 + nsIThread *mThread; 1.155 + Dashboard *mDashboard; 1.156 + 1.157 + nsCString mHost; 1.158 + uint32_t mPort; 1.159 + const char *mProtocol; 1.160 + uint32_t mTimeout; 1.161 + 1.162 + nsString mStatus; 1.163 +}; 1.164 + 1.165 +NS_IMPL_ISUPPORTS(ConnectionData, nsITransportEventSink, nsITimerCallback) 1.166 + 1.167 +NS_IMETHODIMP 1.168 +ConnectionData::OnTransportStatus(nsITransport *aTransport, nsresult aStatus, 1.169 + uint64_t aProgress, uint64_t aProgressMax) 1.170 +{ 1.171 + if (aStatus == NS_NET_STATUS_CONNECTED_TO) { 1.172 + StopTimer(); 1.173 + } 1.174 + 1.175 + CopyASCIItoUTF16(Dashboard::GetErrorString(aStatus), mStatus); 1.176 + nsCOMPtr<nsIRunnable> event = 1.177 + NS_NewRunnableMethodWithArg<nsRefPtr<ConnectionData> > 1.178 + (mDashboard, &Dashboard::GetConnectionStatus, this); 1.179 + mThread->Dispatch(event, NS_DISPATCH_NORMAL); 1.180 + 1.181 + return NS_OK; 1.182 +} 1.183 + 1.184 +NS_IMETHODIMP 1.185 +ConnectionData::Notify(nsITimer *aTimer) 1.186 +{ 1.187 + MOZ_ASSERT(aTimer == mTimer); 1.188 + 1.189 + if (mSocket) { 1.190 + mSocket->Close(NS_ERROR_ABORT); 1.191 + mSocket = nullptr; 1.192 + mStreamIn = nullptr; 1.193 + } 1.194 + 1.195 + mTimer = nullptr; 1.196 + 1.197 + mStatus.Assign(NS_LITERAL_STRING("NS_ERROR_NET_TIMEOUT")); 1.198 + nsCOMPtr<nsIRunnable> event = 1.199 + NS_NewRunnableMethodWithArg<nsRefPtr<ConnectionData> > 1.200 + (mDashboard, &Dashboard::GetConnectionStatus, this); 1.201 + mThread->Dispatch(event, NS_DISPATCH_NORMAL); 1.202 + 1.203 + return NS_OK; 1.204 +} 1.205 + 1.206 +void 1.207 +ConnectionData::StartTimer(uint32_t aTimeout) 1.208 +{ 1.209 + if (!mTimer) { 1.210 + mTimer = do_CreateInstance("@mozilla.org/timer;1"); 1.211 + } 1.212 + 1.213 + mTimer->InitWithCallback(this, aTimeout * 1000, 1.214 + nsITimer::TYPE_ONE_SHOT); 1.215 +} 1.216 + 1.217 +void 1.218 +ConnectionData::StopTimer() 1.219 +{ 1.220 + if (mTimer) { 1.221 + mTimer->Cancel(); 1.222 + mTimer = nullptr; 1.223 + } 1.224 +} 1.225 + 1.226 + 1.227 +class LookupHelper; 1.228 + 1.229 +class LookupArgument 1.230 + : public nsISupports 1.231 +{ 1.232 +public: 1.233 + NS_DECL_THREADSAFE_ISUPPORTS 1.234 + 1.235 + LookupArgument(nsIDNSRecord *aRecord, LookupHelper *aHelper) 1.236 + { 1.237 + mRecord = aRecord; 1.238 + mHelper = aHelper; 1.239 + } 1.240 + 1.241 + virtual ~LookupArgument() 1.242 + { 1.243 + } 1.244 + 1.245 + nsCOMPtr<nsIDNSRecord> mRecord; 1.246 + nsRefPtr<LookupHelper> mHelper; 1.247 +}; 1.248 + 1.249 +NS_IMPL_ISUPPORTS0(LookupArgument) 1.250 + 1.251 + 1.252 +class LookupHelper 1.253 + : public nsIDNSListener 1.254 +{ 1.255 +public: 1.256 + NS_DECL_THREADSAFE_ISUPPORTS 1.257 + NS_DECL_NSIDNSLISTENER 1.258 + 1.259 + LookupHelper() { 1.260 + } 1.261 + 1.262 + virtual ~LookupHelper() 1.263 + { 1.264 + if (mCancel) { 1.265 + mCancel->Cancel(NS_ERROR_ABORT); 1.266 + } 1.267 + } 1.268 + 1.269 + nsresult ConstructAnswer(LookupArgument *aArgument); 1.270 +public: 1.271 + nsCOMPtr<nsICancelable> mCancel; 1.272 + nsMainThreadPtrHandle<NetDashboardCallback> mCallback; 1.273 + nsIThread *mThread; 1.274 + nsresult mStatus; 1.275 +}; 1.276 + 1.277 +NS_IMPL_ISUPPORTS(LookupHelper, nsIDNSListener) 1.278 + 1.279 +NS_IMETHODIMP 1.280 +LookupHelper::OnLookupComplete(nsICancelable *aRequest, 1.281 + nsIDNSRecord *aRecord, nsresult aStatus) 1.282 +{ 1.283 + MOZ_ASSERT(aRequest == mCancel); 1.284 + mCancel = nullptr; 1.285 + mStatus = aStatus; 1.286 + 1.287 + nsRefPtr<LookupArgument> arg = new LookupArgument(aRecord, this); 1.288 + nsCOMPtr<nsIRunnable> event = 1.289 + NS_NewRunnableMethodWithArg<nsRefPtr<LookupArgument> >( 1.290 + this, &LookupHelper::ConstructAnswer, arg); 1.291 + mThread->Dispatch(event, NS_DISPATCH_NORMAL); 1.292 + 1.293 + return NS_OK; 1.294 +} 1.295 + 1.296 +nsresult 1.297 +LookupHelper::ConstructAnswer(LookupArgument *aArgument) 1.298 +{ 1.299 + 1.300 + nsIDNSRecord *aRecord = aArgument->mRecord; 1.301 + AutoSafeJSContext cx; 1.302 + 1.303 + mozilla::dom::DNSLookupDict dict; 1.304 + dict.mAddress.Construct(); 1.305 + 1.306 + Sequence<nsString> &addresses = dict.mAddress.Value(); 1.307 + 1.308 + if (NS_SUCCEEDED(mStatus)) { 1.309 + dict.mAnswer = true; 1.310 + bool hasMore; 1.311 + aRecord->HasMore(&hasMore); 1.312 + while (hasMore) { 1.313 + nsCString nextAddress; 1.314 + aRecord->GetNextAddrAsString(nextAddress); 1.315 + CopyASCIItoUTF16(nextAddress, *addresses.AppendElement()); 1.316 + aRecord->HasMore(&hasMore); 1.317 + } 1.318 + } else { 1.319 + dict.mAnswer = false; 1.320 + CopyASCIItoUTF16(Dashboard::GetErrorString(mStatus), dict.mError); 1.321 + } 1.322 + 1.323 + JS::RootedValue val(cx); 1.324 + if (!dict.ToObject(cx, &val)) { 1.325 + return NS_ERROR_FAILURE; 1.326 + } 1.327 + 1.328 + this->mCallback->OnDashboardDataAvailable(val); 1.329 + 1.330 + return NS_OK; 1.331 +} 1.332 + 1.333 +NS_IMPL_ISUPPORTS(Dashboard, nsIDashboard, nsIDashboardEventNotifier) 1.334 + 1.335 +Dashboard::Dashboard() 1.336 +{ 1.337 + mEnableLogging = false; 1.338 +} 1.339 + 1.340 +Dashboard::~Dashboard() 1.341 +{ 1.342 +} 1.343 + 1.344 +NS_IMETHODIMP 1.345 +Dashboard::RequestSockets(NetDashboardCallback *aCallback) 1.346 +{ 1.347 + nsRefPtr<SocketData> socketData = new SocketData(); 1.348 + socketData->mCallback = 1.349 + new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true); 1.350 + socketData->mThread = NS_GetCurrentThread(); 1.351 + nsCOMPtr<nsIRunnable> event = 1.352 + NS_NewRunnableMethodWithArg<nsRefPtr<SocketData> > 1.353 + (this, &Dashboard::GetSocketsDispatch, socketData); 1.354 + gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL); 1.355 + return NS_OK; 1.356 +} 1.357 + 1.358 +nsresult 1.359 +Dashboard::GetSocketsDispatch(SocketData *aSocketData) 1.360 +{ 1.361 + nsRefPtr<SocketData> socketData = aSocketData; 1.362 + if (gSocketTransportService) { 1.363 + gSocketTransportService->GetSocketConnections(&socketData->mData); 1.364 + socketData->mTotalSent = gSocketTransportService->GetSentBytes(); 1.365 + socketData->mTotalRecv = gSocketTransportService->GetReceivedBytes(); 1.366 + } 1.367 + nsCOMPtr<nsIRunnable> event = 1.368 + NS_NewRunnableMethodWithArg<nsRefPtr<SocketData> > 1.369 + (this, &Dashboard::GetSockets, socketData); 1.370 + socketData->mThread->Dispatch(event, NS_DISPATCH_NORMAL); 1.371 + return NS_OK; 1.372 +} 1.373 + 1.374 +nsresult 1.375 +Dashboard::GetSockets(SocketData *aSocketData) 1.376 +{ 1.377 + nsRefPtr<SocketData> socketData = aSocketData; 1.378 + AutoSafeJSContext cx; 1.379 + 1.380 + mozilla::dom::SocketsDict dict; 1.381 + dict.mSockets.Construct(); 1.382 + dict.mSent = 0; 1.383 + dict.mReceived = 0; 1.384 + 1.385 + Sequence<mozilla::dom::SocketElement> &sockets = dict.mSockets.Value(); 1.386 + 1.387 + uint32_t length = socketData->mData.Length(); 1.388 + if (!sockets.SetCapacity(length)) { 1.389 + JS_ReportOutOfMemory(cx); 1.390 + return NS_ERROR_OUT_OF_MEMORY; 1.391 + } 1.392 + 1.393 + for (uint32_t i = 0; i < socketData->mData.Length(); i++) { 1.394 + mozilla::dom::SocketElement &mSocket = *sockets.AppendElement(); 1.395 + CopyASCIItoUTF16(socketData->mData[i].host, mSocket.mHost); 1.396 + mSocket.mPort = socketData->mData[i].port; 1.397 + mSocket.mActive = socketData->mData[i].active; 1.398 + mSocket.mTcp = socketData->mData[i].tcp; 1.399 + mSocket.mSent = (double) socketData->mData[i].sent; 1.400 + mSocket.mReceived = (double) socketData->mData[i].received; 1.401 + dict.mSent += socketData->mData[i].sent; 1.402 + dict.mReceived += socketData->mData[i].received; 1.403 + } 1.404 + 1.405 + dict.mSent += socketData->mTotalSent; 1.406 + dict.mReceived += socketData->mTotalRecv; 1.407 + JS::RootedValue val(cx); 1.408 + if (!dict.ToObject(cx, &val)) 1.409 + return NS_ERROR_FAILURE; 1.410 + socketData->mCallback->OnDashboardDataAvailable(val); 1.411 + 1.412 + return NS_OK; 1.413 +} 1.414 + 1.415 +NS_IMETHODIMP 1.416 +Dashboard::RequestHttpConnections(NetDashboardCallback *aCallback) 1.417 +{ 1.418 + nsRefPtr<HttpData> httpData = new HttpData(); 1.419 + httpData->mCallback = 1.420 + new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true); 1.421 + httpData->mThread = NS_GetCurrentThread(); 1.422 + 1.423 + nsCOMPtr<nsIRunnable> event = 1.424 + NS_NewRunnableMethodWithArg<nsRefPtr<HttpData> > 1.425 + (this, &Dashboard::GetHttpDispatch, httpData); 1.426 + gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL); 1.427 + return NS_OK; 1.428 +} 1.429 + 1.430 +nsresult 1.431 +Dashboard::GetHttpDispatch(HttpData *aHttpData) 1.432 +{ 1.433 + nsRefPtr<HttpData> httpData = aHttpData; 1.434 + HttpInfo::GetHttpConnectionData(&httpData->mData); 1.435 + nsCOMPtr<nsIRunnable> event = 1.436 + NS_NewRunnableMethodWithArg<nsRefPtr<HttpData> > 1.437 + (this, &Dashboard::GetHttpConnections, httpData); 1.438 + httpData->mThread->Dispatch(event, NS_DISPATCH_NORMAL); 1.439 + return NS_OK; 1.440 +} 1.441 + 1.442 + 1.443 +nsresult 1.444 +Dashboard::GetHttpConnections(HttpData *aHttpData) 1.445 +{ 1.446 + nsRefPtr<HttpData> httpData = aHttpData; 1.447 + AutoSafeJSContext cx; 1.448 + 1.449 + mozilla::dom::HttpConnDict dict; 1.450 + dict.mConnections.Construct(); 1.451 + 1.452 + using mozilla::dom::HalfOpenInfoDict; 1.453 + using mozilla::dom::HttpConnectionElement; 1.454 + using mozilla::dom::HttpConnInfo; 1.455 + Sequence<HttpConnectionElement> &connections = dict.mConnections.Value(); 1.456 + 1.457 + uint32_t length = httpData->mData.Length(); 1.458 + if (!connections.SetCapacity(length)) { 1.459 + JS_ReportOutOfMemory(cx); 1.460 + return NS_ERROR_OUT_OF_MEMORY; 1.461 + } 1.462 + 1.463 + for (uint32_t i = 0; i < httpData->mData.Length(); i++) { 1.464 + HttpConnectionElement &connection = *connections.AppendElement(); 1.465 + 1.466 + CopyASCIItoUTF16(httpData->mData[i].host, connection.mHost); 1.467 + connection.mPort = httpData->mData[i].port; 1.468 + connection.mSpdy = httpData->mData[i].spdy; 1.469 + connection.mSsl = httpData->mData[i].ssl; 1.470 + 1.471 + connection.mActive.Construct(); 1.472 + connection.mIdle.Construct(); 1.473 + connection.mHalfOpens.Construct(); 1.474 + 1.475 + Sequence<HttpConnInfo> &active = connection.mActive.Value(); 1.476 + Sequence<HttpConnInfo> &idle = connection.mIdle.Value(); 1.477 + Sequence<HalfOpenInfoDict> &halfOpens = connection.mHalfOpens.Value(); 1.478 + 1.479 + if (!active.SetCapacity(httpData->mData[i].active.Length()) || 1.480 + !idle.SetCapacity(httpData->mData[i].idle.Length()) || 1.481 + !halfOpens.SetCapacity(httpData->mData[i].halfOpens.Length())) { 1.482 + JS_ReportOutOfMemory(cx); 1.483 + return NS_ERROR_OUT_OF_MEMORY; 1.484 + } 1.485 + 1.486 + for (uint32_t j = 0; j < httpData->mData[i].active.Length(); j++) { 1.487 + HttpConnInfo &info = *active.AppendElement(); 1.488 + info.mRtt = httpData->mData[i].active[j].rtt; 1.489 + info.mTtl = httpData->mData[i].active[j].ttl; 1.490 + info.mProtocolVersion = 1.491 + httpData->mData[i].active[j].protocolVersion; 1.492 + } 1.493 + 1.494 + for (uint32_t j = 0; j < httpData->mData[i].idle.Length(); j++) { 1.495 + HttpConnInfo &info = *idle.AppendElement(); 1.496 + info.mRtt = httpData->mData[i].idle[j].rtt; 1.497 + info.mTtl = httpData->mData[i].idle[j].ttl; 1.498 + info.mProtocolVersion = httpData->mData[i].idle[j].protocolVersion; 1.499 + } 1.500 + 1.501 + for (uint32_t j = 0; j < httpData->mData[i].halfOpens.Length(); j++) { 1.502 + HalfOpenInfoDict &info = *halfOpens.AppendElement(); 1.503 + info.mSpeculative = httpData->mData[i].halfOpens[j].speculative; 1.504 + } 1.505 + } 1.506 + 1.507 + JS::RootedValue val(cx); 1.508 + if (!dict.ToObject(cx, &val)) { 1.509 + return NS_ERROR_FAILURE; 1.510 + } 1.511 + 1.512 + httpData->mCallback->OnDashboardDataAvailable(val); 1.513 + 1.514 + return NS_OK; 1.515 +} 1.516 + 1.517 +NS_IMETHODIMP 1.518 +Dashboard::GetEnableLogging(bool *value) 1.519 +{ 1.520 + *value = mEnableLogging; 1.521 + return NS_OK; 1.522 +} 1.523 + 1.524 +NS_IMETHODIMP 1.525 +Dashboard::SetEnableLogging(const bool value) 1.526 +{ 1.527 + mEnableLogging = value; 1.528 + return NS_OK; 1.529 +} 1.530 + 1.531 +NS_IMETHODIMP 1.532 +Dashboard::AddHost(const nsACString& aHost, uint32_t aSerial, bool aEncrypted) 1.533 +{ 1.534 + if (mEnableLogging) { 1.535 + mozilla::MutexAutoLock lock(mWs.lock); 1.536 + LogData mData(nsCString(aHost), aSerial, aEncrypted); 1.537 + if (mWs.data.Contains(mData)) { 1.538 + return NS_OK; 1.539 + } 1.540 + if (!mWs.data.AppendElement(mData)) { 1.541 + return NS_ERROR_OUT_OF_MEMORY; 1.542 + } 1.543 + return NS_OK; 1.544 + } 1.545 + return NS_ERROR_FAILURE; 1.546 +} 1.547 + 1.548 +NS_IMETHODIMP 1.549 +Dashboard::RemoveHost(const nsACString& aHost, uint32_t aSerial) 1.550 +{ 1.551 + if (mEnableLogging) { 1.552 + mozilla::MutexAutoLock lock(mWs.lock); 1.553 + int32_t index = mWs.IndexOf(nsCString(aHost), aSerial); 1.554 + if (index == -1) 1.555 + return NS_ERROR_FAILURE; 1.556 + mWs.data.RemoveElementAt(index); 1.557 + return NS_OK; 1.558 + } 1.559 + return NS_ERROR_FAILURE; 1.560 +} 1.561 + 1.562 +NS_IMETHODIMP 1.563 +Dashboard::NewMsgSent(const nsACString& aHost, uint32_t aSerial, uint32_t aLength) 1.564 +{ 1.565 + if (mEnableLogging) { 1.566 + mozilla::MutexAutoLock lock(mWs.lock); 1.567 + int32_t index = mWs.IndexOf(nsCString(aHost), aSerial); 1.568 + if (index == -1) 1.569 + return NS_ERROR_FAILURE; 1.570 + mWs.data[index].mMsgSent++; 1.571 + mWs.data[index].mSizeSent += aLength; 1.572 + return NS_OK; 1.573 + } 1.574 + return NS_ERROR_FAILURE; 1.575 +} 1.576 + 1.577 +NS_IMETHODIMP 1.578 +Dashboard::NewMsgReceived(const nsACString& aHost, uint32_t aSerial, uint32_t aLength) 1.579 +{ 1.580 + if (mEnableLogging) { 1.581 + mozilla::MutexAutoLock lock(mWs.lock); 1.582 + int32_t index = mWs.IndexOf(nsCString(aHost), aSerial); 1.583 + if (index == -1) 1.584 + return NS_ERROR_FAILURE; 1.585 + mWs.data[index].mMsgReceived++; 1.586 + mWs.data[index].mSizeReceived += aLength; 1.587 + return NS_OK; 1.588 + } 1.589 + return NS_ERROR_FAILURE; 1.590 +} 1.591 + 1.592 +NS_IMETHODIMP 1.593 +Dashboard::RequestWebsocketConnections(NetDashboardCallback *aCallback) 1.594 +{ 1.595 + nsRefPtr<WebSocketRequest> wsRequest = new WebSocketRequest(); 1.596 + wsRequest->mCallback = 1.597 + new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true); 1.598 + wsRequest->mThread = NS_GetCurrentThread(); 1.599 + 1.600 + nsCOMPtr<nsIRunnable> event = 1.601 + NS_NewRunnableMethodWithArg<nsRefPtr<WebSocketRequest> > 1.602 + (this, &Dashboard::GetWebSocketConnections, wsRequest); 1.603 + wsRequest->mThread->Dispatch(event, NS_DISPATCH_NORMAL); 1.604 + return NS_OK; 1.605 +} 1.606 + 1.607 +nsresult 1.608 +Dashboard::GetWebSocketConnections(WebSocketRequest *aWsRequest) 1.609 +{ 1.610 + nsRefPtr<WebSocketRequest> wsRequest = aWsRequest; 1.611 + AutoSafeJSContext cx; 1.612 + 1.613 + mozilla::dom::WebSocketDict dict; 1.614 + dict.mWebsockets.Construct(); 1.615 + Sequence<mozilla::dom::WebSocketElement> &websockets = 1.616 + dict.mWebsockets.Value(); 1.617 + 1.618 + mozilla::MutexAutoLock lock(mWs.lock); 1.619 + uint32_t length = mWs.data.Length(); 1.620 + if (!websockets.SetCapacity(length)) { 1.621 + JS_ReportOutOfMemory(cx); 1.622 + return NS_ERROR_OUT_OF_MEMORY; 1.623 + } 1.624 + 1.625 + for (uint32_t i = 0; i < mWs.data.Length(); i++) { 1.626 + mozilla::dom::WebSocketElement &websocket = *websockets.AppendElement(); 1.627 + CopyASCIItoUTF16(mWs.data[i].mHost, websocket.mHostport); 1.628 + websocket.mMsgsent = mWs.data[i].mMsgSent; 1.629 + websocket.mMsgreceived = mWs.data[i].mMsgReceived; 1.630 + websocket.mSentsize = mWs.data[i].mSizeSent; 1.631 + websocket.mReceivedsize = mWs.data[i].mSizeReceived; 1.632 + websocket.mEncrypted = mWs.data[i].mEncrypted; 1.633 + } 1.634 + 1.635 + JS::RootedValue val(cx); 1.636 + if (!dict.ToObject(cx, &val)) { 1.637 + return NS_ERROR_FAILURE; 1.638 + } 1.639 + wsRequest->mCallback->OnDashboardDataAvailable(val); 1.640 + 1.641 + return NS_OK; 1.642 +} 1.643 + 1.644 +NS_IMETHODIMP 1.645 +Dashboard::RequestDNSInfo(NetDashboardCallback *aCallback) 1.646 +{ 1.647 + nsRefPtr<DnsData> dnsData = new DnsData(); 1.648 + dnsData->mCallback = 1.649 + new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true); 1.650 + 1.651 + nsresult rv; 1.652 + dnsData->mData.Clear(); 1.653 + dnsData->mThread = NS_GetCurrentThread(); 1.654 + 1.655 + if (!mDnsService) { 1.656 + mDnsService = do_GetService("@mozilla.org/network/dns-service;1", &rv); 1.657 + if (NS_FAILED(rv)) { 1.658 + return rv; 1.659 + } 1.660 + } 1.661 + 1.662 + nsCOMPtr<nsIRunnable> event = 1.663 + NS_NewRunnableMethodWithArg<nsRefPtr<DnsData> > 1.664 + (this, &Dashboard::GetDnsInfoDispatch, dnsData); 1.665 + gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL); 1.666 + return NS_OK; 1.667 +} 1.668 + 1.669 +nsresult 1.670 +Dashboard::GetDnsInfoDispatch(DnsData *aDnsData) 1.671 +{ 1.672 + nsRefPtr<DnsData> dnsData = aDnsData; 1.673 + if (mDnsService) { 1.674 + mDnsService->GetDNSCacheEntries(&dnsData->mData); 1.675 + } 1.676 + nsCOMPtr<nsIRunnable> event = 1.677 + NS_NewRunnableMethodWithArg<nsRefPtr<DnsData> > 1.678 + (this, &Dashboard::GetDNSCacheEntries, dnsData); 1.679 + dnsData->mThread->Dispatch(event, NS_DISPATCH_NORMAL); 1.680 + return NS_OK; 1.681 +} 1.682 + 1.683 +nsresult 1.684 +Dashboard::GetDNSCacheEntries(DnsData *dnsData) 1.685 +{ 1.686 + AutoSafeJSContext cx; 1.687 + 1.688 + mozilla::dom::DNSCacheDict dict; 1.689 + dict.mEntries.Construct(); 1.690 + Sequence<mozilla::dom::DnsCacheEntry> &entries = dict.mEntries.Value(); 1.691 + 1.692 + uint32_t length = dnsData->mData.Length(); 1.693 + if (!entries.SetCapacity(length)) { 1.694 + JS_ReportOutOfMemory(cx); 1.695 + return NS_ERROR_OUT_OF_MEMORY; 1.696 + } 1.697 + 1.698 + for (uint32_t i = 0; i < dnsData->mData.Length(); i++) { 1.699 + mozilla::dom::DnsCacheEntry &entry = *entries.AppendElement(); 1.700 + entry.mHostaddr.Construct(); 1.701 + 1.702 + Sequence<nsString> &addrs = entry.mHostaddr.Value(); 1.703 + if (!addrs.SetCapacity(dnsData->mData[i].hostaddr.Length())) { 1.704 + JS_ReportOutOfMemory(cx); 1.705 + return NS_ERROR_OUT_OF_MEMORY; 1.706 + } 1.707 + 1.708 + CopyASCIItoUTF16(dnsData->mData[i].hostname, entry.mHostname); 1.709 + entry.mExpiration = dnsData->mData[i].expiration; 1.710 + 1.711 + for (uint32_t j = 0; j < dnsData->mData[i].hostaddr.Length(); j++) { 1.712 + CopyASCIItoUTF16(dnsData->mData[i].hostaddr[j], 1.713 + *addrs.AppendElement()); 1.714 + } 1.715 + 1.716 + if (dnsData->mData[i].family == PR_AF_INET6) { 1.717 + CopyASCIItoUTF16("ipv6", entry.mFamily); 1.718 + } else { 1.719 + CopyASCIItoUTF16("ipv4", entry.mFamily); 1.720 + } 1.721 + } 1.722 + 1.723 + JS::RootedValue val(cx); 1.724 + if (!dict.ToObject(cx, &val)) { 1.725 + return NS_ERROR_FAILURE; 1.726 + } 1.727 + dnsData->mCallback->OnDashboardDataAvailable(val); 1.728 + 1.729 + return NS_OK; 1.730 +} 1.731 + 1.732 +NS_IMETHODIMP 1.733 +Dashboard::RequestDNSLookup(const nsACString &aHost, 1.734 + NetDashboardCallback *aCallback) 1.735 +{ 1.736 + nsresult rv; 1.737 + 1.738 + if (!mDnsService) { 1.739 + mDnsService = do_GetService("@mozilla.org/network/dns-service;1", &rv); 1.740 + if (NS_FAILED(rv)) { 1.741 + return rv; 1.742 + } 1.743 + } 1.744 + 1.745 + nsRefPtr<LookupHelper> helper = new LookupHelper(); 1.746 + helper->mCallback = 1.747 + new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true); 1.748 + helper->mThread = NS_GetCurrentThread(); 1.749 + rv = mDnsService->AsyncResolve(aHost, 0, helper.get(), 1.750 + NS_GetCurrentThread(), 1.751 + getter_AddRefs(helper->mCancel)); 1.752 + return rv; 1.753 +} 1.754 + 1.755 +void 1.756 +HttpConnInfo::SetHTTP1ProtocolVersion(uint8_t pv) 1.757 +{ 1.758 + switch (pv) { 1.759 + case NS_HTTP_VERSION_0_9: 1.760 + protocolVersion.Assign(NS_LITERAL_STRING("http/0.9")); 1.761 + break; 1.762 + case NS_HTTP_VERSION_1_0: 1.763 + protocolVersion.Assign(NS_LITERAL_STRING("http/1.0")); 1.764 + break; 1.765 + case NS_HTTP_VERSION_1_1: 1.766 + protocolVersion.Assign(NS_LITERAL_STRING("http/1.1")); 1.767 + break; 1.768 + case NS_HTTP_VERSION_2_0: 1.769 + protocolVersion.Assign(NS_LITERAL_STRING("http/2.0")); 1.770 + break; 1.771 + default: 1.772 + protocolVersion.Assign(NS_LITERAL_STRING("unknown protocol version")); 1.773 + } 1.774 +} 1.775 + 1.776 +void 1.777 +HttpConnInfo::SetHTTP2ProtocolVersion(uint8_t pv) 1.778 +{ 1.779 + if (pv == SPDY_VERSION_3) { 1.780 + protocolVersion.Assign(NS_LITERAL_STRING("spdy/3")); 1.781 + } else if (pv == SPDY_VERSION_31) { 1.782 + protocolVersion.Assign(NS_LITERAL_STRING("spdy/3.1")); 1.783 + } else { 1.784 + MOZ_ASSERT (pv == NS_HTTP2_DRAFT_VERSION); 1.785 + protocolVersion.Assign(NS_LITERAL_STRING(NS_HTTP2_DRAFT_TOKEN)); 1.786 + } 1.787 +} 1.788 + 1.789 +NS_IMETHODIMP 1.790 +Dashboard::RequestConnection(const nsACString& aHost, uint32_t aPort, 1.791 + const char *aProtocol, uint32_t aTimeout, 1.792 + NetDashboardCallback *aCallback) 1.793 +{ 1.794 + nsresult rv; 1.795 + nsRefPtr<ConnectionData> connectionData = new ConnectionData(this); 1.796 + connectionData->mHost = aHost; 1.797 + connectionData->mPort = aPort; 1.798 + connectionData->mProtocol = aProtocol; 1.799 + connectionData->mTimeout = aTimeout; 1.800 + 1.801 + connectionData->mCallback = 1.802 + new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true); 1.803 + connectionData->mThread = NS_GetCurrentThread(); 1.804 + 1.805 + rv = TestNewConnection(connectionData); 1.806 + if (NS_FAILED(rv)) { 1.807 + CopyASCIItoUTF16(GetErrorString(rv), connectionData->mStatus); 1.808 + nsCOMPtr<nsIRunnable> event = 1.809 + NS_NewRunnableMethodWithArg<nsRefPtr<ConnectionData> > 1.810 + (this, &Dashboard::GetConnectionStatus, connectionData); 1.811 + connectionData->mThread->Dispatch(event, NS_DISPATCH_NORMAL); 1.812 + return rv; 1.813 + } 1.814 + 1.815 + return NS_OK; 1.816 +} 1.817 + 1.818 +nsresult 1.819 +Dashboard::GetConnectionStatus(ConnectionData *aConnectionData) 1.820 +{ 1.821 + nsRefPtr<ConnectionData> connectionData = aConnectionData; 1.822 + AutoSafeJSContext cx; 1.823 + 1.824 + mozilla::dom::ConnStatusDict dict; 1.825 + dict.mStatus = connectionData->mStatus; 1.826 + 1.827 + JS::RootedValue val(cx); 1.828 + if (!dict.ToObject(cx, &val)) 1.829 + return NS_ERROR_FAILURE; 1.830 + 1.831 + connectionData->mCallback->OnDashboardDataAvailable(val); 1.832 + 1.833 + return NS_OK; 1.834 +} 1.835 + 1.836 +nsresult 1.837 +Dashboard::TestNewConnection(ConnectionData *aConnectionData) 1.838 +{ 1.839 + nsRefPtr<ConnectionData> connectionData = aConnectionData; 1.840 + 1.841 + nsresult rv; 1.842 + if (!connectionData->mHost.Length() || 1.843 + !net_IsValidHostName(connectionData->mHost)) { 1.844 + return NS_ERROR_UNKNOWN_HOST; 1.845 + } 1.846 + 1.847 + if (connectionData->mProtocol && 1.848 + NS_LITERAL_STRING("ssl").EqualsASCII(connectionData->mProtocol)) { 1.849 + rv = gSocketTransportService->CreateTransport( 1.850 + &connectionData->mProtocol, 1, connectionData->mHost, 1.851 + connectionData->mPort, nullptr, 1.852 + getter_AddRefs(connectionData->mSocket)); 1.853 + } else { 1.854 + rv = gSocketTransportService->CreateTransport( 1.855 + nullptr, 0, connectionData->mHost, 1.856 + connectionData->mPort, nullptr, 1.857 + getter_AddRefs(connectionData->mSocket)); 1.858 + } 1.859 + if (NS_FAILED(rv)) { 1.860 + return rv; 1.861 + } 1.862 + 1.863 + rv = connectionData->mSocket->SetEventSink(connectionData, 1.864 + NS_GetCurrentThread()); 1.865 + if (NS_FAILED(rv)) { 1.866 + return rv; 1.867 + } 1.868 + 1.869 + rv = connectionData->mSocket->OpenInputStream( 1.870 + nsITransport::OPEN_BLOCKING, 0, 0, 1.871 + getter_AddRefs(connectionData->mStreamIn)); 1.872 + if (NS_FAILED(rv)) { 1.873 + return rv; 1.874 + } 1.875 + 1.876 + connectionData->StartTimer(connectionData->mTimeout); 1.877 + 1.878 + return rv; 1.879 +} 1.880 + 1.881 +typedef struct 1.882 +{ 1.883 + nsresult key; 1.884 + const char *error; 1.885 +} ErrorEntry; 1.886 + 1.887 +#undef ERROR 1.888 +#define ERROR(key, val) {key, #key} 1.889 + 1.890 +ErrorEntry errors[] = { 1.891 + #include "ErrorList.h" 1.892 +}; 1.893 + 1.894 +ErrorEntry socketTransportStatuses[] = { 1.895 + ERROR(NS_NET_STATUS_RESOLVING_HOST, FAILURE(3)), 1.896 + ERROR(NS_NET_STATUS_RESOLVED_HOST, FAILURE(11)), 1.897 + ERROR(NS_NET_STATUS_CONNECTING_TO, FAILURE(7)), 1.898 + ERROR(NS_NET_STATUS_CONNECTED_TO, FAILURE(4)), 1.899 + ERROR(NS_NET_STATUS_SENDING_TO, FAILURE(5)), 1.900 + ERROR(NS_NET_STATUS_WAITING_FOR, FAILURE(10)), 1.901 + ERROR(NS_NET_STATUS_RECEIVING_FROM, FAILURE(6)), 1.902 +}; 1.903 +#undef ERROR 1.904 + 1.905 +const char * 1.906 +Dashboard::GetErrorString(nsresult rv) 1.907 +{ 1.908 + int length = sizeof(socketTransportStatuses) / sizeof(ErrorEntry); 1.909 + for (int i = 0;i < length;i++) 1.910 + if (socketTransportStatuses[i].key == rv) { 1.911 + return socketTransportStatuses[i].error; 1.912 + } 1.913 + 1.914 + length = sizeof(errors) / sizeof(ErrorEntry); 1.915 + for (int i = 0;i < length;i++) 1.916 + if (errors[i].key == rv) { 1.917 + return errors[i].error; 1.918 + } 1.919 + 1.920 + return nullptr; 1.921 +} 1.922 + 1.923 +} } // namespace mozilla::net