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

Generated by: LCOV version 1.13