1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 cin et: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include <inttypes.h>
8 #include <stdlib.h>
9 #include "TestCommon.h"
10 #include "nsNetUtil.h"
11 #include "nsComponentManagerUtils.h"
12 #include "nsIIncrementalDownload.h"
13 #include "nsIRequestObserver.h"
14 #include "nsIProgressEventSink.h"
15 #include "nsThreadUtils.h"
16 #include "nsAutoPtr.h"
17 #include "prprf.h"
18 #include "prenv.h"
19 #include "mozilla/Attributes.h"
20 
21 //-----------------------------------------------------------------------------
22 
23 class FetchObserver final : public nsIRequestObserver
24                           , public nsIProgressEventSink
25 {
26   ~FetchObserver() = default;
27 public:
28   NS_DECL_ISUPPORTS
29   NS_DECL_NSIREQUESTOBSERVER
30   NS_DECL_NSIPROGRESSEVENTSINK
31 };
32 
NS_IMPL_ISUPPORTS(FetchObserver,nsIRequestObserver,nsIProgressEventSink)33 NS_IMPL_ISUPPORTS(FetchObserver, nsIRequestObserver,
34                   nsIProgressEventSink)
35 
36 NS_IMETHODIMP
37 FetchObserver::OnStartRequest(nsIRequest *request, nsISupports *context)
38 {
39   printf("FetchObserver::OnStartRequest\n");
40   return NS_OK;
41 }
42 
43 NS_IMETHODIMP
OnProgress(nsIRequest * request,nsISupports * context,int64_t progress,int64_t progressMax)44 FetchObserver::OnProgress(nsIRequest *request, nsISupports *context,
45                           int64_t progress, int64_t progressMax)
46 {
47   printf("FetchObserver::OnProgress [%" PRId64 "/%" PRId64 "]\n",
48          progress, progressMax);
49   return NS_OK;
50 }
51 
52 NS_IMETHODIMP
OnStatus(nsIRequest * request,nsISupports * context,nsresult status,const char16_t * statusText)53 FetchObserver::OnStatus(nsIRequest *request, nsISupports *context,
54                         nsresult status, const char16_t *statusText)
55 {
56   return NS_OK;
57 }
58 
59 NS_IMETHODIMP
OnStopRequest(nsIRequest * request,nsISupports * context,nsresult status)60 FetchObserver::OnStopRequest(nsIRequest *request, nsISupports *context,
61                              nsresult status)
62 {
63   printf("FetchObserver::OnStopRequest [status=%x]\n",
64          static_cast<uint32_t>(status));
65 
66   QuitPumpingEvents();
67   return NS_OK;
68 }
69 
70 //-----------------------------------------------------------------------------
71 
72 static nsresult
DoIncrementalFetch(const char * uriSpec,const char * resultPath,int32_t chunkSize,int32_t interval)73 DoIncrementalFetch(const char *uriSpec, const char *resultPath, int32_t chunkSize,
74                    int32_t interval)
75 {
76   nsCOMPtr<nsIFile> resultFile;
77   nsresult rv = NS_NewNativeLocalFile(nsDependentCString(resultPath),
78                                       false, getter_AddRefs(resultFile));
79   if (NS_FAILED(rv))
80     return rv;
81 
82   nsCOMPtr<nsIURI> uri;
83   rv = NS_NewURI(getter_AddRefs(uri), uriSpec);
84   if (NS_FAILED(rv))
85     return rv;
86 
87   nsCOMPtr<nsIRequestObserver> observer = new FetchObserver();
88   if (!observer)
89     return NS_ERROR_OUT_OF_MEMORY;
90 
91   nsCOMPtr<nsIIncrementalDownload> download =
92       do_CreateInstance(NS_INCREMENTALDOWNLOAD_CONTRACTID, &rv);
93   if (NS_FAILED(rv))
94     return rv;
95 
96   rv = download->Init(uri, resultFile, chunkSize, interval);
97   if (NS_FAILED(rv))
98     return rv;
99 
100   rv = download->Start(observer, nullptr);
101   if (NS_FAILED(rv))
102     return rv;
103 
104   PumpEvents();
105   return NS_OK;
106 }
107 
108 int
main(int argc,char ** argv)109 main(int argc, char **argv)
110 {
111   if (PR_GetEnv("MOZ_BREAK_ON_MAIN"))
112     NS_BREAK();
113 
114   if (argc < 5) {
115     fprintf(stderr, "USAGE: TestIncrementalDownload <url> <file> <chunksize> <interval-in-seconds>\n");
116     return -1;
117   }
118 
119   nsresult rv = NS_InitXPCOM2(nullptr, nullptr, nullptr);
120   if (NS_FAILED(rv))
121     return -1;
122 
123   int32_t chunkSize = atoi(argv[3]);
124   int32_t interval = atoi(argv[4]);
125 
126   rv = DoIncrementalFetch(argv[1], argv[2], chunkSize, interval);
127   if (NS_FAILED(rv))
128     fprintf(stderr, "ERROR: DoIncrementalFetch failed [%x]\n",
129             static_cast<uint32_t>(rv));
130 
131   NS_ShutdownXPCOM(nullptr);
132   return 0;
133 }
134