Coverage Report

Created: 2018-09-25 14:53

/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