/src/mozilla-central/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set sw=2 ts=8 et tw=80 : */ |
3 | | |
4 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
5 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
6 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
7 | | |
8 | | // HttpLog.h should generally be included first |
9 | | #include "HttpLog.h" |
10 | | |
11 | | #include "HttpBackgroundChannelChild.h" |
12 | | |
13 | | #include "HttpChannelChild.h" |
14 | | #include "mozilla/ipc/BackgroundChild.h" |
15 | | #include "mozilla/ipc/PBackgroundChild.h" |
16 | | #include "mozilla/IntegerPrintfMacros.h" |
17 | | #include "mozilla/Unused.h" |
18 | | #include "nsSocketTransportService2.h" |
19 | | |
20 | | using mozilla::ipc::BackgroundChild; |
21 | | using mozilla::ipc::IPCResult; |
22 | | |
23 | | namespace mozilla { |
24 | | namespace net { |
25 | | |
26 | | // HttpBackgroundChannelChild |
27 | 0 | HttpBackgroundChannelChild::HttpBackgroundChannelChild() = default; |
28 | | |
29 | 0 | HttpBackgroundChannelChild::~HttpBackgroundChannelChild() = default; |
30 | | |
31 | | nsresult |
32 | | HttpBackgroundChannelChild::Init(HttpChannelChild* aChannelChild) |
33 | 0 | { |
34 | 0 | LOG(("HttpBackgroundChannelChild::Init [this=%p httpChannel=%p channelId=%" |
35 | 0 | PRIu64 "]\n", this, aChannelChild, aChannelChild->ChannelId())); |
36 | 0 | MOZ_ASSERT(OnSocketThread()); |
37 | 0 | NS_ENSURE_ARG(aChannelChild); |
38 | 0 |
|
39 | 0 | mChannelChild = aChannelChild; |
40 | 0 |
|
41 | 0 | if (NS_WARN_IF(!CreateBackgroundChannel())) { |
42 | 0 | mChannelChild = nullptr; |
43 | 0 | return NS_ERROR_FAILURE; |
44 | 0 | } |
45 | 0 | |
46 | 0 | return NS_OK; |
47 | 0 | } |
48 | | |
49 | | void |
50 | | HttpBackgroundChannelChild::OnChannelClosed() |
51 | 0 | { |
52 | 0 | LOG(("HttpBackgroundChannelChild::OnChannelClosed [this=%p]\n", this)); |
53 | 0 | MOZ_ASSERT(OnSocketThread()); |
54 | 0 |
|
55 | 0 | // HttpChannelChild is not going to handle any incoming message. |
56 | 0 | mChannelChild = nullptr; |
57 | 0 |
|
58 | 0 | // Remove pending IPC messages as well. |
59 | 0 | mQueuedRunnables.Clear(); |
60 | 0 | } |
61 | | |
62 | | void |
63 | | HttpBackgroundChannelChild::OnStartRequestReceived() |
64 | 0 | { |
65 | 0 | LOG(("HttpBackgroundChannelChild::OnStartRequestReceived [this=%p]\n", this)); |
66 | 0 | MOZ_ASSERT(OnSocketThread()); |
67 | 0 | MOZ_ASSERT(mChannelChild); |
68 | 0 | MOZ_ASSERT(!mStartReceived); // Should only be called once. |
69 | 0 |
|
70 | 0 | mStartReceived = true; |
71 | 0 |
|
72 | 0 | nsTArray<nsCOMPtr<nsIRunnable>> runnables; |
73 | 0 | runnables.SwapElements(mQueuedRunnables); |
74 | 0 |
|
75 | 0 | for (const auto& event : runnables) { |
76 | 0 | // Note: these runnables call Recv* methods on HttpBackgroundChannelChild |
77 | 0 | // but not the Process* methods on HttpChannelChild. |
78 | 0 | event->Run(); |
79 | 0 | } |
80 | 0 |
|
81 | 0 | // Ensure no new message is enqueued. |
82 | 0 | MOZ_ASSERT(mQueuedRunnables.IsEmpty()); |
83 | 0 | } |
84 | | |
85 | | bool |
86 | | HttpBackgroundChannelChild::CreateBackgroundChannel() |
87 | 0 | { |
88 | 0 | LOG(("HttpBackgroundChannelChild::CreateBackgroundChannel [this=%p]\n", this)); |
89 | 0 | MOZ_ASSERT(OnSocketThread()); |
90 | 0 | MOZ_ASSERT(mChannelChild); |
91 | 0 |
|
92 | 0 | PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread(); |
93 | 0 | if (NS_WARN_IF(!actorChild)) { |
94 | 0 | return false; |
95 | 0 | } |
96 | 0 | |
97 | 0 | const uint64_t channelId = mChannelChild->ChannelId(); |
98 | 0 | if (!actorChild->SendPHttpBackgroundChannelConstructor(this, channelId)) { |
99 | 0 | return false; |
100 | 0 | } |
101 | 0 | |
102 | 0 | // hold extra reference for IPDL |
103 | 0 | RefPtr<HttpBackgroundChannelChild> self = this; |
104 | 0 | Unused << self.forget().take(); |
105 | 0 |
|
106 | 0 | mChannelChild->OnBackgroundChildReady(this); |
107 | 0 | return true; |
108 | 0 | } |
109 | | |
110 | | bool |
111 | | HttpBackgroundChannelChild::IsWaitingOnStartRequest() |
112 | 0 | { |
113 | 0 | MOZ_ASSERT(OnSocketThread()); |
114 | 0 | // Need to wait for OnStartRequest if it is sent by |
115 | 0 | // parent process but not received by content process. |
116 | 0 | return (mStartSent && !mStartReceived); |
117 | 0 | } |
118 | | |
119 | | // PHttpBackgroundChannelChild |
120 | | IPCResult |
121 | | HttpBackgroundChannelChild::RecvOnStartRequestSent() |
122 | 0 | { |
123 | 0 | LOG(("HttpBackgroundChannelChild::RecvOnStartRequestSent [this=%p]\n", this)); |
124 | 0 | MOZ_ASSERT(OnSocketThread()); |
125 | 0 | MOZ_ASSERT(!mStartSent); // Should only receive this message once. |
126 | 0 |
|
127 | 0 | mStartSent = true; |
128 | 0 | return IPC_OK(); |
129 | 0 | } |
130 | | |
131 | | IPCResult |
132 | | HttpBackgroundChannelChild::RecvOnTransportAndData( |
133 | | const nsresult& aChannelStatus, |
134 | | const nsresult& aTransportStatus, |
135 | | const uint64_t& aOffset, |
136 | | const uint32_t& aCount, |
137 | | const nsCString& aData) |
138 | 0 | { |
139 | 0 | LOG(("HttpBackgroundChannelChild::RecvOnTransportAndData [this=%p]\n", this)); |
140 | 0 | MOZ_ASSERT(OnSocketThread()); |
141 | 0 |
|
142 | 0 | if (NS_WARN_IF(!mChannelChild)) { |
143 | 0 | return IPC_OK(); |
144 | 0 | } |
145 | 0 |
|
146 | 0 | if (IsWaitingOnStartRequest()) { |
147 | 0 | LOG((" > pending until OnStartRequest [offset=%" PRIu64 " count=%" PRIu32 |
148 | 0 | "]\n", aOffset, aCount)); |
149 | 0 |
|
150 | 0 | mQueuedRunnables.AppendElement(NewRunnableMethod<const nsresult, |
151 | 0 | const nsresult, |
152 | 0 | const uint64_t, |
153 | 0 | const uint32_t, |
154 | 0 | const nsCString>( |
155 | 0 | "HttpBackgroundChannelChild::RecvOnTransportAndData", |
156 | 0 | this, |
157 | 0 | &HttpBackgroundChannelChild::RecvOnTransportAndData, |
158 | 0 | aChannelStatus, |
159 | 0 | aTransportStatus, |
160 | 0 | aOffset, |
161 | 0 | aCount, |
162 | 0 | aData)); |
163 | 0 |
|
164 | 0 | return IPC_OK(); |
165 | 0 | } |
166 | 0 |
|
167 | 0 | mChannelChild->ProcessOnTransportAndData(aChannelStatus, |
168 | 0 | aTransportStatus, |
169 | 0 | aOffset, |
170 | 0 | aCount, |
171 | 0 | aData); |
172 | 0 |
|
173 | 0 | return IPC_OK(); |
174 | 0 | } |
175 | | |
176 | | IPCResult |
177 | | HttpBackgroundChannelChild::RecvOnStopRequest( |
178 | | const nsresult& aChannelStatus, |
179 | | const ResourceTimingStruct& aTiming, |
180 | | const TimeStamp& aLastActiveTabOptHit, |
181 | | const nsHttpHeaderArray& aResponseTrailers) |
182 | 0 | { |
183 | 0 | LOG(("HttpBackgroundChannelChild::RecvOnStopRequest [this=%p]\n", this)); |
184 | 0 | MOZ_ASSERT(gSocketTransportService); |
185 | 0 | MOZ_ASSERT(gSocketTransportService->IsOnCurrentThreadInfallible()); |
186 | 0 |
|
187 | 0 | // It's enough to set this from (just before) OnStopRequest notification, since |
188 | 0 | // we don't need this value sooner than a channel was done loading - everything |
189 | 0 | // this timestamp affects takes place only after a channel's OnStopRequest. |
190 | 0 | nsHttp::SetLastActiveTabLoadOptimizationHit(aLastActiveTabOptHit); |
191 | 0 |
|
192 | 0 | if (NS_WARN_IF(!mChannelChild)) { |
193 | 0 | return IPC_OK(); |
194 | 0 | } |
195 | 0 |
|
196 | 0 | if (IsWaitingOnStartRequest()) { |
197 | 0 | LOG((" > pending until OnStartRequest [status=%" PRIx32 "]\n", |
198 | 0 | static_cast<uint32_t>(aChannelStatus))); |
199 | 0 |
|
200 | 0 | mQueuedRunnables.AppendElement( |
201 | 0 | NewRunnableMethod<const nsresult, |
202 | 0 | const ResourceTimingStruct, |
203 | 0 | const TimeStamp, |
204 | 0 | const nsHttpHeaderArray>( |
205 | 0 | "HttpBackgroundChannelChild::RecvOnStopRequest", |
206 | 0 | this, |
207 | 0 | &HttpBackgroundChannelChild::RecvOnStopRequest, |
208 | 0 | aChannelStatus, |
209 | 0 | aTiming, |
210 | 0 | aLastActiveTabOptHit, |
211 | 0 | aResponseTrailers)); |
212 | 0 |
|
213 | 0 | return IPC_OK(); |
214 | 0 | } |
215 | 0 |
|
216 | 0 | mChannelChild->ProcessOnStopRequest(aChannelStatus, aTiming, aResponseTrailers); |
217 | 0 |
|
218 | 0 | return IPC_OK(); |
219 | 0 | } |
220 | | |
221 | | IPCResult |
222 | | HttpBackgroundChannelChild::RecvOnProgress(const int64_t& aProgress, |
223 | | const int64_t& aProgressMax) |
224 | 0 | { |
225 | 0 | LOG(("HttpBackgroundChannelChild::RecvOnProgress [this=%p progress=%" |
226 | 0 | PRId64 " max=%" PRId64 "]\n", this, aProgress, aProgressMax)); |
227 | 0 | MOZ_ASSERT(OnSocketThread()); |
228 | 0 |
|
229 | 0 | if (NS_WARN_IF(!mChannelChild)) { |
230 | 0 | return IPC_OK(); |
231 | 0 | } |
232 | 0 |
|
233 | 0 | if (IsWaitingOnStartRequest()) { |
234 | 0 | LOG((" > pending until OnStartRequest [progress=%" PRId64 " max=%" |
235 | 0 | PRId64 "]\n", aProgress, aProgressMax)); |
236 | 0 |
|
237 | 0 | mQueuedRunnables.AppendElement( |
238 | 0 | NewRunnableMethod<const int64_t, const int64_t>( |
239 | 0 | "HttpBackgroundChannelChild::RecvOnProgress", |
240 | 0 | this, |
241 | 0 | &HttpBackgroundChannelChild::RecvOnProgress, |
242 | 0 | aProgress, |
243 | 0 | aProgressMax)); |
244 | 0 |
|
245 | 0 | return IPC_OK(); |
246 | 0 | } |
247 | 0 |
|
248 | 0 | mChannelChild->ProcessOnProgress(aProgress, aProgressMax); |
249 | 0 |
|
250 | 0 | return IPC_OK(); |
251 | 0 | } |
252 | | |
253 | | IPCResult |
254 | | HttpBackgroundChannelChild::RecvOnStatus(const nsresult& aStatus) |
255 | 0 | { |
256 | 0 | LOG(("HttpBackgroundChannelChild::RecvOnStatus [this=%p status=%" |
257 | 0 | PRIx32 "]\n", this, static_cast<uint32_t>(aStatus))); |
258 | 0 | MOZ_ASSERT(OnSocketThread()); |
259 | 0 |
|
260 | 0 | if (NS_WARN_IF(!mChannelChild)) { |
261 | 0 | return IPC_OK(); |
262 | 0 | } |
263 | 0 |
|
264 | 0 | if (IsWaitingOnStartRequest()) { |
265 | 0 | LOG((" > pending until OnStartRequest [status=%" PRIx32 "]\n", |
266 | 0 | static_cast<uint32_t>(aStatus))); |
267 | 0 |
|
268 | 0 | mQueuedRunnables.AppendElement(NewRunnableMethod<const nsresult>( |
269 | 0 | "HttpBackgroundChannelChild::RecvOnStatus", |
270 | 0 | this, |
271 | 0 | &HttpBackgroundChannelChild::RecvOnStatus, |
272 | 0 | aStatus)); |
273 | 0 |
|
274 | 0 | return IPC_OK(); |
275 | 0 | } |
276 | 0 |
|
277 | 0 | mChannelChild->ProcessOnStatus(aStatus); |
278 | 0 |
|
279 | 0 | return IPC_OK(); |
280 | 0 | } |
281 | | |
282 | | IPCResult |
283 | | HttpBackgroundChannelChild::RecvFlushedForDiversion() |
284 | 0 | { |
285 | 0 | LOG(("HttpBackgroundChannelChild::RecvFlushedForDiversion [this=%p]\n", this)); |
286 | 0 | MOZ_ASSERT(OnSocketThread()); |
287 | 0 |
|
288 | 0 | if (NS_WARN_IF(!mChannelChild)) { |
289 | 0 | return IPC_OK(); |
290 | 0 | } |
291 | 0 |
|
292 | 0 | if (IsWaitingOnStartRequest()) { |
293 | 0 | LOG((" > pending until OnStartRequest\n")); |
294 | 0 |
|
295 | 0 | mQueuedRunnables.AppendElement(NewRunnableMethod( |
296 | 0 | "HttpBackgroundChannelChild::RecvFlushedForDiversion", |
297 | 0 | this, |
298 | 0 | &HttpBackgroundChannelChild::RecvFlushedForDiversion)); |
299 | 0 |
|
300 | 0 | return IPC_OK(); |
301 | 0 | } |
302 | 0 |
|
303 | 0 | mChannelChild->ProcessFlushedForDiversion(); |
304 | 0 |
|
305 | 0 | return IPC_OK(); |
306 | 0 | } |
307 | | |
308 | | IPCResult |
309 | | HttpBackgroundChannelChild::RecvDivertMessages() |
310 | 0 | { |
311 | 0 | LOG(("HttpBackgroundChannelChild::RecvDivertMessages [this=%p]\n", this)); |
312 | 0 | MOZ_ASSERT(OnSocketThread()); |
313 | 0 |
|
314 | 0 | if (NS_WARN_IF(!mChannelChild)) { |
315 | 0 | return IPC_OK(); |
316 | 0 | } |
317 | 0 |
|
318 | 0 | if (IsWaitingOnStartRequest()) { |
319 | 0 | LOG((" > pending until OnStartRequest\n")); |
320 | 0 |
|
321 | 0 | mQueuedRunnables.AppendElement( |
322 | 0 | NewRunnableMethod("HttpBackgroundChannelChild::RecvDivertMessages", |
323 | 0 | this, |
324 | 0 | &HttpBackgroundChannelChild::RecvDivertMessages)); |
325 | 0 |
|
326 | 0 | return IPC_OK(); |
327 | 0 | } |
328 | 0 |
|
329 | 0 | mChannelChild->ProcessDivertMessages(); |
330 | 0 |
|
331 | 0 | return IPC_OK(); |
332 | 0 | } |
333 | | |
334 | | IPCResult |
335 | | HttpBackgroundChannelChild::RecvNotifyTrackingProtectionDisabled() |
336 | 0 | { |
337 | 0 | LOG(("HttpBackgroundChannelChild::RecvNotifyTrackingProtectionDisabled [this=%p]\n", this)); |
338 | 0 | MOZ_ASSERT(OnSocketThread()); |
339 | 0 |
|
340 | 0 | if (NS_WARN_IF(!mChannelChild)) { |
341 | 0 | return IPC_OK(); |
342 | 0 | } |
343 | 0 |
|
344 | 0 | // NotifyTrackingProtectionDisabled has no order dependency to OnStartRequest. |
345 | 0 | // It this be handled as soon as possible |
346 | 0 | mChannelChild->ProcessNotifyTrackingProtectionDisabled(); |
347 | 0 |
|
348 | 0 | return IPC_OK(); |
349 | 0 | } |
350 | | |
351 | | IPCResult |
352 | | HttpBackgroundChannelChild::RecvNotifyTrackingCookieBlocked(const uint32_t& aRejectedReason) |
353 | 0 | { |
354 | 0 | LOG(("HttpBackgroundChannelChild::RecvNotifyTrackingCookieBlocked [this=%p]\n", this)); |
355 | 0 | MOZ_ASSERT(OnSocketThread()); |
356 | 0 |
|
357 | 0 | if (NS_WARN_IF(!mChannelChild)) { |
358 | 0 | return IPC_OK(); |
359 | 0 | } |
360 | 0 |
|
361 | 0 | mChannelChild->ProcessNotifyTrackingCookieBlocked(aRejectedReason); |
362 | 0 |
|
363 | 0 | return IPC_OK(); |
364 | 0 | } |
365 | | |
366 | | IPCResult |
367 | | HttpBackgroundChannelChild::RecvNotifyTrackingResource(const bool& aIsThirdParty) |
368 | 0 | { |
369 | 0 | LOG(("HttpBackgroundChannelChild::RecvNotifyTrackingResource thirdparty=%d " |
370 | 0 | "[this=%p]\n", static_cast<int>(aIsThirdParty), this)); |
371 | 0 | MOZ_ASSERT(OnSocketThread()); |
372 | 0 |
|
373 | 0 | if (NS_WARN_IF(!mChannelChild)) { |
374 | 0 | return IPC_OK(); |
375 | 0 | } |
376 | 0 |
|
377 | 0 | // NotifyTrackingResource has no order dependency to OnStartRequest. |
378 | 0 | // It this be handled as soon as possible |
379 | 0 | mChannelChild->ProcessNotifyTrackingResource(aIsThirdParty); |
380 | 0 |
|
381 | 0 | return IPC_OK(); |
382 | 0 | } |
383 | | |
384 | | IPCResult |
385 | | HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo(const ClassifierInfo& info) |
386 | 0 | { |
387 | 0 | LOG(("HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo [this=%p]\n", this)); |
388 | 0 | MOZ_ASSERT(OnSocketThread()); |
389 | 0 |
|
390 | 0 | if (NS_WARN_IF(!mChannelChild)) { |
391 | 0 | return IPC_OK(); |
392 | 0 | } |
393 | 0 |
|
394 | 0 | // SetClassifierMatchedInfo has no order dependency to OnStartRequest. |
395 | 0 | // It this be handled as soon as possible |
396 | 0 | mChannelChild->ProcessSetClassifierMatchedInfo(info.list(), |
397 | 0 | info.provider(), |
398 | 0 | info.fullhash()); |
399 | 0 |
|
400 | 0 | return IPC_OK(); |
401 | 0 | } |
402 | | |
403 | | void |
404 | | HttpBackgroundChannelChild::ActorDestroy(ActorDestroyReason aWhy) |
405 | 0 | { |
406 | 0 | LOG(("HttpBackgroundChannelChild::ActorDestroy[this=%p]\n", this)); |
407 | 0 | // This function might be called during shutdown phase, so OnSocketThread() |
408 | 0 | // might return false even on STS thread. Use IsOnCurrentThreadInfallible() |
409 | 0 | // to get correct information. |
410 | 0 | MOZ_ASSERT(gSocketTransportService); |
411 | 0 | MOZ_ASSERT(gSocketTransportService->IsOnCurrentThreadInfallible()); |
412 | 0 |
|
413 | 0 | // Ensure all IPC messages received before ActorDestroy can be |
414 | 0 | // handled correctly. If there is any pending IPC message, destroyed |
415 | 0 | // mChannelChild until those messages are flushed. |
416 | 0 | // If background channel is not closed by normal IPDL actor deletion, |
417 | 0 | // remove the HttpChannelChild reference and notify background channel |
418 | 0 | // destroyed immediately. |
419 | 0 | if (aWhy == Deletion && !mQueuedRunnables.IsEmpty()) { |
420 | 0 | LOG((" > pending until queued messages are flushed\n")); |
421 | 0 | RefPtr<HttpBackgroundChannelChild> self = this; |
422 | 0 | mQueuedRunnables.AppendElement(NS_NewRunnableFunction( |
423 | 0 | "HttpBackgroundChannelChild::ActorDestroy", [self]() { |
424 | 0 | MOZ_ASSERT(OnSocketThread()); |
425 | 0 | RefPtr<HttpChannelChild> channelChild = self->mChannelChild.forget(); |
426 | 0 |
|
427 | 0 | if (channelChild) { |
428 | 0 | channelChild->OnBackgroundChildDestroyed(self); |
429 | 0 | } |
430 | 0 | })); |
431 | 0 | return; |
432 | 0 | } |
433 | 0 |
|
434 | 0 | if (mChannelChild) { |
435 | 0 | RefPtr<HttpChannelChild> channelChild = mChannelChild.forget(); |
436 | 0 |
|
437 | 0 | channelChild->OnBackgroundChildDestroyed(this); |
438 | 0 | } |
439 | 0 | } |
440 | | |
441 | | } // namespace net |
442 | | } // namespace mozilla |