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