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