LCOV - code coverage report
Current view: top level - netwerk/base - nsIOService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 223 670 33.3 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim:set ts=4 sw=4 cindent et: */
       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/. */
       6             : 
       7             : #include "mozilla/DebugOnly.h"
       8             : 
       9             : #include "nsIOService.h"
      10             : #include "nsIProtocolHandler.h"
      11             : #include "nsIFileProtocolHandler.h"
      12             : #include "nscore.h"
      13             : #include "nsIURI.h"
      14             : #include "prprf.h"
      15             : #include "nsIErrorService.h"
      16             : #include "netCore.h"
      17             : #include "nsIObserverService.h"
      18             : #include "nsIPrefService.h"
      19             : #include "nsXPCOM.h"
      20             : #include "nsIProxiedProtocolHandler.h"
      21             : #include "nsIProxyInfo.h"
      22             : #include "nsEscape.h"
      23             : #include "nsNetUtil.h"
      24             : #include "nsNetCID.h"
      25             : #include "nsCRT.h"
      26             : #include "nsSecCheckWrapChannel.h"
      27             : #include "nsSimpleNestedURI.h"
      28             : #include "nsTArray.h"
      29             : #include "nsIConsoleService.h"
      30             : #include "nsIUploadChannel2.h"
      31             : #include "nsXULAppAPI.h"
      32             : #include "nsIScriptSecurityManager.h"
      33             : #include "nsIProtocolProxyCallback.h"
      34             : #include "nsICancelable.h"
      35             : #include "nsINetworkLinkService.h"
      36             : #include "nsPISocketTransportService.h"
      37             : #include "nsAsyncRedirectVerifyHelper.h"
      38             : #include "nsURLHelper.h"
      39             : #include "nsIProtocolProxyService2.h"
      40             : #include "MainThreadUtils.h"
      41             : #include "nsINode.h"
      42             : #include "nsIWidget.h"
      43             : #include "nsThreadUtils.h"
      44             : #include "mozilla/LoadInfo.h"
      45             : #include "mozilla/net/NeckoCommon.h"
      46             : #include "mozilla/Services.h"
      47             : #include "mozilla/Telemetry.h"
      48             : #include "mozilla/net/DNS.h"
      49             : #include "mozilla/ipc/URIUtils.h"
      50             : #include "mozilla/net/NeckoChild.h"
      51             : #include "mozilla/net/NeckoParent.h"
      52             : #include "mozilla/dom/ClientInfo.h"
      53             : #include "mozilla/dom/ContentParent.h"
      54             : #include "mozilla/dom/ServiceWorkerDescriptor.h"
      55             : #include "mozilla/net/CaptivePortalService.h"
      56             : #include "mozilla/Unused.h"
      57             : #include "ReferrerPolicy.h"
      58             : #include "nsContentSecurityManager.h"
      59             : #include "nsContentUtils.h"
      60             : #include "xpcpublic.h"
      61             : 
      62             : namespace mozilla {
      63             : namespace net {
      64             : 
      65             : using mozilla::Maybe;
      66             : using mozilla::dom::ClientInfo;
      67             : using mozilla::dom::ServiceWorkerDescriptor;
      68             : 
      69             : #define PORT_PREF_PREFIX           "network.security.ports."
      70             : #define PORT_PREF(x)               PORT_PREF_PREFIX x
      71             : #define MANAGE_OFFLINE_STATUS_PREF "network.manage-offline-status"
      72             : #define OFFLINE_MIRRORS_CONNECTIVITY "network.offline-mirrors-connectivity"
      73             : 
      74             : // Nb: these have been misnomers since bug 715770 removed the buffer cache.
      75             : // "network.segment.count" and "network.segment.size" would be better names,
      76             : // but the old names are still used to preserve backward compatibility.
      77             : #define NECKO_BUFFER_CACHE_COUNT_PREF "network.buffer.cache.count"
      78             : #define NECKO_BUFFER_CACHE_SIZE_PREF  "network.buffer.cache.size"
      79             : #define NETWORK_NOTIFY_CHANGED_PREF   "network.notify.changed"
      80             : #define NETWORK_CAPTIVE_PORTAL_PREF   "network.captive-portal-service.enabled"
      81             : 
      82             : #define MAX_RECURSION_COUNT 50
      83             : 
      84             : nsIOService* gIOService;
      85             : static bool gHasWarnedUploadChannel2;
      86             : static bool gCaptivePortalEnabled = false;
      87             : static LazyLogModule gIOServiceLog("nsIOService");
      88             : #undef LOG
      89             : #define LOG(args)     MOZ_LOG(gIOServiceLog, LogLevel::Debug, args)
      90             : 
      91             : // A general port blacklist.  Connections to these ports will not be allowed
      92             : // unless the protocol overrides.
      93             : //
      94             : // TODO: I am sure that there are more ports to be added.
      95             : //       This cut is based on the classic mozilla codebase
      96             : 
      97             : int16_t gBadPortList[] = {
      98             :   1,    // tcpmux
      99             :   7,    // echo
     100             :   9,    // discard
     101             :   11,   // systat
     102             :   13,   // daytime
     103             :   15,   // netstat
     104             :   17,   // qotd
     105             :   19,   // chargen
     106             :   20,   // ftp-data
     107             :   21,   // ftp
     108             :   22,   // ssh
     109             :   23,   // telnet
     110             :   25,   // smtp
     111             :   37,   // time
     112             :   42,   // name
     113             :   43,   // nicname
     114             :   53,   // domain
     115             :   77,   // priv-rjs
     116             :   79,   // finger
     117             :   87,   // ttylink
     118             :   95,   // supdup
     119             :   101,  // hostriame
     120             :   102,  // iso-tsap
     121             :   103,  // gppitnp
     122             :   104,  // acr-nema
     123             :   109,  // pop2
     124             :   110,  // pop3
     125             :   111,  // sunrpc
     126             :   113,  // auth
     127             :   115,  // sftp
     128             :   117,  // uucp-path
     129             :   119,  // nntp
     130             :   123,  // ntp
     131             :   135,  // loc-srv / epmap
     132             :   139,  // netbios
     133             :   143,  // imap2
     134             :   179,  // bgp
     135             :   389,  // ldap
     136             :   427,  // afp (alternate)
     137             :   465,  // smtp (alternate)
     138             :   512,  // print / exec
     139             :   513,  // login
     140             :   514,  // shell
     141             :   515,  // printer
     142             :   526,  // tempo
     143             :   530,  // courier
     144             :   531,  // chat
     145             :   532,  // netnews
     146             :   540,  // uucp
     147             :   548,  // afp
     148             :   556,  // remotefs
     149             :   563,  // nntp+ssl
     150             :   587,  // smtp (outgoing)
     151             :   601,  // syslog-conn
     152             :   636,  // ldap+ssl
     153             :   993,  // imap+ssl
     154             :   995,  // pop3+ssl
     155             :   2049, // nfs
     156             :   3659, // apple-sasl
     157             :   4045, // lockd
     158             :   6000, // x11
     159             :   6665, // irc (alternate)
     160             :   6666, // irc (alternate)
     161             :   6667, // irc (default)
     162             :   6668, // irc (alternate)
     163             :   6669, // irc (alternate)
     164             :   6697, // irc+tls
     165             :   0,    // Sentinel value: This MUST be zero
     166             : };
     167             : 
     168             : static const char kProfileChangeNetTeardownTopic[] = "profile-change-net-teardown";
     169             : static const char kProfileChangeNetRestoreTopic[] = "profile-change-net-restore";
     170             : static const char kProfileDoChange[] = "profile-do-change";
     171             : 
     172             : // Necko buffer defaults
     173             : uint32_t   nsIOService::gDefaultSegmentSize = 4096;
     174             : uint32_t   nsIOService::gDefaultSegmentCount = 24;
     175             : 
     176             : bool nsIOService::sIsDataURIUniqueOpaqueOrigin = false;
     177             : bool nsIOService::sBlockToplevelDataUriNavigations = false;
     178             : bool nsIOService::sBlockFTPSubresources = false;
     179             : 
     180             : ////////////////////////////////////////////////////////////////////////////////
     181             : 
     182           1 : nsIOService::nsIOService()
     183             :     : mOffline(true)
     184             :     , mOfflineForProfileChange(false)
     185             :     , mManageLinkStatus(false)
     186             :     , mConnectivity(true)
     187             :     , mOfflineMirrorsConnectivity(true)
     188             :     , mSettingOffline(false)
     189             :     , mSetOfflineValue(false)
     190             :     , mShutdown(false)
     191             :     , mHttpHandlerAlreadyShutingDown(false)
     192             :     , mNetworkLinkServiceInitialized(false)
     193             :     , mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY)
     194             :     , mNetworkNotifyChanged(true)
     195             :     , mTotalRequests(0)
     196             :     , mCacheWon(0)
     197             :     , mNetWon(0)
     198             :     , mLastOfflineStateChange(PR_IntervalNow())
     199             :     , mLastConnectivityChange(PR_IntervalNow())
     200             :     , mLastNetworkLinkChange(PR_IntervalNow())
     201          31 :     , mNetTearingDownStarted(0)
     202             : {
     203           0 : }
     204             : 
     205             : nsresult
     206           0 : nsIOService::Init()
     207             : {
     208             :     // XXX hack until xpidl supports error info directly (bug 13423)
     209           2 :     nsCOMPtr<nsIErrorService> errorService = do_GetService(NS_ERRORSERVICE_CONTRACTID);
     210           1 :     if (errorService) {
     211           1 :         errorService->RegisterErrorStringBundle(NS_ERROR_MODULE_NETWORK, NECKO_MSGS_URL);
     212             :     }
     213             :     else
     214           0 :         NS_WARNING("failed to get error service");
     215             : 
     216           0 :     InitializeCaptivePortalService();
     217             : 
     218             :     // setup our bad port list stuff
     219          68 :     for(int i=0; gBadPortList[i]; i++)
     220           0 :         mRestrictedPortList.AppendElement(gBadPortList[i]);
     221             : 
     222             :     // Further modifications to the port list come from prefs
     223           0 :     nsCOMPtr<nsIPrefBranch> prefBranch;
     224           0 :     GetPrefBranch(getter_AddRefs(prefBranch));
     225           0 :     if (prefBranch) {
     226           0 :         prefBranch->AddObserver(PORT_PREF_PREFIX, this, true);
     227           0 :         prefBranch->AddObserver(MANAGE_OFFLINE_STATUS_PREF, this, true);
     228           0 :         prefBranch->AddObserver(NECKO_BUFFER_CACHE_COUNT_PREF, this, true);
     229           0 :         prefBranch->AddObserver(NECKO_BUFFER_CACHE_SIZE_PREF, this, true);
     230           1 :         prefBranch->AddObserver(NETWORK_NOTIFY_CHANGED_PREF, this, true);
     231           1 :         prefBranch->AddObserver(NETWORK_CAPTIVE_PORTAL_PREF, this, true);
     232           1 :         PrefsChanged(prefBranch);
     233             :     }
     234             : 
     235             :     // Register for profile change notifications
     236           0 :     nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
     237           0 :     if (observerService) {
     238           0 :         observerService->AddObserver(this, kProfileChangeNetTeardownTopic, true);
     239           0 :         observerService->AddObserver(this, kProfileChangeNetRestoreTopic, true);
     240           0 :         observerService->AddObserver(this, kProfileDoChange, true);
     241           1 :         observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
     242           1 :         observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, true);
     243           1 :         observerService->AddObserver(this, NS_WIDGET_WAKE_OBSERVER_TOPIC, true);
     244             :     }
     245             :     else
     246           0 :         NS_WARNING("failed to get observer service");
     247             : 
     248             :     Preferences::AddBoolVarCache(&sIsDataURIUniqueOpaqueOrigin,
     249           1 :                                  "security.data_uri.unique_opaque_origin", false);
     250             :     Preferences::AddBoolVarCache(&sBlockToplevelDataUriNavigations,
     251           0 :                                  "security.data_uri.block_toplevel_data_uri_navigations", false);
     252             :     Preferences::AddBoolVarCache(&sBlockFTPSubresources,
     253           0 :                                  "security.block_ftp_subresources", true);
     254           1 :     Preferences::AddBoolVarCache(&mOfflineMirrorsConnectivity, OFFLINE_MIRRORS_CONNECTIVITY, true);
     255             : 
     256           0 :     gIOService = this;
     257             : 
     258           0 :     InitializeNetworkLinkService();
     259           1 :     InitializeProtocolProxyService();
     260             : 
     261           1 :     SetOffline(false);
     262             : 
     263           1 :     return NS_OK;
     264             : }
     265             : 
     266             : 
     267           0 : nsIOService::~nsIOService()
     268             : {
     269           0 :     if (gIOService) {
     270           0 :         MOZ_ASSERT(gIOService == this);
     271           0 :         gIOService = nullptr;
     272             :     }
     273           0 : }
     274             : 
     275             : nsresult
     276           1 : nsIOService::InitializeCaptivePortalService()
     277             : {
     278           1 :     if (XRE_GetProcessType() != GeckoProcessType_Default) {
     279             :         // We only initalize a captive portal service in the main process
     280             :         return NS_OK;
     281             :     }
     282             : 
     283           2 :     mCaptivePortalService = do_GetService(NS_CAPTIVEPORTAL_CID);
     284           2 :     if (mCaptivePortalService) {
     285           1 :         return static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Initialize();
     286             :     }
     287             : 
     288             :     return NS_OK;
     289             : }
     290             : 
     291             : nsresult
     292           1 : nsIOService::InitializeSocketTransportService()
     293             : {
     294           0 :     nsresult rv = NS_OK;
     295             : 
     296           1 :     if (!mSocketTransportService) {
     297           1 :         mSocketTransportService = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
     298           1 :         if (NS_FAILED(rv)) {
     299           0 :             NS_WARNING("failed to get socket transport service");
     300             :         }
     301             :     }
     302             : 
     303           0 :     if (mSocketTransportService) {
     304           1 :         rv = mSocketTransportService->Init();
     305           1 :         NS_ASSERTION(NS_SUCCEEDED(rv), "socket transport service init failed");
     306           0 :         mSocketTransportService->SetOffline(false);
     307             :     }
     308             : 
     309           1 :     return rv;
     310             : }
     311             : 
     312             : nsresult
     313           2 : nsIOService::InitializeNetworkLinkService()
     314             : {
     315           2 :     nsresult rv = NS_OK;
     316             : 
     317           0 :     if (mNetworkLinkServiceInitialized)
     318             :         return rv;
     319             : 
     320           1 :     if (!NS_IsMainThread()) {
     321           0 :         NS_WARNING("Network link service should be created on main thread");
     322           0 :         return NS_ERROR_FAILURE;
     323             :     }
     324             : 
     325             :     // go into managed mode if we can, and chrome process
     326           1 :     if (XRE_IsParentProcess())
     327             :     {
     328           0 :         mNetworkLinkService = do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID, &rv);
     329             :     }
     330             : 
     331           2 :     if (mNetworkLinkService) {
     332           1 :         mNetworkLinkServiceInitialized = true;
     333             :     }
     334             : 
     335             :     // After initializing the networkLinkService, query the connectivity state
     336           1 :     OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN);
     337             : 
     338           1 :     return rv;
     339             : }
     340             : 
     341             : nsresult
     342           0 : nsIOService::InitializeProtocolProxyService()
     343             : {
     344           1 :     nsresult rv = NS_OK;
     345             : 
     346           1 :     if (XRE_IsParentProcess()) {
     347             :         // for early-initialization
     348             :         Unused << do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
     349             :     }
     350             : 
     351           0 :     return rv;
     352             : }
     353             : 
     354             : already_AddRefed<nsIOService>
     355           0 : nsIOService::GetInstance() {
     356           0 :     if (!gIOService) {
     357           0 :         RefPtr<nsIOService> ios = new nsIOService();
     358           1 :         if (NS_SUCCEEDED(ios->Init())) {
     359           1 :             MOZ_ASSERT(gIOService == ios.get());
     360           0 :             return ios.forget();
     361             :         }
     362             :     }
     363           0 :     return do_AddRef(gIOService);
     364             : }
     365             : 
     366       86111 : NS_IMPL_ISUPPORTS(nsIOService,
     367             :                   nsIIOService,
     368             :                   nsINetUtil,
     369             :                   nsISpeculativeConnect,
     370             :                   nsIObserver,
     371             :                   nsIIOServiceInternal,
     372             :                   nsISupportsWeakReference)
     373             : 
     374             : ////////////////////////////////////////////////////////////////////////////////
     375             : 
     376             : nsresult
     377           0 : nsIOService::RecheckCaptivePortal()
     378             : {
     379           0 :   MOZ_ASSERT(NS_IsMainThread(), "Must be called on the main thread");
     380           0 :   if (!mCaptivePortalService) {
     381             :     return NS_OK;
     382             :   }
     383             :   nsCOMPtr<nsIRunnable> task =
     384           0 :     NewRunnableMethod("nsIOService::RecheckCaptivePortal",
     385             :                       mCaptivePortalService,
     386           0 :                       &nsICaptivePortalService::RecheckCaptivePortal);
     387           0 :   return NS_DispatchToMainThread(task);
     388             : }
     389             : 
     390             : nsresult
     391           0 : nsIOService::RecheckCaptivePortalIfLocalRedirect(nsIChannel* newChan)
     392             : {
     393             :     nsresult rv;
     394             : 
     395           0 :     if (!mCaptivePortalService) {
     396             :         return NS_OK;
     397             :     }
     398             : 
     399           0 :     nsCOMPtr<nsIURI> uri;
     400           0 :     rv = newChan->GetURI(getter_AddRefs(uri));
     401           0 :     if (NS_FAILED(rv)) {
     402             :         return rv;
     403             :     }
     404             : 
     405           0 :     nsCString host;
     406           0 :     rv = uri->GetHost(host);
     407           0 :     if (NS_FAILED(rv)) {
     408             :         return rv;
     409             :     }
     410             : 
     411             :     PRNetAddr prAddr;
     412           0 :     if (PR_StringToNetAddr(host.BeginReading(), &prAddr) != PR_SUCCESS) {
     413             :         // The redirect wasn't to an IP literal, so there's probably no need
     414             :         // to trigger the captive portal detection right now. It can wait.
     415             :         return NS_OK;
     416             :     }
     417             : 
     418             :     NetAddr netAddr;
     419           0 :     PRNetAddrToNetAddr(&prAddr, &netAddr);
     420           0 :     if (IsIPAddrLocal(&netAddr)) {
     421             :         // Redirects to local IP addresses are probably captive portals
     422           0 :         RecheckCaptivePortal();
     423             :     }
     424             : 
     425             :     return NS_OK;
     426             : }
     427             : 
     428             : nsresult
     429           0 : nsIOService::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
     430             :                                     uint32_t flags,
     431             :                                     nsAsyncRedirectVerifyHelper *helper)
     432             : {
     433             :     // If a redirect to a local network address occurs, then chances are we
     434             :     // are in a captive portal, so we trigger a recheck.
     435           0 :     RecheckCaptivePortalIfLocalRedirect(newChan);
     436             : 
     437             :     // This is silly. I wish there was a simpler way to get at the global
     438             :     // reference of the contentSecurityManager. But it lives in the XPCOM
     439             :     // service registry.
     440             :     nsCOMPtr<nsIChannelEventSink> sink =
     441           0 :         do_GetService(NS_CONTENTSECURITYMANAGER_CONTRACTID);
     442           0 :     if (sink) {
     443           0 :         nsresult rv = helper->DelegateOnChannelRedirect(sink, oldChan,
     444           0 :                                                         newChan, flags);
     445           0 :         if (NS_FAILED(rv))
     446             :             return rv;
     447             :     }
     448             : 
     449             :     // Finally, our category
     450           0 :     nsCOMArray<nsIChannelEventSink> entries;
     451           0 :     mChannelEventSinks.GetEntries(entries);
     452           0 :     int32_t len = entries.Count();
     453           0 :     for (int32_t i = 0; i < len; ++i) {
     454           0 :         nsresult rv = helper->DelegateOnChannelRedirect(entries[i], oldChan,
     455           0 :                                                         newChan, flags);
     456           0 :         if (NS_FAILED(rv))
     457             :             return rv;
     458             :     }
     459             :     return NS_OK;
     460             : }
     461             : 
     462             : nsresult
     463          13 : nsIOService::CacheProtocolHandler(const char *scheme, nsIProtocolHandler *handler)
     464             : {
     465          13 :     MOZ_ASSERT(NS_IsMainThread());
     466             : 
     467         175 :     for (unsigned int i=0; i<NS_N(gScheme); i++)
     468             :     {
     469           0 :         if (!nsCRT::strcasecmp(scheme, gScheme[i]))
     470             :         {
     471             :             nsresult rv;
     472           0 :             NS_ASSERTION(!mWeakHandler[i], "Protocol handler already cached");
     473             :             // Make sure the handler supports weak references.
     474          20 :             nsCOMPtr<nsISupportsWeakReference> factoryPtr = do_QueryInterface(handler, &rv);
     475          10 :             if (!factoryPtr)
     476             :             {
     477             :                 // Don't cache handlers that don't support weak reference as
     478             :                 // there is real danger of a circular reference.
     479             : #ifdef DEBUG_dp
     480             :                 printf("DEBUG: %s protcol handler doesn't support weak ref. Not cached.\n", scheme);
     481             : #endif /* DEBUG_dp */
     482             :                 return NS_ERROR_FAILURE;
     483             :             }
     484          10 :             mWeakHandler[i] = do_GetWeakReference(handler);
     485          10 :             return NS_OK;
     486             :         }
     487             :     }
     488             :     return NS_ERROR_FAILURE;
     489             : }
     490             : 
     491             : nsresult
     492        6058 : nsIOService::GetCachedProtocolHandler(const char *scheme, nsIProtocolHandler **result, uint32_t start, uint32_t end)
     493             : {
     494           0 :     MOZ_ASSERT(NS_IsMainThread());
     495             : 
     496           0 :     uint32_t len = end - start - 1;
     497       28328 :     for (unsigned int i=0; i<NS_N(gScheme); i++)
     498             :     {
     499       56582 :         if (!mWeakHandler[i])
     500             :             continue;
     501             : 
     502             :         // handle unterminated strings
     503             :         // start is inclusive, end is exclusive, len = end - start - 1
     504       47548 :         if (end ? (!nsCRT::strncasecmp(scheme + start, gScheme[i], len)
     505           0 :                    && gScheme[i][len] == '\0')
     506       47548 :                 : (!nsCRT::strcasecmp(scheme, gScheme[i])))
     507             :         {
     508       12042 :             return CallQueryReferent(mWeakHandler[i].get(), result);
     509             :         }
     510             :     }
     511             :     return NS_ERROR_FAILURE;
     512             : }
     513             : 
     514             : static bool
     515           0 : UsesExternalProtocolHandler(const char* aScheme)
     516             : {
     517         110 :     if (NS_LITERAL_CSTRING("file").Equals(aScheme) ||
     518         145 :         NS_LITERAL_CSTRING("chrome").Equals(aScheme) ||
     519          35 :         NS_LITERAL_CSTRING("resource").Equals(aScheme)) {
     520             :         // Don't allow file:, chrome: or resource: URIs to be handled with
     521             :         // nsExternalProtocolHandler, since internally we rely on being able to
     522             :         // use and read from these URIs.
     523             :         return false;
     524             :     }
     525             : 
     526         230 :     for (const auto & forcedExternalScheme : gForcedExternalSchemes) {
     527         122 :       if (!nsCRT::strcasecmp(forcedExternalScheme, aScheme)) {
     528             :         return true;
     529             :       }
     530             :     }
     531             : 
     532           0 :     nsAutoCString pref("network.protocol-handler.external.");
     533          10 :     pref += aScheme;
     534             : 
     535          10 :     return Preferences::GetBool(pref.get(), false);
     536             : }
     537             : 
     538             : NS_IMETHODIMP
     539        6058 : nsIOService::GetProtocolHandler(const char* scheme, nsIProtocolHandler* *result)
     540             : {
     541             :     nsresult rv;
     542             : 
     543        6058 :     NS_ENSURE_ARG_POINTER(scheme);
     544             :     // XXX we may want to speed this up by introducing our own protocol
     545             :     // scheme -> protocol handler mapping, avoiding the string manipulation
     546             :     // and service manager stuff
     547             : 
     548        6058 :     rv = GetCachedProtocolHandler(scheme, result);
     549           0 :     if (NS_SUCCEEDED(rv))
     550             :         return rv;
     551             : 
     552           0 :     if (scheme[0] != '\0' && !UsesExternalProtocolHandler(scheme)) {
     553          13 :         nsAutoCString contractID(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX);
     554           0 :         contractID += scheme;
     555           0 :         ToLowerCase(contractID);
     556             : 
     557           0 :         rv = CallGetService(contractID.get(), result);
     558          13 :         if (NS_SUCCEEDED(rv)) {
     559          13 :             CacheProtocolHandler(scheme, *result);
     560          13 :             return rv;
     561             :         }
     562             : 
     563             : #ifdef MOZ_WIDGET_GTK
     564             :         // check to see whether GVFS can handle this URI scheme.  if it can
     565             :         // create a nsIURI for the "scheme:", then we assume it has support for
     566             :         // the requested protocol.  otherwise, we failover to using the default
     567             :         // protocol handler.
     568             : 
     569             :         rv = CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"moz-gio",
     570           0 :                             result);
     571           0 :         if (NS_SUCCEEDED(rv)) {
     572           0 :             nsAutoCString spec(scheme);
     573           0 :             spec.Append(':');
     574             : 
     575             :             nsIURI *uri;
     576           0 :             rv = (*result)->NewURI(spec, nullptr, nullptr, &uri);
     577           0 :             if (NS_SUCCEEDED(rv)) {
     578           0 :                 NS_RELEASE(uri);
     579           0 :                 return rv;
     580             :             }
     581             : 
     582           0 :             NS_RELEASE(*result);
     583             :         }
     584             : #endif
     585             :     }
     586             : 
     587             :     // Okay we don't have a protocol handler to handle this url type, so use
     588             :     // the default protocol handler.  This will cause urls to get dispatched
     589             :     // out to the OS ('cause we can't do anything with them) when we try to
     590             :     // read from a channel created by the default protocol handler.
     591             : 
     592             :     rv = CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default",
     593          24 :                         result);
     594           0 :     if (NS_FAILED(rv))
     595             :         return NS_ERROR_UNKNOWN_PROTOCOL;
     596             : 
     597          24 :     return rv;
     598             : }
     599             : 
     600             : NS_IMETHODIMP
     601        1221 : nsIOService::ExtractScheme(const nsACString &inURI, nsACString &scheme)
     602             : {
     603        3734 :     return net_ExtractURLScheme(inURI, scheme);
     604             : }
     605             : 
     606             : NS_IMETHODIMP
     607           0 : nsIOService::HostnameIsLocalIPAddress(nsIURI *aURI, bool *aResult)
     608             : {
     609           0 :   NS_ENSURE_ARG_POINTER(aURI);
     610             : 
     611           0 :   nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
     612           0 :   NS_ENSURE_ARG_POINTER(innerURI);
     613             : 
     614           0 :   nsAutoCString host;
     615           0 :   nsresult rv = innerURI->GetAsciiHost(host);
     616           0 :   if (NS_FAILED(rv)) {
     617             :     return rv;
     618             :   }
     619             : 
     620           0 :   *aResult = false;
     621             : 
     622             :   PRNetAddr addr;
     623           0 :   PRStatus result = PR_StringToNetAddr(host.get(), &addr);
     624           0 :   if (result == PR_SUCCESS) {
     625             :     NetAddr netAddr;
     626           0 :     PRNetAddrToNetAddr(&addr, &netAddr);
     627           0 :     if (IsIPAddrLocal(&netAddr)) {
     628           0 :       *aResult = true;
     629             :     }
     630             :   }
     631             : 
     632             :   return NS_OK;
     633             : }
     634             : 
     635             : NS_IMETHODIMP
     636           0 : nsIOService::GetProtocolFlags(const char* scheme, uint32_t *flags)
     637             : {
     638           0 :     nsCOMPtr<nsIProtocolHandler> handler;
     639           0 :     nsresult rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
     640           0 :     if (NS_FAILED(rv)) return rv;
     641             : 
     642             :     // We can't call DoGetProtocolFlags here because we don't have a URI. This
     643             :     // API is used by (and only used by) extensions, which is why it's still
     644             :     // around. Calling this on a scheme with dynamic flags will throw.
     645           0 :     rv = handler->GetProtocolFlags(flags);
     646             : #if !IS_ORIGIN_IS_FULL_SPEC_DEFINED
     647           0 :     MOZ_RELEASE_ASSERT(!(*flags & nsIProtocolHandler::ORIGIN_IS_FULL_SPEC),
     648             :                        "ORIGIN_IS_FULL_SPEC is unsupported but used");
     649             : #endif
     650             :     return rv;
     651             : }
     652             : 
     653             : class AutoIncrement
     654             : {
     655             :     public:
     656        2513 :         explicit AutoIncrement(uint32_t *var) : mVar(var)
     657             :         {
     658           0 :             ++*var;
     659             :         }
     660           0 :         ~AutoIncrement()
     661        2513 :         {
     662        2513 :             --*mVar;
     663        2513 :         }
     664             :     private:
     665             :         uint32_t *mVar;
     666             : };
     667             : 
     668             : nsresult
     669        2513 : nsIOService::NewURI(const nsACString &aSpec, const char *aCharset, nsIURI *aBaseURI, nsIURI **result)
     670             : {
     671           0 :     NS_ASSERTION(NS_IsMainThread(), "wrong thread");
     672             : 
     673             :     static uint32_t recursionCount = 0;
     674        2513 :     if (recursionCount >= MAX_RECURSION_COUNT)
     675             :         return NS_ERROR_MALFORMED_URI;
     676           0 :     AutoIncrement inc(&recursionCount);
     677             : 
     678        5026 :     nsAutoCString scheme;
     679           0 :     nsresult rv = ExtractScheme(aSpec, scheme);
     680        2513 :     if (NS_FAILED(rv)) {
     681             :         // then aSpec is relative
     682           0 :         if (!aBaseURI)
     683             :             return NS_ERROR_MALFORMED_URI;
     684             : 
     685           0 :         if (!aSpec.IsEmpty() && aSpec[0] == '#') {
     686             :             // Looks like a reference instead of a fully-specified URI.
     687             :             // --> initialize |uri| as a clone of |aBaseURI|, with ref appended.
     688           0 :             return aBaseURI->CloneWithNewRef(aSpec, result);
     689             :         }
     690             : 
     691         456 :         rv = aBaseURI->GetScheme(scheme);
     692         456 :         if (NS_FAILED(rv)) return rv;
     693             :     }
     694             : 
     695             :     // now get the handler for this scheme
     696        5002 :     nsCOMPtr<nsIProtocolHandler> handler;
     697           0 :     rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
     698        2501 :     if (NS_FAILED(rv)) return rv;
     699             : 
     700        2501 :     return handler->NewURI(aSpec, aCharset, aBaseURI, result);
     701             : }
     702             : 
     703             : 
     704             : NS_IMETHODIMP
     705           0 : nsIOService::NewFileURI(nsIFile *file, nsIURI **result)
     706             : {
     707             :     nsresult rv;
     708          37 :     NS_ENSURE_ARG_POINTER(file);
     709             : 
     710           0 :     nsCOMPtr<nsIProtocolHandler> handler;
     711             : 
     712           0 :     rv = GetProtocolHandler("file", getter_AddRefs(handler));
     713           0 :     if (NS_FAILED(rv)) return rv;
     714             : 
     715           0 :     nsCOMPtr<nsIFileProtocolHandler> fileHandler( do_QueryInterface(handler, &rv) );
     716          37 :     if (NS_FAILED(rv)) return rv;
     717             : 
     718          37 :     return fileHandler->NewFileURI(file, result);
     719             : }
     720             : 
     721             : NS_IMETHODIMP
     722          58 : nsIOService::NewChannelFromURI2(nsIURI* aURI,
     723             :                                 nsINode* aLoadingNode,
     724             :                                 nsIPrincipal* aLoadingPrincipal,
     725             :                                 nsIPrincipal* aTriggeringPrincipal,
     726             :                                 uint32_t aSecurityFlags,
     727             :                                 uint32_t aContentPolicyType,
     728             :                                 nsIChannel** result)
     729             : {
     730             :     return NewChannelFromURIWithProxyFlags2(aURI,
     731             :                                             nullptr, // aProxyURI
     732             :                                             0,       // aProxyFlags
     733             :                                             aLoadingNode,
     734             :                                             aLoadingPrincipal,
     735             :                                             aTriggeringPrincipal,
     736             :                                             aSecurityFlags,
     737             :                                             aContentPolicyType,
     738           0 :                                             result);
     739             : }
     740             : nsresult
     741         429 : nsIOService::NewChannelFromURIWithClientAndController(nsIURI* aURI,
     742             :                                                       nsINode* aLoadingNode,
     743             :                                                       nsIPrincipal* aLoadingPrincipal,
     744             :                                                       nsIPrincipal* aTriggeringPrincipal,
     745             :                                                       const Maybe<ClientInfo>& aLoadingClientInfo,
     746             :                                                       const Maybe<ServiceWorkerDescriptor>& aController,
     747             :                                                       uint32_t aSecurityFlags,
     748             :                                                       uint32_t aContentPolicyType,
     749             :                                                       nsIChannel** aResult)
     750             : {
     751             :     return NewChannelFromURIWithProxyFlagsInternal(aURI,
     752             :                                                    nullptr, // aProxyURI
     753             :                                                    0,       // aProxyFlags
     754             :                                                    aLoadingNode,
     755             :                                                    aLoadingPrincipal,
     756             :                                                    aTriggeringPrincipal,
     757             :                                                    aLoadingClientInfo,
     758             :                                                    aController,
     759             :                                                    aSecurityFlags,
     760             :                                                    aContentPolicyType,
     761         429 :                                                    aResult);
     762             : }
     763             : 
     764             : NS_IMETHODIMP
     765         440 : nsIOService::NewChannelFromURIWithLoadInfo(nsIURI* aURI,
     766             :                                            nsILoadInfo* aLoadInfo,
     767             :                                            nsIChannel** result)
     768             : {
     769             :   return NewChannelFromURIWithProxyFlagsInternal(aURI,
     770             :                                                  nullptr, // aProxyURI
     771             :                                                  0,       // aProxyFlags
     772             :                                                  aLoadInfo,
     773         440 :                                                  result);
     774             : }
     775             : 
     776             : 
     777             : nsresult
     778         487 : nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
     779             :                                                      nsIURI* aProxyURI,
     780             :                                                      uint32_t aProxyFlags,
     781             :                                                      nsINode* aLoadingNode,
     782             :                                                      nsIPrincipal* aLoadingPrincipal,
     783             :                                                      nsIPrincipal* aTriggeringPrincipal,
     784             :                                                      const Maybe<ClientInfo>& aLoadingClientInfo,
     785             :                                                      const Maybe<ServiceWorkerDescriptor>& aController,
     786             :                                                      uint32_t aSecurityFlags,
     787             :                                                      uint32_t aContentPolicyType,
     788             :                                                      nsIChannel** result)
     789             : {
     790             :     // Ideally all callers of NewChannelFromURIWithProxyFlagsInternal provide
     791             :     // the necessary arguments to create a loadinfo.
     792             :     //
     793             :     // Note, historically this could be called with nullptr aLoadingNode,
     794             :     // aLoadingPrincipal, and aTriggeringPrincipal from addons using
     795             :     // newChannelFromURIWithProxyFlags().  This code tried to accomodate
     796             :     // by not creating a LoadInfo in such cases.  Now that both the legacy
     797             :     // addons and that API are gone we could possibly require always creating a
     798             :     // LoadInfo here.  See bug 1432205.
     799         974 :     nsCOMPtr<nsILoadInfo> loadInfo;
     800             : 
     801             :     // TYPE_DOCUMENT loads don't require a loadingNode or principal, but other
     802             :     // types do.
     803         487 :     if (aLoadingNode || aLoadingPrincipal ||
     804             :         aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
     805             :       loadInfo = new LoadInfo(aLoadingPrincipal,
     806             :                               aTriggeringPrincipal,
     807             :                               aLoadingNode,
     808             :                               aSecurityFlags,
     809             :                               aContentPolicyType,
     810             :                               aLoadingClientInfo,
     811           0 :                               aController);
     812             :     }
     813         487 :     NS_ASSERTION(loadInfo, "Please pass security info when creating a channel");
     814         487 :     return NewChannelFromURIWithProxyFlagsInternal(aURI,
     815             :                                                    aProxyURI,
     816             :                                                    aProxyFlags,
     817             :                                                    loadInfo,
     818         974 :                                                    result);
     819             : }
     820             : 
     821             : nsresult
     822         927 : nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
     823             :                                                      nsIURI* aProxyURI,
     824             :                                                      uint32_t aProxyFlags,
     825             :                                                      nsILoadInfo* aLoadInfo,
     826             :                                                      nsIChannel** result)
     827             : {
     828             :     nsresult rv;
     829           0 :     NS_ENSURE_ARG_POINTER(aURI);
     830             : 
     831         927 :     nsAutoCString scheme;
     832         927 :     rv = aURI->GetScheme(scheme);
     833           0 :     if (NS_FAILED(rv))
     834             :         return rv;
     835             : 
     836        1854 :     nsCOMPtr<nsIProtocolHandler> handler;
     837         927 :     rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
     838         927 :     if (NS_FAILED(rv))
     839             :         return rv;
     840             : 
     841             :     uint32_t protoFlags;
     842         927 :     rv = handler->DoGetProtocolFlags(aURI, &protoFlags);
     843         927 :     if (NS_FAILED(rv))
     844             :         return rv;
     845             : 
     846             :     // Ideally we are creating new channels by calling NewChannel2 (NewProxiedChannel2).
     847             :     // Keep in mind that Addons can implement their own Protocolhandlers, hence
     848             :     // NewChannel2() might *not* be implemented.
     849             :     // We do not want to break those addons, therefore we first try to create a channel
     850             :     // calling NewChannel2(); if that fails:
     851             :     // * we fall back to creating a channel by calling NewChannel()
     852             :     // * wrap the addon channel
     853             :     // * and attach the loadInfo to the channel wrapper
     854           0 :     nsCOMPtr<nsIChannel> channel;
     855           0 :     nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler);
     856         927 :     if (pph) {
     857           6 :         rv = pph->NewProxiedChannel2(aURI, nullptr, aProxyFlags, aProxyURI,
     858           0 :                                      aLoadInfo, getter_AddRefs(channel));
     859             :         // if calling NewProxiedChannel2() fails we try to fall back to
     860             :         // creating a new proxied channel by calling NewProxiedChannel().
     861           1 :         if (NS_FAILED(rv)) {
     862           0 :             rv = pph->NewProxiedChannel(aURI, nullptr, aProxyFlags, aProxyURI,
     863           0 :                                         getter_AddRefs(channel));
     864           0 :             NS_ENSURE_SUCCESS(rv, rv);
     865             : 
     866             :             // The protocol handler does not implement NewProxiedChannel2, so
     867             :             // maybe we need to wrap the channel (see comment in MaybeWrap
     868             :             // function).
     869           0 :             channel = nsSecCheckWrapChannel::MaybeWrap(channel, aLoadInfo);
     870             :         }
     871             :     }
     872             :     else {
     873           0 :         rv = handler->NewChannel2(aURI, aLoadInfo, getter_AddRefs(channel));
     874             :         // if an implementation of NewChannel2() is missing we try to fall back to
     875             :         // creating a new channel by calling NewChannel().
     876        1848 :         if (rv == NS_ERROR_NOT_IMPLEMENTED ||
     877           0 :             rv == NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED) {
     878           0 :             LOG(("NewChannel2 not implemented rv=%" PRIx32
     879             :                  ". Falling back to NewChannel\n", static_cast<uint32_t>(rv)));
     880           0 :             rv = handler->NewChannel(aURI, getter_AddRefs(channel));
     881           0 :             if (NS_FAILED(rv)) {
     882             :                 return rv;
     883             :             }
     884             :             // The protocol handler does not implement NewChannel2, so
     885             :             // maybe we need to wrap the channel (see comment in MaybeWrap
     886             :             // function).
     887           0 :             channel = nsSecCheckWrapChannel::MaybeWrap(channel, aLoadInfo);
     888         924 :         } else if (NS_FAILED(rv)) {
     889             :             return rv;
     890             :         }
     891             :     }
     892             : 
     893             :     // Make sure that all the individual protocolhandlers attach a loadInfo.
     894           0 :     if (aLoadInfo) {
     895             :       // make sure we have the same instance of loadInfo on the newly created channel
     896        1854 :       nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
     897         927 :       if (aLoadInfo != loadInfo) {
     898           0 :         MOZ_ASSERT(false, "newly created channel must have a loadinfo attached");
     899             :         return NS_ERROR_UNEXPECTED;
     900             :       }
     901             : 
     902             :       // If we're sandboxed, make sure to clear any owner the channel
     903             :       // might already have.
     904         927 :       if (loadInfo->GetLoadingSandboxed()) {
     905          40 :         channel->SetOwner(nullptr);
     906             :       }
     907             :     }
     908             : 
     909             :     // Some extensions override the http protocol handler and provide their own
     910             :     // implementation. The channels returned from that implementation doesn't
     911             :     // seem to always implement the nsIUploadChannel2 interface, presumably
     912             :     // because it's a new interface.
     913             :     // Eventually we should remove this and simply require that http channels
     914             :     // implement the new interface.
     915             :     // See bug 529041
     916         927 :     if (!gHasWarnedUploadChannel2 && scheme.EqualsLiteral("http")) {
     917           1 :         nsCOMPtr<nsIUploadChannel2> uploadChannel2 = do_QueryInterface(channel);
     918           1 :         if (!uploadChannel2) {
     919             :             nsCOMPtr<nsIConsoleService> consoleService =
     920           0 :                 do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     921           0 :             if (consoleService) {
     922           0 :                 consoleService->LogStringMessage(u"Http channel implementation "
     923             :                     "doesn't support nsIUploadChannel2. An extension has "
     924             :                     "supplied a non-functional http protocol handler. This will "
     925           0 :                     "break behavior and in future releases not work at all.");
     926             :             }
     927           0 :             gHasWarnedUploadChannel2 = true;
     928             :         }
     929             :     }
     930             : 
     931         927 :     channel.forget(result);
     932         927 :     return NS_OK;
     933             : }
     934             : 
     935             : NS_IMETHODIMP
     936          58 : nsIOService::NewChannelFromURIWithProxyFlags2(nsIURI* aURI,
     937             :                                               nsIURI* aProxyURI,
     938             :                                               uint32_t aProxyFlags,
     939             :                                               nsINode* aLoadingNode,
     940             :                                               nsIPrincipal* aLoadingPrincipal,
     941             :                                               nsIPrincipal* aTriggeringPrincipal,
     942             :                                               uint32_t aSecurityFlags,
     943             :                                               uint32_t aContentPolicyType,
     944             :                                               nsIChannel** result)
     945             : {
     946             :     return NewChannelFromURIWithProxyFlagsInternal(aURI,
     947             :                                                    aProxyURI,
     948             :                                                    aProxyFlags,
     949             :                                                    aLoadingNode,
     950             :                                                    aLoadingPrincipal,
     951             :                                                    aTriggeringPrincipal,
     952         116 :                                                    Maybe<ClientInfo>(),
     953           0 :                                                    Maybe<ServiceWorkerDescriptor>(),
     954             :                                                    aSecurityFlags,
     955             :                                                    aContentPolicyType,
     956         116 :                                                    result);
     957             : }
     958             : 
     959             : NS_IMETHODIMP
     960           1 : nsIOService::NewChannel2(const nsACString& aSpec,
     961             :                          const char* aCharset,
     962             :                          nsIURI* aBaseURI,
     963             :                          nsINode* aLoadingNode,
     964             :                          nsIPrincipal* aLoadingPrincipal,
     965             :                          nsIPrincipal* aTriggeringPrincipal,
     966             :                          uint32_t aSecurityFlags,
     967             :                          uint32_t aContentPolicyType,
     968             :                          nsIChannel** result)
     969             : {
     970             :     nsresult rv;
     971           2 :     nsCOMPtr<nsIURI> uri;
     972           0 :     rv = NewURI(aSpec, aCharset, aBaseURI, getter_AddRefs(uri));
     973           1 :     if (NS_FAILED(rv)) return rv;
     974             : 
     975           1 :     return NewChannelFromURI2(uri,
     976             :                               aLoadingNode,
     977             :                               aLoadingPrincipal,
     978             :                               aTriggeringPrincipal,
     979             :                               aSecurityFlags,
     980             :                               aContentPolicyType,
     981           1 :                               result);
     982             : }
     983             : 
     984             : bool
     985           0 : nsIOService::IsLinkUp()
     986             : {
     987           0 :     InitializeNetworkLinkService();
     988             : 
     989           0 :     if (!mNetworkLinkService) {
     990             :         // We cannot decide, assume the link is up
     991             :         return true;
     992             :     }
     993             : 
     994             :     bool isLinkUp;
     995             :     nsresult rv;
     996           0 :     rv = mNetworkLinkService->GetIsLinkUp(&isLinkUp);
     997           0 :     if (NS_FAILED(rv)) {
     998             :         return true;
     999             :     }
    1000             : 
    1001           0 :     return isLinkUp;
    1002             : }
    1003             : 
    1004             : NS_IMETHODIMP
    1005           1 : nsIOService::GetOffline(bool *offline)
    1006             : {
    1007           0 :     if (mOfflineMirrorsConnectivity) {
    1008           0 :         *offline = mOffline || !mConnectivity;
    1009             :     } else {
    1010          32 :         *offline = mOffline;
    1011             :     }
    1012          32 :     return NS_OK;
    1013             : }
    1014             : 
    1015             : NS_IMETHODIMP
    1016           1 : nsIOService::SetOffline(bool offline)
    1017             : {
    1018           0 :     LOG(("nsIOService::SetOffline offline=%d\n", offline));
    1019             :     // When someone wants to go online (!offline) after we got XPCOM shutdown
    1020             :     // throw ERROR_NOT_AVAILABLE to prevent return to online state.
    1021           1 :     if ((mShutdown || mOfflineForProfileChange) && !offline)
    1022             :         return NS_ERROR_NOT_AVAILABLE;
    1023             : 
    1024             :     // SetOffline() may re-enter while it's shutting down services.
    1025             :     // If that happens, save the most recent value and it will be
    1026             :     // processed when the first SetOffline() call is done bringing
    1027             :     // down the service.
    1028           1 :     mSetOfflineValue = offline;
    1029           1 :     if (mSettingOffline) {
    1030             :         return NS_OK;
    1031             :     }
    1032             : 
    1033           1 :     mSettingOffline = true;
    1034             : 
    1035           2 :     nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
    1036             : 
    1037           0 :     NS_ASSERTION(observerService, "The observer service should not be null");
    1038             : 
    1039           1 :     if (XRE_IsParentProcess()) {
    1040           1 :         if (observerService) {
    1041           0 :             (void)observerService->NotifyObservers(nullptr,
    1042             :                 NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC, offline ?
    1043             :                 u"true" :
    1044           2 :                 u"false");
    1045             :         }
    1046             :     }
    1047             : 
    1048           1 :     nsIIOService *subject = static_cast<nsIIOService *>(this);
    1049           0 :     while (mSetOfflineValue != mOffline) {
    1050           0 :         offline = mSetOfflineValue;
    1051             : 
    1052           1 :         if (offline && !mOffline) {
    1053           0 :             mOffline = true; // indicate we're trying to shutdown
    1054             : 
    1055             :             // don't care if notifications fail
    1056           0 :             if (observerService)
    1057           0 :                 observerService->NotifyObservers(subject,
    1058             :                                                  NS_IOSERVICE_GOING_OFFLINE_TOPIC,
    1059           0 :                                                  u"" NS_IOSERVICE_OFFLINE);
    1060             : 
    1061           0 :             if (mSocketTransportService)
    1062           0 :                 mSocketTransportService->SetOffline(true);
    1063             : 
    1064           0 :             mLastOfflineStateChange = PR_IntervalNow();
    1065           0 :             if (observerService)
    1066           0 :                 observerService->NotifyObservers(subject,
    1067             :                                                  NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
    1068           0 :                                                  u"" NS_IOSERVICE_OFFLINE);
    1069             :         }
    1070           0 :         else if (!offline && mOffline) {
    1071             :             // go online
    1072           1 :             InitializeSocketTransportService();
    1073           0 :             mOffline = false;    // indicate success only AFTER we've
    1074             :                                     // brought up the services
    1075             : 
    1076           0 :             mLastOfflineStateChange = PR_IntervalNow();
    1077             :             // don't care if notification fails
    1078             :             // Only send the ONLINE notification if there is connectivity
    1079           0 :             if (observerService && mConnectivity) {
    1080           1 :                 observerService->NotifyObservers(subject,
    1081             :                                                  NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
    1082           1 :                                                  (u"" NS_IOSERVICE_ONLINE));
    1083             :             }
    1084             :         }
    1085             :     }
    1086             : 
    1087             :     // Don't notify here, as the above notifications (if used) suffice.
    1088           0 :     if ((mShutdown || mOfflineForProfileChange) && mOffline) {
    1089           0 :         if (mSocketTransportService) {
    1090           0 :             DebugOnly<nsresult> rv = mSocketTransportService->Shutdown(mShutdown);
    1091           0 :             NS_ASSERTION(NS_SUCCEEDED(rv), "socket transport service shutdown failed");
    1092             :         }
    1093             :     }
    1094             : 
    1095           1 :     mSettingOffline = false;
    1096             : 
    1097             :     return NS_OK;
    1098             : }
    1099             : 
    1100             : NS_IMETHODIMP
    1101           0 : nsIOService::GetConnectivity(bool *aConnectivity)
    1102             : {
    1103          26 :     *aConnectivity = mConnectivity;
    1104          26 :     return NS_OK;
    1105             : }
    1106             : 
    1107             : NS_IMETHODIMP
    1108           0 : nsIOService::SetConnectivity(bool aConnectivity)
    1109             : {
    1110           0 :     LOG(("nsIOService::SetConnectivity aConnectivity=%d\n", aConnectivity));
    1111             :     // This should only be called from ContentChild to pass the connectivity
    1112             :     // value from the chrome process to the content process.
    1113           0 :     if (XRE_IsParentProcess()) {
    1114             :         return NS_ERROR_NOT_AVAILABLE;
    1115             :     }
    1116           0 :     return SetConnectivityInternal(aConnectivity);
    1117             : }
    1118             : 
    1119             : nsresult
    1120           0 : nsIOService::SetConnectivityInternal(bool aConnectivity)
    1121             : {
    1122           2 :     LOG(("nsIOService::SetConnectivityInternal aConnectivity=%d\n", aConnectivity));
    1123           2 :     if (mConnectivity == aConnectivity) {
    1124             :         // Nothing to do here.
    1125             :         return NS_OK;
    1126             :     }
    1127           0 :     mConnectivity = aConnectivity;
    1128             : 
    1129             :     // This is used for PR_Connect PR_Close telemetry so it is important that
    1130             :     // we have statistic about network change event even if we are offline.
    1131           0 :     mLastConnectivityChange = PR_IntervalNow();
    1132             : 
    1133           0 :     if (mCaptivePortalService) {
    1134           0 :         if (aConnectivity && !xpc::AreNonLocalConnectionsDisabled() && gCaptivePortalEnabled) {
    1135             :             // This will also trigger a captive portal check for the new network
    1136           0 :             static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Start();
    1137             :         } else {
    1138           0 :             static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Stop();
    1139             :         }
    1140             :     }
    1141             : 
    1142           0 :     nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
    1143           0 :     if (!observerService) {
    1144             :         return NS_OK;
    1145             :     }
    1146             :     // This notification sends the connectivity to the child processes
    1147           0 :     if (XRE_IsParentProcess()) {
    1148           0 :         observerService->NotifyObservers(nullptr,
    1149             :             NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC, aConnectivity ?
    1150             :             u"true" :
    1151           0 :             u"false");
    1152             :     }
    1153             : 
    1154           0 :     if (mOffline) {
    1155             :       // We don't need to send any notifications if we're offline
    1156             :       return NS_OK;
    1157             :     }
    1158             : 
    1159           0 :     if (aConnectivity) {
    1160             :         // If we were previously offline due to connectivity=false,
    1161             :         // send the ONLINE notification
    1162           0 :         observerService->NotifyObservers(
    1163             :             static_cast<nsIIOService *>(this),
    1164             :             NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
    1165           0 :             (u"" NS_IOSERVICE_ONLINE));
    1166             :     } else {
    1167             :         // If we were previously online and lost connectivity
    1168             :         // send the OFFLINE notification
    1169           0 :         observerService->NotifyObservers(static_cast<nsIIOService *>(this),
    1170             :                                          NS_IOSERVICE_GOING_OFFLINE_TOPIC,
    1171           0 :                                          u"" NS_IOSERVICE_OFFLINE);
    1172           0 :         observerService->NotifyObservers(static_cast<nsIIOService *>(this),
    1173             :                                          NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
    1174           0 :                                          u"" NS_IOSERVICE_OFFLINE);
    1175             :     }
    1176             :     return NS_OK;
    1177             : }
    1178             : 
    1179             : NS_IMETHODIMP
    1180           0 : nsIOService::AllowPort(int32_t inPort, const char *scheme, bool *_retval)
    1181             : {
    1182           0 :     int16_t port = inPort;
    1183           0 :     if (port == -1) {
    1184           0 :         *_retval = true;
    1185           0 :         return NS_OK;
    1186             :     }
    1187             : 
    1188           0 :     if (port == 0) {
    1189           0 :         *_retval = false;
    1190           0 :         return NS_OK;
    1191             :     }
    1192             : 
    1193             :     // first check to see if the port is in our blacklist:
    1194           0 :     int32_t badPortListCnt = mRestrictedPortList.Length();
    1195           0 :     for (int i=0; i<badPortListCnt; i++)
    1196             :     {
    1197           0 :         if (port == mRestrictedPortList[i])
    1198             :         {
    1199           0 :             *_retval = false;
    1200             : 
    1201             :             // check to see if the protocol wants to override
    1202           0 :             if (!scheme)
    1203             :                 return NS_OK;
    1204             : 
    1205           0 :             nsCOMPtr<nsIProtocolHandler> handler;
    1206           0 :             nsresult rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
    1207           0 :             if (NS_FAILED(rv)) return rv;
    1208             : 
    1209             :             // let the protocol handler decide
    1210           0 :             return handler->AllowPort(port, scheme, _retval);
    1211             :         }
    1212             :     }
    1213             : 
    1214           0 :     *_retval = true;
    1215           0 :     return NS_OK;
    1216             : }
    1217             : 
    1218             : ////////////////////////////////////////////////////////////////////////////////
    1219             : 
    1220             : void
    1221           3 : nsIOService::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
    1222             : {
    1223           0 :     if (!prefs) return;
    1224             : 
    1225             :     // Look for extra ports to block
    1226           3 :     if (!pref || strcmp(pref, PORT_PREF("banned")) == 0)
    1227           0 :         ParsePortList(prefs, PORT_PREF("banned"), false);
    1228             : 
    1229             :     // ...as well as previous blocks to remove.
    1230           0 :     if (!pref || strcmp(pref, PORT_PREF("banned.override")) == 0)
    1231           1 :         ParsePortList(prefs, PORT_PREF("banned.override"), true);
    1232             : 
    1233           0 :     if (!pref || strcmp(pref, MANAGE_OFFLINE_STATUS_PREF) == 0) {
    1234             :         bool manage;
    1235           0 :         if (mNetworkLinkServiceInitialized &&
    1236           0 :             NS_SUCCEEDED(prefs->GetBoolPref(MANAGE_OFFLINE_STATUS_PREF,
    1237             :                                             &manage))) {
    1238           2 :             LOG(("nsIOService::PrefsChanged ManageOfflineStatus manage=%d\n", manage));
    1239           2 :             SetManageOfflineStatus(manage);
    1240             :         }
    1241             :     }
    1242             : 
    1243           3 :     if (!pref || strcmp(pref, NECKO_BUFFER_CACHE_COUNT_PREF) == 0) {
    1244             :         int32_t count;
    1245           0 :         if (NS_SUCCEEDED(prefs->GetIntPref(NECKO_BUFFER_CACHE_COUNT_PREF,
    1246             :                                            &count)))
    1247             :             /* check for bogus values and default if we find such a value */
    1248           1 :             if (count > 0)
    1249           0 :                 gDefaultSegmentCount = count;
    1250             :     }
    1251             : 
    1252           3 :     if (!pref || strcmp(pref, NECKO_BUFFER_CACHE_SIZE_PREF) == 0) {
    1253             :         int32_t size;
    1254           1 :         if (NS_SUCCEEDED(prefs->GetIntPref(NECKO_BUFFER_CACHE_SIZE_PREF,
    1255             :                                            &size)))
    1256             :             /* check for bogus values and default if we find such a value
    1257             :              * the upper limit here is arbitrary. having a 1mb segment size
    1258             :              * is pretty crazy.  if you remove this, consider adding some
    1259             :              * integer rollover test.
    1260             :              */
    1261           1 :             if (size > 0 && size < 1024*1024)
    1262           1 :                 gDefaultSegmentSize = size;
    1263           1 :         NS_WARNING_ASSERTION(!(size & (size - 1)),
    1264             :                              "network segment size is not a power of 2!");
    1265             :     }
    1266             : 
    1267           0 :     if (!pref || strcmp(pref, NETWORK_NOTIFY_CHANGED_PREF) == 0) {
    1268             :         bool allow;
    1269           1 :         nsresult rv = prefs->GetBoolPref(NETWORK_NOTIFY_CHANGED_PREF, &allow);
    1270           1 :         if (NS_SUCCEEDED(rv)) {
    1271           1 :             mNetworkNotifyChanged = allow;
    1272             :         }
    1273             :     }
    1274             : 
    1275           0 :     if (!pref || strcmp(pref, NETWORK_CAPTIVE_PORTAL_PREF) == 0) {
    1276           0 :         nsresult rv = prefs->GetBoolPref(NETWORK_CAPTIVE_PORTAL_PREF, &gCaptivePortalEnabled);
    1277           2 :         if (NS_SUCCEEDED(rv) && mCaptivePortalService) {
    1278           0 :             if (gCaptivePortalEnabled && !xpc::AreNonLocalConnectionsDisabled()) {
    1279           2 :                 static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Start();
    1280             :             } else {
    1281           0 :                 static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Stop();
    1282             :             }
    1283             :         }
    1284             :     }
    1285             : }
    1286             : 
    1287             : void
    1288           2 : nsIOService::ParsePortList(nsIPrefBranch *prefBranch, const char *pref, bool remove)
    1289             : {
    1290           0 :     nsAutoCString portList;
    1291             : 
    1292             :     // Get a pref string and chop it up into a list of ports.
    1293           1 :     prefBranch->GetCharPref(pref, portList);
    1294           4 :     if (!portList.IsVoid()) {
    1295           0 :         nsTArray<nsCString> portListArray;
    1296           0 :         ParseString(portList, ',', portListArray);
    1297             :         uint32_t index;
    1298           0 :         for (index=0; index < portListArray.Length(); index++) {
    1299           0 :             portListArray[index].StripWhitespace();
    1300             :             int32_t portBegin, portEnd;
    1301             : 
    1302           0 :             if (PR_sscanf(portListArray[index].get(), "%d-%d", &portBegin, &portEnd) == 2) {
    1303           0 :                if ((portBegin < 65536) && (portEnd < 65536)) {
    1304             :                    int32_t curPort;
    1305           0 :                    if (remove) {
    1306           0 :                         for (curPort=portBegin; curPort <= portEnd; curPort++)
    1307           0 :                             mRestrictedPortList.RemoveElement(curPort);
    1308             :                    } else {
    1309           0 :                         for (curPort=portBegin; curPort <= portEnd; curPort++)
    1310           0 :                             mRestrictedPortList.AppendElement(curPort);
    1311             :                    }
    1312             :                }
    1313             :             } else {
    1314             :                nsresult aErrorCode;
    1315           0 :                int32_t port = portListArray[index].ToInteger(&aErrorCode);
    1316           0 :                if (NS_SUCCEEDED(aErrorCode) && port < 65536) {
    1317           0 :                    if (remove)
    1318           0 :                        mRestrictedPortList.RemoveElement(port);
    1319             :                    else
    1320           0 :                        mRestrictedPortList.AppendElement(port);
    1321             :                }
    1322             :             }
    1323             : 
    1324             :         }
    1325             :     }
    1326           0 : }
    1327             : 
    1328             : void
    1329           0 : nsIOService::GetPrefBranch(nsIPrefBranch **result)
    1330             : {
    1331           2 :     *result = nullptr;
    1332           2 :     CallGetService(NS_PREFSERVICE_CONTRACTID, result);
    1333           2 : }
    1334             : 
    1335             : class nsWakeupNotifier : public Runnable
    1336             : {
    1337             : public:
    1338           0 :   explicit nsWakeupNotifier(nsIIOServiceInternal* ioService)
    1339           0 :     : Runnable("net::nsWakeupNotifier")
    1340           0 :     , mIOService(ioService)
    1341             :   {
    1342           0 :   }
    1343             : 
    1344           0 :   NS_IMETHOD Run() override { return mIOService->NotifyWakeup(); }
    1345             : 
    1346             : private:
    1347           0 :     virtual ~nsWakeupNotifier() = default;
    1348             :     nsCOMPtr<nsIIOServiceInternal> mIOService;
    1349             : };
    1350             : 
    1351             : NS_IMETHODIMP
    1352           0 : nsIOService::NotifyWakeup()
    1353             : {
    1354           0 :     nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
    1355             : 
    1356           0 :     NS_ASSERTION(observerService, "The observer service should not be null");
    1357             : 
    1358           0 :     if (observerService && mNetworkNotifyChanged) {
    1359           0 :         (void)observerService->
    1360             :             NotifyObservers(nullptr,
    1361             :                             NS_NETWORK_LINK_TOPIC,
    1362           0 :                             (u"" NS_NETWORK_LINK_DATA_CHANGED));
    1363             :     }
    1364             : 
    1365           0 :     RecheckCaptivePortal();
    1366             : 
    1367           0 :     return NS_OK;
    1368             : }
    1369             : 
    1370             : void
    1371           0 : nsIOService::SetHttpHandlerAlreadyShutingDown()
    1372             : {
    1373           0 :     if (!mShutdown && !mOfflineForProfileChange) {
    1374           0 :         mNetTearingDownStarted = PR_IntervalNow();
    1375           0 :         mHttpHandlerAlreadyShutingDown = true;
    1376             :     }
    1377           0 : }
    1378             : 
    1379             : // nsIObserver interface
    1380             : NS_IMETHODIMP
    1381           2 : nsIOService::Observe(nsISupports *subject,
    1382             :                      const char *topic,
    1383             :                      const char16_t *data)
    1384             : {
    1385           0 :     if (!strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
    1386           0 :         nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
    1387           0 :         if (prefBranch)
    1388           0 :             PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
    1389           1 :     } else if (!strcmp(topic, kProfileChangeNetTeardownTopic)) {
    1390           0 :         if (!mHttpHandlerAlreadyShutingDown) {
    1391           0 :           mNetTearingDownStarted = PR_IntervalNow();
    1392             :         }
    1393           0 :         mHttpHandlerAlreadyShutingDown = false;
    1394           0 :         if (!mOffline) {
    1395           0 :             mOfflineForProfileChange = true;
    1396           0 :             SetOffline(true);
    1397             :         }
    1398           1 :     } else if (!strcmp(topic, kProfileChangeNetRestoreTopic)) {
    1399           0 :         if (mOfflineForProfileChange) {
    1400           0 :             mOfflineForProfileChange = false;
    1401           0 :             SetOffline(false);
    1402             :         }
    1403           0 :     } else if (!strcmp(topic, kProfileDoChange)) {
    1404           2 :         if (data && NS_LITERAL_STRING("startup").Equals(data)) {
    1405             :             // Lazy initialization of network link service (see bug 620472)
    1406           0 :             InitializeNetworkLinkService();
    1407             :             // Set up the initilization flag regardless the actuall result.
    1408             :             // If we fail here, we will fail always on.
    1409           0 :             mNetworkLinkServiceInitialized = true;
    1410             : 
    1411             :             // And now reflect the preference setting
    1412           2 :             nsCOMPtr<nsIPrefBranch> prefBranch;
    1413           1 :             GetPrefBranch(getter_AddRefs(prefBranch));
    1414           1 :             PrefsChanged(prefBranch, MANAGE_OFFLINE_STATUS_PREF);
    1415             : 
    1416             :             // Bug 870460 - Read cookie database at an early-as-possible time
    1417             :             // off main thread. Hence, we have more chance to finish db query
    1418             :             // before something calls into the cookie service.
    1419           2 :             nsCOMPtr<nsISupports> cookieServ = do_GetService(NS_COOKIESERVICE_CONTRACTID);
    1420             :         }
    1421           0 :     } else if (!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
    1422             :         // Remember we passed XPCOM shutdown notification to prevent any
    1423             :         // changes of the offline status from now. We must not allow going
    1424             :         // online after this point.
    1425           0 :         mShutdown = true;
    1426             : 
    1427           0 :         if (!mHttpHandlerAlreadyShutingDown && !mOfflineForProfileChange) {
    1428           0 :           mNetTearingDownStarted = PR_IntervalNow();
    1429             :         }
    1430           0 :         mHttpHandlerAlreadyShutingDown = false;
    1431             : 
    1432           0 :         SetOffline(true);
    1433             : 
    1434           0 :         if (mCaptivePortalService) {
    1435           0 :             static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Stop();
    1436           0 :             mCaptivePortalService = nullptr;
    1437             :         }
    1438             : 
    1439           0 :     } else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
    1440           0 :         OnNetworkLinkEvent(NS_ConvertUTF16toUTF8(data).get());
    1441           0 :     } else if (!strcmp(topic, NS_WIDGET_WAKE_OBSERVER_TOPIC)) {
    1442             :         // coming back alive from sleep
    1443             :         // this indirection brought to you by:
    1444             :         // https://bugzilla.mozilla.org/show_bug.cgi?id=1152048#c19
    1445           0 :         nsCOMPtr<nsIRunnable> wakeupNotifier = new nsWakeupNotifier(this);
    1446           0 :         NS_DispatchToMainThread(wakeupNotifier);
    1447             :     }
    1448             : 
    1449           2 :     return NS_OK;
    1450             : }
    1451             : 
    1452             : // nsINetUtil interface
    1453             : NS_IMETHODIMP
    1454           0 : nsIOService::ParseRequestContentType(const nsACString &aTypeHeader,
    1455             :                                      nsACString &aCharset,
    1456             :                                      bool *aHadCharset,
    1457             :                                      nsACString &aContentType)
    1458             : {
    1459           0 :     net_ParseRequestContentType(aTypeHeader, aContentType, aCharset, aHadCharset);
    1460           0 :     return NS_OK;
    1461             : }
    1462             : 
    1463             : // nsINetUtil interface
    1464             : NS_IMETHODIMP
    1465         103 : nsIOService::ParseResponseContentType(const nsACString &aTypeHeader,
    1466             :                                       nsACString &aCharset,
    1467             :                                       bool *aHadCharset,
    1468             :                                       nsACString &aContentType)
    1469             : {
    1470         103 :     net_ParseContentType(aTypeHeader, aContentType, aCharset, aHadCharset);
    1471         103 :     return NS_OK;
    1472             : }
    1473             : 
    1474             : NS_IMETHODIMP
    1475        1287 : nsIOService::ProtocolHasFlags(nsIURI   *uri,
    1476             :                               uint32_t  flags,
    1477             :                               bool     *result)
    1478             : {
    1479           0 :     NS_ENSURE_ARG(uri);
    1480             : 
    1481           0 :     *result = false;
    1482        1287 :     nsAutoCString scheme;
    1483        1287 :     nsresult rv = uri->GetScheme(scheme);
    1484        1287 :     NS_ENSURE_SUCCESS(rv, rv);
    1485             : 
    1486             :     // Grab the protocol flags from the URI.
    1487             :     uint32_t protocolFlags;
    1488           0 :     nsCOMPtr<nsIProtocolHandler> handler;
    1489           0 :     rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
    1490        1287 :     NS_ENSURE_SUCCESS(rv, rv);
    1491           0 :     rv = handler->DoGetProtocolFlags(uri, &protocolFlags);
    1492           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1493             : 
    1494        1287 :     *result = (protocolFlags & flags) == flags;
    1495        1287 :     return NS_OK;
    1496             : }
    1497             : 
    1498             : NS_IMETHODIMP
    1499         855 : nsIOService::URIChainHasFlags(nsIURI   *uri,
    1500             :                               uint32_t  flags,
    1501             :                               bool     *result)
    1502             : {
    1503           0 :     nsresult rv = ProtocolHasFlags(uri, flags, result);
    1504         855 :     NS_ENSURE_SUCCESS(rv, rv);
    1505             : 
    1506         855 :     if (*result) {
    1507             :         return rv;
    1508             :     }
    1509             : 
    1510             :     // Dig deeper into the chain.  Note that this is not a do/while loop to
    1511             :     // avoid the extra addref/release on |uri| in the common (non-nested) case.
    1512           0 :     nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(uri);
    1513           0 :     while (nestedURI) {
    1514         140 :         nsCOMPtr<nsIURI> innerURI;
    1515           0 :         rv = nestedURI->GetInnerURI(getter_AddRefs(innerURI));
    1516         116 :         NS_ENSURE_SUCCESS(rv, rv);
    1517             : 
    1518         116 :         rv = ProtocolHasFlags(innerURI, flags, result);
    1519             : 
    1520         116 :         if (*result) {
    1521             :             return rv;
    1522             :         }
    1523             : 
    1524          48 :         nestedURI = do_QueryInterface(innerURI);
    1525             :     }
    1526             : 
    1527             :     return rv;
    1528             : }
    1529             : 
    1530             : NS_IMETHODIMP
    1531           0 : nsIOService::SetManageOfflineStatus(bool aManage)
    1532             : {
    1533           2 :     LOG(("nsIOService::SetManageOfflineStatus aManage=%d\n", aManage));
    1534           0 :     mManageLinkStatus = aManage;
    1535             : 
    1536             :     // When detection is not activated, the default connectivity state is true.
    1537           2 :     if (!mManageLinkStatus) {
    1538           2 :         SetConnectivityInternal(true);
    1539           0 :         return NS_OK;
    1540             :     }
    1541             : 
    1542           0 :     InitializeNetworkLinkService();
    1543             :     // If the NetworkLinkService is already initialized, it does not call
    1544             :     // OnNetworkLinkEvent. This is needed, when mManageLinkStatus goes from
    1545             :     // false to true.
    1546           0 :     OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN);
    1547           0 :     return NS_OK;
    1548             : }
    1549             : 
    1550             : NS_IMETHODIMP
    1551           0 : nsIOService::GetManageOfflineStatus(bool* aManage)
    1552             : {
    1553           0 :     *aManage = mManageLinkStatus;
    1554           0 :     return NS_OK;
    1555             : }
    1556             : 
    1557             : // input argument 'data' is already UTF8'ed
    1558             : nsresult
    1559           1 : nsIOService::OnNetworkLinkEvent(const char *data)
    1560             : {
    1561           1 :     if (IsNeckoChild()) {
    1562             :         // There is nothing IO service could do on the child process
    1563             :         // with this at the moment.  Feel free to add functionality
    1564             :         // here at will, though.
    1565             :         return NS_OK;
    1566             :     }
    1567             : 
    1568           1 :     if (mShutdown) {
    1569             :         return NS_ERROR_NOT_AVAILABLE;
    1570             :     }
    1571             : 
    1572           1 :     nsCString dataAsString(data);
    1573           2 :     for (auto* cp : mozilla::dom::ContentParent::AllProcesses(mozilla::dom::ContentParent::eLive)) {
    1574           0 :         PNeckoParent* neckoParent = SingleManagedOrNull(cp->ManagedPNeckoParent());
    1575           0 :         if (!neckoParent) {
    1576             :             continue;
    1577             :         }
    1578           0 :         Unused << neckoParent->SendNetworkChangeNotification(dataAsString);
    1579             :     }
    1580             : 
    1581           1 :     LOG(("nsIOService::OnNetworkLinkEvent data:%s\n", data));
    1582           2 :     if (!mNetworkLinkService) {
    1583             :         return NS_ERROR_FAILURE;
    1584             :     }
    1585             : 
    1586           1 :     if (!mManageLinkStatus) {
    1587           1 :         LOG(("nsIOService::OnNetworkLinkEvent mManageLinkStatus=false\n"));
    1588             :         return NS_OK;
    1589             :     }
    1590             : 
    1591           0 :     bool isUp = true;
    1592           0 :     if (!strcmp(data, NS_NETWORK_LINK_DATA_CHANGED)) {
    1593           0 :         mLastNetworkLinkChange = PR_IntervalNow();
    1594             :         // CHANGED means UP/DOWN didn't change
    1595             :         // but the status of the captive portal may have changed.
    1596           0 :         RecheckCaptivePortal();
    1597           0 :         return NS_OK;
    1598             :     }
    1599           0 :     if (!strcmp(data, NS_NETWORK_LINK_DATA_DOWN)) {
    1600           0 :         isUp = false;
    1601           0 :     } else if (!strcmp(data, NS_NETWORK_LINK_DATA_UP)) {
    1602             :         isUp = true;
    1603           0 :     } else if (!strcmp(data, NS_NETWORK_LINK_DATA_UNKNOWN)) {
    1604           0 :         nsresult rv = mNetworkLinkService->GetIsLinkUp(&isUp);
    1605           0 :         NS_ENSURE_SUCCESS(rv, rv);
    1606             :     } else {
    1607           0 :         NS_WARNING("Unhandled network event!");
    1608           0 :         return NS_OK;
    1609             :     }
    1610             : 
    1611           0 :     return SetConnectivityInternal(isUp);
    1612             : }
    1613             : 
    1614             : NS_IMETHODIMP
    1615           0 : nsIOService::EscapeString(const nsACString& aString,
    1616             :                           uint32_t aEscapeType,
    1617             :                           nsACString& aResult)
    1618             : {
    1619           0 :   NS_ENSURE_ARG_MAX(aEscapeType, 4);
    1620             : 
    1621           0 :   nsAutoCString stringCopy(aString);
    1622           0 :   nsCString result;
    1623             : 
    1624           0 :   if (!NS_Escape(stringCopy, result, (nsEscapeMask) aEscapeType))
    1625             :     return NS_ERROR_OUT_OF_MEMORY;
    1626             : 
    1627           0 :   aResult.Assign(result);
    1628             : 
    1629           0 :   return NS_OK;
    1630             : }
    1631             : 
    1632             : NS_IMETHODIMP
    1633           0 : nsIOService::EscapeURL(const nsACString &aStr,
    1634             :                        uint32_t aFlags, nsACString &aResult)
    1635             : {
    1636           0 :   aResult.Truncate();
    1637           0 :   NS_EscapeURL(aStr.BeginReading(), aStr.Length(),
    1638           0 :                aFlags | esc_AlwaysCopy, aResult);
    1639           0 :   return NS_OK;
    1640             : }
    1641             : 
    1642             : NS_IMETHODIMP
    1643           0 : nsIOService::UnescapeString(const nsACString &aStr,
    1644             :                             uint32_t aFlags, nsACString &aResult)
    1645             : {
    1646           0 :   aResult.Truncate();
    1647           0 :   NS_UnescapeURL(aStr.BeginReading(), aStr.Length(),
    1648           0 :                  aFlags | esc_AlwaysCopy, aResult);
    1649           0 :   return NS_OK;
    1650             : }
    1651             : 
    1652             : NS_IMETHODIMP
    1653           1 : nsIOService::ExtractCharsetFromContentType(const nsACString &aTypeHeader,
    1654             :                                            nsACString &aCharset,
    1655             :                                            int32_t *aCharsetStart,
    1656             :                                            int32_t *aCharsetEnd,
    1657             :                                            bool *aHadCharset)
    1658             : {
    1659           0 :     nsAutoCString ignored;
    1660             :     net_ParseContentType(aTypeHeader, ignored, aCharset, aHadCharset,
    1661           1 :                          aCharsetStart, aCharsetEnd);
    1662           0 :     if (*aHadCharset && *aCharsetStart == *aCharsetEnd) {
    1663           0 :         *aHadCharset = false;
    1664             :     }
    1665           2 :     return NS_OK;
    1666             : }
    1667             : 
    1668             : // parse policyString to policy enum value (see ReferrerPolicy.h)
    1669             : NS_IMETHODIMP
    1670           0 : nsIOService::ParseAttributePolicyString(const nsAString& policyString,
    1671             :                                                 uint32_t *outPolicyEnum)
    1672             : {
    1673           0 :   NS_ENSURE_ARG(outPolicyEnum);
    1674           0 :   *outPolicyEnum = (uint32_t)AttributeReferrerPolicyFromString(policyString);
    1675           0 :   return NS_OK;
    1676             : }
    1677             : 
    1678             : // nsISpeculativeConnect
    1679             : class IOServiceProxyCallback final : public nsIProtocolProxyCallback
    1680             : {
    1681           0 :     ~IOServiceProxyCallback() = default;
    1682             : 
    1683             : public:
    1684             :     NS_DECL_ISUPPORTS
    1685             :     NS_DECL_NSIPROTOCOLPROXYCALLBACK
    1686             : 
    1687           0 :     IOServiceProxyCallback(nsIInterfaceRequestor *aCallbacks,
    1688             :                            nsIOService *aIOService)
    1689           0 :         : mCallbacks(aCallbacks)
    1690           0 :         , mIOService(aIOService)
    1691           0 :     { }
    1692             : 
    1693             : private:
    1694             :     RefPtr<nsIInterfaceRequestor> mCallbacks;
    1695             :     RefPtr<nsIOService>           mIOService;
    1696             : };
    1697             : 
    1698           0 : NS_IMPL_ISUPPORTS(IOServiceProxyCallback, nsIProtocolProxyCallback)
    1699             : 
    1700             : NS_IMETHODIMP
    1701           0 : IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIChannel *channel,
    1702             :                                          nsIProxyInfo *pi, nsresult status)
    1703             : {
    1704             :     // Checking proxy status for speculative connect
    1705           0 :     nsAutoCString type;
    1706           0 :     if (NS_SUCCEEDED(status) && pi &&
    1707           0 :         NS_SUCCEEDED(pi->GetType(type)) &&
    1708           0 :         !type.EqualsLiteral("direct")) {
    1709             :         // proxies dont do speculative connect
    1710             :         return NS_OK;
    1711             :     }
    1712             : 
    1713           0 :     nsCOMPtr<nsIURI> uri;
    1714           0 :     nsresult rv = channel->GetURI(getter_AddRefs(uri));
    1715           0 :     if (NS_FAILED(rv)) {
    1716             :         return NS_OK;
    1717             :     }
    1718             : 
    1719           0 :     nsAutoCString scheme;
    1720           0 :     rv = uri->GetScheme(scheme);
    1721           0 :     if (NS_FAILED(rv))
    1722             :         return NS_OK;
    1723             : 
    1724           0 :     nsCOMPtr<nsIProtocolHandler> handler;
    1725           0 :     rv = mIOService->GetProtocolHandler(scheme.get(),
    1726           0 :                                         getter_AddRefs(handler));
    1727           0 :     if (NS_FAILED(rv))
    1728             :         return NS_OK;
    1729             : 
    1730             :     nsCOMPtr<nsISpeculativeConnect> speculativeHandler =
    1731           0 :         do_QueryInterface(handler);
    1732           0 :     if (!speculativeHandler)
    1733             :         return NS_OK;
    1734             : 
    1735           0 :     nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
    1736           0 :     nsCOMPtr<nsIPrincipal> principal;
    1737           0 :     if (loadInfo) {
    1738           0 :       principal = loadInfo->LoadingPrincipal();
    1739             :     }
    1740             : 
    1741           0 :     nsLoadFlags loadFlags = 0;
    1742           0 :     channel->GetLoadFlags(&loadFlags);
    1743           0 :     if (loadFlags & nsIRequest::LOAD_ANONYMOUS) {
    1744           0 :         speculativeHandler->SpeculativeAnonymousConnect2(uri, principal, mCallbacks);
    1745             :     } else {
    1746           0 :         speculativeHandler->SpeculativeConnect2(uri, principal, mCallbacks);
    1747             :     }
    1748             : 
    1749             :     return NS_OK;
    1750             : }
    1751             : 
    1752             : nsresult
    1753           0 : nsIOService::SpeculativeConnectInternal(nsIURI *aURI,
    1754             :                                         nsIPrincipal *aPrincipal,
    1755             :                                         nsIInterfaceRequestor *aCallbacks,
    1756             :                                         bool aAnonymous)
    1757             : {
    1758           0 :     NS_ENSURE_ARG(aURI);
    1759             : 
    1760             :     bool isHTTP, isHTTPS;
    1761           0 :     if (!(NS_SUCCEEDED(aURI->SchemeIs("http", &isHTTP)) && isHTTP) &&
    1762           0 :         !(NS_SUCCEEDED(aURI->SchemeIs("https", &isHTTPS)) && isHTTPS)) {
    1763             :         // We don't speculatively connect to non-HTTP[S] URIs.
    1764             :         return NS_OK;
    1765             :     }
    1766             : 
    1767           0 :     if (IsNeckoChild()) {
    1768           0 :         ipc::URIParams params;
    1769           0 :         SerializeURI(aURI, params);
    1770           0 :         gNeckoChild->SendSpeculativeConnect(params,
    1771           0 :                                             IPC::Principal(aPrincipal),
    1772           0 :                                             aAnonymous);
    1773             :         return NS_OK;
    1774             :     }
    1775             : 
    1776             :     // Check for proxy information. If there is a proxy configured then a
    1777             :     // speculative connect should not be performed because the potential
    1778             :     // reward is slim with tcp peers closely located to the browser.
    1779             :     nsresult rv;
    1780             :     nsCOMPtr<nsIProtocolProxyService> pps =
    1781           0 :             do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
    1782           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1783             : 
    1784           0 :     nsCOMPtr<nsIPrincipal> loadingPrincipal = aPrincipal;
    1785             : 
    1786           0 :     NS_ASSERTION(aPrincipal, "We expect passing a principal here.");
    1787             : 
    1788             :     // If the principal is given, we use this principal directly. Otherwise,
    1789             :     // we fallback to use the system principal.
    1790           0 :     if (!aPrincipal) {
    1791           0 :         loadingPrincipal = nsContentUtils::GetSystemPrincipal();
    1792             :     }
    1793             : 
    1794             :     // dummy channel used to create a TCP connection.
    1795             :     // we perform security checks on the *real* channel, responsible
    1796             :     // for any network loads. this real channel just checks the TCP
    1797             :     // pool if there is an available connection created by the
    1798             :     // channel we create underneath - hence it's safe to use
    1799             :     // the systemPrincipal as the loadingPrincipal for this channel.
    1800           0 :     nsCOMPtr<nsIChannel> channel;
    1801           0 :     rv = NewChannelFromURI2(aURI,
    1802             :                             nullptr, // aLoadingNode,
    1803             :                             loadingPrincipal,
    1804             :                             nullptr, //aTriggeringPrincipal,
    1805             :                             nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
    1806             :                             nsIContentPolicy::TYPE_SPECULATIVE,
    1807           0 :                             getter_AddRefs(channel));
    1808           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1809             : 
    1810           0 :     if (aAnonymous) {
    1811           0 :         nsLoadFlags loadFlags = 0;
    1812           0 :         channel->GetLoadFlags(&loadFlags);
    1813           0 :         loadFlags |= nsIRequest::LOAD_ANONYMOUS;
    1814           0 :         channel->SetLoadFlags(loadFlags);
    1815             :     }
    1816             : 
    1817           0 :     nsCOMPtr<nsICancelable> cancelable;
    1818             :     RefPtr<IOServiceProxyCallback> callback =
    1819           0 :         new IOServiceProxyCallback(aCallbacks, this);
    1820           0 :     nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
    1821           0 :     if (pps2) {
    1822           0 :         return pps2->AsyncResolve2(channel, 0, callback, nullptr,
    1823           0 :                                    getter_AddRefs(cancelable));
    1824             :     }
    1825           0 :     return pps->AsyncResolve(channel, 0, callback, nullptr,
    1826           0 :                              getter_AddRefs(cancelable));
    1827             : }
    1828             : 
    1829             : NS_IMETHODIMP
    1830           0 : nsIOService::SpeculativeConnect(nsIURI *aURI,
    1831             :                                 nsIInterfaceRequestor *aCallbacks)
    1832             : {
    1833           0 :     return SpeculativeConnectInternal(aURI, nullptr, aCallbacks, false);
    1834             : }
    1835             : 
    1836             : NS_IMETHODIMP
    1837           0 : nsIOService::SpeculativeConnect2(nsIURI *aURI,
    1838             :                                  nsIPrincipal *aPrincipal,
    1839             :                                  nsIInterfaceRequestor *aCallbacks)
    1840             : {
    1841           0 :     return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, false);
    1842             : }
    1843             : 
    1844             : NS_IMETHODIMP
    1845           0 : nsIOService::SpeculativeAnonymousConnect(nsIURI *aURI,
    1846             :                                          nsIInterfaceRequestor *aCallbacks)
    1847             : {
    1848           0 :     return SpeculativeConnectInternal(aURI, nullptr, aCallbacks, true);
    1849             : }
    1850             : 
    1851             : NS_IMETHODIMP
    1852           0 : nsIOService::SpeculativeAnonymousConnect2(nsIURI *aURI,
    1853             :                                           nsIPrincipal *aPrincipal,
    1854             :                                           nsIInterfaceRequestor *aCallbacks)
    1855             : {
    1856           0 :     return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, true);
    1857             : }
    1858             : 
    1859             : /*static*/ bool
    1860          29 : nsIOService::IsDataURIUniqueOpaqueOrigin()
    1861             : {
    1862          29 :   return sIsDataURIUniqueOpaqueOrigin;
    1863             : }
    1864             : 
    1865             : /*static*/ bool
    1866           7 : nsIOService::BlockToplevelDataUriNavigations()
    1867             : {
    1868           7 :   return sBlockToplevelDataUriNavigations;
    1869             : }
    1870             : 
    1871             : /*static*/ bool
    1872         532 : nsIOService::BlockFTPSubresources()
    1873             : {
    1874         532 :   return sBlockFTPSubresources;
    1875             : }
    1876             : 
    1877             : NS_IMETHODIMP
    1878             : nsIOService::NotImplemented()
    1879             : {
    1880             :   return NS_ERROR_NOT_IMPLEMENTED;
    1881             : }
    1882             : 
    1883             : } // namespace net
    1884             : } // namespace mozilla

Generated by: LCOV version 1.13-14-ga5dd952