netwerk/base/src/Dashboard.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http:mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "mozilla/dom/NetDashboardBinding.h"
michael@0 6 #include "mozilla/net/Dashboard.h"
michael@0 7 #include "mozilla/net/HttpInfo.h"
michael@0 8 #include "nsCxPusher.h"
michael@0 9 #include "nsHttp.h"
michael@0 10 #include "nsICancelable.h"
michael@0 11 #include "nsIDNSService.h"
michael@0 12 #include "nsIDNSRecord.h"
michael@0 13 #include "nsIInputStream.h"
michael@0 14 #include "nsISocketTransport.h"
michael@0 15 #include "nsIThread.h"
michael@0 16 #include "nsProxyRelease.h"
michael@0 17 #include "nsSocketTransportService2.h"
michael@0 18 #include "nsThreadUtils.h"
michael@0 19 #include "nsURLHelper.h"
michael@0 20
michael@0 21 using mozilla::AutoSafeJSContext;
michael@0 22 using mozilla::dom::Sequence;
michael@0 23
michael@0 24 namespace mozilla {
michael@0 25 namespace net {
michael@0 26
michael@0 27 class SocketData
michael@0 28 : public nsISupports
michael@0 29 {
michael@0 30 public:
michael@0 31 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 32
michael@0 33 SocketData()
michael@0 34 {
michael@0 35 mTotalSent = 0;
michael@0 36 mTotalRecv = 0;
michael@0 37 mThread = nullptr;
michael@0 38 }
michael@0 39
michael@0 40 virtual ~SocketData()
michael@0 41 {
michael@0 42 }
michael@0 43
michael@0 44 uint64_t mTotalSent;
michael@0 45 uint64_t mTotalRecv;
michael@0 46 nsTArray<SocketInfo> mData;
michael@0 47 nsMainThreadPtrHandle<NetDashboardCallback> mCallback;
michael@0 48 nsIThread *mThread;
michael@0 49 };
michael@0 50
michael@0 51 NS_IMPL_ISUPPORTS0(SocketData)
michael@0 52
michael@0 53
michael@0 54 class HttpData
michael@0 55 : public nsISupports
michael@0 56 {
michael@0 57 public:
michael@0 58 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 59
michael@0 60 HttpData()
michael@0 61 {
michael@0 62 mThread = nullptr;
michael@0 63 }
michael@0 64
michael@0 65 virtual ~HttpData()
michael@0 66 {
michael@0 67 }
michael@0 68
michael@0 69 nsTArray<HttpRetParams> mData;
michael@0 70 nsMainThreadPtrHandle<NetDashboardCallback> mCallback;
michael@0 71 nsIThread *mThread;
michael@0 72 };
michael@0 73
michael@0 74 NS_IMPL_ISUPPORTS0(HttpData)
michael@0 75
michael@0 76
michael@0 77 class WebSocketRequest
michael@0 78 : public nsISupports
michael@0 79 {
michael@0 80 public:
michael@0 81 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 82
michael@0 83 WebSocketRequest()
michael@0 84 {
michael@0 85 mThread = nullptr;
michael@0 86 }
michael@0 87
michael@0 88 virtual ~WebSocketRequest()
michael@0 89 {
michael@0 90 }
michael@0 91
michael@0 92 nsMainThreadPtrHandle<NetDashboardCallback> mCallback;
michael@0 93 nsIThread *mThread;
michael@0 94 };
michael@0 95
michael@0 96 NS_IMPL_ISUPPORTS0(WebSocketRequest)
michael@0 97
michael@0 98
michael@0 99 class DnsData
michael@0 100 : public nsISupports
michael@0 101 {
michael@0 102 public:
michael@0 103 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 104
michael@0 105 DnsData()
michael@0 106 {
michael@0 107 mThread = nullptr;
michael@0 108 }
michael@0 109
michael@0 110 virtual ~DnsData()
michael@0 111 {
michael@0 112 }
michael@0 113
michael@0 114 nsTArray<DNSCacheEntries> mData;
michael@0 115 nsMainThreadPtrHandle<NetDashboardCallback> mCallback;
michael@0 116 nsIThread *mThread;
michael@0 117 };
michael@0 118
michael@0 119 NS_IMPL_ISUPPORTS0(DnsData)
michael@0 120
michael@0 121
michael@0 122 class ConnectionData
michael@0 123 : public nsITransportEventSink
michael@0 124 , public nsITimerCallback
michael@0 125 {
michael@0 126 public:
michael@0 127 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 128 NS_DECL_NSITRANSPORTEVENTSINK
michael@0 129 NS_DECL_NSITIMERCALLBACK
michael@0 130
michael@0 131 void StartTimer(uint32_t aTimeout);
michael@0 132 void StopTimer();
michael@0 133
michael@0 134 ConnectionData(Dashboard *target)
michael@0 135 {
michael@0 136 mThread = nullptr;
michael@0 137 mDashboard = target;
michael@0 138 }
michael@0 139
michael@0 140 virtual ~ConnectionData()
michael@0 141 {
michael@0 142 if (mTimer) {
michael@0 143 mTimer->Cancel();
michael@0 144 }
michael@0 145 }
michael@0 146
michael@0 147 nsCOMPtr<nsISocketTransport> mSocket;
michael@0 148 nsCOMPtr<nsIInputStream> mStreamIn;
michael@0 149 nsCOMPtr<nsITimer> mTimer;
michael@0 150 nsMainThreadPtrHandle<NetDashboardCallback> mCallback;
michael@0 151 nsIThread *mThread;
michael@0 152 Dashboard *mDashboard;
michael@0 153
michael@0 154 nsCString mHost;
michael@0 155 uint32_t mPort;
michael@0 156 const char *mProtocol;
michael@0 157 uint32_t mTimeout;
michael@0 158
michael@0 159 nsString mStatus;
michael@0 160 };
michael@0 161
michael@0 162 NS_IMPL_ISUPPORTS(ConnectionData, nsITransportEventSink, nsITimerCallback)
michael@0 163
michael@0 164 NS_IMETHODIMP
michael@0 165 ConnectionData::OnTransportStatus(nsITransport *aTransport, nsresult aStatus,
michael@0 166 uint64_t aProgress, uint64_t aProgressMax)
michael@0 167 {
michael@0 168 if (aStatus == NS_NET_STATUS_CONNECTED_TO) {
michael@0 169 StopTimer();
michael@0 170 }
michael@0 171
michael@0 172 CopyASCIItoUTF16(Dashboard::GetErrorString(aStatus), mStatus);
michael@0 173 nsCOMPtr<nsIRunnable> event =
michael@0 174 NS_NewRunnableMethodWithArg<nsRefPtr<ConnectionData> >
michael@0 175 (mDashboard, &Dashboard::GetConnectionStatus, this);
michael@0 176 mThread->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 177
michael@0 178 return NS_OK;
michael@0 179 }
michael@0 180
michael@0 181 NS_IMETHODIMP
michael@0 182 ConnectionData::Notify(nsITimer *aTimer)
michael@0 183 {
michael@0 184 MOZ_ASSERT(aTimer == mTimer);
michael@0 185
michael@0 186 if (mSocket) {
michael@0 187 mSocket->Close(NS_ERROR_ABORT);
michael@0 188 mSocket = nullptr;
michael@0 189 mStreamIn = nullptr;
michael@0 190 }
michael@0 191
michael@0 192 mTimer = nullptr;
michael@0 193
michael@0 194 mStatus.Assign(NS_LITERAL_STRING("NS_ERROR_NET_TIMEOUT"));
michael@0 195 nsCOMPtr<nsIRunnable> event =
michael@0 196 NS_NewRunnableMethodWithArg<nsRefPtr<ConnectionData> >
michael@0 197 (mDashboard, &Dashboard::GetConnectionStatus, this);
michael@0 198 mThread->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 199
michael@0 200 return NS_OK;
michael@0 201 }
michael@0 202
michael@0 203 void
michael@0 204 ConnectionData::StartTimer(uint32_t aTimeout)
michael@0 205 {
michael@0 206 if (!mTimer) {
michael@0 207 mTimer = do_CreateInstance("@mozilla.org/timer;1");
michael@0 208 }
michael@0 209
michael@0 210 mTimer->InitWithCallback(this, aTimeout * 1000,
michael@0 211 nsITimer::TYPE_ONE_SHOT);
michael@0 212 }
michael@0 213
michael@0 214 void
michael@0 215 ConnectionData::StopTimer()
michael@0 216 {
michael@0 217 if (mTimer) {
michael@0 218 mTimer->Cancel();
michael@0 219 mTimer = nullptr;
michael@0 220 }
michael@0 221 }
michael@0 222
michael@0 223
michael@0 224 class LookupHelper;
michael@0 225
michael@0 226 class LookupArgument
michael@0 227 : public nsISupports
michael@0 228 {
michael@0 229 public:
michael@0 230 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 231
michael@0 232 LookupArgument(nsIDNSRecord *aRecord, LookupHelper *aHelper)
michael@0 233 {
michael@0 234 mRecord = aRecord;
michael@0 235 mHelper = aHelper;
michael@0 236 }
michael@0 237
michael@0 238 virtual ~LookupArgument()
michael@0 239 {
michael@0 240 }
michael@0 241
michael@0 242 nsCOMPtr<nsIDNSRecord> mRecord;
michael@0 243 nsRefPtr<LookupHelper> mHelper;
michael@0 244 };
michael@0 245
michael@0 246 NS_IMPL_ISUPPORTS0(LookupArgument)
michael@0 247
michael@0 248
michael@0 249 class LookupHelper
michael@0 250 : public nsIDNSListener
michael@0 251 {
michael@0 252 public:
michael@0 253 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 254 NS_DECL_NSIDNSLISTENER
michael@0 255
michael@0 256 LookupHelper() {
michael@0 257 }
michael@0 258
michael@0 259 virtual ~LookupHelper()
michael@0 260 {
michael@0 261 if (mCancel) {
michael@0 262 mCancel->Cancel(NS_ERROR_ABORT);
michael@0 263 }
michael@0 264 }
michael@0 265
michael@0 266 nsresult ConstructAnswer(LookupArgument *aArgument);
michael@0 267 public:
michael@0 268 nsCOMPtr<nsICancelable> mCancel;
michael@0 269 nsMainThreadPtrHandle<NetDashboardCallback> mCallback;
michael@0 270 nsIThread *mThread;
michael@0 271 nsresult mStatus;
michael@0 272 };
michael@0 273
michael@0 274 NS_IMPL_ISUPPORTS(LookupHelper, nsIDNSListener)
michael@0 275
michael@0 276 NS_IMETHODIMP
michael@0 277 LookupHelper::OnLookupComplete(nsICancelable *aRequest,
michael@0 278 nsIDNSRecord *aRecord, nsresult aStatus)
michael@0 279 {
michael@0 280 MOZ_ASSERT(aRequest == mCancel);
michael@0 281 mCancel = nullptr;
michael@0 282 mStatus = aStatus;
michael@0 283
michael@0 284 nsRefPtr<LookupArgument> arg = new LookupArgument(aRecord, this);
michael@0 285 nsCOMPtr<nsIRunnable> event =
michael@0 286 NS_NewRunnableMethodWithArg<nsRefPtr<LookupArgument> >(
michael@0 287 this, &LookupHelper::ConstructAnswer, arg);
michael@0 288 mThread->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 289
michael@0 290 return NS_OK;
michael@0 291 }
michael@0 292
michael@0 293 nsresult
michael@0 294 LookupHelper::ConstructAnswer(LookupArgument *aArgument)
michael@0 295 {
michael@0 296
michael@0 297 nsIDNSRecord *aRecord = aArgument->mRecord;
michael@0 298 AutoSafeJSContext cx;
michael@0 299
michael@0 300 mozilla::dom::DNSLookupDict dict;
michael@0 301 dict.mAddress.Construct();
michael@0 302
michael@0 303 Sequence<nsString> &addresses = dict.mAddress.Value();
michael@0 304
michael@0 305 if (NS_SUCCEEDED(mStatus)) {
michael@0 306 dict.mAnswer = true;
michael@0 307 bool hasMore;
michael@0 308 aRecord->HasMore(&hasMore);
michael@0 309 while (hasMore) {
michael@0 310 nsCString nextAddress;
michael@0 311 aRecord->GetNextAddrAsString(nextAddress);
michael@0 312 CopyASCIItoUTF16(nextAddress, *addresses.AppendElement());
michael@0 313 aRecord->HasMore(&hasMore);
michael@0 314 }
michael@0 315 } else {
michael@0 316 dict.mAnswer = false;
michael@0 317 CopyASCIItoUTF16(Dashboard::GetErrorString(mStatus), dict.mError);
michael@0 318 }
michael@0 319
michael@0 320 JS::RootedValue val(cx);
michael@0 321 if (!dict.ToObject(cx, &val)) {
michael@0 322 return NS_ERROR_FAILURE;
michael@0 323 }
michael@0 324
michael@0 325 this->mCallback->OnDashboardDataAvailable(val);
michael@0 326
michael@0 327 return NS_OK;
michael@0 328 }
michael@0 329
michael@0 330 NS_IMPL_ISUPPORTS(Dashboard, nsIDashboard, nsIDashboardEventNotifier)
michael@0 331
michael@0 332 Dashboard::Dashboard()
michael@0 333 {
michael@0 334 mEnableLogging = false;
michael@0 335 }
michael@0 336
michael@0 337 Dashboard::~Dashboard()
michael@0 338 {
michael@0 339 }
michael@0 340
michael@0 341 NS_IMETHODIMP
michael@0 342 Dashboard::RequestSockets(NetDashboardCallback *aCallback)
michael@0 343 {
michael@0 344 nsRefPtr<SocketData> socketData = new SocketData();
michael@0 345 socketData->mCallback =
michael@0 346 new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true);
michael@0 347 socketData->mThread = NS_GetCurrentThread();
michael@0 348 nsCOMPtr<nsIRunnable> event =
michael@0 349 NS_NewRunnableMethodWithArg<nsRefPtr<SocketData> >
michael@0 350 (this, &Dashboard::GetSocketsDispatch, socketData);
michael@0 351 gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 352 return NS_OK;
michael@0 353 }
michael@0 354
michael@0 355 nsresult
michael@0 356 Dashboard::GetSocketsDispatch(SocketData *aSocketData)
michael@0 357 {
michael@0 358 nsRefPtr<SocketData> socketData = aSocketData;
michael@0 359 if (gSocketTransportService) {
michael@0 360 gSocketTransportService->GetSocketConnections(&socketData->mData);
michael@0 361 socketData->mTotalSent = gSocketTransportService->GetSentBytes();
michael@0 362 socketData->mTotalRecv = gSocketTransportService->GetReceivedBytes();
michael@0 363 }
michael@0 364 nsCOMPtr<nsIRunnable> event =
michael@0 365 NS_NewRunnableMethodWithArg<nsRefPtr<SocketData> >
michael@0 366 (this, &Dashboard::GetSockets, socketData);
michael@0 367 socketData->mThread->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 368 return NS_OK;
michael@0 369 }
michael@0 370
michael@0 371 nsresult
michael@0 372 Dashboard::GetSockets(SocketData *aSocketData)
michael@0 373 {
michael@0 374 nsRefPtr<SocketData> socketData = aSocketData;
michael@0 375 AutoSafeJSContext cx;
michael@0 376
michael@0 377 mozilla::dom::SocketsDict dict;
michael@0 378 dict.mSockets.Construct();
michael@0 379 dict.mSent = 0;
michael@0 380 dict.mReceived = 0;
michael@0 381
michael@0 382 Sequence<mozilla::dom::SocketElement> &sockets = dict.mSockets.Value();
michael@0 383
michael@0 384 uint32_t length = socketData->mData.Length();
michael@0 385 if (!sockets.SetCapacity(length)) {
michael@0 386 JS_ReportOutOfMemory(cx);
michael@0 387 return NS_ERROR_OUT_OF_MEMORY;
michael@0 388 }
michael@0 389
michael@0 390 for (uint32_t i = 0; i < socketData->mData.Length(); i++) {
michael@0 391 mozilla::dom::SocketElement &mSocket = *sockets.AppendElement();
michael@0 392 CopyASCIItoUTF16(socketData->mData[i].host, mSocket.mHost);
michael@0 393 mSocket.mPort = socketData->mData[i].port;
michael@0 394 mSocket.mActive = socketData->mData[i].active;
michael@0 395 mSocket.mTcp = socketData->mData[i].tcp;
michael@0 396 mSocket.mSent = (double) socketData->mData[i].sent;
michael@0 397 mSocket.mReceived = (double) socketData->mData[i].received;
michael@0 398 dict.mSent += socketData->mData[i].sent;
michael@0 399 dict.mReceived += socketData->mData[i].received;
michael@0 400 }
michael@0 401
michael@0 402 dict.mSent += socketData->mTotalSent;
michael@0 403 dict.mReceived += socketData->mTotalRecv;
michael@0 404 JS::RootedValue val(cx);
michael@0 405 if (!dict.ToObject(cx, &val))
michael@0 406 return NS_ERROR_FAILURE;
michael@0 407 socketData->mCallback->OnDashboardDataAvailable(val);
michael@0 408
michael@0 409 return NS_OK;
michael@0 410 }
michael@0 411
michael@0 412 NS_IMETHODIMP
michael@0 413 Dashboard::RequestHttpConnections(NetDashboardCallback *aCallback)
michael@0 414 {
michael@0 415 nsRefPtr<HttpData> httpData = new HttpData();
michael@0 416 httpData->mCallback =
michael@0 417 new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true);
michael@0 418 httpData->mThread = NS_GetCurrentThread();
michael@0 419
michael@0 420 nsCOMPtr<nsIRunnable> event =
michael@0 421 NS_NewRunnableMethodWithArg<nsRefPtr<HttpData> >
michael@0 422 (this, &Dashboard::GetHttpDispatch, httpData);
michael@0 423 gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 424 return NS_OK;
michael@0 425 }
michael@0 426
michael@0 427 nsresult
michael@0 428 Dashboard::GetHttpDispatch(HttpData *aHttpData)
michael@0 429 {
michael@0 430 nsRefPtr<HttpData> httpData = aHttpData;
michael@0 431 HttpInfo::GetHttpConnectionData(&httpData->mData);
michael@0 432 nsCOMPtr<nsIRunnable> event =
michael@0 433 NS_NewRunnableMethodWithArg<nsRefPtr<HttpData> >
michael@0 434 (this, &Dashboard::GetHttpConnections, httpData);
michael@0 435 httpData->mThread->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 436 return NS_OK;
michael@0 437 }
michael@0 438
michael@0 439
michael@0 440 nsresult
michael@0 441 Dashboard::GetHttpConnections(HttpData *aHttpData)
michael@0 442 {
michael@0 443 nsRefPtr<HttpData> httpData = aHttpData;
michael@0 444 AutoSafeJSContext cx;
michael@0 445
michael@0 446 mozilla::dom::HttpConnDict dict;
michael@0 447 dict.mConnections.Construct();
michael@0 448
michael@0 449 using mozilla::dom::HalfOpenInfoDict;
michael@0 450 using mozilla::dom::HttpConnectionElement;
michael@0 451 using mozilla::dom::HttpConnInfo;
michael@0 452 Sequence<HttpConnectionElement> &connections = dict.mConnections.Value();
michael@0 453
michael@0 454 uint32_t length = httpData->mData.Length();
michael@0 455 if (!connections.SetCapacity(length)) {
michael@0 456 JS_ReportOutOfMemory(cx);
michael@0 457 return NS_ERROR_OUT_OF_MEMORY;
michael@0 458 }
michael@0 459
michael@0 460 for (uint32_t i = 0; i < httpData->mData.Length(); i++) {
michael@0 461 HttpConnectionElement &connection = *connections.AppendElement();
michael@0 462
michael@0 463 CopyASCIItoUTF16(httpData->mData[i].host, connection.mHost);
michael@0 464 connection.mPort = httpData->mData[i].port;
michael@0 465 connection.mSpdy = httpData->mData[i].spdy;
michael@0 466 connection.mSsl = httpData->mData[i].ssl;
michael@0 467
michael@0 468 connection.mActive.Construct();
michael@0 469 connection.mIdle.Construct();
michael@0 470 connection.mHalfOpens.Construct();
michael@0 471
michael@0 472 Sequence<HttpConnInfo> &active = connection.mActive.Value();
michael@0 473 Sequence<HttpConnInfo> &idle = connection.mIdle.Value();
michael@0 474 Sequence<HalfOpenInfoDict> &halfOpens = connection.mHalfOpens.Value();
michael@0 475
michael@0 476 if (!active.SetCapacity(httpData->mData[i].active.Length()) ||
michael@0 477 !idle.SetCapacity(httpData->mData[i].idle.Length()) ||
michael@0 478 !halfOpens.SetCapacity(httpData->mData[i].halfOpens.Length())) {
michael@0 479 JS_ReportOutOfMemory(cx);
michael@0 480 return NS_ERROR_OUT_OF_MEMORY;
michael@0 481 }
michael@0 482
michael@0 483 for (uint32_t j = 0; j < httpData->mData[i].active.Length(); j++) {
michael@0 484 HttpConnInfo &info = *active.AppendElement();
michael@0 485 info.mRtt = httpData->mData[i].active[j].rtt;
michael@0 486 info.mTtl = httpData->mData[i].active[j].ttl;
michael@0 487 info.mProtocolVersion =
michael@0 488 httpData->mData[i].active[j].protocolVersion;
michael@0 489 }
michael@0 490
michael@0 491 for (uint32_t j = 0; j < httpData->mData[i].idle.Length(); j++) {
michael@0 492 HttpConnInfo &info = *idle.AppendElement();
michael@0 493 info.mRtt = httpData->mData[i].idle[j].rtt;
michael@0 494 info.mTtl = httpData->mData[i].idle[j].ttl;
michael@0 495 info.mProtocolVersion = httpData->mData[i].idle[j].protocolVersion;
michael@0 496 }
michael@0 497
michael@0 498 for (uint32_t j = 0; j < httpData->mData[i].halfOpens.Length(); j++) {
michael@0 499 HalfOpenInfoDict &info = *halfOpens.AppendElement();
michael@0 500 info.mSpeculative = httpData->mData[i].halfOpens[j].speculative;
michael@0 501 }
michael@0 502 }
michael@0 503
michael@0 504 JS::RootedValue val(cx);
michael@0 505 if (!dict.ToObject(cx, &val)) {
michael@0 506 return NS_ERROR_FAILURE;
michael@0 507 }
michael@0 508
michael@0 509 httpData->mCallback->OnDashboardDataAvailable(val);
michael@0 510
michael@0 511 return NS_OK;
michael@0 512 }
michael@0 513
michael@0 514 NS_IMETHODIMP
michael@0 515 Dashboard::GetEnableLogging(bool *value)
michael@0 516 {
michael@0 517 *value = mEnableLogging;
michael@0 518 return NS_OK;
michael@0 519 }
michael@0 520
michael@0 521 NS_IMETHODIMP
michael@0 522 Dashboard::SetEnableLogging(const bool value)
michael@0 523 {
michael@0 524 mEnableLogging = value;
michael@0 525 return NS_OK;
michael@0 526 }
michael@0 527
michael@0 528 NS_IMETHODIMP
michael@0 529 Dashboard::AddHost(const nsACString& aHost, uint32_t aSerial, bool aEncrypted)
michael@0 530 {
michael@0 531 if (mEnableLogging) {
michael@0 532 mozilla::MutexAutoLock lock(mWs.lock);
michael@0 533 LogData mData(nsCString(aHost), aSerial, aEncrypted);
michael@0 534 if (mWs.data.Contains(mData)) {
michael@0 535 return NS_OK;
michael@0 536 }
michael@0 537 if (!mWs.data.AppendElement(mData)) {
michael@0 538 return NS_ERROR_OUT_OF_MEMORY;
michael@0 539 }
michael@0 540 return NS_OK;
michael@0 541 }
michael@0 542 return NS_ERROR_FAILURE;
michael@0 543 }
michael@0 544
michael@0 545 NS_IMETHODIMP
michael@0 546 Dashboard::RemoveHost(const nsACString& aHost, uint32_t aSerial)
michael@0 547 {
michael@0 548 if (mEnableLogging) {
michael@0 549 mozilla::MutexAutoLock lock(mWs.lock);
michael@0 550 int32_t index = mWs.IndexOf(nsCString(aHost), aSerial);
michael@0 551 if (index == -1)
michael@0 552 return NS_ERROR_FAILURE;
michael@0 553 mWs.data.RemoveElementAt(index);
michael@0 554 return NS_OK;
michael@0 555 }
michael@0 556 return NS_ERROR_FAILURE;
michael@0 557 }
michael@0 558
michael@0 559 NS_IMETHODIMP
michael@0 560 Dashboard::NewMsgSent(const nsACString& aHost, uint32_t aSerial, uint32_t aLength)
michael@0 561 {
michael@0 562 if (mEnableLogging) {
michael@0 563 mozilla::MutexAutoLock lock(mWs.lock);
michael@0 564 int32_t index = mWs.IndexOf(nsCString(aHost), aSerial);
michael@0 565 if (index == -1)
michael@0 566 return NS_ERROR_FAILURE;
michael@0 567 mWs.data[index].mMsgSent++;
michael@0 568 mWs.data[index].mSizeSent += aLength;
michael@0 569 return NS_OK;
michael@0 570 }
michael@0 571 return NS_ERROR_FAILURE;
michael@0 572 }
michael@0 573
michael@0 574 NS_IMETHODIMP
michael@0 575 Dashboard::NewMsgReceived(const nsACString& aHost, uint32_t aSerial, uint32_t aLength)
michael@0 576 {
michael@0 577 if (mEnableLogging) {
michael@0 578 mozilla::MutexAutoLock lock(mWs.lock);
michael@0 579 int32_t index = mWs.IndexOf(nsCString(aHost), aSerial);
michael@0 580 if (index == -1)
michael@0 581 return NS_ERROR_FAILURE;
michael@0 582 mWs.data[index].mMsgReceived++;
michael@0 583 mWs.data[index].mSizeReceived += aLength;
michael@0 584 return NS_OK;
michael@0 585 }
michael@0 586 return NS_ERROR_FAILURE;
michael@0 587 }
michael@0 588
michael@0 589 NS_IMETHODIMP
michael@0 590 Dashboard::RequestWebsocketConnections(NetDashboardCallback *aCallback)
michael@0 591 {
michael@0 592 nsRefPtr<WebSocketRequest> wsRequest = new WebSocketRequest();
michael@0 593 wsRequest->mCallback =
michael@0 594 new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true);
michael@0 595 wsRequest->mThread = NS_GetCurrentThread();
michael@0 596
michael@0 597 nsCOMPtr<nsIRunnable> event =
michael@0 598 NS_NewRunnableMethodWithArg<nsRefPtr<WebSocketRequest> >
michael@0 599 (this, &Dashboard::GetWebSocketConnections, wsRequest);
michael@0 600 wsRequest->mThread->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 601 return NS_OK;
michael@0 602 }
michael@0 603
michael@0 604 nsresult
michael@0 605 Dashboard::GetWebSocketConnections(WebSocketRequest *aWsRequest)
michael@0 606 {
michael@0 607 nsRefPtr<WebSocketRequest> wsRequest = aWsRequest;
michael@0 608 AutoSafeJSContext cx;
michael@0 609
michael@0 610 mozilla::dom::WebSocketDict dict;
michael@0 611 dict.mWebsockets.Construct();
michael@0 612 Sequence<mozilla::dom::WebSocketElement> &websockets =
michael@0 613 dict.mWebsockets.Value();
michael@0 614
michael@0 615 mozilla::MutexAutoLock lock(mWs.lock);
michael@0 616 uint32_t length = mWs.data.Length();
michael@0 617 if (!websockets.SetCapacity(length)) {
michael@0 618 JS_ReportOutOfMemory(cx);
michael@0 619 return NS_ERROR_OUT_OF_MEMORY;
michael@0 620 }
michael@0 621
michael@0 622 for (uint32_t i = 0; i < mWs.data.Length(); i++) {
michael@0 623 mozilla::dom::WebSocketElement &websocket = *websockets.AppendElement();
michael@0 624 CopyASCIItoUTF16(mWs.data[i].mHost, websocket.mHostport);
michael@0 625 websocket.mMsgsent = mWs.data[i].mMsgSent;
michael@0 626 websocket.mMsgreceived = mWs.data[i].mMsgReceived;
michael@0 627 websocket.mSentsize = mWs.data[i].mSizeSent;
michael@0 628 websocket.mReceivedsize = mWs.data[i].mSizeReceived;
michael@0 629 websocket.mEncrypted = mWs.data[i].mEncrypted;
michael@0 630 }
michael@0 631
michael@0 632 JS::RootedValue val(cx);
michael@0 633 if (!dict.ToObject(cx, &val)) {
michael@0 634 return NS_ERROR_FAILURE;
michael@0 635 }
michael@0 636 wsRequest->mCallback->OnDashboardDataAvailable(val);
michael@0 637
michael@0 638 return NS_OK;
michael@0 639 }
michael@0 640
michael@0 641 NS_IMETHODIMP
michael@0 642 Dashboard::RequestDNSInfo(NetDashboardCallback *aCallback)
michael@0 643 {
michael@0 644 nsRefPtr<DnsData> dnsData = new DnsData();
michael@0 645 dnsData->mCallback =
michael@0 646 new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true);
michael@0 647
michael@0 648 nsresult rv;
michael@0 649 dnsData->mData.Clear();
michael@0 650 dnsData->mThread = NS_GetCurrentThread();
michael@0 651
michael@0 652 if (!mDnsService) {
michael@0 653 mDnsService = do_GetService("@mozilla.org/network/dns-service;1", &rv);
michael@0 654 if (NS_FAILED(rv)) {
michael@0 655 return rv;
michael@0 656 }
michael@0 657 }
michael@0 658
michael@0 659 nsCOMPtr<nsIRunnable> event =
michael@0 660 NS_NewRunnableMethodWithArg<nsRefPtr<DnsData> >
michael@0 661 (this, &Dashboard::GetDnsInfoDispatch, dnsData);
michael@0 662 gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 663 return NS_OK;
michael@0 664 }
michael@0 665
michael@0 666 nsresult
michael@0 667 Dashboard::GetDnsInfoDispatch(DnsData *aDnsData)
michael@0 668 {
michael@0 669 nsRefPtr<DnsData> dnsData = aDnsData;
michael@0 670 if (mDnsService) {
michael@0 671 mDnsService->GetDNSCacheEntries(&dnsData->mData);
michael@0 672 }
michael@0 673 nsCOMPtr<nsIRunnable> event =
michael@0 674 NS_NewRunnableMethodWithArg<nsRefPtr<DnsData> >
michael@0 675 (this, &Dashboard::GetDNSCacheEntries, dnsData);
michael@0 676 dnsData->mThread->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 677 return NS_OK;
michael@0 678 }
michael@0 679
michael@0 680 nsresult
michael@0 681 Dashboard::GetDNSCacheEntries(DnsData *dnsData)
michael@0 682 {
michael@0 683 AutoSafeJSContext cx;
michael@0 684
michael@0 685 mozilla::dom::DNSCacheDict dict;
michael@0 686 dict.mEntries.Construct();
michael@0 687 Sequence<mozilla::dom::DnsCacheEntry> &entries = dict.mEntries.Value();
michael@0 688
michael@0 689 uint32_t length = dnsData->mData.Length();
michael@0 690 if (!entries.SetCapacity(length)) {
michael@0 691 JS_ReportOutOfMemory(cx);
michael@0 692 return NS_ERROR_OUT_OF_MEMORY;
michael@0 693 }
michael@0 694
michael@0 695 for (uint32_t i = 0; i < dnsData->mData.Length(); i++) {
michael@0 696 mozilla::dom::DnsCacheEntry &entry = *entries.AppendElement();
michael@0 697 entry.mHostaddr.Construct();
michael@0 698
michael@0 699 Sequence<nsString> &addrs = entry.mHostaddr.Value();
michael@0 700 if (!addrs.SetCapacity(dnsData->mData[i].hostaddr.Length())) {
michael@0 701 JS_ReportOutOfMemory(cx);
michael@0 702 return NS_ERROR_OUT_OF_MEMORY;
michael@0 703 }
michael@0 704
michael@0 705 CopyASCIItoUTF16(dnsData->mData[i].hostname, entry.mHostname);
michael@0 706 entry.mExpiration = dnsData->mData[i].expiration;
michael@0 707
michael@0 708 for (uint32_t j = 0; j < dnsData->mData[i].hostaddr.Length(); j++) {
michael@0 709 CopyASCIItoUTF16(dnsData->mData[i].hostaddr[j],
michael@0 710 *addrs.AppendElement());
michael@0 711 }
michael@0 712
michael@0 713 if (dnsData->mData[i].family == PR_AF_INET6) {
michael@0 714 CopyASCIItoUTF16("ipv6", entry.mFamily);
michael@0 715 } else {
michael@0 716 CopyASCIItoUTF16("ipv4", entry.mFamily);
michael@0 717 }
michael@0 718 }
michael@0 719
michael@0 720 JS::RootedValue val(cx);
michael@0 721 if (!dict.ToObject(cx, &val)) {
michael@0 722 return NS_ERROR_FAILURE;
michael@0 723 }
michael@0 724 dnsData->mCallback->OnDashboardDataAvailable(val);
michael@0 725
michael@0 726 return NS_OK;
michael@0 727 }
michael@0 728
michael@0 729 NS_IMETHODIMP
michael@0 730 Dashboard::RequestDNSLookup(const nsACString &aHost,
michael@0 731 NetDashboardCallback *aCallback)
michael@0 732 {
michael@0 733 nsresult rv;
michael@0 734
michael@0 735 if (!mDnsService) {
michael@0 736 mDnsService = do_GetService("@mozilla.org/network/dns-service;1", &rv);
michael@0 737 if (NS_FAILED(rv)) {
michael@0 738 return rv;
michael@0 739 }
michael@0 740 }
michael@0 741
michael@0 742 nsRefPtr<LookupHelper> helper = new LookupHelper();
michael@0 743 helper->mCallback =
michael@0 744 new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true);
michael@0 745 helper->mThread = NS_GetCurrentThread();
michael@0 746 rv = mDnsService->AsyncResolve(aHost, 0, helper.get(),
michael@0 747 NS_GetCurrentThread(),
michael@0 748 getter_AddRefs(helper->mCancel));
michael@0 749 return rv;
michael@0 750 }
michael@0 751
michael@0 752 void
michael@0 753 HttpConnInfo::SetHTTP1ProtocolVersion(uint8_t pv)
michael@0 754 {
michael@0 755 switch (pv) {
michael@0 756 case NS_HTTP_VERSION_0_9:
michael@0 757 protocolVersion.Assign(NS_LITERAL_STRING("http/0.9"));
michael@0 758 break;
michael@0 759 case NS_HTTP_VERSION_1_0:
michael@0 760 protocolVersion.Assign(NS_LITERAL_STRING("http/1.0"));
michael@0 761 break;
michael@0 762 case NS_HTTP_VERSION_1_1:
michael@0 763 protocolVersion.Assign(NS_LITERAL_STRING("http/1.1"));
michael@0 764 break;
michael@0 765 case NS_HTTP_VERSION_2_0:
michael@0 766 protocolVersion.Assign(NS_LITERAL_STRING("http/2.0"));
michael@0 767 break;
michael@0 768 default:
michael@0 769 protocolVersion.Assign(NS_LITERAL_STRING("unknown protocol version"));
michael@0 770 }
michael@0 771 }
michael@0 772
michael@0 773 void
michael@0 774 HttpConnInfo::SetHTTP2ProtocolVersion(uint8_t pv)
michael@0 775 {
michael@0 776 if (pv == SPDY_VERSION_3) {
michael@0 777 protocolVersion.Assign(NS_LITERAL_STRING("spdy/3"));
michael@0 778 } else if (pv == SPDY_VERSION_31) {
michael@0 779 protocolVersion.Assign(NS_LITERAL_STRING("spdy/3.1"));
michael@0 780 } else {
michael@0 781 MOZ_ASSERT (pv == NS_HTTP2_DRAFT_VERSION);
michael@0 782 protocolVersion.Assign(NS_LITERAL_STRING(NS_HTTP2_DRAFT_TOKEN));
michael@0 783 }
michael@0 784 }
michael@0 785
michael@0 786 NS_IMETHODIMP
michael@0 787 Dashboard::RequestConnection(const nsACString& aHost, uint32_t aPort,
michael@0 788 const char *aProtocol, uint32_t aTimeout,
michael@0 789 NetDashboardCallback *aCallback)
michael@0 790 {
michael@0 791 nsresult rv;
michael@0 792 nsRefPtr<ConnectionData> connectionData = new ConnectionData(this);
michael@0 793 connectionData->mHost = aHost;
michael@0 794 connectionData->mPort = aPort;
michael@0 795 connectionData->mProtocol = aProtocol;
michael@0 796 connectionData->mTimeout = aTimeout;
michael@0 797
michael@0 798 connectionData->mCallback =
michael@0 799 new nsMainThreadPtrHolder<NetDashboardCallback>(aCallback, true);
michael@0 800 connectionData->mThread = NS_GetCurrentThread();
michael@0 801
michael@0 802 rv = TestNewConnection(connectionData);
michael@0 803 if (NS_FAILED(rv)) {
michael@0 804 CopyASCIItoUTF16(GetErrorString(rv), connectionData->mStatus);
michael@0 805 nsCOMPtr<nsIRunnable> event =
michael@0 806 NS_NewRunnableMethodWithArg<nsRefPtr<ConnectionData> >
michael@0 807 (this, &Dashboard::GetConnectionStatus, connectionData);
michael@0 808 connectionData->mThread->Dispatch(event, NS_DISPATCH_NORMAL);
michael@0 809 return rv;
michael@0 810 }
michael@0 811
michael@0 812 return NS_OK;
michael@0 813 }
michael@0 814
michael@0 815 nsresult
michael@0 816 Dashboard::GetConnectionStatus(ConnectionData *aConnectionData)
michael@0 817 {
michael@0 818 nsRefPtr<ConnectionData> connectionData = aConnectionData;
michael@0 819 AutoSafeJSContext cx;
michael@0 820
michael@0 821 mozilla::dom::ConnStatusDict dict;
michael@0 822 dict.mStatus = connectionData->mStatus;
michael@0 823
michael@0 824 JS::RootedValue val(cx);
michael@0 825 if (!dict.ToObject(cx, &val))
michael@0 826 return NS_ERROR_FAILURE;
michael@0 827
michael@0 828 connectionData->mCallback->OnDashboardDataAvailable(val);
michael@0 829
michael@0 830 return NS_OK;
michael@0 831 }
michael@0 832
michael@0 833 nsresult
michael@0 834 Dashboard::TestNewConnection(ConnectionData *aConnectionData)
michael@0 835 {
michael@0 836 nsRefPtr<ConnectionData> connectionData = aConnectionData;
michael@0 837
michael@0 838 nsresult rv;
michael@0 839 if (!connectionData->mHost.Length() ||
michael@0 840 !net_IsValidHostName(connectionData->mHost)) {
michael@0 841 return NS_ERROR_UNKNOWN_HOST;
michael@0 842 }
michael@0 843
michael@0 844 if (connectionData->mProtocol &&
michael@0 845 NS_LITERAL_STRING("ssl").EqualsASCII(connectionData->mProtocol)) {
michael@0 846 rv = gSocketTransportService->CreateTransport(
michael@0 847 &connectionData->mProtocol, 1, connectionData->mHost,
michael@0 848 connectionData->mPort, nullptr,
michael@0 849 getter_AddRefs(connectionData->mSocket));
michael@0 850 } else {
michael@0 851 rv = gSocketTransportService->CreateTransport(
michael@0 852 nullptr, 0, connectionData->mHost,
michael@0 853 connectionData->mPort, nullptr,
michael@0 854 getter_AddRefs(connectionData->mSocket));
michael@0 855 }
michael@0 856 if (NS_FAILED(rv)) {
michael@0 857 return rv;
michael@0 858 }
michael@0 859
michael@0 860 rv = connectionData->mSocket->SetEventSink(connectionData,
michael@0 861 NS_GetCurrentThread());
michael@0 862 if (NS_FAILED(rv)) {
michael@0 863 return rv;
michael@0 864 }
michael@0 865
michael@0 866 rv = connectionData->mSocket->OpenInputStream(
michael@0 867 nsITransport::OPEN_BLOCKING, 0, 0,
michael@0 868 getter_AddRefs(connectionData->mStreamIn));
michael@0 869 if (NS_FAILED(rv)) {
michael@0 870 return rv;
michael@0 871 }
michael@0 872
michael@0 873 connectionData->StartTimer(connectionData->mTimeout);
michael@0 874
michael@0 875 return rv;
michael@0 876 }
michael@0 877
michael@0 878 typedef struct
michael@0 879 {
michael@0 880 nsresult key;
michael@0 881 const char *error;
michael@0 882 } ErrorEntry;
michael@0 883
michael@0 884 #undef ERROR
michael@0 885 #define ERROR(key, val) {key, #key}
michael@0 886
michael@0 887 ErrorEntry errors[] = {
michael@0 888 #include "ErrorList.h"
michael@0 889 };
michael@0 890
michael@0 891 ErrorEntry socketTransportStatuses[] = {
michael@0 892 ERROR(NS_NET_STATUS_RESOLVING_HOST, FAILURE(3)),
michael@0 893 ERROR(NS_NET_STATUS_RESOLVED_HOST, FAILURE(11)),
michael@0 894 ERROR(NS_NET_STATUS_CONNECTING_TO, FAILURE(7)),
michael@0 895 ERROR(NS_NET_STATUS_CONNECTED_TO, FAILURE(4)),
michael@0 896 ERROR(NS_NET_STATUS_SENDING_TO, FAILURE(5)),
michael@0 897 ERROR(NS_NET_STATUS_WAITING_FOR, FAILURE(10)),
michael@0 898 ERROR(NS_NET_STATUS_RECEIVING_FROM, FAILURE(6)),
michael@0 899 };
michael@0 900 #undef ERROR
michael@0 901
michael@0 902 const char *
michael@0 903 Dashboard::GetErrorString(nsresult rv)
michael@0 904 {
michael@0 905 int length = sizeof(socketTransportStatuses) / sizeof(ErrorEntry);
michael@0 906 for (int i = 0;i < length;i++)
michael@0 907 if (socketTransportStatuses[i].key == rv) {
michael@0 908 return socketTransportStatuses[i].error;
michael@0 909 }
michael@0 910
michael@0 911 length = sizeof(errors) / sizeof(ErrorEntry);
michael@0 912 for (int i = 0;i < length;i++)
michael@0 913 if (errors[i].key == rv) {
michael@0 914 return errors[i].error;
michael@0 915 }
michael@0 916
michael@0 917 return nullptr;
michael@0 918 }
michael@0 919
michael@0 920 } } // namespace mozilla::net

mercurial