LCOV - code coverage report
Current view: directory - netwerk/base/src - nsIOService.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 492 374 76.0 %
Date: 2012-06-02 Functions: 42 37 88.1 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* vim:set ts=4 sw=4 cindent et: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *      Prasad Sunkari <prasad@medhas.org>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "nsIOService.h"
      41                 : #include "nsIProtocolHandler.h"
      42                 : #include "nsIFileProtocolHandler.h"
      43                 : #include "nscore.h"
      44                 : #include "nsIServiceManager.h"
      45                 : #include "nsIURI.h"
      46                 : #include "nsIStreamListener.h"
      47                 : #include "prprf.h"
      48                 : #include "prlog.h"
      49                 : #include "nsLoadGroup.h"
      50                 : #include "nsInputStreamChannel.h"
      51                 : #include "nsXPIDLString.h" 
      52                 : #include "nsReadableUtils.h"
      53                 : #include "nsIErrorService.h" 
      54                 : #include "netCore.h"
      55                 : #include "nsIObserverService.h"
      56                 : #include "nsIPrefService.h"
      57                 : #include "nsIPrefLocalizedString.h"
      58                 : #include "nsICategoryManager.h"
      59                 : #include "nsXPCOM.h"
      60                 : #include "nsISupportsPrimitives.h"
      61                 : #include "nsIProxiedProtocolHandler.h"
      62                 : #include "nsIProxyInfo.h"
      63                 : #include "nsEscape.h"
      64                 : #include "nsNetCID.h"
      65                 : #include "nsISocketTransport.h"
      66                 : #include "nsCRT.h"
      67                 : #include "nsSimpleNestedURI.h"
      68                 : #include "nsNetUtil.h"
      69                 : #include "nsThreadUtils.h"
      70                 : #include "nsIPermissionManager.h"
      71                 : #include "nsTArray.h"
      72                 : #include "nsIConsoleService.h"
      73                 : #include "nsIUploadChannel2.h"
      74                 : #include "nsXULAppAPI.h"
      75                 : 
      76                 : #include "mozilla/FunctionTimer.h"
      77                 : 
      78                 : #if defined(XP_WIN) || defined(MOZ_PLATFORM_MAEMO)
      79                 : #include "nsNativeConnectionHelper.h"
      80                 : #endif
      81                 : 
      82                 : #define PORT_PREF_PREFIX           "network.security.ports."
      83                 : #define PORT_PREF(x)               PORT_PREF_PREFIX x
      84                 : #define AUTODIAL_PREF              "network.autodial-helper.enabled"
      85                 : #define MANAGE_OFFLINE_STATUS_PREF "network.manage-offline-status"
      86                 : 
      87                 : // Nb: these have been misnomers since bug 715770 removed the buffer cache.
      88                 : // "network.segment.count" and "network.segment.size" would be better names,
      89                 : // but the old names are still used to preserve backward compatibility.
      90                 : #define NECKO_BUFFER_CACHE_COUNT_PREF "network.buffer.cache.count"
      91                 : #define NECKO_BUFFER_CACHE_SIZE_PREF  "network.buffer.cache.size"
      92                 : 
      93                 : #define MAX_RECURSION_COUNT 50
      94                 : 
      95                 : nsIOService* gIOService = nsnull;
      96                 : static bool gHasWarnedUploadChannel2;
      97                 : 
      98                 : // A general port blacklist.  Connections to these ports will not be allowed unless 
      99                 : // the protocol overrides.
     100                 : //
     101                 : // TODO: I am sure that there are more ports to be added.  
     102                 : //       This cut is based on the classic mozilla codebase
     103                 : 
     104                 : PRInt16 gBadPortList[] = { 
     105                 :   1,    // tcpmux          
     106                 :   7,    // echo     
     107                 :   9,    // discard          
     108                 :   11,   // systat   
     109                 :   13,   // daytime          
     110                 :   15,   // netstat  
     111                 :   17,   // qotd             
     112                 :   19,   // chargen  
     113                 :   20,   // ftp-data         
     114                 :   21,   // ftp-cntl 
     115                 :   22,   // ssh              
     116                 :   23,   // telnet   
     117                 :   25,   // smtp     
     118                 :   37,   // time     
     119                 :   42,   // name     
     120                 :   43,   // nicname  
     121                 :   53,   // domain  
     122                 :   77,   // priv-rjs 
     123                 :   79,   // finger   
     124                 :   87,   // ttylink  
     125                 :   95,   // supdup   
     126                 :   101,  // hostriame
     127                 :   102,  // iso-tsap 
     128                 :   103,  // gppitnp  
     129                 :   104,  // acr-nema 
     130                 :   109,  // pop2     
     131                 :   110,  // pop3     
     132                 :   111,  // sunrpc   
     133                 :   113,  // auth     
     134                 :   115,  // sftp     
     135                 :   117,  // uucp-path
     136                 :   119,  // nntp     
     137                 :   123,  // NTP
     138                 :   135,  // loc-srv / epmap         
     139                 :   139,  // netbios
     140                 :   143,  // imap2  
     141                 :   179,  // BGP
     142                 :   389,  // ldap        
     143                 :   465,  // smtp+ssl
     144                 :   512,  // print / exec          
     145                 :   513,  // login         
     146                 :   514,  // shell         
     147                 :   515,  // printer         
     148                 :   526,  // tempo         
     149                 :   530,  // courier        
     150                 :   531,  // Chat         
     151                 :   532,  // netnews        
     152                 :   540,  // uucp       
     153                 :   556,  // remotefs    
     154                 :   563,  // nntp+ssl
     155                 :   587,  //
     156                 :   601,  //       
     157                 :   636,  // ldap+ssl
     158                 :   993,  // imap+ssl
     159                 :   995,  // pop3+ssl
     160                 :   2049, // nfs
     161                 :   4045, // lockd
     162                 :   6000, // x11        
     163                 :   0,    // This MUST be zero so that we can populating the array
     164                 : };
     165                 : 
     166                 : static const char kProfileChangeNetTeardownTopic[] = "profile-change-net-teardown";
     167                 : static const char kProfileChangeNetRestoreTopic[] = "profile-change-net-restore";
     168                 : static const char kProfileDoChange[] = "profile-do-change";
     169                 : 
     170                 : // Necko buffer defaults
     171                 : PRUint32   nsIOService::gDefaultSegmentSize = 4096;
     172                 : PRUint32   nsIOService::gDefaultSegmentCount = 24;
     173                 : 
     174                 : ////////////////////////////////////////////////////////////////////////////////
     175                 : 
     176            1419 : nsIOService::nsIOService()
     177                 :     : mOffline(true)
     178                 :     , mOfflineForProfileChange(false)
     179                 :     , mManageOfflineStatus(false)
     180                 :     , mSettingOffline(false)
     181                 :     , mSetOfflineValue(false)
     182                 :     , mShutdown(false)
     183                 :     , mNetworkLinkServiceInitialized(false)
     184                 :     , mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY)
     185                 :     , mContentSniffers(NS_CONTENT_SNIFFER_CATEGORY)
     186            1419 :     , mAutoDialEnabled(false)
     187                 : {
     188            1419 : }
     189                 : 
     190                 : nsresult
     191            1419 : nsIOService::Init()
     192                 : {
     193                 :     NS_TIME_FUNCTION;
     194                 : 
     195                 :     nsresult rv;
     196                 : 
     197                 :     // We need to get references to the DNS service so that we can shut it
     198                 :     // down later. If we wait until the nsIOService is being shut down,
     199                 :     // GetService will fail at that point.
     200                 : 
     201            1419 :     mDNSService = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
     202            1419 :     if (NS_FAILED(rv)) {
     203               0 :         NS_WARNING("failed to get DNS service");
     204               0 :         return rv;
     205                 :     }
     206                 : 
     207                 :     NS_TIME_FUNCTION_MARK("got DNS Service");
     208                 : 
     209                 :     // XXX hack until xpidl supports error info directly (bug 13423)
     210            2838 :     nsCOMPtr<nsIErrorService> errorService = do_GetService(NS_ERRORSERVICE_CONTRACTID);
     211            1419 :     if (errorService) {
     212            1419 :         errorService->RegisterErrorStringBundle(NS_ERROR_MODULE_NETWORK, NECKO_MSGS_URL);
     213                 :     }
     214                 :     else
     215               0 :         NS_WARNING("failed to get error service");
     216                 :     
     217                 :     NS_TIME_FUNCTION_MARK("got Error Service");
     218                 : 
     219                 :     // setup our bad port list stuff
     220           83721 :     for(int i=0; gBadPortList[i]; i++)
     221           82302 :         mRestrictedPortList.AppendElement(gBadPortList[i]);
     222                 : 
     223                 :     // Further modifications to the port list come from prefs
     224            2838 :     nsCOMPtr<nsIPrefBranch> prefBranch;
     225            1419 :     GetPrefBranch(getter_AddRefs(prefBranch));
     226            1419 :     if (prefBranch) {
     227            1419 :         prefBranch->AddObserver(PORT_PREF_PREFIX, this, true);
     228            1419 :         prefBranch->AddObserver(AUTODIAL_PREF, this, true);
     229            1419 :         prefBranch->AddObserver(MANAGE_OFFLINE_STATUS_PREF, this, true);
     230            1419 :         PrefsChanged(prefBranch);
     231                 :     }
     232                 :     
     233                 :     // Register for profile change notifications
     234                 :     nsCOMPtr<nsIObserverService> observerService =
     235            2838 :         mozilla::services::GetObserverService();
     236            1419 :     if (observerService) {
     237            1419 :         observerService->AddObserver(this, kProfileChangeNetTeardownTopic, true);
     238            1419 :         observerService->AddObserver(this, kProfileChangeNetRestoreTopic, true);
     239            1419 :         observerService->AddObserver(this, kProfileDoChange, true);
     240            1419 :         observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
     241            1419 :         observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, true);
     242                 :     }
     243                 :     else
     244               0 :         NS_WARNING("failed to get observer service");
     245                 :         
     246                 :     NS_TIME_FUNCTION_MARK("Registered observers");
     247                 : 
     248            1419 :     gIOService = this;
     249                 : 
     250            1419 :     InitializeNetworkLinkService();
     251                 :  
     252                 :     NS_TIME_FUNCTION_MARK("Set up network link service");
     253                 : 
     254            1419 :     return NS_OK;
     255                 : }
     256                 : 
     257                 : 
     258           12744 : nsIOService::~nsIOService()
     259                 : {
     260            1416 :     gIOService = nsnull;
     261           11328 : }
     262                 : 
     263                 : nsresult
     264            1426 : nsIOService::InitializeSocketTransportService()
     265                 : {
     266                 :     NS_TIME_FUNCTION;
     267                 : 
     268            1426 :     nsresult rv = NS_OK;
     269                 : 
     270            1426 :     if (!mSocketTransportService) {
     271            1419 :         mSocketTransportService = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
     272            1419 :         if (NS_FAILED(rv)) {
     273               0 :             NS_WARNING("failed to get socket transport service");
     274                 :         }
     275                 :     }
     276                 : 
     277            1426 :     if (mSocketTransportService) {
     278            1426 :         rv = mSocketTransportService->Init();
     279            1426 :         NS_ASSERTION(NS_SUCCEEDED(rv), "socket transport service init failed");
     280            1426 :         mSocketTransportService->SetAutodialEnabled(mAutoDialEnabled);
     281                 :     }
     282                 : 
     283            1426 :     return rv;
     284                 : }
     285                 : 
     286                 : nsresult
     287            4225 : nsIOService::InitializeNetworkLinkService()
     288                 : {
     289                 :     NS_TIME_FUNCTION;
     290                 : 
     291            4225 :     nsresult rv = NS_OK;
     292                 : 
     293            4225 :     if (mNetworkLinkServiceInitialized)
     294               1 :         return rv;
     295                 : 
     296            4224 :     if (!NS_IsMainThread()) {
     297               0 :         NS_WARNING("Network link service should be created on main thread"); 
     298               0 :         return NS_ERROR_FAILURE; 
     299                 :     }
     300                 : 
     301                 :     // go into managed mode if we can, and chrome process
     302            4224 :     if (XRE_GetProcessType() == GeckoProcessType_Default)
     303                 :     {
     304            4224 :         mNetworkLinkService = do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID, &rv);
     305                 :     }
     306                 : 
     307            4224 :     if (mNetworkLinkService) {
     308            1386 :         mNetworkLinkServiceInitialized = true;
     309                 :     }
     310                 :     else {
     311                 :         // We can't really determine if the machine has a usable network connection,
     312                 :         // so let's cross our fingers!
     313            2838 :         mManageOfflineStatus = false;
     314                 :     }
     315                 :    
     316                 : 
     317            4224 :     if (mManageOfflineStatus)
     318               0 :         TrackNetworkLinkStatusForOffline();
     319                 :     else
     320            4224 :         SetOffline(false);
     321                 :     
     322            4224 :     return rv;
     323                 : }
     324                 : 
     325                 : nsIOService*
     326            1465 : nsIOService::GetInstance() {
     327            1465 :     if (!gIOService) {
     328            1419 :         gIOService = new nsIOService();
     329            1419 :         if (!gIOService)
     330               0 :             return nsnull;
     331            1419 :         NS_ADDREF(gIOService);
     332                 : 
     333            1419 :         nsresult rv = gIOService->Init();
     334            1419 :         if (NS_FAILED(rv)) {
     335               0 :             NS_RELEASE(gIOService);
     336               0 :             return nsnull;
     337                 :         }
     338            1419 :         return gIOService;
     339                 :     }
     340              46 :     NS_ADDREF(gIOService);
     341              46 :     return gIOService;
     342                 : }
     343                 : 
     344         2587249 : NS_IMPL_THREADSAFE_ISUPPORTS5(nsIOService,
     345                 :                               nsIIOService,
     346                 :                               nsIIOService2,
     347                 :                               nsINetUtil,
     348                 :                               nsIObserver,
     349                 :                               nsISupportsWeakReference)
     350                 : 
     351                 : ////////////////////////////////////////////////////////////////////////////////
     352                 : 
     353                 : nsresult
     354             155 : nsIOService::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
     355                 :                                     PRUint32 flags,
     356                 :                                     nsAsyncRedirectVerifyHelper *helper)
     357                 : {
     358                 :     nsCOMPtr<nsIChannelEventSink> sink =
     359             310 :         do_GetService(NS_GLOBAL_CHANNELEVENTSINK_CONTRACTID);
     360             155 :     if (sink) {
     361                 :         nsresult rv = helper->DelegateOnChannelRedirect(sink, oldChan,
     362             155 :                                                         newChan, flags);
     363             155 :         if (NS_FAILED(rv))
     364               2 :             return rv;
     365                 :     }
     366                 : 
     367                 :     // Finally, our category
     368                 :     const nsCOMArray<nsIChannelEventSink>& entries =
     369             153 :         mChannelEventSinks.GetEntries();
     370             153 :     PRInt32 len = entries.Count();
     371             306 :     for (PRInt32 i = 0; i < len; ++i) {
     372                 :         nsresult rv = helper->DelegateOnChannelRedirect(entries[i], oldChan,
     373             154 :                                                         newChan, flags);
     374             154 :         if (NS_FAILED(rv))
     375               1 :             return rv;
     376                 :     }
     377             152 :     return NS_OK;
     378                 : }
     379                 : 
     380                 : nsresult
     381           11798 : nsIOService::CacheProtocolHandler(const char *scheme, nsIProtocolHandler *handler)
     382                 : {
     383           54323 :     for (unsigned int i=0; i<NS_N(gScheme); i++)
     384                 :     {
     385           47587 :         if (!nsCRT::strcasecmp(scheme, gScheme[i]))
     386                 :         {
     387                 :             nsresult rv;
     388            5062 :             NS_ASSERTION(!mWeakHandler[i], "Protocol handler already cached");
     389                 :             // Make sure the handler supports weak references.
     390           10124 :             nsCOMPtr<nsISupportsWeakReference> factoryPtr = do_QueryInterface(handler, &rv);
     391            5062 :             if (!factoryPtr)
     392                 :             {
     393                 :                 // Don't cache handlers that don't support weak reference as
     394                 :                 // there is real danger of a circular reference.
     395                 : #ifdef DEBUG_dp
     396                 :                 printf("DEBUG: %s protcol handler doesn't support weak ref. Not cached.\n", scheme);
     397                 : #endif /* DEBUG_dp */
     398               0 :                 return NS_ERROR_FAILURE;
     399                 :             }
     400            5062 :             mWeakHandler[i] = do_GetWeakReference(handler);
     401            5062 :             return NS_OK;
     402                 :         }
     403                 :     }
     404            6736 :     return NS_ERROR_FAILURE;
     405                 : }
     406                 : 
     407                 : nsresult
     408          533538 : nsIOService::GetCachedProtocolHandler(const char *scheme, nsIProtocolHandler **result, PRUint32 start, PRUint32 end)
     409                 : {
     410          533538 :     PRUint32 len = end - start - 1;
     411         1458779 :     for (unsigned int i=0; i<NS_N(gScheme); i++)
     412                 :     {
     413         1446722 :         if (!mWeakHandler[i])
     414          192926 :             continue;
     415                 : 
     416                 :         // handle unterminated strings
     417                 :         // start is inclusive, end is exclusive, len = end - start - 1
     418         2507592 :         if (end ? (!nsCRT::strncasecmp(scheme + start, gScheme[i], len)
     419               0 :                    && gScheme[i][len] == '\0')
     420         1253796 :                 : (!nsCRT::strcasecmp(scheme, gScheme[i])))
     421                 :         {
     422          521481 :             return CallQueryReferent(mWeakHandler[i].get(), result);
     423                 :         }
     424                 :     }
     425           12057 :     return NS_ERROR_FAILURE;
     426                 : }
     427                 :  
     428                 : NS_IMETHODIMP
     429          533538 : nsIOService::GetProtocolHandler(const char* scheme, nsIProtocolHandler* *result)
     430                 : {
     431                 :     nsresult rv;
     432                 : 
     433          533538 :     NS_ENSURE_ARG_POINTER(scheme);
     434                 :     // XXX we may want to speed this up by introducing our own protocol 
     435                 :     // scheme -> protocol handler mapping, avoiding the string manipulation
     436                 :     // and service manager stuff
     437                 : 
     438          533538 :     rv = GetCachedProtocolHandler(scheme, result);
     439          533538 :     if (NS_SUCCEEDED(rv))
     440          521481 :         return rv;
     441                 : 
     442           12057 :     bool externalProtocol = false;
     443           24114 :     nsCOMPtr<nsIPrefBranch> prefBranch;
     444           12057 :     GetPrefBranch(getter_AddRefs(prefBranch));
     445           12057 :     if (prefBranch) {
     446           24114 :         nsCAutoString externalProtocolPref("network.protocol-handler.external.");
     447           12057 :         externalProtocolPref += scheme;
     448           12057 :         rv = prefBranch->GetBoolPref(externalProtocolPref.get(), &externalProtocol);
     449           12057 :         if (NS_FAILED(rv)) {
     450            7712 :             externalProtocol = false;
     451                 :         }
     452                 :     }
     453                 : 
     454           12057 :     if (!externalProtocol) {
     455           24014 :         nsCAutoString contractID(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX);
     456           12007 :         contractID += scheme;
     457           12007 :         ToLowerCase(contractID);
     458                 : 
     459           12007 :         rv = CallGetService(contractID.get(), result);
     460           12007 :         if (NS_SUCCEEDED(rv)) {
     461           11798 :             CacheProtocolHandler(scheme, *result);
     462           11798 :             return rv;
     463                 :         }
     464                 : 
     465                 : #ifdef MOZ_X11
     466                 :         // check to see whether GVFS can handle this URI scheme.  if it can
     467                 :         // create a nsIURI for the "scheme:", then we assume it has support for
     468                 :         // the requested protocol.  otherwise, we failover to using the default
     469                 :         // protocol handler.
     470                 : 
     471                 :         rv = CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"moz-gio",
     472             209 :                             result);
     473             209 :         if (NS_SUCCEEDED(rv)) {
     474               0 :             nsCAutoString spec(scheme);
     475               0 :             spec.Append(':');
     476                 : 
     477                 :             nsIURI *uri;
     478               0 :             rv = (*result)->NewURI(spec, nsnull, nsnull, &uri);
     479               0 :             if (NS_SUCCEEDED(rv)) {
     480               0 :                 NS_RELEASE(uri);
     481               0 :                 return rv;
     482                 :             }
     483                 : 
     484               0 :             NS_RELEASE(*result);
     485                 :         }
     486                 : 
     487                 :         // check to see whether GnomeVFS can handle this URI scheme.  if it can
     488                 :         // create a nsIURI for the "scheme:", then we assume it has support for
     489                 :         // the requested protocol.  otherwise, we failover to using the default
     490                 :         // protocol handler.
     491                 : 
     492                 :         // XXX should this be generalized into something that searches a
     493                 :         // category?  (see bug 234714)
     494                 : 
     495                 :         rv = CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"moz-gnomevfs",
     496             209 :                             result);
     497             209 :         if (NS_SUCCEEDED(rv)) {
     498             418 :             nsCAutoString spec(scheme);
     499             209 :             spec.Append(':');
     500                 : 
     501                 :             nsIURI *uri;
     502             209 :             rv = (*result)->NewURI(spec, nsnull, nsnull, &uri);
     503             209 :             if (NS_SUCCEEDED(rv)) {
     504               0 :                 NS_RELEASE(uri);
     505               0 :                 return rv;
     506                 :             }
     507                 : 
     508             418 :             NS_RELEASE(*result);
     509                 :         }
     510                 : #endif
     511                 :     }
     512                 : 
     513                 :     // Okay we don't have a protocol handler to handle this url type, so use
     514                 :     // the default protocol handler.  This will cause urls to get dispatched
     515                 :     // out to the OS ('cause we can't do anything with them) when we try to
     516                 :     // read from a channel created by the default protocol handler.
     517                 : 
     518                 :     rv = CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default",
     519             259 :                         result);
     520             259 :     if (NS_FAILED(rv))
     521               0 :         return NS_ERROR_UNKNOWN_PROTOCOL;
     522                 : 
     523             259 :     return rv;
     524                 : }
     525                 : 
     526                 : NS_IMETHODIMP
     527          283251 : nsIOService::ExtractScheme(const nsACString &inURI, nsACString &scheme)
     528                 : {
     529          283251 :     return net_ExtractURLScheme(inURI, nsnull, nsnull, &scheme);
     530                 : }
     531                 : 
     532                 : NS_IMETHODIMP 
     533          105049 : nsIOService::GetProtocolFlags(const char* scheme, PRUint32 *flags)
     534                 : {
     535          210098 :     nsCOMPtr<nsIProtocolHandler> handler;
     536          105049 :     nsresult rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
     537          105049 :     if (NS_FAILED(rv)) return rv;
     538                 : 
     539          105049 :     rv = handler->GetProtocolFlags(flags);
     540          105049 :     return rv;
     541                 : }
     542                 : 
     543                 : class AutoIncrement
     544                 : {
     545                 :     public:
     546          281091 :         AutoIncrement(PRUint32 *var) : mVar(var)
     547                 :         {
     548          281091 :             ++*var;
     549          281091 :         }
     550          281091 :         ~AutoIncrement()
     551                 :         {
     552          281091 :             --*mVar;
     553          281091 :         }
     554                 :     private:
     555                 :         PRUint32 *mVar;
     556                 : };
     557                 : 
     558                 : nsresult
     559          281092 : nsIOService::NewURI(const nsACString &aSpec, const char *aCharset, nsIURI *aBaseURI, nsIURI **result)
     560                 : {
     561          281092 :     NS_ASSERTION(NS_IsMainThread(), "wrong thread");
     562                 : 
     563                 :     static PRUint32 recursionCount = 0;
     564          281092 :     if (recursionCount >= MAX_RECURSION_COUNT)
     565               1 :         return NS_ERROR_MALFORMED_URI;
     566          562182 :     AutoIncrement inc(&recursionCount);
     567                 : 
     568          562182 :     nsCAutoString scheme;
     569          281091 :     nsresult rv = ExtractScheme(aSpec, scheme);
     570          281091 :     if (NS_FAILED(rv)) {
     571                 :         // then aSpec is relative
     572           63077 :         if (!aBaseURI)
     573             324 :             return NS_ERROR_MALFORMED_URI;
     574                 : 
     575           62753 :         rv = aBaseURI->GetScheme(scheme);
     576           62753 :         if (NS_FAILED(rv)) return rv;
     577                 :     }
     578                 : 
     579                 :     // now get the handler for this scheme
     580          561534 :     nsCOMPtr<nsIProtocolHandler> handler;
     581          280767 :     rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
     582          280767 :     if (NS_FAILED(rv)) return rv;
     583                 : 
     584          280767 :     return handler->NewURI(aSpec, aCharset, aBaseURI, result);
     585                 : }
     586                 : 
     587                 : 
     588                 : NS_IMETHODIMP 
     589            6324 : nsIOService::NewFileURI(nsIFile *file, nsIURI **result)
     590                 : {
     591                 :     nsresult rv;
     592            6324 :     NS_ENSURE_ARG_POINTER(file);
     593                 : 
     594           12648 :     nsCOMPtr<nsIProtocolHandler> handler;
     595                 : 
     596            6324 :     rv = GetProtocolHandler("file", getter_AddRefs(handler));
     597            6324 :     if (NS_FAILED(rv)) return rv;
     598                 : 
     599           12648 :     nsCOMPtr<nsIFileProtocolHandler> fileHandler( do_QueryInterface(handler, &rv) );
     600            6324 :     if (NS_FAILED(rv)) return rv;
     601                 :     
     602            6324 :     return fileHandler->NewFileURI(file, result);
     603                 : }
     604                 : 
     605                 : NS_IMETHODIMP
     606          104361 : nsIOService::NewChannelFromURI(nsIURI *aURI, nsIChannel **result)
     607                 : {
     608          104361 :     return NewChannelFromURIWithProxyFlags(aURI, nsnull, 0, result);
     609                 : }
     610                 : 
     611                 : NS_IMETHODIMP
     612          104361 : nsIOService::NewChannelFromURIWithProxyFlags(nsIURI *aURI,
     613                 :                                              nsIURI *aProxyURI,
     614                 :                                              PRUint32 proxyFlags,
     615                 :                                              nsIChannel **result)
     616                 : {
     617                 :     nsresult rv;
     618          104361 :     NS_ENSURE_ARG_POINTER(aURI);
     619                 : 
     620          208722 :     nsCAutoString scheme;
     621          104361 :     rv = aURI->GetScheme(scheme);
     622          104361 :     if (NS_FAILED(rv))
     623               0 :         return rv;
     624                 : 
     625          208722 :     nsCOMPtr<nsIProtocolHandler> handler;
     626          104361 :     rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
     627          104361 :     if (NS_FAILED(rv))
     628               0 :         return rv;
     629                 : 
     630                 :     PRUint32 protoFlags;
     631          104361 :     rv = handler->GetProtocolFlags(&protoFlags);
     632          104361 :     if (NS_FAILED(rv))
     633               0 :         return rv;
     634                 : 
     635                 :     // Talk to the PPS if the protocol handler allows proxying.  Otherwise,
     636                 :     // skip this step.  This allows us to lazily load the PPS at startup.
     637          104361 :     if (protoFlags & nsIProtocolHandler::ALLOWS_PROXY) {
     638            7030 :         nsCOMPtr<nsIProxyInfo> pi;
     639            3515 :         if (!mProxyService) {
     640             277 :             mProxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
     641             277 :             if (!mProxyService)
     642               0 :                 NS_WARNING("failed to get protocol proxy service");
     643                 :         }
     644            3515 :         if (mProxyService) {
     645            3515 :             PRUint32 flags = 0;
     646            3515 :             if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))
     647            3493 :                 flags = nsIProtocolProxyService::RESOLVE_NON_BLOCKING;
     648            3515 :             rv = mProxyService->Resolve(aProxyURI ? aProxyURI : aURI, proxyFlags,
     649            3515 :                                         getter_AddRefs(pi));
     650            3515 :             if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
     651                 :                 // Use an UNKNOWN proxy to defer resolution and avoid blocking.
     652               0 :                 rv = mProxyService->NewProxyInfo(NS_LITERAL_CSTRING("unknown"),
     653               0 :                                                  NS_LITERAL_CSTRING(""),
     654                 :                                                  -1, 0, 0, nsnull,
     655               0 :                                                  getter_AddRefs(pi));
     656                 :             }
     657            3515 :             if (NS_FAILED(rv))
     658               0 :                 pi = nsnull;
     659                 :         }
     660            3515 :         if (pi) {
     661              34 :             nsCAutoString type;
     662              17 :             if (NS_SUCCEEDED(pi->GetType(type)) && type.EqualsLiteral("http")) {
     663                 :                 // we are going to proxy this channel using an http proxy
     664               7 :                 rv = GetProtocolHandler("http", getter_AddRefs(handler));
     665               7 :                 if (NS_FAILED(rv))
     666               0 :                     return rv;
     667                 :             }
     668              34 :             nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler);
     669              17 :             if (pph)
     670              17 :                 return pph->NewProxiedChannel(aURI, pi, result);
     671                 :         }
     672                 :     }
     673                 : 
     674          104344 :     rv = handler->NewChannel(aURI, result);
     675          104344 :     NS_ENSURE_SUCCESS(rv, rv);
     676                 : 
     677                 :     // Some extensions override the http protocol handler and provide their own
     678                 :     // implementation. The channels returned from that implementation doesn't
     679                 :     // seem to always implement the nsIUploadChannel2 interface, presumably
     680                 :     // because it's a new interface.
     681                 :     // Eventually we should remove this and simply require that http channels
     682                 :     // implement the new interface.
     683                 :     // See bug 529041
     684          103452 :     if (!gHasWarnedUploadChannel2 && scheme.EqualsLiteral("http")) {
     685            6942 :         nsCOMPtr<nsIUploadChannel2> uploadChannel2 = do_QueryInterface(*result);
     686            3471 :         if (!uploadChannel2) {
     687                 :             nsCOMPtr<nsIConsoleService> consoleService =
     688               0 :                 do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     689               0 :             if (consoleService) {
     690               0 :                 consoleService->LogStringMessage(NS_LITERAL_STRING(
     691                 :                     "Http channel implementation doesn't support nsIUploadChannel2. An extension has supplied a non-functional http protocol handler. This will break behavior and in future releases not work at all."
     692               0 :                                                                    ).get());
     693                 :             }
     694               0 :             gHasWarnedUploadChannel2 = true;
     695                 :         }
     696                 :     }
     697                 : 
     698          103452 :     return NS_OK;
     699                 : }
     700                 : 
     701                 : NS_IMETHODIMP
     702           50575 : nsIOService::NewChannel(const nsACString &aSpec, const char *aCharset, nsIURI *aBaseURI, nsIChannel **result)
     703                 : {
     704                 :     nsresult rv;
     705          101150 :     nsCOMPtr<nsIURI> uri;
     706           50575 :     rv = NewURI(aSpec, aCharset, aBaseURI, getter_AddRefs(uri));
     707           50575 :     if (NS_FAILED(rv)) return rv;
     708                 : 
     709           50574 :     return NewChannelFromURI(uri, result);
     710                 : }
     711                 : 
     712                 : bool
     713               0 : nsIOService::IsLinkUp()
     714                 : {
     715               0 :     InitializeNetworkLinkService();
     716                 : 
     717               0 :     if (!mNetworkLinkService) {
     718                 :         // We cannot decide, assume the link is up
     719               0 :         return true;
     720                 :     }
     721                 : 
     722                 :     bool isLinkUp;
     723                 :     nsresult rv;
     724               0 :     rv = mNetworkLinkService->GetIsLinkUp(&isLinkUp);
     725               0 :     if (NS_FAILED(rv)) {
     726               0 :         return true;
     727                 :     }
     728                 : 
     729               0 :     return isLinkUp;
     730                 : }
     731                 : 
     732                 : NS_IMETHODIMP
     733            8293 : nsIOService::GetOffline(bool *offline)
     734                 : {
     735            8293 :     *offline = mOffline;
     736            8293 :     return NS_OK;
     737                 : }
     738                 : 
     739                 : NS_IMETHODIMP
     740            7853 : nsIOService::SetOffline(bool offline)
     741                 : {
     742                 :     // When someone wants to go online (!offline) after we got XPCOM shutdown
     743                 :     // throw ERROR_NOT_AVAILABLE to prevent return to online state.
     744            7853 :     if (mShutdown && !offline)
     745               0 :         return NS_ERROR_NOT_AVAILABLE;
     746                 : 
     747                 :     // SetOffline() may re-enter while it's shutting down services.
     748                 :     // If that happens, save the most recent value and it will be
     749                 :     // processed when the first SetOffline() call is done bringing
     750                 :     // down the service.
     751            7853 :     mSetOfflineValue = offline;
     752            7853 :     if (mSettingOffline) {
     753               0 :         return NS_OK;
     754                 :     }
     755                 : 
     756            7853 :     mSettingOffline = true;
     757                 : 
     758                 :     nsCOMPtr<nsIObserverService> observerService =
     759           15706 :         mozilla::services::GetObserverService();
     760                 : 
     761            7853 :     NS_ASSERTION(observerService, "The observer service should not be null");
     762                 : 
     763            7853 :     if (XRE_GetProcessType() == GeckoProcessType_Default) {
     764            7853 :         if (observerService) {
     765            7853 :             (void)observerService->NotifyObservers(nsnull,
     766                 :                 NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC, offline ? 
     767           10087 :                 NS_LITERAL_STRING("true").get() :
     768           10087 :                 NS_LITERAL_STRING("false").get());
     769                 :         }
     770                 :     }
     771                 : 
     772           18558 :     while (mSetOfflineValue != mOffline) {
     773            2852 :         offline = mSetOfflineValue;
     774                 : 
     775                 :         nsresult rv;
     776            2852 :         if (offline && !mOffline) {
     777            2852 :             NS_NAMED_LITERAL_STRING(offlineString, NS_IOSERVICE_OFFLINE);
     778            1426 :             mOffline = true; // indicate we're trying to shutdown
     779                 : 
     780                 :             // don't care if notification fails
     781                 :             // this allows users to attempt a little cleanup before dns and socket transport are shut down.
     782            1426 :             if (observerService)
     783            1426 :                 observerService->NotifyObservers(static_cast<nsIIOService *>(this),
     784                 :                                                  NS_IOSERVICE_GOING_OFFLINE_TOPIC,
     785            1426 :                                                  offlineString.get());
     786                 : 
     787                 :             // be sure to try and shutdown both (even if the first fails)...
     788                 :             // shutdown dns service first, because it has callbacks for socket transport
     789            1426 :             if (mDNSService) {
     790            1426 :                 rv = mDNSService->Shutdown();
     791            1426 :                 NS_ASSERTION(NS_SUCCEEDED(rv), "DNS service shutdown failed");
     792                 :             }
     793            1426 :             if (mSocketTransportService) {
     794            1426 :                 rv = mSocketTransportService->Shutdown();
     795            1426 :                 NS_ASSERTION(NS_SUCCEEDED(rv), "socket transport service shutdown failed");
     796                 :             }
     797                 : 
     798                 :             // don't care if notification fails
     799            1426 :             if (observerService)
     800            1426 :                 observerService->NotifyObservers(static_cast<nsIIOService *>(this),
     801                 :                                                  NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
     802            2852 :                                                  offlineString.get());
     803                 :         }
     804            1426 :         else if (!offline && mOffline) {
     805                 :             // go online
     806            1426 :             if (mDNSService) {
     807            1426 :                 rv = mDNSService->Init();
     808            1426 :                 NS_ASSERTION(NS_SUCCEEDED(rv), "DNS service init failed");
     809                 :             }
     810            1426 :             InitializeSocketTransportService();
     811            1426 :             mOffline = false;    // indicate success only AFTER we've
     812                 :                                     // brought up the services
     813                 : 
     814                 :             // trigger a PAC reload when we come back online
     815            1426 :             if (mProxyService)
     816               6 :                 mProxyService->ReloadPAC();
     817                 : 
     818                 :             // don't care if notification fails
     819            1426 :             if (observerService)
     820            1426 :                 observerService->NotifyObservers(static_cast<nsIIOService *>(this),
     821                 :                                                  NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
     822            1426 :                                                  NS_LITERAL_STRING(NS_IOSERVICE_ONLINE).get());
     823                 :         }
     824                 :     }
     825                 : 
     826            7853 :     mSettingOffline = false;
     827                 : 
     828            7853 :     return NS_OK;
     829                 : }
     830                 : 
     831                 : 
     832                 : NS_IMETHODIMP
     833            3125 : nsIOService::AllowPort(PRInt32 inPort, const char *scheme, bool *_retval)
     834                 : {
     835            3125 :     PRInt16 port = inPort;
     836            3125 :     if (port == -1) {
     837               0 :         *_retval = true;
     838               0 :         return NS_OK;
     839                 :     }
     840                 :         
     841                 :     // first check to see if the port is in our blacklist:
     842            3125 :     PRInt32 badPortListCnt = mRestrictedPortList.Length();
     843          184375 :     for (int i=0; i<badPortListCnt; i++)
     844                 :     {
     845          181250 :         if (port == mRestrictedPortList[i])
     846                 :         {
     847               0 :             *_retval = false;
     848                 : 
     849                 :             // check to see if the protocol wants to override
     850               0 :             if (!scheme)
     851               0 :                 return NS_OK;
     852                 :             
     853               0 :             nsCOMPtr<nsIProtocolHandler> handler;
     854               0 :             nsresult rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
     855               0 :             if (NS_FAILED(rv)) return rv;
     856                 : 
     857                 :             // let the protocol handler decide
     858               0 :             return handler->AllowPort(port, scheme, _retval);
     859                 :         }
     860                 :     }
     861                 : 
     862            3125 :     *_retval = true;
     863            3125 :     return NS_OK;
     864                 : }
     865                 : 
     866                 : ////////////////////////////////////////////////////////////////////////////////
     867                 : 
     868                 : void
     869            1420 : nsIOService::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
     870                 : {
     871            1420 :     if (!prefs) return;
     872                 : 
     873                 :     // Look for extra ports to block
     874            1420 :     if (!pref || strcmp(pref, PORT_PREF("banned")) == 0)
     875            1419 :         ParsePortList(prefs, PORT_PREF("banned"), false);
     876                 : 
     877                 :     // ...as well as previous blocks to remove.
     878            1420 :     if (!pref || strcmp(pref, PORT_PREF("banned.override")) == 0)
     879            1419 :         ParsePortList(prefs, PORT_PREF("banned.override"), true);
     880                 : 
     881            1420 :     if (!pref || strcmp(pref, AUTODIAL_PREF) == 0) {
     882            1419 :         bool enableAutodial = false;
     883            1419 :         nsresult rv = prefs->GetBoolPref(AUTODIAL_PREF, &enableAutodial);
     884                 :         // If pref not found, default to disabled.
     885            1419 :         mAutoDialEnabled = enableAutodial;
     886            1419 :         if (NS_SUCCEEDED(rv)) {
     887               0 :             if (mSocketTransportService)
     888               0 :                 mSocketTransportService->SetAutodialEnabled(enableAutodial);
     889                 :         }
     890                 :     }
     891                 : 
     892            1420 :     if (!pref || strcmp(pref, MANAGE_OFFLINE_STATUS_PREF) == 0) {
     893                 :         bool manage;
     894            1420 :         if (NS_SUCCEEDED(prefs->GetBoolPref(MANAGE_OFFLINE_STATUS_PREF,
     895                 :                                             &manage)))
     896            1420 :             SetManageOfflineStatus(manage);
     897                 :     }
     898                 : 
     899            1420 :     if (!pref || strcmp(pref, NECKO_BUFFER_CACHE_COUNT_PREF) == 0) {
     900                 :         PRInt32 count;
     901            1419 :         if (NS_SUCCEEDED(prefs->GetIntPref(NECKO_BUFFER_CACHE_COUNT_PREF,
     902                 :                                            &count)))
     903                 :             /* check for bogus values and default if we find such a value */
     904            1419 :             if (count > 0)
     905            1419 :                 gDefaultSegmentCount = count;
     906                 :     }
     907                 :     
     908            1420 :     if (!pref || strcmp(pref, NECKO_BUFFER_CACHE_SIZE_PREF) == 0) {
     909                 :         PRInt32 size;
     910            1419 :         if (NS_SUCCEEDED(prefs->GetIntPref(NECKO_BUFFER_CACHE_SIZE_PREF,
     911                 :                                            &size)))
     912                 :             /* check for bogus values and default if we find such a value
     913                 :              * the upper limit here is arbitrary. having a 1mb segment size
     914                 :              * is pretty crazy.  if you remove this, consider adding some
     915                 :              * integer rollover test.
     916                 :              */
     917            1419 :             if (size > 0 && size < 1024*1024)
     918            1419 :                 gDefaultSegmentSize = size;
     919            1419 :         NS_WARN_IF_FALSE( (!(size & (size - 1))) , "network segment size is not a power of 2!");
     920                 :     }
     921                 : }
     922                 : 
     923                 : void
     924            2838 : nsIOService::ParsePortList(nsIPrefBranch *prefBranch, const char *pref, bool remove)
     925                 : {
     926            5676 :     nsXPIDLCString portList;
     927                 : 
     928                 :     // Get a pref string and chop it up into a list of ports.
     929            2838 :     prefBranch->GetCharPref(pref, getter_Copies(portList));
     930            2838 :     if (portList) {
     931               0 :         nsTArray<nsCString> portListArray;
     932               0 :         ParseString(portList, ',', portListArray);
     933                 :         PRUint32 index;
     934               0 :         for (index=0; index < portListArray.Length(); index++) {
     935               0 :             portListArray[index].StripWhitespace();
     936                 :             PRInt32 aErrorCode, portBegin, portEnd;
     937                 : 
     938               0 :             if (PR_sscanf(portListArray[index].get(), "%d-%d", &portBegin, &portEnd) == 2) {
     939               0 :                if ((portBegin < 65536) && (portEnd < 65536)) {
     940                 :                    PRInt32 curPort;
     941               0 :                    if (remove) {
     942               0 :                         for (curPort=portBegin; curPort <= portEnd; curPort++)
     943               0 :                             mRestrictedPortList.RemoveElement(curPort);
     944                 :                    } else {
     945               0 :                         for (curPort=portBegin; curPort <= portEnd; curPort++)
     946               0 :                             mRestrictedPortList.AppendElement(curPort);
     947                 :                    }
     948                 :                }
     949                 :             } else {
     950               0 :                PRInt32 port = portListArray[index].ToInteger(&aErrorCode);
     951               0 :                if (NS_SUCCEEDED(aErrorCode) && port < 65536) {
     952               0 :                    if (remove)
     953               0 :                        mRestrictedPortList.RemoveElement(port);
     954                 :                    else
     955               0 :                        mRestrictedPortList.AppendElement(port);
     956                 :                }
     957                 :             }
     958                 : 
     959                 :         }
     960                 :     }
     961            2838 : }
     962                 : 
     963                 : void
     964           13476 : nsIOService::GetPrefBranch(nsIPrefBranch **result)
     965                 : {
     966           13476 :     *result = nsnull;
     967           13476 :     CallGetService(NS_PREFSERVICE_CONTRACTID, result);
     968           13476 : }
     969                 : 
     970                 : // nsIObserver interface
     971                 : NS_IMETHODIMP
     972            2234 : nsIOService::Observe(nsISupports *subject,
     973                 :                      const char *topic,
     974                 :                      const PRUnichar *data)
     975                 : {
     976            2234 :     if (!strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
     977               2 :         nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
     978               1 :         if (prefBranch)
     979               1 :             PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
     980                 :     }
     981            2233 :     else if (!strcmp(topic, kProfileChangeNetTeardownTopic)) {
     982             814 :         if (!mOffline) {
     983             807 :             SetOffline(true);
     984             807 :             mOfflineForProfileChange = true;
     985                 :         }
     986                 :     }
     987            1419 :     else if (!strcmp(topic, kProfileChangeNetRestoreTopic)) {
     988               0 :         if (mOfflineForProfileChange) {
     989               0 :             mOfflineForProfileChange = false;
     990               0 :             if (!mManageOfflineStatus ||
     991               0 :                 NS_FAILED(TrackNetworkLinkStatusForOffline())) {
     992               0 :                 SetOffline(false);
     993                 :             }
     994                 :         } 
     995                 :     } 
     996            1419 :     else if (!strcmp(topic, kProfileDoChange)) { 
     997               0 :         if (data && NS_LITERAL_STRING("startup").Equals(data)) {
     998                 :             // Lazy initialization of network link service (see bug 620472)
     999               0 :             InitializeNetworkLinkService();
    1000                 :             // Set up the initilization flag regardless the actuall result.
    1001                 :             // If we fail here, we will fail always on.
    1002               0 :             mNetworkLinkServiceInitialized = true;
    1003                 :         }
    1004                 :     }
    1005            1419 :     else if (!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
    1006                 :         // Remember we passed XPCOM shutdown notification to prevent any
    1007                 :         // changes of the offline status from now. We must not allow going
    1008                 :         // online after this point.
    1009            1419 :         mShutdown = true;
    1010                 : 
    1011            1419 :         SetOffline(true);
    1012                 : 
    1013                 :         // Break circular reference.
    1014            1419 :         mProxyService = nsnull;
    1015                 :     }
    1016               0 :     else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
    1017               0 :         if (!mOfflineForProfileChange && mManageOfflineStatus) {
    1018               0 :             TrackNetworkLinkStatusForOffline();
    1019                 :         }
    1020                 :     }
    1021                 :     
    1022            2234 :     return NS_OK;
    1023                 : }
    1024                 : 
    1025                 : // nsINetUtil interface
    1026                 : NS_IMETHODIMP
    1027             128 : nsIOService::ParseContentType(const nsACString &aTypeHeader,
    1028                 :                               nsACString &aCharset,
    1029                 :                               bool *aHadCharset,
    1030                 :                               nsACString &aContentType)
    1031                 : {
    1032             128 :     net_ParseContentType(aTypeHeader, aContentType, aCharset, aHadCharset);
    1033             128 :     return NS_OK;
    1034                 : }
    1035                 : 
    1036                 : NS_IMETHODIMP
    1037          105049 : nsIOService::ProtocolHasFlags(nsIURI   *uri,
    1038                 :                               PRUint32  flags,
    1039                 :                               bool     *result)
    1040                 : {
    1041          105049 :     NS_ENSURE_ARG(uri);
    1042                 : 
    1043          105049 :     *result = false;
    1044          210098 :     nsCAutoString scheme;
    1045          105049 :     nsresult rv = uri->GetScheme(scheme);
    1046          105049 :     NS_ENSURE_SUCCESS(rv, rv);
    1047                 :   
    1048                 :     PRUint32 protocolFlags;
    1049          105049 :     rv = GetProtocolFlags(scheme.get(), &protocolFlags);
    1050                 : 
    1051          105049 :     if (NS_SUCCEEDED(rv)) {
    1052          105049 :         *result = (protocolFlags & flags) == flags;
    1053                 :     }
    1054                 :   
    1055          105049 :     return rv;
    1056                 : }
    1057                 : 
    1058                 : NS_IMETHODIMP
    1059          105022 : nsIOService::URIChainHasFlags(nsIURI   *uri,
    1060                 :                               PRUint32  flags,
    1061                 :                               bool     *result)
    1062                 : {
    1063          105022 :     nsresult rv = ProtocolHasFlags(uri, flags, result);
    1064          105022 :     NS_ENSURE_SUCCESS(rv, rv);
    1065                 : 
    1066          105022 :     if (*result) {
    1067           85531 :         return rv;
    1068                 :     }
    1069                 : 
    1070                 :     // Dig deeper into the chain.  Note that this is not a do/while loop to
    1071                 :     // avoid the extra addref/release on |uri| in the common (non-nested) case.
    1072           38982 :     nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(uri);
    1073           38990 :     while (nestedURI) {
    1074              48 :         nsCOMPtr<nsIURI> innerURI;
    1075              24 :         rv = nestedURI->GetInnerURI(getter_AddRefs(innerURI));
    1076              24 :         NS_ENSURE_SUCCESS(rv, rv);
    1077                 : 
    1078              24 :         rv = ProtocolHasFlags(innerURI, flags, result);
    1079                 : 
    1080              24 :         if (*result) {
    1081              16 :             return rv;
    1082                 :         }
    1083                 : 
    1084              32 :         nestedURI = do_QueryInterface(innerURI);
    1085                 :     }
    1086                 : 
    1087           19475 :     return rv;
    1088                 : }
    1089                 : 
    1090                 : NS_IMETHODIMP
    1091            2184 : nsIOService::ToImmutableURI(nsIURI* uri, nsIURI** result)
    1092                 : {
    1093            2184 :     if (!uri) {
    1094             469 :         *result = nsnull;
    1095             469 :         return NS_OK;
    1096                 :     }
    1097                 : 
    1098            1715 :     nsresult rv = NS_EnsureSafeToReturn(uri, result);
    1099            1715 :     NS_ENSURE_SUCCESS(rv, rv);
    1100                 : 
    1101            1715 :     NS_TryToSetImmutable(*result);
    1102            1715 :     return NS_OK;
    1103                 : }
    1104                 : 
    1105                 : NS_IMETHODIMP
    1106               6 : nsIOService::NewSimpleNestedURI(nsIURI* aURI, nsIURI** aResult)
    1107                 : {
    1108               6 :     NS_ENSURE_ARG(aURI);
    1109                 : 
    1110              12 :     nsCOMPtr<nsIURI> safeURI;
    1111               6 :     nsresult rv = NS_EnsureSafeToReturn(aURI, getter_AddRefs(safeURI));
    1112               6 :     NS_ENSURE_SUCCESS(rv, rv);
    1113                 : 
    1114              12 :     NS_IF_ADDREF(*aResult = new nsSimpleNestedURI(safeURI));
    1115               6 :     return *aResult ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
    1116                 : }
    1117                 : 
    1118                 : NS_IMETHODIMP
    1119            2806 : nsIOService::SetManageOfflineStatus(bool aManage) {
    1120            2806 :     nsresult rv = NS_OK;
    1121                 : 
    1122                 :     // SetManageOfflineStatus must throw when we fail to go from non-managed
    1123                 :     // to managed.  Usually because there is no link monitoring service 
    1124                 :     // available.  Failure to do this switch is detected by a failure of 
    1125                 :     // TrackNetworkLinkStatusForOffline().  When there is no network link 
    1126                 :     // available during call to InitializeNetworkLinkService(), application is
    1127                 :     // put to offline mode.  And when we change mMangeOfflineStatus to false 
    1128                 :     // on the next line we get stuck on being offline even though the link 
    1129                 :     // becomes later available.
    1130            2806 :     bool wasManaged = mManageOfflineStatus;
    1131            2806 :     mManageOfflineStatus = aManage;
    1132                 : 
    1133            2806 :     InitializeNetworkLinkService();
    1134                 : 
    1135            2806 :     if (mManageOfflineStatus && !wasManaged) {
    1136               0 :         rv = TrackNetworkLinkStatusForOffline();
    1137               0 :         if (NS_FAILED(rv))
    1138               0 :             mManageOfflineStatus = false;
    1139                 :     }
    1140            2806 :     return rv;
    1141                 : }
    1142                 : 
    1143                 : NS_IMETHODIMP
    1144               0 : nsIOService::GetManageOfflineStatus(bool* aManage) {
    1145               0 :     *aManage = mManageOfflineStatus;
    1146               0 :     return NS_OK;
    1147                 : }
    1148                 : 
    1149                 : nsresult
    1150               0 : nsIOService::TrackNetworkLinkStatusForOffline()
    1151                 : {
    1152               0 :     NS_ASSERTION(mManageOfflineStatus,
    1153                 :                  "Don't call this unless we're managing the offline status");
    1154               0 :     if (!mNetworkLinkService)
    1155               0 :         return NS_ERROR_FAILURE;
    1156                 : 
    1157               0 :     if (mShutdown)
    1158               0 :         return NS_ERROR_NOT_AVAILABLE;
    1159                 :   
    1160                 :     // check to make sure this won't collide with Autodial
    1161               0 :     if (mSocketTransportService) {
    1162               0 :         bool autodialEnabled = false;
    1163               0 :         mSocketTransportService->GetAutodialEnabled(&autodialEnabled);
    1164                 :         // If autodialing-on-link-down is enabled, check if the OS auto dial 
    1165                 :         // option is set to always autodial. If so, then we are 
    1166                 :         // always up for the purposes of offline management.
    1167               0 :         if (autodialEnabled) {
    1168                 : #if defined(XP_WIN) || defined(MOZ_PLATFORM_MAEMO)
    1169                 :             // On Windows and Maemo (libconic) we should first check with the OS
    1170                 :             // to see if autodial is enabled.  If it is enabled then we are
    1171                 :             // allowed to manage the offline state.
    1172                 :             if(nsNativeConnectionHelper::IsAutodialEnabled()) 
    1173                 :                 return SetOffline(false);
    1174                 : #else
    1175               0 :             return SetOffline(false);
    1176                 : #endif
    1177                 :         }
    1178                 :     }
    1179                 : 
    1180                 :     bool isUp;
    1181               0 :     nsresult rv = mNetworkLinkService->GetIsLinkUp(&isUp);
    1182               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1183               0 :     return SetOffline(!isUp);
    1184                 : }
    1185                 : 
    1186                 : NS_IMETHODIMP
    1187               0 : nsIOService::EscapeString(const nsACString& aString,
    1188                 :                           PRUint32 aEscapeType,
    1189                 :                           nsACString& aResult)
    1190                 : {
    1191               0 :   NS_ENSURE_ARG_RANGE(aEscapeType, 0, 4);
    1192                 : 
    1193               0 :   nsCAutoString stringCopy(aString);
    1194               0 :   nsCString result;
    1195                 : 
    1196               0 :   if (!NS_Escape(stringCopy, result, (nsEscapeMask) aEscapeType))
    1197               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1198                 : 
    1199               0 :   aResult.Assign(result);
    1200                 : 
    1201               0 :   return NS_OK;
    1202                 : }
    1203                 : 
    1204                 : NS_IMETHODIMP 
    1205               0 : nsIOService::EscapeURL(const nsACString &aStr, 
    1206                 :                        PRUint32 aFlags, nsACString &aResult)
    1207                 : {
    1208               0 :   aResult.Truncate();
    1209               0 :   NS_EscapeURL(aStr.BeginReading(), aStr.Length(), 
    1210               0 :                aFlags | esc_AlwaysCopy, aResult);
    1211               0 :   return NS_OK;
    1212                 : }
    1213                 : 
    1214                 : NS_IMETHODIMP 
    1215              12 : nsIOService::UnescapeString(const nsACString &aStr, 
    1216                 :                             PRUint32 aFlags, nsACString &aResult)
    1217                 : {
    1218              12 :   aResult.Truncate();
    1219              12 :   NS_UnescapeURL(aStr.BeginReading(), aStr.Length(), 
    1220              24 :                  aFlags | esc_AlwaysCopy, aResult);
    1221              12 :   return NS_OK;
    1222                 : }
    1223                 : 
    1224                 : NS_IMETHODIMP
    1225              27 : nsIOService::ExtractCharsetFromContentType(const nsACString &aTypeHeader,
    1226                 :                                            nsACString &aCharset,
    1227                 :                                            PRInt32 *aCharsetStart,
    1228                 :                                            PRInt32 *aCharsetEnd,
    1229                 :                                            bool *aHadCharset)
    1230                 : {
    1231              54 :     nsCAutoString ignored;
    1232                 :     net_ParseContentType(aTypeHeader, ignored, aCharset, aHadCharset,
    1233              27 :                          aCharsetStart, aCharsetEnd);
    1234              27 :     if (*aHadCharset && *aCharsetStart == *aCharsetEnd) {
    1235               1 :         *aHadCharset = false;
    1236                 :     }
    1237              27 :     return NS_OK;
    1238                 : }

Generated by: LCOV version 1.7