Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/protocol/http/HttpBackgroundChannelParent.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 "HttpBackgroundChannelParent.h"
12
13
#include "HttpChannelParent.h"
14
#include "mozilla/ipc/BackgroundParent.h"
15
#include "mozilla/IntegerPrintfMacros.h"
16
#include "mozilla/Unused.h"
17
#include "nsIBackgroundChannelRegistrar.h"
18
#include "nsNetCID.h"
19
#include "nsQueryObject.h"
20
#include "nsThreadUtils.h"
21
22
using mozilla::dom::ContentParent;
23
using mozilla::ipc::AssertIsInMainProcess;
24
using mozilla::ipc::AssertIsOnBackgroundThread;
25
using mozilla::ipc::BackgroundParent;
26
using mozilla::ipc::IPCResult;
27
using mozilla::ipc::IsOnBackgroundThread;
28
29
namespace mozilla {
30
namespace net {
31
32
/*
33
 * Helper class for continuing the AsyncOpen procedure on main thread.
34
 */
35
class ContinueAsyncOpenRunnable final : public Runnable
36
{
37
public:
38
  ContinueAsyncOpenRunnable(HttpBackgroundChannelParent* aActor,
39
                            const uint64_t& aChannelId)
40
    : Runnable("net::ContinueAsyncOpenRunnable")
41
    , mActor(aActor)
42
    , mChannelId(aChannelId)
43
0
  {
44
0
    AssertIsInMainProcess();
45
0
    AssertIsOnBackgroundThread();
46
0
    MOZ_ASSERT(mActor);
47
0
  }
48
49
  NS_IMETHOD Run() override
50
0
  {
51
0
    LOG(("HttpBackgroundChannelParent::ContinueAsyncOpen [this=%p channelId=%"
52
0
         PRIu64 "]\n", mActor.get(), mChannelId));
53
0
    AssertIsInMainProcess();
54
0
    MOZ_ASSERT(NS_IsMainThread());
55
0
56
0
    nsCOMPtr<nsIBackgroundChannelRegistrar> registrar =
57
0
      do_GetService(NS_BACKGROUNDCHANNELREGISTRAR_CONTRACTID);
58
0
    MOZ_ASSERT(registrar);
59
0
60
0
    registrar->LinkBackgroundChannel(mChannelId, mActor);
61
0
    return NS_OK;
62
0
  }
63
64
private:
65
  RefPtr<HttpBackgroundChannelParent> mActor;
66
  const uint64_t mChannelId;
67
};
68
69
HttpBackgroundChannelParent::HttpBackgroundChannelParent()
70
  : mIPCOpened(true)
71
  , mBgThreadMutex("HttpBackgroundChannelParent::BgThreadMutex")
72
0
{
73
0
  AssertIsInMainProcess();
74
0
  AssertIsOnBackgroundThread();
75
0
76
0
  {
77
0
    MutexAutoLock lock(mBgThreadMutex);
78
0
    mBackgroundThread = NS_GetCurrentThread();
79
0
  }
80
0
}
81
82
HttpBackgroundChannelParent::~HttpBackgroundChannelParent()
83
0
{
84
0
  MOZ_ASSERT(NS_IsMainThread() || IsOnBackgroundThread());
85
0
  MOZ_ASSERT(!mIPCOpened);
86
0
}
87
88
nsresult
89
HttpBackgroundChannelParent::Init(const uint64_t& aChannelId)
90
0
{
91
0
  LOG(("HttpBackgroundChannelParent::Init [this=%p channelId=%" PRIu64 "]\n",
92
0
       this, aChannelId));
93
0
  AssertIsInMainProcess();
94
0
  AssertIsOnBackgroundThread();
95
0
96
0
  RefPtr<ContinueAsyncOpenRunnable> runnable =
97
0
    new ContinueAsyncOpenRunnable(this, aChannelId);
98
0
99
0
  return NS_DispatchToMainThread(runnable);
100
0
}
101
102
void
103
HttpBackgroundChannelParent::LinkToChannel(HttpChannelParent* aChannelParent)
104
0
{
105
0
  LOG(("HttpBackgroundChannelParent::LinkToChannel [this=%p channel=%p]\n",
106
0
       this, aChannelParent));
107
0
  AssertIsInMainProcess();
108
0
  MOZ_ASSERT(NS_IsMainThread());
109
0
110
0
  if (!mIPCOpened) {
111
0
    return;
112
0
  }
113
0
114
0
  mChannelParent = aChannelParent;
115
0
}
116
117
void
118
HttpBackgroundChannelParent::OnChannelClosed()
119
0
{
120
0
  LOG(("HttpBackgroundChannelParent::OnChannelClosed [this=%p]\n", this));
121
0
  AssertIsInMainProcess();
122
0
  MOZ_ASSERT(NS_IsMainThread());
123
0
124
0
  if (!mIPCOpened) {
125
0
    return;
126
0
  }
127
0
128
0
  nsresult rv;
129
0
130
0
  {
131
0
    MutexAutoLock lock(mBgThreadMutex);
132
0
    RefPtr<HttpBackgroundChannelParent> self = this;
133
0
    rv = mBackgroundThread->Dispatch(
134
0
      NS_NewRunnableFunction(
135
0
        "net::HttpBackgroundChannelParent::OnChannelClosed",
136
0
        [self]() {
137
0
          LOG(("HttpBackgroundChannelParent::DeleteRunnable [this=%p]\n",
138
0
               self.get()));
139
0
          AssertIsOnBackgroundThread();
140
0
141
0
          if (!self->mIPCOpened.compareExchange(true, false)) {
142
0
            return;
143
0
          }
144
0
145
0
          Unused << self->Send__delete__(self);
146
0
        }),
147
0
      NS_DISPATCH_NORMAL);
148
0
  }
149
0
150
0
  Unused << NS_WARN_IF(NS_FAILED(rv));
151
0
}
152
153
bool
154
HttpBackgroundChannelParent::OnStartRequestSent()
155
0
{
156
0
  LOG(("HttpBackgroundChannelParent::OnStartRequestSent [this=%p]\n", this));
157
0
  AssertIsInMainProcess();
158
0
159
0
  if (NS_WARN_IF(!mIPCOpened)) {
160
0
    return false;
161
0
  }
162
0
163
0
  if (!IsOnBackgroundThread()) {
164
0
    MutexAutoLock lock(mBgThreadMutex);
165
0
    nsresult rv = mBackgroundThread->Dispatch(
166
0
      NewRunnableMethod("net::HttpBackgroundChannelParent::OnStartRequestSent",
167
0
                        this,
168
0
                        &HttpBackgroundChannelParent::OnStartRequestSent),
169
0
      NS_DISPATCH_NORMAL);
170
0
171
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
172
0
173
0
    return NS_SUCCEEDED(rv);
174
0
  }
175
0
176
0
  return SendOnStartRequestSent();
177
0
}
178
179
bool
180
HttpBackgroundChannelParent::OnTransportAndData(
181
                                               const nsresult& aChannelStatus,
182
                                               const nsresult& aTransportStatus,
183
                                               const uint64_t& aOffset,
184
                                               const uint32_t& aCount,
185
                                               const nsCString& aData)
186
0
{
187
0
  LOG(("HttpBackgroundChannelParent::OnTransportAndData [this=%p]\n", this));
188
0
  AssertIsInMainProcess();
189
0
190
0
  if (NS_WARN_IF(!mIPCOpened)) {
191
0
    return false;
192
0
  }
193
0
194
0
  if (!IsOnBackgroundThread()) {
195
0
    MutexAutoLock lock(mBgThreadMutex);
196
0
    nsresult rv = mBackgroundThread->Dispatch(
197
0
      NewRunnableMethod<const nsresult,
198
0
                        const nsresult,
199
0
                        const uint64_t,
200
0
                        const uint32_t,
201
0
                        const nsCString>(
202
0
        "net::HttpBackgroundChannelParent::OnTransportAndData",
203
0
        this,
204
0
        &HttpBackgroundChannelParent::OnTransportAndData,
205
0
        aChannelStatus,
206
0
        aTransportStatus,
207
0
        aOffset,
208
0
        aCount,
209
0
        aData),
210
0
      NS_DISPATCH_NORMAL);
211
0
212
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
213
0
214
0
    return NS_SUCCEEDED(rv);
215
0
  }
216
0
217
0
  return SendOnTransportAndData(aChannelStatus, aTransportStatus,
218
0
                                aOffset, aCount, aData);
219
0
}
220
221
bool
222
HttpBackgroundChannelParent::OnStopRequest(const nsresult& aChannelStatus,
223
                                           const ResourceTimingStruct& aTiming,
224
                                           const nsHttpHeaderArray& aResponseTrailers)
225
0
{
226
0
  LOG(("HttpBackgroundChannelParent::OnStopRequest [this=%p "
227
0
        "status=%" PRIx32 "]\n", this, static_cast<uint32_t>(aChannelStatus)));
228
0
  AssertIsInMainProcess();
229
0
230
0
  if (NS_WARN_IF(!mIPCOpened)) {
231
0
    return false;
232
0
  }
233
0
234
0
  if (!IsOnBackgroundThread()) {
235
0
    MutexAutoLock lock(mBgThreadMutex);
236
0
    nsresult rv = mBackgroundThread->Dispatch(
237
0
      NewRunnableMethod<const nsresult,
238
0
                        const ResourceTimingStruct,
239
0
                        const nsHttpHeaderArray>(
240
0
        "net::HttpBackgroundChannelParent::OnStopRequest",
241
0
        this,
242
0
        &HttpBackgroundChannelParent::OnStopRequest,
243
0
        aChannelStatus,
244
0
        aTiming,
245
0
        aResponseTrailers),
246
0
      NS_DISPATCH_NORMAL);
247
0
248
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
249
0
250
0
    return NS_SUCCEEDED(rv);
251
0
  }
252
0
253
0
  // See the child code for why we do this.
254
0
  TimeStamp lastActTabOpt = nsHttp::GetLastActiveTabLoadOptimizationHit();
255
0
256
0
  return SendOnStopRequest(aChannelStatus, aTiming, lastActTabOpt, aResponseTrailers);
257
0
}
258
259
bool
260
HttpBackgroundChannelParent::OnProgress(const int64_t& aProgress,
261
                                        const int64_t& aProgressMax)
262
0
{
263
0
  LOG(("HttpBackgroundChannelParent::OnProgress [this=%p progress=%" PRId64
264
0
       " max=%" PRId64 "]\n", this, aProgress, aProgressMax));
265
0
  AssertIsInMainProcess();
266
0
267
0
  if (NS_WARN_IF(!mIPCOpened)) {
268
0
    return false;
269
0
  }
270
0
271
0
  if (!IsOnBackgroundThread()) {
272
0
    MutexAutoLock lock(mBgThreadMutex);
273
0
    nsresult rv = mBackgroundThread->Dispatch(
274
0
      NewRunnableMethod<const int64_t, const int64_t>(
275
0
        "net::HttpBackgroundChannelParent::OnProgress",
276
0
        this,
277
0
        &HttpBackgroundChannelParent::OnProgress,
278
0
        aProgress,
279
0
        aProgressMax),
280
0
      NS_DISPATCH_NORMAL);
281
0
282
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
283
0
284
0
    return NS_SUCCEEDED(rv);
285
0
  }
286
0
287
0
  return SendOnProgress(aProgress, aProgressMax);
288
0
}
289
290
bool
291
HttpBackgroundChannelParent::OnStatus(const nsresult& aStatus)
292
0
{
293
0
  LOG(("HttpBackgroundChannelParent::OnStatus [this=%p stauts=%" PRIx32
294
0
       "]\n", this, static_cast<uint32_t>(aStatus)));
295
0
  AssertIsInMainProcess();
296
0
297
0
  if (NS_WARN_IF(!mIPCOpened)) {
298
0
    return false;
299
0
  }
300
0
301
0
  if (!IsOnBackgroundThread()) {
302
0
    MutexAutoLock lock(mBgThreadMutex);
303
0
    nsresult rv = mBackgroundThread->Dispatch(
304
0
      NewRunnableMethod<const nsresult>(
305
0
        "net::HttpBackgroundChannelParent::OnStatus",
306
0
        this,
307
0
        &HttpBackgroundChannelParent::OnStatus,
308
0
        aStatus),
309
0
      NS_DISPATCH_NORMAL);
310
0
311
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
312
0
313
0
    return NS_SUCCEEDED(rv);
314
0
  }
315
0
316
0
  return SendOnStatus(aStatus);
317
0
}
318
319
bool
320
HttpBackgroundChannelParent::OnDiversion()
321
0
{
322
0
  LOG(("HttpBackgroundChannelParent::OnDiversion [this=%p]\n", this));
323
0
  AssertIsInMainProcess();
324
0
325
0
  if (NS_WARN_IF(!mIPCOpened)) {
326
0
    return false;
327
0
  }
328
0
329
0
  if (!IsOnBackgroundThread()) {
330
0
    MutexAutoLock lock(mBgThreadMutex);
331
0
    nsresult rv = mBackgroundThread->Dispatch(
332
0
      NewRunnableMethod("net::HttpBackgroundChannelParent::OnDiversion",
333
0
                        this,
334
0
                        &HttpBackgroundChannelParent::OnDiversion),
335
0
      NS_DISPATCH_NORMAL);
336
0
337
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
338
0
339
0
    return NS_SUCCEEDED(rv);
340
0
  }
341
0
342
0
  if (!SendFlushedForDiversion()) {
343
0
    return false;
344
0
  }
345
0
346
0
  // The listener chain should now be setup; tell HttpChannelChild to divert
347
0
  // the OnDataAvailables and OnStopRequest to associated HttpChannelParent.
348
0
  if (!SendDivertMessages()) {
349
0
    return false;
350
0
  }
351
0
352
0
  return true;
353
0
}
354
355
bool
356
HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled()
357
0
{
358
0
  LOG(("HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled [this=%p]\n", this));
359
0
  AssertIsInMainProcess();
360
0
361
0
  if (NS_WARN_IF(!mIPCOpened)) {
362
0
    return false;
363
0
  }
364
0
365
0
  if (!IsOnBackgroundThread()) {
366
0
    MutexAutoLock lock(mBgThreadMutex);
367
0
    nsresult rv = mBackgroundThread->Dispatch(
368
0
      NewRunnableMethod(
369
0
        "net::HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled",
370
0
        this,
371
0
        &HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled),
372
0
      NS_DISPATCH_NORMAL);
373
0
374
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
375
0
376
0
    return NS_SUCCEEDED(rv);
377
0
  }
378
0
379
0
  return SendNotifyTrackingProtectionDisabled();
380
0
}
381
382
bool
383
HttpBackgroundChannelParent::OnNotifyTrackingCookieBlocked(uint32_t aRejectedReason)
384
0
{
385
0
  LOG(("HttpBackgroundChannelParent::OnNotifyTrackingCookieBlocked [this=%p]\n", this));
386
0
  AssertIsInMainProcess();
387
0
388
0
  if (NS_WARN_IF(!mIPCOpened)) {
389
0
    return false;
390
0
  }
391
0
392
0
  if (!IsOnBackgroundThread()) {
393
0
    MutexAutoLock lock(mBgThreadMutex);
394
0
    RefPtr<HttpBackgroundChannelParent> self = this;
395
0
    nsresult rv = mBackgroundThread->Dispatch(
396
0
      NS_NewRunnableFunction(
397
0
        "net::HttpBackgroundChannelParent::OnNotifyTrackingCookieBlocked",
398
0
        [self, aRejectedReason]() {
399
0
          self->OnNotifyTrackingCookieBlocked(aRejectedReason);
400
0
        }),
401
0
      NS_DISPATCH_NORMAL);
402
0
403
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
404
0
405
0
    return NS_SUCCEEDED(rv);
406
0
  }
407
0
408
0
  return SendNotifyTrackingCookieBlocked(aRejectedReason);
409
0
}
410
411
bool
412
HttpBackgroundChannelParent::OnNotifyTrackingResource(bool aIsThirdParty)
413
0
{
414
0
  LOG(("HttpBackgroundChannelParent::OnNotifyTrackingResource thirdparty=%d "
415
0
       "[this=%p]\n", static_cast<int>(aIsThirdParty), this));
416
0
  AssertIsInMainProcess();
417
0
418
0
  if (NS_WARN_IF(!mIPCOpened)) {
419
0
    return false;
420
0
  }
421
0
422
0
  if (!IsOnBackgroundThread()) {
423
0
    MutexAutoLock lock(mBgThreadMutex);
424
0
    nsresult rv = mBackgroundThread->Dispatch(
425
0
      NewRunnableMethod<bool>(
426
0
        "net::HttpBackgroundChannelParent::OnNotifyTrackingResource",
427
0
        this,
428
0
        &HttpBackgroundChannelParent::OnNotifyTrackingResource,
429
0
        aIsThirdParty),
430
0
      NS_DISPATCH_NORMAL);
431
0
432
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
433
0
434
0
    return NS_SUCCEEDED(rv);
435
0
  }
436
0
437
0
  return SendNotifyTrackingResource(aIsThirdParty);
438
0
}
439
440
bool
441
HttpBackgroundChannelParent::OnSetClassifierMatchedInfo(const nsACString& aList,
442
                                                        const nsACString& aProvider,
443
                                                        const nsACString& aFullHash)
444
0
{
445
0
  LOG(("HttpBackgroundChannelParent::OnSetClassifierMatchedInfo [this=%p]\n", this));
446
0
  AssertIsInMainProcess();
447
0
448
0
  if (NS_WARN_IF(!mIPCOpened)) {
449
0
    return false;
450
0
  }
451
0
452
0
  if (!IsOnBackgroundThread()) {
453
0
    MutexAutoLock lock(mBgThreadMutex);
454
0
    nsresult rv = mBackgroundThread->Dispatch(
455
0
      NewRunnableMethod<const nsCString, const nsCString, const nsCString>(
456
0
        "net::HttpBackgroundChannelParent::OnSetClassifierMatchedInfo",
457
0
        this,
458
0
        &HttpBackgroundChannelParent::OnSetClassifierMatchedInfo,
459
0
        aList,
460
0
        aProvider,
461
0
        aFullHash),
462
0
      NS_DISPATCH_NORMAL);
463
0
464
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
465
0
466
0
    return NS_SUCCEEDED(rv);
467
0
  }
468
0
469
0
  ClassifierInfo info;
470
0
  info.list() = aList;
471
0
  info.fullhash() = aFullHash;
472
0
  info.provider() = aProvider;
473
0
474
0
  return SendSetClassifierMatchedInfo(info);
475
0
}
476
477
void
478
HttpBackgroundChannelParent::ActorDestroy(ActorDestroyReason aWhy)
479
0
{
480
0
  LOG(("HttpBackgroundChannelParent::ActorDestroy [this=%p]\n", this));
481
0
  AssertIsInMainProcess();
482
0
  AssertIsOnBackgroundThread();
483
0
484
0
  mIPCOpened = false;
485
0
486
0
  RefPtr<HttpBackgroundChannelParent> self = this;
487
0
  DebugOnly<nsresult> rv = NS_DispatchToMainThread(NS_NewRunnableFunction(
488
0
    "net::HttpBackgroundChannelParent::ActorDestroy", [self]() {
489
0
      MOZ_ASSERT(NS_IsMainThread());
490
0
491
0
      RefPtr<HttpChannelParent> channelParent =
492
0
        self->mChannelParent.forget();
493
0
494
0
      if (channelParent) {
495
0
        channelParent->OnBackgroundParentDestroyed();
496
0
      }
497
0
    }));
498
0
  MOZ_ASSERT(NS_SUCCEEDED(rv));
499
0
}
500
501
} // namespace net
502
} // namespace mozilla