Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/ipc/ContentProcessManager.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 file,
5
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "ContentProcessManager.h"
8
#include "ContentParent.h"
9
#include "mozilla/dom/TabParent.h"
10
11
#include "mozilla/StaticPtr.h"
12
#include "mozilla/ClearOnShutdown.h"
13
14
#include "nsPrintfCString.h"
15
#include "nsIScriptSecurityManager.h"
16
17
// XXX need another bug to move this to a common header.
18
#ifdef DISABLE_ASSERTS_FOR_FUZZING
19
#define ASSERT_UNLESS_FUZZING(...) do { } while (0)
20
#else
21
0
#define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
22
#endif
23
24
namespace mozilla {
25
namespace dom {
26
27
/* static */
28
StaticAutoPtr<ContentProcessManager>
29
ContentProcessManager::sSingleton;
30
31
/* static */ ContentProcessManager*
32
ContentProcessManager::GetSingleton()
33
0
{
34
0
  MOZ_ASSERT(XRE_IsParentProcess());
35
0
36
0
  if (!sSingleton) {
37
0
    sSingleton = new ContentProcessManager();
38
0
    ClearOnShutdown(&sSingleton);
39
0
  }
40
0
  return sSingleton;
41
0
}
42
43
void
44
ContentProcessManager::AddContentProcess(ContentParent* aChildCp,
45
                                         const ContentParentId& aParentCpId)
46
0
{
47
0
  MOZ_ASSERT(NS_IsMainThread());
48
0
  MOZ_ASSERT(aChildCp);
49
0
50
0
  ContentProcessInfo& info = mContentParentMap[aChildCp->ChildID()];
51
0
  if (!info.mCp) {
52
0
    info.mCp = aChildCp;
53
0
  } else {
54
0
    MOZ_ASSERT(info.mCp == aChildCp);
55
0
    MOZ_ASSERT_IF(!!info.mParentCpId, info.mParentCpId == aParentCpId);
56
0
  }
57
0
  info.mParentCpId = aParentCpId;
58
0
}
59
60
void
61
ContentProcessManager::RemoveContentProcess(const ContentParentId& aChildCpId)
62
0
{
63
0
  MOZ_ASSERT(NS_IsMainThread());
64
0
  MOZ_ASSERT(mContentParentMap.find(aChildCpId) != mContentParentMap.end());
65
0
66
0
  mContentParentMap.erase(aChildCpId);
67
0
  for (auto iter = mContentParentMap.begin();
68
0
       iter != mContentParentMap.end();
69
0
       ++iter) {
70
0
    if (!iter->second.mChildrenCpId.empty()) {
71
0
      iter->second.mChildrenCpId.erase(aChildCpId);
72
0
    }
73
0
  }
74
0
}
75
76
bool
77
ContentProcessManager::AddGrandchildProcess(const ContentParentId& aParentCpId,
78
                                            const ContentParentId& aChildCpId)
79
0
{
80
0
  MOZ_ASSERT(NS_IsMainThread());
81
0
82
0
  auto iter = mContentParentMap.find(aParentCpId);
83
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
84
0
    ASSERT_UNLESS_FUZZING("Parent process should be already in map!");
85
0
    return false;
86
0
  }
87
0
  iter->second.mChildrenCpId.insert(aChildCpId);
88
0
  return true;
89
0
}
90
91
bool
92
ContentProcessManager::GetParentProcessId(const ContentParentId& aChildCpId,
93
                                          /*out*/ ContentParentId* aParentCpId)
94
0
{
95
0
  MOZ_ASSERT(NS_IsMainThread());
96
0
97
0
  auto iter = mContentParentMap.find(aChildCpId);
98
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
99
0
    ASSERT_UNLESS_FUZZING();
100
0
    return false;
101
0
  }
102
0
  *aParentCpId = iter->second.mParentCpId;
103
0
  return true;
104
0
}
105
106
ContentParent*
107
ContentProcessManager::GetContentProcessById(const ContentParentId& aChildCpId)
108
0
{
109
0
  MOZ_ASSERT(NS_IsMainThread());
110
0
111
0
  auto iter = mContentParentMap.find(aChildCpId);
112
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
113
0
    ASSERT_UNLESS_FUZZING();
114
0
    return nullptr;
115
0
  }
116
0
  return iter->second.mCp;
117
0
}
118
119
nsTArray<ContentParentId>
120
ContentProcessManager::GetAllChildProcessById(const ContentParentId& aParentCpId)
121
0
{
122
0
  MOZ_ASSERT(NS_IsMainThread());
123
0
124
0
  nsTArray<ContentParentId> cpIdArray;
125
0
  auto iter = mContentParentMap.find(aParentCpId);
126
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
127
0
    ASSERT_UNLESS_FUZZING();
128
0
    return cpIdArray;
129
0
  }
