Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsPACMan.h"
8 #include "nsThreadUtils.h"
9 #include "nsIAuthPrompt.h"
10 #include "nsIPromptFactory.h"
11 #include "nsIHttpChannel.h"
12 #include "nsIPrefService.h"
13 #include "nsIPrefBranch.h"
14 #include "nsNetUtil.h"
15 #include "nsIAsyncVerifyRedirectCallback.h"
16 #include "nsISystemProxySettings.h"
17 #ifdef MOZ_NUWA_PROCESS
18 #include "ipc/Nuwa.h"
19 #endif
21 //-----------------------------------------------------------------------------
22 using namespace mozilla;
23 using namespace mozilla::net;
25 #if defined(PR_LOGGING)
26 #endif
27 #undef LOG
28 #define LOG(args) PR_LOG(GetProxyLog(), PR_LOG_DEBUG, args)
30 // The PAC thread does evaluations of both PAC files and
31 // nsISystemProxySettings because they can both block the calling thread and we
32 // don't want that on the main thread
34 // Check to see if the underlying request was not an error page in the case of
35 // a HTTP request. For other types of channels, just return true.
36 static bool
37 HttpRequestSucceeded(nsIStreamLoader *loader)
38 {
39 nsCOMPtr<nsIRequest> request;
40 loader->GetRequest(getter_AddRefs(request));
42 bool result = true; // default to assuming success
44 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request);
45 if (httpChannel)
46 httpChannel->GetRequestSucceeded(&result);
48 return result;
49 }
51 //-----------------------------------------------------------------------------
53 // The ExecuteCallback runnable is triggered by
54 // nsPACManCallback::OnQueryComplete on the Main thread when its completion is
55 // discovered on the pac thread
57 class ExecuteCallback MOZ_FINAL : public nsRunnable
58 {
59 public:
60 ExecuteCallback(nsPACManCallback *aCallback,
61 nsresult status)
62 : mCallback(aCallback)
63 , mStatus(status)
64 {
65 }
67 void SetPACString(const nsCString &pacString)
68 {
69 mPACString = pacString;
70 }
72 void SetPACURL(const nsCString &pacURL)
73 {
74 mPACURL = pacURL;
75 }
77 NS_IMETHODIMP Run()
78 {
79 mCallback->OnQueryComplete(mStatus, mPACString, mPACURL);
80 mCallback = nullptr;
81 return NS_OK;
82 }
84 private:
85 nsRefPtr<nsPACManCallback> mCallback;
86 nsresult mStatus;
87 nsCString mPACString;
88 nsCString mPACURL;
89 };
91 //-----------------------------------------------------------------------------
93 // The PAC thread must be deleted from the main thread, this class
94 // acts as a proxy to do that, as the PACMan is reference counted
95 // and might be destroyed on either thread
97 class ShutdownThread MOZ_FINAL : public nsRunnable
98 {
99 public:
100 ShutdownThread(nsIThread *thread)
101 : mThread(thread)
102 {
103 }
105 NS_IMETHODIMP Run()
106 {
107 NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
108 mThread->Shutdown();
109 return NS_OK;
110 }
112 private:
113 nsCOMPtr<nsIThread> mThread;
114 };
116 // Dispatch this to wait until the PAC thread shuts down.
118 class WaitForThreadShutdown MOZ_FINAL : public nsRunnable
119 {
120 public:
121 explicit WaitForThreadShutdown(nsPACMan *aPACMan)
122 : mPACMan(aPACMan)
123 {
124 }
126 NS_IMETHODIMP Run()
127 {
128 NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
129 if (mPACMan->mPACThread) {
130 mPACMan->mPACThread->Shutdown();
131 mPACMan->mPACThread = nullptr;
132 }
133 return NS_OK;
134 }
136 private:
137 nsRefPtr<nsPACMan> mPACMan;
138 };
140 //-----------------------------------------------------------------------------
142 // PACLoadComplete allows the PAC thread to tell the main thread that
143 // the javascript PAC file has been installed (perhaps unsuccessfully)
144 // and that there is no reason to queue executions anymore
146 class PACLoadComplete MOZ_FINAL : public nsRunnable
147 {
148 public:
149 PACLoadComplete(nsPACMan *aPACMan)
150 : mPACMan(aPACMan)
151 {
152 }
154 NS_IMETHODIMP Run()
155 {
156 NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
157 mPACMan->mLoader = nullptr;
158 mPACMan->PostProcessPendingQ();
159 return NS_OK;
160 }
162 private:
163 nsRefPtr<nsPACMan> mPACMan;
164 };
166 //-----------------------------------------------------------------------------
168 // ExecutePACThreadAction is used to proxy actions from the main
169 // thread onto the PAC thread. There are 3 options: process the queue,
170 // cancel the queue, and setup the javascript context with a new PAC file
172 class ExecutePACThreadAction MOZ_FINAL : public nsRunnable
173 {
174 public:
175 // by default we just process the queue
176 ExecutePACThreadAction(nsPACMan *aPACMan)
177 : mPACMan(aPACMan)
178 , mCancel(false)
179 , mSetupPAC(false)
180 { }
182 void CancelQueue (nsresult status)
183 {
184 mCancel = true;
185 mCancelStatus = status;
186 }
188 void SetupPAC (const char *text, uint32_t datalen, nsCString &pacURI)
189 {
190 mSetupPAC = true;
191 mSetupPACData.Assign(text, datalen);
192 mSetupPACURI = pacURI;
193 }
195 NS_IMETHODIMP Run()
196 {
197 NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
198 if (mCancel) {
199 mPACMan->CancelPendingQ(mCancelStatus);
200 mCancel = false;
201 return NS_OK;
202 }
204 if (mSetupPAC) {
205 mSetupPAC = false;
207 mPACMan->mPAC.Init(mSetupPACURI,
208 mSetupPACData);
210 nsRefPtr<PACLoadComplete> runnable = new PACLoadComplete(mPACMan);
211 NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
212 return NS_OK;
213 }
215 mPACMan->ProcessPendingQ();
216 return NS_OK;
217 }
219 private:
220 nsRefPtr<nsPACMan> mPACMan;
222 bool mCancel;
223 nsresult mCancelStatus;
225 bool mSetupPAC;
226 nsCString mSetupPACData;
227 nsCString mSetupPACURI;
228 };
230 //-----------------------------------------------------------------------------
232 PendingPACQuery::PendingPACQuery(nsPACMan *pacMan, nsIURI *uri,
233 nsPACManCallback *callback,
234 bool mainThreadResponse)
235 : mPACMan(pacMan)
236 , mCallback(callback)
237 , mOnMainThreadOnly(mainThreadResponse)
238 {
239 uri->GetAsciiSpec(mSpec);
240 uri->GetAsciiHost(mHost);
241 uri->GetScheme(mScheme);
242 uri->GetPort(&mPort);
243 }
245 void
246 PendingPACQuery::Complete(nsresult status, const nsCString &pacString)
247 {
248 if (!mCallback)
249 return;
250 nsRefPtr<ExecuteCallback> runnable = new ExecuteCallback(mCallback, status);
251 runnable->SetPACString(pacString);
252 if (mOnMainThreadOnly)
253 NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
254 else
255 runnable->Run();
256 }
258 void
259 PendingPACQuery::UseAlternatePACFile(const nsCString &pacURL)
260 {
261 if (!mCallback)
262 return;
264 nsRefPtr<ExecuteCallback> runnable = new ExecuteCallback(mCallback, NS_OK);
265 runnable->SetPACURL(pacURL);
266 if (mOnMainThreadOnly)
267 NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
268 else
269 runnable->Run();
270 }
272 NS_IMETHODIMP
273 PendingPACQuery::Run()
274 {
275 NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
276 mPACMan->PostQuery(this);
277 return NS_OK;
278 }
280 //-----------------------------------------------------------------------------
282 nsPACMan::nsPACMan()
283 : mLoadPending(false)
284 , mShutdown(false)
285 , mLoadFailureCount(0)
286 , mInProgress(false)
287 {
288 NS_ABORT_IF_FALSE(NS_IsMainThread(), "pacman must be created on main thread");
289 }
291 nsPACMan::~nsPACMan()
292 {
293 if (mPACThread) {
294 if (NS_IsMainThread()) {
295 mPACThread->Shutdown();
296 }
297 else {
298 nsRefPtr<ShutdownThread> runnable = new ShutdownThread(mPACThread);
299 NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
300 }
301 }
303 NS_ASSERTION(mLoader == nullptr, "pac man not shutdown properly");
304 NS_ASSERTION(mPendingQ.isEmpty(), "pac man not shutdown properly");
305 }
307 void
308 nsPACMan::Shutdown()
309 {
310 NS_ABORT_IF_FALSE(NS_IsMainThread(), "pacman must be shutdown on main thread");
311 if (mShutdown) {
312 return;
313 }
314 mShutdown = true;
315 CancelExistingLoad();
316 PostCancelPendingQ(NS_ERROR_ABORT);
318 nsRefPtr<WaitForThreadShutdown> runnable = new WaitForThreadShutdown(this);
319 NS_DispatchToMainThread(runnable);
320 }
322 nsresult
323 nsPACMan::AsyncGetProxyForChannel(nsIChannel *channel, nsPACManCallback *callback,
324 bool mainThreadResponse)
325 {
326 NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
327 if (mShutdown)
328 return NS_ERROR_NOT_AVAILABLE;
330 // Maybe Reload PAC
331 if (!mPACURISpec.IsEmpty() && !mScheduledReload.IsNull() &&
332 TimeStamp::Now() > mScheduledReload)
333 LoadPACFromURI(EmptyCString());
335 nsCOMPtr<nsIURI> uri;
336 nsresult rv = channel->GetURI(getter_AddRefs(uri));
337 if (NS_FAILED(rv))
338 return rv;
340 nsRefPtr<PendingPACQuery> query =
341 new PendingPACQuery(this, uri, callback, mainThreadResponse);
343 if (IsPACURI(uri)) {
344 // deal with this directly instead of queueing it
345 query->Complete(NS_OK, EmptyCString());
346 return NS_OK;
347 }
349 return mPACThread->Dispatch(query, nsIEventTarget::DISPATCH_NORMAL);
350 }
352 nsresult
353 nsPACMan::PostQuery(PendingPACQuery *query)
354 {
355 NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
357 if (mShutdown) {
358 query->Complete(NS_ERROR_NOT_AVAILABLE, EmptyCString());
359 return NS_OK;
360 }
362 // add a reference to the query while it is in the pending list
363 nsRefPtr<PendingPACQuery> addref(query);
364 mPendingQ.insertBack(addref.forget().take());
365 ProcessPendingQ();
366 return NS_OK;
367 }
369 nsresult
370 nsPACMan::LoadPACFromURI(const nsCString &spec)
371 {
372 NS_ENSURE_STATE(!mShutdown);
373 NS_ENSURE_ARG(!spec.IsEmpty() || !mPACURISpec.IsEmpty());
375 nsCOMPtr<nsIStreamLoader> loader =
376 do_CreateInstance(NS_STREAMLOADER_CONTRACTID);
377 NS_ENSURE_STATE(loader);
379 // Since we might get called from nsProtocolProxyService::Init, we need to
380 // post an event back to the main thread before we try to use the IO service.
381 //
382 // But, we need to flag ourselves as loading, so that we queue up any PAC
383 // queries the enter between now and when we actually load the PAC file.
385 if (!mLoadPending) {
386 nsCOMPtr<nsIRunnable> event =
387 NS_NewRunnableMethod(this, &nsPACMan::StartLoading);
388 nsresult rv;
389 if (NS_FAILED(rv = NS_DispatchToCurrentThread(event)))
390 return rv;
391 mLoadPending = true;
392 }
394 CancelExistingLoad();
396 mLoader = loader;
397 if (!spec.IsEmpty()) {
398 mPACURISpec = spec;
399 mPACURIRedirectSpec.Truncate();
400 mNormalPACURISpec.Truncate(); // set at load time
401 mLoadFailureCount = 0; // reset
402 }
404 // reset to Null
405 mScheduledReload = TimeStamp();
406 return NS_OK;
407 }
409 void
410 nsPACMan::StartLoading()
411 {
412 NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
413 mLoadPending = false;
415 // CancelExistingLoad was called...
416 if (!mLoader) {
417 PostCancelPendingQ(NS_ERROR_ABORT);
418 return;
419 }
421 if (NS_SUCCEEDED(mLoader->Init(this))) {
422 // Always hit the origin server when loading PAC.
423 nsCOMPtr<nsIIOService> ios = do_GetIOService();
424 if (ios) {
425 nsCOMPtr<nsIChannel> channel;
426 nsCOMPtr<nsIURI> pacURI;
427 NS_NewURI(getter_AddRefs(pacURI), mPACURISpec);
429 // NOTE: This results in GetProxyForURI being called
430 if (pacURI) {
431 pacURI->GetSpec(mNormalPACURISpec);
432 ios->NewChannelFromURI(pacURI, getter_AddRefs(channel));
433 }
434 else {
435 LOG(("nsPACMan::StartLoading Failed pacspec uri conversion %s\n",
436 mPACURISpec.get()));
437 }
439 if (channel) {
440 channel->SetLoadFlags(nsIRequest::LOAD_BYPASS_CACHE);
441 channel->SetNotificationCallbacks(this);
442 if (NS_SUCCEEDED(channel->AsyncOpen(mLoader, nullptr)))
443 return;
444 }
445 }
446 }
448 CancelExistingLoad();
449 PostCancelPendingQ(NS_ERROR_UNEXPECTED);
450 }
453 void
454 nsPACMan::OnLoadFailure()
455 {
456 int32_t minInterval = 5; // 5 seconds
457 int32_t maxInterval = 300; // 5 minutes
459 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
460 if (prefs) {
461 prefs->GetIntPref("network.proxy.autoconfig_retry_interval_min",
462 &minInterval);
463 prefs->GetIntPref("network.proxy.autoconfig_retry_interval_max",
464 &maxInterval);
465 }
467 int32_t interval = minInterval << mLoadFailureCount++; // seconds
468 if (!interval || interval > maxInterval)
469 interval = maxInterval;
471 mScheduledReload = TimeStamp::Now() + TimeDuration::FromSeconds(interval);
473 // while we wait for the retry queued members should try direct
474 // even if that means fast failure.
475 PostCancelPendingQ(NS_ERROR_NOT_AVAILABLE);
476 }
478 void
479 nsPACMan::CancelExistingLoad()
480 {
481 if (mLoader) {
482 nsCOMPtr<nsIRequest> request;
483 mLoader->GetRequest(getter_AddRefs(request));
484 if (request)
485 request->Cancel(NS_ERROR_ABORT);
486 mLoader = nullptr;
487 }
488 }
490 void
491 nsPACMan::PostProcessPendingQ()
492 {
493 NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
494 nsRefPtr<ExecutePACThreadAction> pending =
495 new ExecutePACThreadAction(this);
496 if (mPACThread)
497 mPACThread->Dispatch(pending, nsIEventTarget::DISPATCH_NORMAL);
498 }
500 void
501 nsPACMan::PostCancelPendingQ(nsresult status)
502 {
503 NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
504 nsRefPtr<ExecutePACThreadAction> pending =
505 new ExecutePACThreadAction(this);
506 pending->CancelQueue(status);
507 if (mPACThread)
508 mPACThread->Dispatch(pending, nsIEventTarget::DISPATCH_NORMAL);
509 }
511 void
512 nsPACMan::CancelPendingQ(nsresult status)
513 {
514 NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
515 nsRefPtr<PendingPACQuery> query;
517 while (!mPendingQ.isEmpty()) {
518 query = dont_AddRef(mPendingQ.popLast());
519 query->Complete(status, EmptyCString());
520 }
522 if (mShutdown)
523 mPAC.Shutdown();
524 }
526 void
527 nsPACMan::ProcessPendingQ()
528 {
529 NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
530 while (ProcessPending());
532 if (mShutdown) {
533 mPAC.Shutdown();
534 } else {
535 // do GC while the thread has nothing pending
536 mPAC.GC();
537 }
538 }
540 // returns true if progress was made by shortening the queue
541 bool
542 nsPACMan::ProcessPending()
543 {
544 if (mPendingQ.isEmpty())
545 return false;
547 // queue during normal load, but if we are retrying a failed load then
548 // fast fail the queries
549 if (mInProgress || (IsLoading() && !mLoadFailureCount))
550 return false;
552 nsRefPtr<PendingPACQuery> query(dont_AddRef(mPendingQ.popFirst()));
554 if (mShutdown || IsLoading()) {
555 query->Complete(NS_ERROR_NOT_AVAILABLE, EmptyCString());
556 return true;
557 }
559 nsAutoCString pacString;
560 bool completed = false;
561 mInProgress = true;
562 nsAutoCString PACURI;
564 // first we need to consider the system proxy changing the pac url
565 if (mSystemProxySettings &&
566 NS_SUCCEEDED(mSystemProxySettings->GetPACURI(PACURI)) &&
567 !PACURI.IsEmpty() &&
568 !PACURI.Equals(mPACURISpec)) {
569 query->UseAlternatePACFile(PACURI);
570 completed = true;
571 }
573 // now try the system proxy settings for this particular url if
574 // PAC was not specified
575 if (!completed && mSystemProxySettings && PACURI.IsEmpty() &&
576 NS_SUCCEEDED(mSystemProxySettings->
577 GetProxyForURI(query->mSpec, query->mScheme,
578 query->mHost, query->mPort,
579 pacString))) {
580 query->Complete(NS_OK, pacString);
581 completed = true;
582 }
584 // the systemproxysettings didn't complete the resolution. try via PAC
585 if (!completed) {
586 nsresult status = mPAC.GetProxyForURI(query->mSpec, query->mHost, pacString);
587 query->Complete(status, pacString);
588 }
590 mInProgress = false;
591 return true;
592 }
594 NS_IMPL_ISUPPORTS(nsPACMan, nsIStreamLoaderObserver,
595 nsIInterfaceRequestor, nsIChannelEventSink)
597 NS_IMETHODIMP
598 nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
599 nsISupports *context,
600 nsresult status,
601 uint32_t dataLen,
602 const uint8_t *data)
603 {
604 NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
605 if (mLoader != loader) {
606 // If this happens, then it means that LoadPACFromURI was called more
607 // than once before the initial call completed. In this case, status
608 // should be NS_ERROR_ABORT, and if so, then we know that we can and
609 // should delay any processing.
610 if (status == NS_ERROR_ABORT)
611 return NS_OK;
612 }
614 if (NS_SUCCEEDED(status) && HttpRequestSucceeded(loader)) {
615 // Get the URI spec used to load this PAC script.
616 nsAutoCString pacURI;
617 {
618 nsCOMPtr<nsIRequest> request;
619 loader->GetRequest(getter_AddRefs(request));
620 nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
621 if (channel) {
622 nsCOMPtr<nsIURI> uri;
623 channel->GetURI(getter_AddRefs(uri));
624 if (uri)
625 uri->GetAsciiSpec(pacURI);
626 }
627 }
629 // We assume that the PAC text is ASCII (or ISO-Latin-1). We've had this
630 // assumption forever, and some real-world PAC scripts actually have some
631 // non-ASCII text in comment blocks (see bug 296163).
632 const char *text = (const char *) data;
634 // we have succeeded in loading the pac file using a bunch of interfaces that
635 // are main thread only, unfortunately we have to initialize the instance of
636 // the PAC evaluator (NS_PROXYAUTOCONFIG_CONTRACTID) on the pac thread, because
637 // that is where it will be used.
639 nsRefPtr<ExecutePACThreadAction> pending =
640 new ExecutePACThreadAction(this);
641 pending->SetupPAC(text, dataLen, pacURI);
642 if (mPACThread)
643 mPACThread->Dispatch(pending, nsIEventTarget::DISPATCH_NORMAL);
645 // Even if the PAC file could not be parsed, we did succeed in loading the
646 // data for it.
647 mLoadFailureCount = 0;
648 } else {
649 // We were unable to load the PAC file (presumably because of a network
650 // failure). Try again a little later.
651 OnLoadFailure();
652 }
654 if (NS_SUCCEEDED(status))
655 PostProcessPendingQ();
656 else
657 PostCancelPendingQ(status);
659 return NS_OK;
660 }
662 NS_IMETHODIMP
663 nsPACMan::GetInterface(const nsIID &iid, void **result)
664 {
665 // In case loading the PAC file requires authentication.
666 if (iid.Equals(NS_GET_IID(nsIAuthPrompt))) {
667 nsCOMPtr<nsIPromptFactory> promptFac = do_GetService("@mozilla.org/prompter;1");
668 NS_ENSURE_TRUE(promptFac, NS_ERROR_FAILURE);
669 return promptFac->GetPrompt(nullptr, iid, reinterpret_cast<void**>(result));
670 }
672 // In case loading the PAC file results in a redirect.
673 if (iid.Equals(NS_GET_IID(nsIChannelEventSink))) {
674 NS_ADDREF_THIS();
675 *result = static_cast<nsIChannelEventSink *>(this);
676 return NS_OK;
677 }
679 return NS_ERROR_NO_INTERFACE;
680 }
682 NS_IMETHODIMP
683 nsPACMan::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel,
684 uint32_t flags,
685 nsIAsyncVerifyRedirectCallback *callback)
686 {
687 NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
689 nsresult rv = NS_OK;
690 nsCOMPtr<nsIURI> pacURI;
691 if (NS_FAILED((rv = newChannel->GetURI(getter_AddRefs(pacURI)))))
692 return rv;
694 rv = pacURI->GetSpec(mPACURIRedirectSpec);
695 if (NS_FAILED(rv))
696 return rv;
698 LOG(("nsPACMan redirect from original %s to redirected %s\n",
699 mPACURISpec.get(), mPACURIRedirectSpec.get()));
701 // do not update mPACURISpec - that needs to stay as the
702 // configured URI so that we can determine when the config changes.
703 // However do track the most recent URI in the redirect change
704 // as mPACURIRedirectSpec so that URI can be allowed to bypass
705 // the proxy and actually fetch the pac file.
707 callback->OnRedirectVerifyCallback(NS_OK);
708 return NS_OK;
709 }
711 void
712 nsPACMan::NamePACThread()
713 {
714 NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
715 PR_SetCurrentThreadName("Proxy Resolution");
716 #ifdef MOZ_NUWA_PROCESS
717 if (IsNuwaProcess()) {
718 NS_ASSERTION(NuwaMarkCurrentThread != nullptr,
719 "NuwaMarkCurrentThread is undefined!");
720 NuwaMarkCurrentThread(nullptr, nullptr);
721 }
722 #endif
723 }
725 nsresult
726 nsPACMan::Init(nsISystemProxySettings *systemProxySettings)
727 {
728 mSystemProxySettings = systemProxySettings;
730 nsresult rv = NS_NewThread(getter_AddRefs(mPACThread), nullptr);
731 if (NS_FAILED(rv))
732 return rv;
734 nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &nsPACMan::NamePACThread);
735 // don't check return value as it is not a big deal for this to fail.
736 mPACThread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
738 return NS_OK;
739 }
741 namespace mozilla {
742 namespace net {
744 PRLogModuleInfo*
745 GetProxyLog()
746 {
747 static PRLogModuleInfo *sLog;
748 if (!sLog)
749 sLog = PR_NewLogModule("proxy");
750 return sLog;
751 }
753 }
754 }