|
1 #include "nsNetUtil.h" |
|
2 #include "nsIEventQueueService.h" |
|
3 #include "nsIServiceManager.h" |
|
4 #include "nsIComponentRegistrar.h" |
|
5 #include "nsIInterfaceRequestor.h" |
|
6 #include "nsIInterfaceRequestorUtils.h" |
|
7 #include "nsIProgressEventSink.h" |
|
8 #include <algorithm> |
|
9 |
|
10 #define RETURN_IF_FAILED(rv, step) \ |
|
11 PR_BEGIN_MACRO \ |
|
12 if (NS_FAILED(rv)) { \ |
|
13 printf(">>> %s failed: rv=%x\n", step, rv); \ |
|
14 return rv;\ |
|
15 } \ |
|
16 PR_END_MACRO |
|
17 |
|
18 static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); |
|
19 static nsIEventQueue* gEventQ = nullptr; |
|
20 static bool gKeepRunning = true; |
|
21 |
|
22 //----------------------------------------------------------------------------- |
|
23 // nsIStreamListener implementation |
|
24 //----------------------------------------------------------------------------- |
|
25 |
|
26 class MyListener : public nsIStreamListener |
|
27 { |
|
28 public: |
|
29 NS_DECL_ISUPPORTS |
|
30 NS_DECL_NSIREQUESTOBSERVER |
|
31 NS_DECL_NSISTREAMLISTENER |
|
32 |
|
33 MyListener() { } |
|
34 virtual ~MyListener() {} |
|
35 }; |
|
36 |
|
37 NS_IMPL_ISUPPORTS(MyListener, |
|
38 nsIRequestObserver, |
|
39 nsIStreamListener) |
|
40 |
|
41 NS_IMETHODIMP |
|
42 MyListener::OnStartRequest(nsIRequest *req, nsISupports *ctxt) |
|
43 { |
|
44 printf(">>> OnStartRequest\n"); |
|
45 return NS_OK; |
|
46 } |
|
47 |
|
48 NS_IMETHODIMP |
|
49 MyListener::OnStopRequest(nsIRequest *req, nsISupports *ctxt, nsresult status) |
|
50 { |
|
51 printf(">>> OnStopRequest status=%x\n", status); |
|
52 gKeepRunning = false; |
|
53 return NS_OK; |
|
54 } |
|
55 |
|
56 NS_IMETHODIMP |
|
57 MyListener::OnDataAvailable(nsIRequest *req, nsISupports *ctxt, |
|
58 nsIInputStream *stream, |
|
59 uint64_t offset, uint32_t count) |
|
60 { |
|
61 printf(">>> OnDataAvailable [count=%u]\n", count); |
|
62 |
|
63 char buf[256]; |
|
64 nsresult rv; |
|
65 uint32_t bytesRead=0; |
|
66 |
|
67 while (count) { |
|
68 uint32_t amount = std::min<uint32_t>(count, sizeof(buf)); |
|
69 |
|
70 rv = stream->Read(buf, amount, &bytesRead); |
|
71 if (NS_FAILED(rv)) { |
|
72 printf(">>> stream->Read failed with rv=%x\n", rv); |
|
73 return rv; |
|
74 } |
|
75 |
|
76 fwrite(buf, 1, bytesRead, stdout); |
|
77 |
|
78 count -= bytesRead; |
|
79 } |
|
80 return NS_OK; |
|
81 } |
|
82 |
|
83 //----------------------------------------------------------------------------- |
|
84 // NotificationCallbacks implementation |
|
85 //----------------------------------------------------------------------------- |
|
86 |
|
87 class MyNotifications : public nsIInterfaceRequestor |
|
88 , public nsIProgressEventSink |
|
89 { |
|
90 public: |
|
91 NS_DECL_THREADSAFE_ISUPPORTS |
|
92 NS_DECL_NSIINTERFACEREQUESTOR |
|
93 NS_DECL_NSIPROGRESSEVENTSINK |
|
94 |
|
95 MyNotifications() { } |
|
96 virtual ~MyNotifications() {} |
|
97 }; |
|
98 |
|
99 NS_IMPL_ISUPPORTS(MyNotifications, |
|
100 nsIInterfaceRequestor, |
|
101 nsIProgressEventSink) |
|
102 |
|
103 NS_IMETHODIMP |
|
104 MyNotifications::GetInterface(const nsIID &iid, void **result) |
|
105 { |
|
106 return QueryInterface(iid, result); |
|
107 } |
|
108 |
|
109 NS_IMETHODIMP |
|
110 MyNotifications::OnStatus(nsIRequest *req, nsISupports *ctx, |
|
111 nsresult status, const char16_t *statusText) |
|
112 { |
|
113 printf("status: %x\n", status); |
|
114 return NS_OK; |
|
115 } |
|
116 |
|
117 NS_IMETHODIMP |
|
118 MyNotifications::OnProgress(nsIRequest *req, nsISupports *ctx, |
|
119 uint64_t progress, uint64_t progressMax) |
|
120 { |
|
121 printf("progress: %llu/%llu\n", progress, progressMax); |
|
122 return NS_OK; |
|
123 } |
|
124 |
|
125 //----------------------------------------------------------------------------- |
|
126 // main, etc.. |
|
127 //----------------------------------------------------------------------------- |
|
128 |
|
129 |
|
130 int main(int argc, char **argv) |
|
131 { |
|
132 nsresult rv; |
|
133 |
|
134 if (argc == 1) { |
|
135 printf("usage: TestHttp <url>\n"); |
|
136 return -1; |
|
137 } |
|
138 { |
|
139 nsCOMPtr<nsIServiceManager> servMan; |
|
140 NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); |
|
141 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan); |
|
142 NS_ASSERTION(registrar, "Null nsIComponentRegistrar"); |
|
143 if (registrar) |
|
144 registrar->AutoRegister(nullptr); |
|
145 |
|
146 // Create the Event Queue for this thread... |
|
147 nsCOMPtr<nsIEventQueueService> eqs = |
|
148 do_GetService(kEventQueueServiceCID, &rv); |
|
149 RETURN_IF_FAILED(rv, "do_GetService(EventQueueService)"); |
|
150 |
|
151 rv = eqs->CreateMonitoredThreadEventQueue(); |
|
152 RETURN_IF_FAILED(rv, "CreateMonitoredThreadEventQueue"); |
|
153 |
|
154 rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); |
|
155 RETURN_IF_FAILED(rv, "GetThreadEventQueue"); |
|
156 |
|
157 nsCOMPtr<nsIURI> uri; |
|
158 nsCOMPtr<nsIChannel> chan; |
|
159 nsCOMPtr<nsIStreamListener> listener = new MyListener(); |
|
160 nsCOMPtr<nsIInterfaceRequestor> callbacks = new MyNotifications(); |
|
161 |
|
162 rv = NS_NewURI(getter_AddRefs(uri), argv[1]); |
|
163 RETURN_IF_FAILED(rv, "NS_NewURI"); |
|
164 |
|
165 rv = NS_NewChannel(getter_AddRefs(chan), uri, nullptr, nullptr, callbacks); |
|
166 RETURN_IF_FAILED(rv, "NS_OpenURI"); |
|
167 |
|
168 rv = chan->AsyncOpen(listener, nullptr); |
|
169 RETURN_IF_FAILED(rv, "AsyncOpen"); |
|
170 |
|
171 while (gKeepRunning) |
|
172 gEventQ->ProcessPendingEvents(); |
|
173 |
|
174 printf(">>> done\n"); |
|
175 } // this scopes the nsCOMPtrs |
|
176 // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM |
|
177 rv = NS_ShutdownXPCOM(nullptr); |
|
178 NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); |
|
179 return 0; |
|
180 } |