1999-06-07 21:33:30 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* The contents of this file are subject to the Netscape Public
|
|
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.mozilla.org/NPL/
|
1999-06-07 21:33:30 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
1999-06-07 21:33:30 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
1999-06-07 21:33:30 +00:00
|
|
|
* Communications Corporation. Portions created by Netscape are
|
1999-11-06 03:40:37 +00:00
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
1999-06-07 21:33:30 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "nsIOService.h"
|
|
|
|
#include "nsIProtocolHandler.h"
|
|
|
|
#include "nscore.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsIEventQueueService.h"
|
|
|
|
#include "nsIFileTransportService.h"
|
|
|
|
#include "nsIURI.h"
|
1999-06-12 08:07:05 +00:00
|
|
|
#include "nsIStreamListener.h"
|
1999-06-08 19:04:13 +00:00
|
|
|
#include "prprf.h"
|
1999-06-24 22:58:42 +00:00
|
|
|
#include "nsLoadGroup.h"
|
1999-07-03 04:05:14 +00:00
|
|
|
#include "nsInputStreamChannel.h"
|
1999-07-10 05:00:23 +00:00
|
|
|
#include "nsXPIDLString.h"
|
2000-07-25 05:45:56 +00:00
|
|
|
#include "nsIErrorService.h"
|
2001-01-17 19:51:28 +00:00
|
|
|
#include "netCore.h"
|
|
|
|
#include "nsIObserverService.h"
|
1999-06-07 21:33:30 +00:00
|
|
|
|
|
|
|
static NS_DEFINE_CID(kFileTransportService, NS_FILETRANSPORTSERVICE_CID);
|
|
|
|
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
|
2000-01-05 03:44:42 +00:00
|
|
|
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
|
|
|
|
static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID);
|
2000-07-25 05:45:56 +00:00
|
|
|
static NS_DEFINE_CID(kErrorServiceCID, NS_ERRORSERVICE_CID);
|
1999-08-29 16:42:27 +00:00
|
|
|
|
1999-06-07 21:33:30 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
nsIOService::nsIOService()
|
2000-02-08 06:27:34 +00:00
|
|
|
: mOffline(PR_FALSE)
|
1999-06-07 21:33:30 +00:00
|
|
|
{
|
|
|
|
NS_INIT_REFCNT();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsIOService::Init()
|
|
|
|
{
|
2000-02-08 06:27:34 +00:00
|
|
|
nsresult rv = NS_OK;
|
2000-01-19 07:58:40 +00:00
|
|
|
// We need to get references to these services so that we can shut them
|
|
|
|
// down later. If we wait until the nsIOService is being shut down,
|
|
|
|
// GetService will fail at that point.
|
|
|
|
rv = nsServiceManager::GetService(kSocketTransportServiceCID,
|
|
|
|
NS_GET_IID(nsISocketTransportService),
|
|
|
|
getter_AddRefs(mSocketTransportService));
|
2000-02-08 06:27:34 +00:00
|
|
|
|
2000-01-19 07:58:40 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
2000-06-13 03:00:53 +00:00
|
|
|
|
2000-01-19 07:58:40 +00:00
|
|
|
rv = nsServiceManager::GetService(kFileTransportService,
|
|
|
|
NS_GET_IID(nsIFileTransportService),
|
|
|
|
getter_AddRefs(mFileTransportService));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = nsServiceManager::GetService(kDNSServiceCID,
|
|
|
|
NS_GET_IID(nsIDNSService),
|
|
|
|
getter_AddRefs(mDNSService));
|
2000-07-25 05:45:56 +00:00
|
|
|
|
|
|
|
// XXX hack until xpidl supports error info directly (http://bugzilla.mozilla.org/show_bug.cgi?id=13423)
|
|
|
|
nsCOMPtr<nsIErrorService> errorService = do_GetService(kErrorServiceCID, &rv);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = errorService->RegisterErrorStringBundle(NS_ERROR_MODULE_NETWORK, NECKO_MSGS_URL);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_READ_FROM, "ReadFrom");
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_WROTE_TO, "WroteTo");
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_RESOLVING_HOST, "ResolvingHost");
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_CONNECTED_TO, "ConnectedTo");
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_SENDING_TO, "SendingTo");
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_RECEIVING_FROM, "ReceivingFrom");
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_CONNECTING_TO, "ConnectingTo");
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
2000-06-13 03:00:53 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-06-07 21:33:30 +00:00
|
|
|
|
|
|
|
nsIOService::~nsIOService()
|
|
|
|
{
|
2000-02-08 06:27:34 +00:00
|
|
|
(void)SetOffline(PR_TRUE);
|
1999-06-07 21:33:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_METHOD
|
|
|
|
nsIOService::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
|
|
|
{
|
2000-06-13 03:00:53 +00:00
|
|
|
static nsISupports *_rValue = nsnull;
|
|
|
|
|
1999-07-23 16:35:53 +00:00
|
|
|
nsresult rv;
|
2000-05-03 21:47:56 +00:00
|
|
|
NS_ENSURE_NO_AGGREGATION(aOuter);
|
1999-06-07 21:33:30 +00:00
|
|
|
|
2000-06-13 03:00:53 +00:00
|
|
|
if (_rValue)
|
|
|
|
{
|
|
|
|
NS_ADDREF (_rValue);
|
|
|
|
*aResult = _rValue;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-07-10 05:00:23 +00:00
|
|
|
nsIOService* _ios = new nsIOService();
|
|
|
|
if (_ios == nsnull)
|
1999-06-07 21:33:30 +00:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1999-07-10 05:00:23 +00:00
|
|
|
NS_ADDREF(_ios);
|
1999-07-23 16:35:53 +00:00
|
|
|
rv = _ios->Init();
|
2000-06-13 03:00:53 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
{
|
1999-07-23 16:35:53 +00:00
|
|
|
delete _ios;
|
|
|
|
return rv;
|
|
|
|
}
|
2000-06-13 03:00:53 +00:00
|
|
|
|
1999-07-23 16:35:53 +00:00
|
|
|
rv = _ios->QueryInterface(aIID, aResult);
|
2000-06-13 03:00:53 +00:00
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
delete _ios;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
_rValue = NS_STATIC_CAST (nsISupports*, *aResult);
|
|
|
|
NS_RELEASE (_rValue);
|
|
|
|
_rValue = nsnull;
|
|
|
|
|
1999-06-07 21:33:30 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2000-03-05 21:26:01 +00:00
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS1(nsIOService, nsIIOService);
|
1999-06-07 21:33:30 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#define MAX_SCHEME_LENGTH 64 // XXX big enough?
|
|
|
|
|
2000-09-13 23:57:52 +00:00
|
|
|
#define MAX_NET_CONTRACTID_LENGTH (MAX_SCHEME_LENGTH + NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX_LENGTH + 1)
|
1999-06-07 21:33:30 +00:00
|
|
|
|
2000-08-22 06:16:50 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsIOService::CacheProtocolHandler(const char *scheme, nsIProtocolHandler *handler)
|
|
|
|
{
|
|
|
|
for (unsigned int i=0; i<NS_N(gScheme); i++)
|
|
|
|
{
|
|
|
|
if (!nsCRT::strcasecmp(scheme, gScheme[i]))
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
NS_ASSERTION(!mWeakHandler[i], "Protocol handler already cached");
|
|
|
|
// Make sure the handler supports weak references.
|
|
|
|
nsCOMPtr<nsISupportsWeakReference> factoryPtr = do_QueryInterface(handler, &rv);
|
|
|
|
if (!factoryPtr)
|
|
|
|
{
|
|
|
|
// Dont cache handlers that dont support weak reference as
|
|
|
|
// there is real danger of a circular reference.
|
2000-10-28 22:17:53 +00:00
|
|
|
#ifdef DEBUG_dp
|
|
|
|
printf("DEBUG: %s protcol handler doesn't support weak ref. Not cached.\n", scheme);
|
|
|
|
#endif /* DEBUG_dp */
|
2000-08-22 06:16:50 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
mWeakHandler[i] = getter_AddRefs(NS_GetWeakReference(handler));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsIOService::GetCachedProtocolHandler(const char *scheme, nsIProtocolHandler **result)
|
|
|
|
{
|
|
|
|
for (unsigned int i=0; i<NS_N(gScheme); i++)
|
|
|
|
{
|
|
|
|
if (!nsCRT::strcasecmp(scheme, gScheme[i]))
|
|
|
|
if (mWeakHandler[i])
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIProtocolHandler> temp = do_QueryReferent(mWeakHandler[i]);
|
|
|
|
if (temp)
|
|
|
|
{
|
|
|
|
*result = temp.get();
|
|
|
|
NS_ADDREF(*result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-06-07 21:33:30 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsIOService::GetProtocolHandler(const char* scheme, nsIProtocolHandler* *result)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
2000-09-13 23:57:52 +00:00
|
|
|
NS_ASSERTION(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX_LENGTH
|
|
|
|
== nsCRT::strlen(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX),
|
|
|
|
"need to fix NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX_LENGTH");
|
1999-06-07 21:33:30 +00:00
|
|
|
|
2000-05-03 21:47:56 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(scheme);
|
1999-06-07 21:33:30 +00:00
|
|
|
// XXX we may want to speed this up by introducing our own protocol
|
|
|
|
// scheme -> protocol handler mapping, avoiding the string manipulation
|
|
|
|
// and service manager stuff
|
|
|
|
|
2000-08-22 06:16:50 +00:00
|
|
|
rv = GetCachedProtocolHandler(scheme, result);
|
|
|
|
if (NS_SUCCEEDED(rv)) return NS_OK;
|
|
|
|
|
2000-09-13 23:57:52 +00:00
|
|
|
char buf[MAX_NET_CONTRACTID_LENGTH];
|
|
|
|
nsCAutoString contractID(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX);
|
|
|
|
contractID += scheme;
|
|
|
|
contractID.ToLowerCase();
|
|
|
|
contractID.ToCString(buf, MAX_NET_CONTRACTID_LENGTH);
|
1999-06-07 21:33:30 +00:00
|
|
|
|
1999-11-02 01:40:14 +00:00
|
|
|
rv = nsServiceManager::GetService(buf, NS_GET_IID(nsIProtocolHandler), (nsISupports **)result);
|
1999-07-30 04:17:23 +00:00
|
|
|
if (NS_FAILED(rv))
|
2001-02-07 05:54:35 +00:00
|
|
|
{
|
|
|
|
// okay we don't have a protocol handler to handle this url type, so use the default protocol handler.
|
|
|
|
// this will cause urls to get dispatched out to the OS ('cause we can't do anything with them) when
|
|
|
|
// we try to read from a channel created by the default protocol handler.
|
|
|
|
|
|
|
|
rv = nsServiceManager::GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default", NS_GET_IID(nsIProtocolHandler), (nsISupports **)result);
|
|
|
|
if (NS_FAILED(rv)) return NS_ERROR_UNKNOWN_PROTOCOL;
|
|
|
|
}
|
1999-06-07 21:33:30 +00:00
|
|
|
|
2000-08-22 06:16:50 +00:00
|
|
|
CacheProtocolHandler(scheme, *result);
|
|
|
|
|
1999-06-07 21:33:30 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-11-12 06:13:13 +00:00
|
|
|
NS_IMETHODIMP
|
2000-05-07 10:49:29 +00:00
|
|
|
nsIOService::ExtractScheme(const char* inURI, PRUint32 *startPos,
|
|
|
|
PRUint32 *endPos, char* *scheme)
|
1999-07-10 11:26:43 +00:00
|
|
|
{
|
2000-05-07 10:49:29 +00:00
|
|
|
return ExtractURLScheme(inURI, startPos, endPos, scheme);
|
1999-07-10 11:26:43 +00:00
|
|
|
}
|
|
|
|
|
1999-09-26 10:11:36 +00:00
|
|
|
nsresult
|
1999-06-07 21:33:30 +00:00
|
|
|
nsIOService::NewURI(const char* aSpec, nsIURI* aBaseURI,
|
1999-09-26 10:11:36 +00:00
|
|
|
nsIURI* *result, nsIProtocolHandler* *hdlrResult)
|
1999-06-07 21:33:30 +00:00
|
|
|
{
|
|
|
|
nsresult rv;
|
1999-07-27 08:45:20 +00:00
|
|
|
nsIURI* base;
|
2000-05-03 21:47:56 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aSpec);
|
1999-07-10 11:26:43 +00:00
|
|
|
char* scheme;
|
1999-11-12 06:13:13 +00:00
|
|
|
rv = ExtractScheme(aSpec, nsnull, nsnull, &scheme);
|
1999-07-27 08:45:20 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// then aSpec is absolute
|
|
|
|
// ignore aBaseURI in this case
|
|
|
|
base = nsnull;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// then aSpec is relative
|
|
|
|
if (aBaseURI == nsnull)
|
|
|
|
return NS_ERROR_MALFORMED_URI;
|
|
|
|
rv = aBaseURI->GetScheme(&scheme);
|
1999-07-10 11:26:43 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-07-27 08:45:20 +00:00
|
|
|
base = aBaseURI;
|
1999-07-10 11:26:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIProtocolHandler> handler;
|
|
|
|
rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
|
|
|
|
nsCRT::free(scheme);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-06-07 21:33:30 +00:00
|
|
|
|
1999-09-26 10:11:36 +00:00
|
|
|
if (hdlrResult) {
|
|
|
|
*hdlrResult = handler;
|
|
|
|
NS_ADDREF(*hdlrResult);
|
|
|
|
}
|
1999-07-27 08:45:20 +00:00
|
|
|
return handler->NewURI(aSpec, base, result);
|
1999-06-07 21:33:30 +00:00
|
|
|
}
|
|
|
|
|
1999-09-26 10:11:36 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsIOService::NewURI(const char* aSpec, nsIURI* aBaseURI,
|
|
|
|
nsIURI* *result)
|
|
|
|
{
|
|
|
|
return NewURI(aSpec, aBaseURI, result, nsnull);
|
|
|
|
}
|
|
|
|
|
1999-06-07 21:33:30 +00:00
|
|
|
NS_IMETHODIMP
|
2000-03-29 03:58:50 +00:00
|
|
|
nsIOService::NewChannelFromURI(nsIURI *aURI, nsIChannel **result)
|
1999-06-07 21:33:30 +00:00
|
|
|
{
|
1999-06-08 18:28:10 +00:00
|
|
|
nsresult rv;
|
2000-05-03 21:47:56 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aURI);
|
1999-06-08 18:28:10 +00:00
|
|
|
|
1999-07-10 05:00:23 +00:00
|
|
|
nsXPIDLCString scheme;
|
|
|
|
rv = aURI->GetScheme(getter_Copies(scheme));
|
1999-06-08 18:28:10 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
1999-06-08 19:04:13 +00:00
|
|
|
nsCOMPtr<nsIProtocolHandler> handler;
|
1999-07-10 05:00:23 +00:00
|
|
|
rv = GetProtocolHandler((const char*)scheme, getter_AddRefs(handler));
|
1999-06-08 18:28:10 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2000-03-29 03:58:50 +00:00
|
|
|
rv = handler->NewChannel(aURI, result);
|
1999-06-08 18:28:10 +00:00
|
|
|
return rv;
|
1999-06-07 21:33:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2000-03-29 03:58:50 +00:00
|
|
|
nsIOService::NewChannel(const char *aSpec, nsIURI *aBaseURI, nsIChannel **result)
|
1999-06-07 21:33:30 +00:00
|
|
|
{
|
1999-06-08 18:28:10 +00:00
|
|
|
nsresult rv;
|
1999-09-26 10:11:36 +00:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsCOMPtr<nsIProtocolHandler> handler;
|
|
|
|
rv = NewURI(aSpec, aBaseURI, getter_AddRefs(uri), getter_AddRefs(handler));
|
1999-06-08 18:28:10 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-11-17 08:14:52 +00:00
|
|
|
|
2000-03-29 03:58:50 +00:00
|
|
|
rv = handler->NewChannel(uri, result);
|
1999-06-08 19:04:13 +00:00
|
|
|
return rv;
|
1999-06-07 21:33:30 +00:00
|
|
|
}
|
|
|
|
|
2000-01-05 02:44:23 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsIOService::GetOffline(PRBool *offline)
|
|
|
|
{
|
|
|
|
*offline = mOffline;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsIOService::SetOffline(PRBool offline)
|
|
|
|
{
|
2001-01-17 19:51:28 +00:00
|
|
|
nsCOMPtr<nsIObserverService>
|
|
|
|
observerService(do_GetService(NS_OBSERVERSERVICE_CONTRACTID));
|
|
|
|
|
2000-03-27 22:17:48 +00:00
|
|
|
nsresult rv1 = NS_OK;
|
|
|
|
nsresult rv2 = NS_OK;
|
2000-01-05 03:44:42 +00:00
|
|
|
if (offline) {
|
2000-05-12 23:41:40 +00:00
|
|
|
mOffline = PR_TRUE; // indicate we're trying to shutdown
|
2000-01-05 03:44:42 +00:00
|
|
|
// be sure to try and shutdown both (even if the first fails)
|
2000-02-17 03:34:16 +00:00
|
|
|
if (mDNSService)
|
2000-05-12 23:41:40 +00:00
|
|
|
rv1 = mDNSService->Shutdown(); // shutdown dns service first, because it has callbacks for socket transport
|
|
|
|
if (mSocketTransportService)
|
|
|
|
rv2 = mSocketTransportService->Shutdown();
|
2000-01-05 03:44:42 +00:00
|
|
|
if (NS_FAILED(rv1)) return rv1;
|
|
|
|
if (NS_FAILED(rv2)) return rv2;
|
2001-01-17 19:51:28 +00:00
|
|
|
|
|
|
|
// don't care if notification fails
|
2001-01-17 23:42:42 +00:00
|
|
|
if (observerService)
|
|
|
|
(void)observerService->Notify(this,
|
|
|
|
NS_LITERAL_STRING("network:offline-status-changed"),
|
|
|
|
NS_LITERAL_STRING("offline"));
|
2000-01-05 03:44:42 +00:00
|
|
|
}
|
2000-03-27 22:17:48 +00:00
|
|
|
else if (!offline && mOffline) {
|
|
|
|
// go online
|
|
|
|
if (mDNSService)
|
2000-05-12 23:41:40 +00:00
|
|
|
rv1 = mDNSService->Init();
|
|
|
|
if (NS_FAILED(rv2)) return rv1;
|
|
|
|
|
|
|
|
if (mSocketTransportService)
|
|
|
|
rv2 = mSocketTransportService->Init(); //XXX should we shutdown the dns service?
|
|
|
|
if (NS_FAILED(rv2)) return rv1;
|
2001-01-17 19:51:28 +00:00
|
|
|
mOffline = PR_FALSE; // indicate success only AFTER we've
|
|
|
|
// brought up the services
|
|
|
|
// don't care if notification fails
|
2001-01-17 23:42:42 +00:00
|
|
|
if (observerService)
|
|
|
|
(void)observerService->Notify(this,
|
|
|
|
NS_LITERAL_STRING("network:offline-status-changed"),
|
|
|
|
NS_LITERAL_STRING("online"));
|
2000-03-27 22:17:48 +00:00
|
|
|
}
|
2000-01-05 02:44:23 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-08-22 07:03:33 +00:00
|
|
|
|
2001-02-12 03:14:23 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsIOService::ConsumeInput(nsIChannel* channel, nsISupports* context,
|
|
|
|
nsIStreamListener* consumer)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIInputStream> in;
|
|
|
|
rv = channel->OpenInputStream(getter_AddRefs(in));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = consumer->OnStartRequest(channel, context);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
PRUint32 sourceOffset = 0;
|
|
|
|
while (1) {
|
|
|
|
char buf[1024];
|
|
|
|
PRUint32 readCount;
|
|
|
|
rv = in->Read(buf, sizeof(buf), &readCount);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (readCount == 0) // eof
|
|
|
|
break;
|
|
|
|
|
|
|
|
rv = consumer->OnDataAvailable(channel, context, 0, sourceOffset, readCount);
|
|
|
|
sourceOffset += readCount;
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rv = consumer->OnStopRequest(channel, context, rv, nsnull);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-07-10 11:26:43 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2000-01-27 08:57:14 +00:00
|
|
|
// URL parsing utilities
|
|
|
|
|
2000-03-18 11:07:04 +00:00
|
|
|
/* encode characters into % escaped hexcodes */
|
|
|
|
|
|
|
|
/* use the following masks to specify which
|
|
|
|
part of an URL you want to escape:
|
|
|
|
|
|
|
|
url_Scheme = 1
|
|
|
|
url_Username = 2
|
|
|
|
url_Password = 4
|
|
|
|
url_Host = 8
|
|
|
|
url_Directory = 16
|
|
|
|
url_FileBaseName = 32
|
|
|
|
url_FileExtension = 64
|
|
|
|
url_Param = 128
|
|
|
|
url_Query = 256
|
|
|
|
url_Ref = 512
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* by default this function will not escape parts of a string
|
|
|
|
that already look escaped, which means it already includes
|
|
|
|
a valid hexcode. This is done to avoid multiple escapes of
|
|
|
|
a string. Use the following mask to force escaping of a
|
|
|
|
string:
|
|
|
|
|
|
|
|
url_Forced = 1024
|
|
|
|
*/
|
2000-01-27 08:57:14 +00:00
|
|
|
NS_IMETHODIMP
|
2000-02-25 06:17:57 +00:00
|
|
|
nsIOService::Escape(const char *str, PRInt16 mask, char** result)
|
2000-01-27 08:57:14 +00:00
|
|
|
{
|
2000-02-25 06:17:57 +00:00
|
|
|
nsCAutoString esc_str;
|
|
|
|
nsresult rv = nsURLEscape((char*)str,mask,esc_str);
|
|
|
|
CRTFREEIF(*result);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
*result = esc_str.ToNewCString();
|
|
|
|
if (!*result)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
return NS_OK;
|
2000-01-27 08:57:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsIOService::Unescape(const char *str, char **result)
|
|
|
|
{
|
2000-02-03 03:44:22 +00:00
|
|
|
return nsURLUnescape((char*)str,result);
|
2000-01-27 08:57:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsIOService::ExtractPort(const char *str, PRInt32 *result)
|
|
|
|
{
|
2000-02-03 03:44:22 +00:00
|
|
|
PRInt32 returnValue = -1;
|
|
|
|
*result = (0 < PR_sscanf(str, "%d", &returnValue)) ? returnValue : -1;
|
|
|
|
return NS_OK;
|
2000-01-27 08:57:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsIOService::ResolveRelativePath(const char *relativePath, const char* basePath,
|
|
|
|
char **result)
|
|
|
|
{
|
|
|
|
nsCAutoString name;
|
|
|
|
nsCAutoString path(basePath);
|
2000-07-12 07:39:34 +00:00
|
|
|
PRBool needsDelim = PR_FALSE;
|
|
|
|
|
|
|
|
if ( !path.IsEmpty() ) {
|
|
|
|
PRUnichar last = path.Last();
|
|
|
|
needsDelim = !(last == '/' || last == '\\' );
|
|
|
|
}
|
2000-01-27 08:57:14 +00:00
|
|
|
|
|
|
|
PRBool end = PR_FALSE;
|
|
|
|
char c;
|
|
|
|
while (!end) {
|
|
|
|
c = *relativePath++;
|
|
|
|
switch (c) {
|
|
|
|
case '\0':
|
|
|
|
case '#':
|
|
|
|
case ';':
|
|
|
|
case '?':
|
|
|
|
end = PR_TRUE;
|
|
|
|
// fall through...
|
|
|
|
case '/':
|
|
|
|
case '\\':
|
|
|
|
// delimiter found
|
|
|
|
if (name.Equals("..")) {
|
|
|
|
// pop path
|
|
|
|
PRInt32 pos = path.RFind("/");
|
|
|
|
if (pos > 0) {
|
|
|
|
path.Truncate(pos + 1);
|
|
|
|
path += name;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return NS_ERROR_MALFORMED_URI;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (name.Equals(".") || name.Equals("")) {
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// append name to path
|
|
|
|
if (needsDelim)
|
|
|
|
path += "/";
|
|
|
|
path += name;
|
|
|
|
needsDelim = PR_TRUE;
|
|
|
|
}
|
|
|
|
name = "";
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// append char to name
|
|
|
|
name += c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// append anything left on relativePath (e.g. #..., ;..., ?...)
|
|
|
|
if (c != '\0')
|
|
|
|
path += --relativePath;
|
|
|
|
|
|
|
|
*result = path.ToNewCString();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|