Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/ipc/TabContext.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/TabContext.h"
8
#include "mozilla/dom/PTabContext.h"
9
#include "mozilla/dom/TabParent.h"
10
#include "mozilla/dom/TabChild.h"
11
#include "mozilla/StaticPrefs.h"
12
#include "nsIScriptSecurityManager.h"
13
#include "nsServiceManagerUtils.h"
14
15
#define NO_APP_ID (nsIScriptSecurityManager::NO_APP_ID)
16
17
using namespace mozilla::dom::ipc;
18
using namespace mozilla::layout;
19
20
namespace mozilla {
21
namespace dom {
22
23
TabContext::TabContext()
24
  : mInitialized(false)
25
  , mIsMozBrowserElement(false)
26
  , mChromeOuterWindowID(0)
27
  , mJSPluginID(-1)
28
  , mShowAccelerators(UIStateChangeType_NoChange)
29
  , mShowFocusRings(UIStateChangeType_NoChange)
30
0
{
31
0
}
32
33
bool
34
TabContext::IsMozBrowserElement() const
35
0
{
36
0
  return mIsMozBrowserElement;
37
0
}
38
39
bool
40
TabContext::IsIsolatedMozBrowserElement() const
41
0
{
42
0
  return mOriginAttributes.mInIsolatedMozBrowser;
43
0
}
44
45
bool
46
TabContext::IsMozBrowser() const
47
0
{
48
0
  return IsMozBrowserElement();
49
0
}
50
51
bool
52
TabContext::IsJSPlugin() const
53
0
{
54
0
  return mJSPluginID >= 0;
55
0
}
56
57
int32_t
58
TabContext::JSPluginId() const
59
0
{
60
0
  return mJSPluginID;
61
0
}
62
63
uint64_t
64
TabContext::ChromeOuterWindowID() const
65
0
{
66
0
  return mChromeOuterWindowID;
67
0
}
68
69
bool
70
TabContext::SetTabContext(const TabContext& aContext)
71
0
{
72
0
  NS_ENSURE_FALSE(mInitialized, false);
73
0
74
0
  *this = aContext;
75
0
  mInitialized = true;
76
0
77
0
  return true;
78
0
}
79
80
void
81
TabContext::SetPrivateBrowsingAttributes(bool aIsPrivateBrowsing)
82
0
{
83
0
  mOriginAttributes.SyncAttributesWithPrivateBrowsing(aIsPrivateBrowsing);
84
0
}
85
86
bool
87
TabContext::UpdateTabContextAfterSwap(const TabContext& aContext)
88
0
{
89
0
  // This is only used after already initialized.
90
0
  MOZ_ASSERT(mInitialized);
91
0
92
0
  // The only permissable changes are to `mIsMozBrowserElement` and
93
0
  // mChromeOuterWindowID.  All other fields must match for the change
94
0
  // to be accepted.
95
0
  if (aContext.mOriginAttributes != mOriginAttributes) {
96
0
    return false;
97
0
  }
98
0
99
0
  mChromeOuterWindowID = aContext.mChromeOuterWindowID;
100
0
  mIsMozBrowserElement = aContext.mIsMozBrowserElement;
101
0
  return true;
102
0
}
103
104
const OriginAttributes&
105
TabContext::OriginAttributesRef() const
106
0
{
107
0
  return mOriginAttributes;
108
0
}
109
110
const nsAString&
111
TabContext::PresentationURL() const
112
0
{
113
0
  return mPresentationURL;
114
0
}
115
116
UIStateChangeType
117
TabContext::ShowAccelerators() const
118
0
{
119
0
  return mShowAccelerators;
120
0
}
121
122
UIStateChangeType
123
TabContext::ShowFocusRings() const
124
0
{
125
0
  return mShowFocusRings;
126
0
}
127
128
bool
129
TabContext::SetTabContext(bool aIsMozBrowserElement,
130
                          uint64_t aChromeOuterWindowID,
131
                          UIStateChangeType aShowAccelerators,
132
                          UIStateChangeType aShowFocusRings,
133
                          const OriginAttributes& aOriginAttributes,
134
                          const nsAString& aPresentationURL)
135
0
{
136
0
  NS_ENSURE_FALSE(mInitialized, false);
137
0
138
0
  // Veryify that app id matches mAppId passed in originAttributes
139
0
  MOZ_RELEASE_ASSERT(aOriginAttributes.mAppId == NO_APP_ID);
140
0
141
0
  mInitialized = true;
142
0
  mIsMozBrowserElement = aIsMozBrowserElement;
143
0
  mChromeOuterWindowID = aChromeOuterWindowID;
144
0
  mOriginAttributes = aOriginAttributes;
145
0
  mPresentationURL = aPresentationURL;
146
0
  mShowAccelerators = aShowAccelerators;
147
0
  mShowFocusRings = aShowFocusRings;
148
0
  return true;
149
0
}
150
151
bool
152
TabContext::SetTabContextForJSPluginFrame(int32_t aJSPluginID)
153
0
{
154
0
  NS_ENSURE_FALSE(mInitialized, false);
155
0
156
0
  mInitialized = true;
157
0
  mJSPluginID = aJSPluginID;
158
0
  return true;
159
0
}
160
161
IPCTabContext
162
TabContext::AsIPCTabContext() const
163
0
{
164
0
  if (IsJSPlugin()) {
165
0
    return IPCTabContext(JSPluginFrameIPCTabContext(mJSPluginID));
166
0
  }
167
0
168
0
  return IPCTabContext(FrameIPCTabContext(mOriginAttributes,
169
0
                                          mIsMozBrowserElement,
170
0
                                          mChromeOuterWindowID,
171
0
                                          mPresentationURL,
172
0
                                          mShowAccelerators,
173
0
                                          mShowFocusRings));
174
0
}
175
176
MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
177
  : mInvalidReason(nullptr)
178
0
{
179
0
  bool isMozBrowserElement = false;
180
0
  uint64_t chromeOuterWindowID = 0;
181
0
  int32_t jsPluginId = -1;
182
0
  OriginAttributes originAttributes;
183
0
  nsAutoString presentationURL;
184
0
  UIStateChangeType showAccelerators = UIStateChangeType_NoChange;
185
0
  UIStateChangeType showFocusRings = UIStateChangeType_NoChange;
186
0
187
0
  switch(aParams.type()) {
188
0
    case IPCTabContext::TPopupIPCTabContext: {
189
0
      const PopupIPCTabContext &ipcContext = aParams.get_PopupIPCTabContext();
190
0
191
0
      TabContext *context;
192
0
      if (ipcContext.opener().type() == PBrowserOrId::TPBrowserParent) {
193
0
        context = TabParent::GetFrom(ipcContext.opener().get_PBrowserParent());
194
0
        if (!context) {
195
0
          mInvalidReason = "Child is-browser process tried to "
196
0
                           "open a null tab.";
197
0
          return;
198
0
        }
199
0
        if (context->IsMozBrowserElement() &&
200
0
            !ipcContext.isMozBrowserElement()) {
201
0
          // If the TabParent corresponds to a browser element, then it can only
202
0
          // open other browser elements, for security reasons.  We should have
203
0
          // checked this before calling the TabContext constructor, so this is
204
0
          // a fatal error.
205
0
          mInvalidReason = "Child is-browser process tried to "
206
0
                           "open a non-browser tab.";
207
0
          return;
208
0
        }
209
0
      } else if (ipcContext.opener().type() == PBrowserOrId::TPBrowserChild) {
210
0
        context = static_cast<TabChild*>(ipcContext.opener().get_PBrowserChild());
211
0
      } else if (ipcContext.opener().type() == PBrowserOrId::TTabId) {
212
0
        // We should never get here because this PopupIPCTabContext is only
213
0
        // used for allocating a new tab id, not for allocating a PBrowser.
214
0
        mInvalidReason = "Child process tried to open an tab without the opener information.";
215
0
        return;
216
0
      } else {
217
0
        // This should be unreachable because PopupIPCTabContext::opener is not a
218
0
        // nullable field.
219
0
        mInvalidReason = "PopupIPCTabContext::opener was null (?!).";
220
0
        return;
221
0
      }
222
0
223
0
      // Browser elements can't nest other browser elements.  So if
224
0
      // our opener is browser element, we must be a new DOM window
225
0
      // opened by it.  In that case we inherit our containing app ID
226
0
      // (if any).
227
0
      //
228
0
      // Otherwise, we're a new app window and we inherit from our
229
0
      // opener app.
230
0
      isMozBrowserElement = ipcContext.isMozBrowserElement();
231
0
      originAttributes = context->mOriginAttributes;
232
0
      chromeOuterWindowID = ipcContext.chromeOuterWindowID();
233
0
      break;
234
0
    }
235
0
    case IPCTabContext::TJSPluginFrameIPCTabContext: {
236
0
      const JSPluginFrameIPCTabContext &ipcContext =
237
0
        aParams.get_JSPluginFrameIPCTabContext();
238
0
239
0
      jsPluginId = ipcContext.jsPluginId();
240
0
      break;
241
0
    }
242
0
    case IPCTabContext::TFrameIPCTabContext: {
243
0
      const FrameIPCTabContext &ipcContext =
244
0
        aParams.get_FrameIPCTabContext();
245
0
246
0
      isMozBrowserElement = ipcContext.isMozBrowserElement();
247
0
      chromeOuterWindowID = ipcContext.chromeOuterWindowID();
248
0
      presentationURL = ipcContext.presentationURL();
249
0
      showAccelerators = ipcContext.showAccelerators();
250
0
      showFocusRings = ipcContext.showFocusRings();
251
0
      originAttributes = ipcContext.originAttributes();
252
0
      break;
253
0
    }
254
0
    case IPCTabContext::TUnsafeIPCTabContext: {
255
0
      // XXXcatalinb: This used *only* by ServiceWorkerClients::OpenWindow.
256
0
      // It is meant as a temporary solution until service workers can
257
0
      // provide a TabChild equivalent. Don't allow this on b2g since
258
0
      // it might be used to escalate privileges.
259
0
      if (!StaticPrefs::dom_serviceWorkers_enabled()) {
260
0
        mInvalidReason = "ServiceWorkers should be enabled.";
261
0
        return;
262
0
      }
263
0
264
0
      break;
265
0
    }
266
0
    default: {
267
0
      MOZ_CRASH();
268
0
    }
269
0
  }
270
0
271
0
  bool rv;
272
0
  if (jsPluginId >= 0) {
273
0
    rv = mTabContext.SetTabContextForJSPluginFrame(jsPluginId);
274
0
  } else {
275
0
    rv = mTabContext.SetTabContext(isMozBrowserElement,
276
0
                                   chromeOuterWindowID,
277
0
                                   showAccelerators,
278
0
                                   showFocusRings,
279
0
                                   originAttributes,
280
0
                                   presentationURL);
281
0
  }
282
0
  if (!rv) {
283
0
    mInvalidReason = "Couldn't initialize TabContext.";
284
0
  }
285
0
}
286
287
bool
288
MaybeInvalidTabContext::IsValid()
289
0
{
290
0
  return mInvalidReason == nullptr;
291
0
}
292
293
const char*
294
MaybeInvalidTabContext::GetInvalidReason()
295
0
{
296
0
  return mInvalidReason;
297
0
}
298
299
const TabContext&
300
MaybeInvalidTabContext::GetTabContext()
301
0
{
302
0
  if (!IsValid()) {
303
0
    MOZ_CRASH("Can't GetTabContext() if !IsValid().");
304
0
  }
305
0
306
0
  return mTabContext;
307
0
}
308
309
} // namespace dom
310
} // namespace mozilla