michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "TestCommon.h" michael@0: #include "nsNetUtil.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsIInterfaceRequestor.h" michael@0: #include "nsIInterfaceRequestorUtils.h" michael@0: #include "nsIProgressEventSink.h" michael@0: #include "nsIComponentManager.h" michael@0: #include "prprf.h" michael@0: #include "nsXPCOM.h" michael@0: #include "nsISupportsPrimitives.h" michael@0: #include "plstr.h" michael@0: #include "nsCOMArray.h" michael@0: #include "nsIComponentRegistrar.h" michael@0: #include michael@0: michael@0: namespace TestPageLoad { michael@0: michael@0: int getStrLine(const char *src, char *str, int ind, int max); michael@0: nsresult auxLoad(char *uriBuf); michael@0: //---------------------------------------------------------------------- michael@0: michael@0: michael@0: #define RETURN_IF_FAILED(rv, ret, step) \ michael@0: PR_BEGIN_MACRO \ michael@0: if (NS_FAILED(rv)) { \ michael@0: printf(">>> %s failed: rv=%x\n", step, static_cast(rv)); \ michael@0: return ret;\ michael@0: } \ michael@0: PR_END_MACRO michael@0: michael@0: static nsCString globalStream; michael@0: //static char urlBuf[256]; michael@0: static nsCOMPtr baseURI; michael@0: static nsCOMArray uriList; michael@0: michael@0: //Temp, should remove: michael@0: static int numStart=0; michael@0: static int numFound=0; michael@0: michael@0: static int32_t gKeepRunning = 0; michael@0: michael@0: michael@0: //--------writer fun---------------------- michael@0: michael@0: static NS_METHOD streamParse (nsIInputStream* in, michael@0: void* closure, michael@0: const char* fromRawSegment, michael@0: uint32_t toOffset, michael@0: uint32_t count, michael@0: uint32_t *writeCount) { michael@0: michael@0: char parseBuf[2048], loc[2048], lineBuf[2048]; michael@0: char *loc_t, *loc_t2; michael@0: int i = 0; michael@0: const char *tmp; michael@0: michael@0: if(!globalStream.IsEmpty()) { michael@0: globalStream.Append(fromRawSegment); michael@0: tmp = globalStream.get(); michael@0: //printf("\n>>NOW:\n^^^^^\n%s\n^^^^^^^^^^^^^^", tmp); michael@0: } else { michael@0: tmp = fromRawSegment; michael@0: } michael@0: michael@0: while(i < (int)count) { michael@0: i = getStrLine(tmp, lineBuf, i, count); michael@0: if(i < 0) { michael@0: *writeCount = count; michael@0: return NS_OK; michael@0: } michael@0: parseBuf[0]='\0'; michael@0: if((loc_t=PL_strcasestr(lineBuf, "img"))!= nullptr michael@0: || (loc_t=PL_strcasestr(lineBuf, "script"))!=nullptr) { michael@0: loc_t2=PL_strcasestr(loc_t, "src"); michael@0: if(loc_t2!=nullptr) { michael@0: loc_t2+=3; michael@0: strcpy(loc, loc_t2); michael@0: sscanf(loc, "=\"%[^\"]", parseBuf); michael@0: if(parseBuf[0]=='\0') michael@0: sscanf(loc, "=%s", parseBuf); michael@0: if(parseBuf[0]!='\0'){ michael@0: numFound++; michael@0: auxLoad(parseBuf); michael@0: } michael@0: } michael@0: } michael@0: michael@0: /***NEED BETTER CHECK FOR STYLESHEETS michael@0: if((loc_t=PL_strcasestr(lineBuf, "link"))!= nullptr) { michael@0: loc_t2=PL_strcasestr(loc_t, "href"); michael@0: if(loc_t2!=nullptr) { michael@0: loc_t2+=4; michael@0: strcpy(loc, loc_t2); michael@0: //printf("%s\n", loc); michael@0: sscanf(loc, "=\"%[^\"]", parseBuf); michael@0: if(parseBuf[0]!='\0'){ michael@0: //printf("%s\n", parseBuf); michael@0: numFound++; michael@0: auxLoad(parseBuf); michael@0: } michael@0: } michael@0: } michael@0: */ michael@0: if((loc_t=PL_strcasestr(lineBuf, "background"))!=nullptr) { michael@0: loc_t+=10; michael@0: strcpy(loc, loc_t); michael@0: sscanf(loc, "=\"%[^\"]", parseBuf); michael@0: if(parseBuf[0]!='\0') { michael@0: numFound++; michael@0: auxLoad(parseBuf); michael@0: } michael@0: } michael@0: i++; michael@0: michael@0: } michael@0: *writeCount = count; michael@0: return NS_OK; michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsIStreamListener implementation michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: class MyListener : public nsIStreamListener michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIREQUESTOBSERVER michael@0: NS_DECL_NSISTREAMLISTENER michael@0: michael@0: MyListener() { } michael@0: virtual ~MyListener() {} michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(MyListener, michael@0: nsIRequestObserver, michael@0: nsIStreamListener) michael@0: michael@0: NS_IMETHODIMP michael@0: MyListener::OnStartRequest(nsIRequest *req, nsISupports *ctxt) michael@0: { michael@0: //printf(">>> OnStartRequest\n"); michael@0: numStart++; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MyListener::OnStopRequest(nsIRequest *req, nsISupports *ctxt, nsresult status) michael@0: { michael@0: //printf(">>> OnStopRequest status=%x\n", status); michael@0: if (--gKeepRunning == 0) michael@0: QuitPumpingEvents(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MyListener::OnDataAvailable(nsIRequest *req, nsISupports *ctxt, michael@0: nsIInputStream *stream, michael@0: uint64_t offset, uint32_t count) michael@0: { michael@0: //printf(">>> OnDataAvailable [count=%u]\n", count); michael@0: nsresult rv = NS_ERROR_FAILURE; michael@0: uint32_t bytesRead=0; michael@0: char buf[1024]; michael@0: michael@0: if(ctxt == nullptr) { michael@0: bytesRead=0; michael@0: rv = stream->ReadSegments(streamParse, nullptr, count, &bytesRead); michael@0: } else { michael@0: while (count) { michael@0: uint32_t amount = std::min(count, sizeof(buf)); michael@0: rv = stream->Read(buf, amount, &bytesRead); michael@0: count -= bytesRead; michael@0: } michael@0: } michael@0: michael@0: if (NS_FAILED(rv)) { michael@0: printf(">>> stream->Read failed with rv=%x\n", michael@0: static_cast(rv)); michael@0: return rv; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // NotificationCallbacks implementation michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: class MyNotifications : public nsIInterfaceRequestor michael@0: , public nsIProgressEventSink michael@0: { michael@0: public: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSIINTERFACEREQUESTOR michael@0: NS_DECL_NSIPROGRESSEVENTSINK michael@0: michael@0: MyNotifications() { } michael@0: virtual ~MyNotifications() {} michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(MyNotifications, michael@0: nsIInterfaceRequestor, michael@0: nsIProgressEventSink) michael@0: michael@0: NS_IMETHODIMP michael@0: MyNotifications::GetInterface(const nsIID &iid, void **result) michael@0: { michael@0: return QueryInterface(iid, result); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MyNotifications::OnStatus(nsIRequest *req, nsISupports *ctx, michael@0: nsresult status, const char16_t *statusText) michael@0: { michael@0: //printf("status: %x\n", status); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MyNotifications::OnProgress(nsIRequest *req, nsISupports *ctx, michael@0: uint64_t progress, uint64_t progressMax) michael@0: { michael@0: // char buf[100]; michael@0: // PR_snprintf(buf, sizeof(buf), "%llu/%llu\n", progress, progressMax); michael@0: // printf("%s", buf); michael@0: return NS_OK; michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // main, etc.. michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: //---------getStrLine Helper function--------------- michael@0: //Finds a newline in src starting at ind. Puts the michael@0: //line in str (must be big enough). Returns the index michael@0: //of the newline, or -1 if at end of string. If reaches michael@0: //end of string ('\0'), then will copy contents to michael@0: //globalStream. michael@0: int getStrLine(const char *src, char *str, int ind, int max) { michael@0: char c = src[ind]; michael@0: int i=0; michael@0: globalStream.Assign('\0'); michael@0: while(c!='\n' && c!='\0' && i myBool = do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID); michael@0: michael@0: nsCOMPtr uri; michael@0: nsCOMPtr chan; michael@0: nsCOMPtr listener = new MyListener(); michael@0: nsCOMPtr callbacks = new MyNotifications(); michael@0: michael@0: printf("Getting: %s", uriBuf); michael@0: michael@0: //If relative link michael@0: if(strncmp(uriBuf, "http:", 5)) { michael@0: //Relative link michael@0: rv = NS_NewURI(getter_AddRefs(uri), uriBuf, baseURI); michael@0: if (NS_FAILED(rv)) return(rv); michael@0: } else { michael@0: //Absolute link, no base needed michael@0: rv = NS_NewURI(getter_AddRefs(uri), uriBuf); michael@0: if (NS_FAILED(rv)) return(rv); michael@0: } michael@0: michael@0: //Compare to see if exists michael@0: bool equal; michael@0: for(int32_t i = 0; i < uriList.Count(); i++) { michael@0: uri->Equals(uriList[i], &equal); michael@0: if(equal) { michael@0: printf("(duplicate, canceling) %s\n",uriBuf); michael@0: return NS_OK; michael@0: } michael@0: } michael@0: printf("\n"); michael@0: uriList.AppendObject(uri); michael@0: rv = NS_NewChannel(getter_AddRefs(chan), uri, nullptr, nullptr, callbacks); michael@0: RETURN_IF_FAILED(rv, rv, "NS_NewChannel"); michael@0: michael@0: gKeepRunning++; michael@0: rv = chan->AsyncOpen(listener, myBool); michael@0: RETURN_IF_FAILED(rv, rv, "AsyncOpen"); michael@0: michael@0: return NS_OK; michael@0: michael@0: } michael@0: michael@0: //---------Buffer writer fun--------- michael@0: michael@0: } // namespace michael@0: michael@0: using namespace TestPageLoad; michael@0: michael@0: //---------MAIN----------- michael@0: michael@0: int main(int argc, char **argv) michael@0: { michael@0: if (test_common_init(&argc, &argv) != 0) michael@0: return -1; michael@0: michael@0: nsresult rv; michael@0: michael@0: if (argc == 1) { michael@0: printf("usage: TestPageLoad \n"); michael@0: return -1; michael@0: } michael@0: { michael@0: nsCOMPtr servMan; michael@0: NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); michael@0: michael@0: PRTime start, finish; michael@0: michael@0: printf("Loading necko ... \n"); michael@0: nsCOMPtr chan; michael@0: nsCOMPtr listener = new MyListener(); michael@0: nsCOMPtr callbacks = new MyNotifications(); michael@0: michael@0: rv = NS_NewURI(getter_AddRefs(baseURI), argv[1]); michael@0: RETURN_IF_FAILED(rv, -1, "NS_NewURI"); michael@0: michael@0: rv = NS_NewChannel(getter_AddRefs(chan), baseURI, nullptr, nullptr, callbacks); michael@0: RETURN_IF_FAILED(rv, -1, "NS_OpenURI"); michael@0: gKeepRunning++; michael@0: michael@0: //TIMER STARTED----------------------- michael@0: printf("Starting clock ... \n"); michael@0: start = PR_Now(); michael@0: rv = chan->AsyncOpen(listener, nullptr); michael@0: RETURN_IF_FAILED(rv, -1, "AsyncOpen"); michael@0: michael@0: PumpEvents(); michael@0: michael@0: finish = PR_Now(); michael@0: uint32_t totalTime32 = uint32_t(finish - start); michael@0: michael@0: printf("\n\n--------------------\nAll done:\nnum found:%d\nnum start:%d\n", numFound, numStart); michael@0: michael@0: printf("\n\n>>PageLoadTime>>%u>>\n\n", totalTime32); michael@0: } // this scopes the nsCOMPtrs michael@0: // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM michael@0: rv = NS_ShutdownXPCOM(nullptr); michael@0: NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); michael@0: return 0; michael@0: }