130
0
131
0
  for (auto cpIter = iter->second.mChildrenCpId.begin();
132
0
       cpIter != iter->second.mChildrenCpId.end();
133
0
       ++cpIter) {
134
0
    cpIdArray.AppendElement(*cpIter);
135
0
  }
136
0
137
0
  return cpIdArray;
138
0
}
139
140
bool
141
ContentProcessManager::RegisterRemoteFrame(const TabId& aTabId,
142
                                           const ContentParentId& aOpenerCpId,
143
                                           const TabId& aOpenerTabId,
144
                                           const IPCTabContext& aContext,
145
                                           const ContentParentId& aChildCpId)
146
0
{
147
0
  MOZ_ASSERT(NS_IsMainThread());
148
0
149
0
  auto iter = mContentParentMap.find(aChildCpId);
150
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
151
0
    ASSERT_UNLESS_FUZZING();
152
0
    return false;
153
0
  }
154
0
155
0
  struct RemoteFrameInfo info;
156
0
157
0
  // If it's a PopupIPCTabContext, it's the case that a TabChild want to
158
0
  // open a new tab. aOpenerTabId has to be it's parent frame's opener id.
159
0
  if (aContext.type() == IPCTabContext::TPopupIPCTabContext) {
160
0
    auto remoteFrameIter = iter->second.mRemoteFrames.find(aOpenerTabId);
161
0
    if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
162
0
      ASSERT_UNLESS_FUZZING("Failed to find parent frame's opener id.");
163
0
      return false;
164
0
    }
165
0
166
0
    info.mOpenerCpId = remoteFrameIter->second.mOpenerCpId;
167
0
    info.mOpenerTabId = remoteFrameIter->second.mOpenerTabId;
168
0
    info.mContext = remoteFrameIter->second.mContext;
169
0
  }
170
0
  else {
171
0
    MaybeInvalidTabContext tc(aContext);
172
0
    if (!tc.IsValid()) {
173
0
      NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
174
0
                               "the child process. (%s)",
175
0
                               tc.GetInvalidReason()).get());
176
0
      return false;
177
0
    }
178
0
    info.mOpenerCpId = aOpenerCpId;
179
0
    info.mOpenerTabId = aOpenerTabId;
180
0
    info.mContext = tc.GetTabContext();
181
0
  }
182
0
183
0
  iter->second.mRemoteFrames[aTabId] = info;
184
0
  return true;
185
0
}
186
187
void
188
ContentProcessManager::UnregisterRemoteFrame(const ContentParentId& aChildCpId,
189
                                             const TabId& aChildTabId)
190
0
{
191
0
  MOZ_ASSERT(NS_IsMainThread());
192
0
193
0
  auto iter = mContentParentMap.find(aChildCpId);
194
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
195
0
    ASSERT_UNLESS_FUZZING();
196
0
    return;
197
0
  }
198
0
199
0
  auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
200
0
  if (remoteFrameIter != iter->second.mRemoteFrames.end()) {
201
0
    iter->second.mRemoteFrames.erase(aChildTabId);
202
0
  }
203
0
}
204
205
bool
206
ContentProcessManager::GetTabContextByProcessAndTabId(const ContentParentId& aChildCpId,
207
                                                      const TabId& aChildTabId,
208
                                                      /*out*/ TabContext* aTabContext)
209
0
{
210
0
  MOZ_ASSERT(NS_IsMainThread());
211
0
  MOZ_ASSERT(aTabContext);
212
0
213
0
  auto iter = mContentParentMap.find(aChildCpId);
214
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
215
0
    ASSERT_UNLESS_FUZZING();
216
0
    return false;
217
0
  }
218
0
219
0
  auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
220
0
  if (NS_WARN_IF(remoteFrameIter == iter->second.mRemoteFrames.end())) {
221
0
    ASSERT_UNLESS_FUZZING();
222
0
    return false;
223
0
  }
224
0
225
0
  *aTabContext = remoteFrameIter->second.mContext;
226
0
227
0
  return true;
228
0
}
229
230
nsTArray<TabContext>
231
ContentProcessManager::GetTabContextByContentProcess(const ContentParentId& aChildCpId)
232
0
{
233
0
  MOZ_ASSERT(NS_IsMainThread());
234
0
235
0
  nsTArray<TabContext> tabContextArray;
236
0
  auto iter = mContentParentMap.find(aChildCpId);
237
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
238
0
    ASSERT_UNLESS_FUZZING();
239
0
    return tabContextArray;
240
0
  }
241
0
242
0
  for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
243
0
       remoteFrameIter != iter->second.mRemoteFrames.end();
244
0
       ++remoteFrameIter) {
245
0
    tabContextArray.AppendElement(remoteFrameIter->second.mContext);
246
0
  }
247
0
248
0
  return tabContextArray;
