Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/cache/CacheStreamControlChild.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 ts=8 sts=2 et sw=2 tw=80: */
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 "mozilla/dom/cache/CacheStreamControlChild.h"
8
9
#include "mozilla/Unused.h"
10
#include "mozilla/dom/cache/ActorUtils.h"
11
#include "mozilla/dom/cache/CacheTypes.h"
12
#include "mozilla/dom/cache/CacheWorkerHolder.h"
13
#include "mozilla/dom/cache/ReadStream.h"
14
#include "mozilla/ipc/FileDescriptorSetChild.h"
15
#include "mozilla/ipc/IPCStreamUtils.h"
16
#include "mozilla/ipc/PBackgroundChild.h"
17
#include "mozilla/ipc/PFileDescriptorSetChild.h"
18
#include "nsISupportsImpl.h"
19
20
namespace mozilla {
21
namespace dom {
22
namespace cache {
23
24
using mozilla::dom::OptionalFileDescriptorSet;
25
using mozilla::ipc::AutoIPCStream;
26
using mozilla::ipc::FileDescriptor;
27
using mozilla::ipc::FileDescriptorSetChild;
28
using mozilla::ipc::PFileDescriptorSetChild;
29
30
// declared in ActorUtils.h
31
PCacheStreamControlChild*
32
AllocPCacheStreamControlChild()
33
0
{
34
0
  return new CacheStreamControlChild();
35
0
}
36
37
// declared in ActorUtils.h
38
void
39
DeallocPCacheStreamControlChild(PCacheStreamControlChild* aActor)
40
0
{
41
0
  delete aActor;
42
0
}
43
44
CacheStreamControlChild::CacheStreamControlChild()
45
  : mDestroyStarted(false)
46
  , mDestroyDelayed(false)
47
0
{
48
0
  MOZ_COUNT_CTOR(cache::CacheStreamControlChild);
49
0
}
50
51
CacheStreamControlChild::~CacheStreamControlChild()
52
0
{
53
0
  NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
54
0
  MOZ_COUNT_DTOR(cache::CacheStreamControlChild);
55
0
}
56
57
void
58
CacheStreamControlChild::StartDestroy()
59
0
{
60
0
  NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
61
0
  // This can get called twice under some circumstances.  For example, if the
62
0
  // actor is added to a CacheWorkerHolder that has already been notified and
63
0
  // the Cache actor has no mListener.
64
0
  if (mDestroyStarted) {
65
0
    return;
66
0
  }
67
0
  mDestroyStarted = true;
68
0
69
0
  // If any of the streams have started to be read, then wait for them to close
70
0
  // naturally.
71
0
  if (HasEverBeenRead()) {
72
0
    // Note that we are delaying so that we can re-check for active streams
73
0
    // in NoteClosedAfterForget().
74
0
    mDestroyDelayed = true;
75
0
    return;
76
0
  }
77
0
78
0
  // Otherwise, if the streams have not been touched then just pre-emptively
79
0
  // close them now.  This handles the case where someone retrieves a Response
80
0
  // from the Cache, but never accesses the body.  We should not keep the
81
0
  // Worker alive until that Response is GC'd just because of its ignored
82
0
  // body stream.
83
0
84
0
  // Begin shutting down all streams.  This is the same as if the parent had
85
0
  // asked us to shutdown.  So simulate the CloseAll IPC message.
86
0
  RecvCloseAll();
87
0
}
88
89
void
90
CacheStreamControlChild::SerializeControl(CacheReadStream* aReadStreamOut)
91
0
{
92
0
  NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
93
0
  MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
94
0
  aReadStreamOut->controlParent() = nullptr;
95
0
  aReadStreamOut->controlChild() = this;
96
0
}
97
98
void
99
CacheStreamControlChild::SerializeStream(CacheReadStream* aReadStreamOut,
100
                                         nsIInputStream* aStream,
101
                                         nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList)
102
0
{
103
0
  NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
104
0
  MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
105
0
  UniquePtr<AutoIPCStream> autoStream(new AutoIPCStream(aReadStreamOut->stream()));
106
0
  autoStream->Serialize(aStream, Manager());
107
0
  aStreamCleanupList.AppendElement(std::move(autoStream));
108
0
}
109
110
void
111
CacheStreamControlChild::OpenStream(const nsID& aId, InputStreamResolver&& aResolver)
112
0
{
113
0
  NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
114
0
115
0
  if (mDestroyStarted) {
116
0
    aResolver(nullptr);
117
0
    return;
118
0
  }
119
0
120
0
  // If we are on a worker, then we need to hold it alive until the async
121
0
  // IPC operation below completes.  While the IPC layer will trigger a
122
0
  // rejection here in many cases, we must handle the case where the
123
0
  // MozPromise resolve runnable is already in the event queue when the
124
0
  // worker wants to shut down.
125
0
  RefPtr<CacheWorkerHolder> holder = GetWorkerHolder();
126
0
127
0
  SendOpenStream(aId)->Then(GetCurrentThreadSerialEventTarget(), __func__,
128
0
  [aResolver, holder](const RefPtr<nsIInputStream>& aOptionalStream) {
129
0
    aResolver(nsCOMPtr<nsIInputStream>(aOptionalStream));
130
0
  }, [aResolver, holder](ResponseRejectReason aReason) {
131
0
    aResolver(nullptr);
132
0
  });
133
0
}
134
135
void
136
CacheStreamControlChild::NoteClosedAfterForget(const nsID& aId)
137
0
{
138
0
  NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
139
0
  Unused << SendNoteClosed(aId);
140
0
141
0
  // A stream has closed.  If we delayed StartDestry() due to this stream
142
0
  // being read, then we should check to see if any of the remaining streams
143
0
  // are active.  If none of our other streams have been read, then we can
144
0
  // proceed with the shutdown now.
145
0
  if (mDestroyDelayed && !HasEverBeenRead()) {
146
0
    mDestroyDelayed = false;
147
0
    RecvCloseAll();
148
0
  }
149
0
}
150
151
#ifdef DEBUG
152
void
153
CacheStreamControlChild::AssertOwningThread()
154
{
155
  NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
156
}
157
#endif
158
159
void
160
CacheStreamControlChild::ActorDestroy(ActorDestroyReason aReason)
161
0
{
162
0
  NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
163
0
  CloseAllReadStreamsWithoutReporting();
164
0
  RemoveWorkerHolder();
165
0
}
166
167
mozilla::ipc::IPCResult
168
CacheStreamControlChild::RecvClose(const nsID& aId)
169
0
{
170
0
  NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
171
0
  CloseReadStreams(aId);
172
0
  return IPC_OK();
173
0
}
174
175
mozilla::ipc::IPCResult
176
CacheStreamControlChild::RecvCloseAll()
177
0
{
178
0
  NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
179
0
  CloseAllReadStreams();
180
0
  return IPC_OK();
181
0
}
182
183
} // namespace cache
184
} // namespace dom
185
} // namespace mozilla