netwerk/base/src/nsPACMan.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.

     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 }

mercurial