/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * 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/ * * 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. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ #include #ifdef WIN32 #include #endif #include "nspr.h" #include "nscore.h" #include "nsCOMPtr.h" #include "nsIEventQueueService.h" #include "nsIIOService.h" #include "nsIServiceManager.h" #include "nsIStreamListener.h" #include "nsIInputStream.h" #include "nsIBufferInputStream.h" #include "nsCRT.h" #include "nsIChannel.h" #include "nsIURL.h" #include "nsIInterfaceRequestor.h" #include "nsIDNSService.h" #include "nsISimpleEnumerator.h" #include "nsXPIDLString.h" #include "nsNetUtil.h" static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); static int gKeepRunning = 0; static nsIEventQueue* gEventQ = nsnull; static PRBool gError = PR_FALSE; #define NS_IEQUALS_IID \ { 0x11c5c8ee, 0x1dd2, 0x11b2, \ { 0xa8, 0x93, 0xbb, 0x23, 0xa1, 0xb6, 0x27, 0x76 }} class nsIEquals : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_IEQUALS_IID) NS_IMETHOD Equals(void *aPtr, PRBool *_retval) = 0; }; class ConsumerContext : public nsIEquals { public: NS_DECL_ISUPPORTS ConsumerContext() { NS_INIT_REFCNT();} NS_IMETHOD Equals(void *aPtr, PRBool *_retval) { *_retval = PR_TRUE; if (aPtr != this) *_retval = PR_FALSE; return NS_OK; }; }; NS_IMPL_THREADSAFE_ISUPPORTS1(ConsumerContext, nsIEquals); class Consumer : public nsIStreamListener { public: NS_DECL_ISUPPORTS NS_DECL_NSISTREAMOBSERVER NS_DECL_NSISTREAMLISTENER Consumer(); virtual ~Consumer(); nsresult Init(nsIURI *aURI, nsIChannel *aChannel, nsISupports *aContext); nsresult Validate(nsIChannel *aChannel, nsISupports *aContext); // member data PRBool mOnStart; // have we received an OnStart? PRBool mOnStop; // have we received an onStop? PRInt32 mOnDataCount; // number of times OnData was called. nsCOMPtr mURI; nsCOMPtr mChannel; nsCOMPtr mContext; }; // nsISupports implementation NS_IMPL_THREADSAFE_ISUPPORTS2(Consumer, nsIStreamListener, nsIStreamObserver); // nsIStreamObserver implementation NS_IMETHODIMP Consumer::OnStartRequest(nsIChannel *aChannel, nsISupports* aContext) { fprintf(stderr, "Consumer::OnStart() -> in\n\n"); if (mOnStart) { fprintf(stderr, "INFO: multiple OnStarts received\n"); } mOnStart = PR_TRUE; nsresult rv = Validate(aChannel, aContext); if (NS_FAILED(rv)) return rv; fprintf(stderr, "Consumer::OnStart() -> out\n\n"); return rv; } NS_IMETHODIMP Consumer::OnStopRequest(nsIChannel *aChannel, nsISupports *aContext, nsresult aStatus, const PRUnichar* aMsg) { fprintf(stderr, "Consumer::OnStop() -> in\n\n"); if (!mOnStart) { gError = PR_TRUE; fprintf(stderr, "ERROR: No OnStart received\n"); } if (mOnStop) { fprintf(stderr, "INFO: multiple OnStops received\n"); } fprintf(stderr, "INFO: received %d OnData()s\n", mOnDataCount); mOnStop = PR_TRUE; nsresult rv = Validate(aChannel, aContext); if (NS_FAILED(rv)) return rv; fprintf(stderr, "Consumer::OnStop() -> out\n\n"); gKeepRunning--; return rv; } // nsIStreamListener implementation NS_IMETHODIMP Consumer::OnDataAvailable(nsIChannel *aChannel, nsISupports *aContext, nsIInputStream *aIStream, PRUint32 aOffset, PRUint32 aLength) { fprintf(stderr, "Consumer::OnData() -> in\n\n"); if (!mOnStart) { gError = PR_TRUE; fprintf(stderr, "ERROR: No OnStart received\n"); } mOnDataCount += 1; nsresult rv = Validate(aChannel, aContext); if (NS_FAILED(rv)) return rv; fprintf(stderr, "Consumer::OnData() -> out\n\n"); return rv; } // Consumer implementation Consumer::Consumer() { NS_INIT_REFCNT(); mOnStart = mOnStop = PR_FALSE; mOnDataCount = 0; } Consumer::~Consumer() { fprintf(stderr, "Consumer::~Consumer -> in\n\n"); if (!mOnStart) { gError = PR_TRUE; fprintf(stderr, "ERROR: Never got an OnStart\n"); } if (!mOnStop) { gError = PR_TRUE; fprintf(stderr, "ERROR: Never got an OnStop \n"); } fprintf(stderr, "Consumer::~Consumer -> out\n\n"); } nsresult Consumer::Init(nsIURI *aURI, nsIChannel *aChannel, nsISupports *aContext) { mURI = aURI; mChannel = aChannel; mContext = do_QueryInterface(aContext); return NS_OK; } nsresult Consumer::Validate(nsIChannel *aChannel, nsISupports *aContext) { nsresult rv = NS_OK; nsCOMPtr uri; rv = aChannel->GetURI(getter_AddRefs(uri)); if (NS_FAILED(rv)) return rv; PRBool same = PR_FALSE; rv = mURI->Equals(uri, &same); if (NS_FAILED(rv)) return rv; if (!same) fprintf(stderr, "INFO: URIs do not match\n"); rv = mContext->Equals((void*)aContext, &same); if (NS_FAILED(rv)) return rv; if (!same) { gError = PR_TRUE; fprintf(stderr, "ERROR: Contexts do not match\n"); } return rv; } nsresult StartLoad(char *); int main(int argc, char *argv[]) { nsresult rv = NS_OK; rv = NS_InitXPCOM(nsnull, nsnull); if (NS_FAILED(rv)) return rv; // Create the Event Queue for this thread... NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv); if (NS_FAILED(rv)) return rv; rv = eventQService->CreateThreadEventQueue(); if (NS_FAILED(rv)) return rv; rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); if (NS_FAILED(rv)) return rv; rv = StartLoad("http://badhostnamexyz/test.txt"); if (NS_FAILED(rv)) return rv; // Enter the message pump to allow the URL load to proceed. while ( gKeepRunning ) { #ifdef WIN32 MSG msg; if (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { gKeepRunning = 0; } #else #ifdef XP_MAC /* Mac stuff is missing here! */ #else PLEvent *gEvent; rv = gEventQ->GetEvent(&gEvent); rv = gEventQ->HandleEvent(gEvent); #endif /* XP_UNIX */ #endif /* !WIN32 */ } NS_ShutdownXPCOM(nsnull); return rv; } nsresult StartLoad(char *aURISpec) { nsresult rv = NS_OK; gKeepRunning++; // create a context ConsumerContext *context = new ConsumerContext; nsCOMPtr contextSup = do_QueryInterface(context, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr serv; rv = nsServiceManager::GetService(kIOServiceCID, NS_GET_IID(nsIIOService), getter_AddRefs(serv)); if (NS_FAILED(rv)) return rv; // create a uri nsCOMPtr uri; rv = NS_NewURI(getter_AddRefs(uri), aURISpec); if (NS_FAILED(rv)) return rv; // create a channel nsCOMPtr channel; rv = serv->NewChannelFromURI(uri, getter_AddRefs(channel)); if (NS_FAILED(rv)) return rv; Consumer *consumer = new Consumer; rv = consumer->Init(uri, channel, contextSup); if (NS_FAILED(rv)) return rv; // kick off the load return channel->AsyncRead(NS_STATIC_CAST(nsIStreamListener*, consumer), contextSup); }