249
0
}
250
251
bool
252
ContentProcessManager::GetRemoteFrameOpenerTabId(const ContentParentId& aChildCpId,
253
                                                 const TabId& aChildTabId,
254
                                                 /*out*/ContentParentId* aOpenerCpId,
255
                                                 /*out*/TabId* aOpenerTabId)
256
0
{
257
0
  MOZ_ASSERT(NS_IsMainThread());
258
0
  auto iter = mContentParentMap.find(aChildCpId);
259
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
260
0
    ASSERT_UNLESS_FUZZING();
261
0
    return false;
262
0
  }
263
0
264
0
  auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
265
0
  if (NS_WARN_IF(remoteFrameIter == iter->second.mRemoteFrames.end())) {
266
0
    ASSERT_UNLESS_FUZZING();
267
0
    return false;
268
0
  }
269
0
270
0
  *aOpenerCpId = remoteFrameIter->second.mOpenerCpId;
271
0
  *aOpenerTabId = remoteFrameIter->second.mOpenerTabId;
272
0
273
0
  return true;
274
0
}
275
276
already_AddRefed<TabParent>
277
ContentProcessManager::GetTabParentByProcessAndTabId(const ContentParentId& aChildCpId,
278
                                                     const TabId& aChildTabId)
279
0
{
280
0
  MOZ_ASSERT(NS_IsMainThread());
281
0
282
0
  auto iter = mContentParentMap.find(aChildCpId);
283
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
284
0
    ASSERT_UNLESS_FUZZING();
285
0
    return nullptr;
286
0
  }
287
0
288
0
  const ManagedContainer<PBrowserParent>& browsers = iter->second.mCp->ManagedPBrowserParent();
289
0
  for (auto iter = browsers.ConstIter(); !iter.Done(); iter.Next()) {
290
0
    RefPtr<TabParent> tab = TabParent::GetFrom(iter.Get()->GetKey());
291
0
    if (tab->GetTabId() == aChildTabId) {
292
0
      return tab.forget();
293
0
    }
294
0
  }
295
0
296
0
  return nullptr;
297
0
}
298
299
already_AddRefed<TabParent>
300
ContentProcessManager::GetTopLevelTabParentByProcessAndTabId(const ContentParentId& aChildCpId,
301
                                                             const TabId& aChildTabId)
302
0
{
303
0
  MOZ_ASSERT(NS_IsMainThread());
304
0
305
0
  // Used to keep the current ContentParentId and the current TabId
306
0
  // in the iteration(do-while loop below)
307
0
  ContentParentId currentCpId;
308
0
  TabId currentTabId;
309
0
310
0
  // To get the ContentParentId and the TabParentId on upper level
311
0
  ContentParentId parentCpId = aChildCpId;
312
0
  TabId openerTabId = aChildTabId;
313
0
314
0
  // Stop this loop when the upper ContentParentId of
315
0
  // the current ContentParentId is chrome(ContentParentId = 0).
316
0
  do {
317
0
    // Update the current ContentParentId and TabId in iteration
318
0
    currentCpId = parentCpId;
319
0
    currentTabId = openerTabId;
320
0
321
0
    // Get the ContentParentId and TabId on upper level
322
0
    if (!GetRemoteFrameOpenerTabId(currentCpId, currentTabId, &parentCpId, &openerTabId)) {
323
0
      return nullptr;
324
0
    }
325
0
  } while (parentCpId);
326
0
327
0
  // Get the top level TabParent by the current ContentParentId and TabId
328
0
  return GetTabParentByProcessAndTabId(currentCpId, currentTabId);
329
0
}
330
331
nsTArray<TabId>
332
ContentProcessManager::GetTabParentsByProcessId(const ContentParentId& aChildCpId)
333
0
{
334
0
  MOZ_ASSERT(NS_IsMainThread());
335
0
336
0
  nsTArray<TabId> tabIdList;
337
0
  auto iter = mContentParentMap.find(aChildCpId);
338
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
339
0
    ASSERT_UNLESS_FUZZING();
340
0
    return tabIdList;
341
0
  }
342
0
343
0
  for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
344
0
      remoteFrameIter != iter->second.mRemoteFrames.end();
345
0
      ++remoteFrameIter) {
346
0
    tabIdList.AppendElement(remoteFrameIter->first);
347
0
  }
348
0
349
0
  return tabIdList;
350
0
}
351
352
uint32_t
353
ContentProcessManager::GetTabParentCountByProcessId(const ContentParentId& aChildCpId)
354
0
{
355
0
  MOZ_ASSERT(NS_IsMainThread());
356
0
357
0
  auto iter = mContentParentMap.find(aChildCpId);
358
0
  if (NS_WARN_IF(iter == mContentParentMap.end())) {
359
0
    return 0;
360
0
  }
361
0
362
0
  return iter->second.mRemoteFrames.size();
363
0
}
364
365
} // namespace dom
366
} // namespace mozilla