dom/ipc/TabContext.cpp

changeset 2
7e26c7da4463
equal deleted inserted replaced
-1:000000000000 0:34370a7cf1f8
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 /* 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 "nsIAppsService.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 , mOwnAppId(NO_APP_ID)
26 , mContainingAppId(NO_APP_ID)
27 , mScrollingBehavior(DEFAULT_SCROLLING)
28 , mIsBrowser(false)
29 {
30 }
31
32 bool
33 TabContext::IsBrowserElement() const
34 {
35 return mIsBrowser;
36 }
37
38 bool
39 TabContext::IsBrowserOrApp() const
40 {
41 return HasOwnApp() || IsBrowserElement();
42 }
43
44 uint32_t
45 TabContext::OwnAppId() const
46 {
47 return mOwnAppId;
48 }
49
50 already_AddRefed<mozIApplication>
51 TabContext::GetOwnApp() const
52 {
53 nsCOMPtr<mozIApplication> ownApp = mOwnApp;
54 return ownApp.forget();
55 }
56
57 bool
58 TabContext::HasOwnApp() const
59 {
60 nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
61 return !!ownApp;
62 }
63
64 uint32_t
65 TabContext::BrowserOwnerAppId() const
66 {
67 if (IsBrowserElement()) {
68 return mContainingAppId;
69 }
70 return NO_APP_ID;
71 }
72
73 already_AddRefed<mozIApplication>
74 TabContext::GetBrowserOwnerApp() const
75 {
76 nsCOMPtr<mozIApplication> ownerApp;
77 if (IsBrowserElement()) {
78 ownerApp = mContainingApp;
79 }
80 return ownerApp.forget();
81 }
82
83 bool
84 TabContext::HasBrowserOwnerApp() const
85 {
86 nsCOMPtr<mozIApplication> ownerApp = GetBrowserOwnerApp();
87 return !!ownerApp;
88 }
89
90 uint32_t
91 TabContext::AppOwnerAppId() const
92 {
93 if (HasOwnApp()) {
94 return mContainingAppId;
95 }
96 return NO_APP_ID;
97 }
98
99 already_AddRefed<mozIApplication>
100 TabContext::GetAppOwnerApp() const
101 {
102 nsCOMPtr<mozIApplication> ownerApp;
103 if (HasOwnApp()) {
104 ownerApp = mContainingApp;
105 }
106 return ownerApp.forget();
107 }
108
109 bool
110 TabContext::HasAppOwnerApp() const
111 {
112 nsCOMPtr<mozIApplication> ownerApp = GetAppOwnerApp();
113 return !!ownerApp;
114 }
115
116 uint32_t
117 TabContext::OwnOrContainingAppId() const
118 {
119 if (HasOwnApp()) {
120 return mOwnAppId;
121 }
122
123 return mContainingAppId;
124 }
125
126 already_AddRefed<mozIApplication>
127 TabContext::GetOwnOrContainingApp() const
128 {
129 nsCOMPtr<mozIApplication> ownOrContainingApp;
130 if (HasOwnApp()) {
131 ownOrContainingApp = mOwnApp;
132 } else {
133 ownOrContainingApp = mContainingApp;
134 }
135
136 return ownOrContainingApp.forget();
137 }
138
139 bool
140 TabContext::HasOwnOrContainingApp() const
141 {
142 nsCOMPtr<mozIApplication> ownOrContainingApp = GetOwnOrContainingApp();
143 return !!ownOrContainingApp;
144 }
145
146 bool
147 TabContext::SetTabContext(const TabContext& aContext)
148 {
149 NS_ENSURE_FALSE(mInitialized, false);
150
151 *this = aContext;
152 mInitialized = true;
153
154 return true;
155 }
156
157 bool
158 TabContext::SetTabContextForAppFrame(mozIApplication* aOwnApp,
159 mozIApplication* aAppFrameOwnerApp,
160 ScrollingBehavior aRequestedBehavior)
161 {
162 NS_ENSURE_FALSE(mInitialized, false);
163
164 // Get ids for both apps and only write to our member variables after we've
165 // verified that this worked.
166 uint32_t ownAppId = NO_APP_ID;
167 if (aOwnApp) {
168 nsresult rv = aOwnApp->GetLocalId(&ownAppId);
169 NS_ENSURE_SUCCESS(rv, false);
170 NS_ENSURE_TRUE(ownAppId != NO_APP_ID, false);
171 }
172
173 uint32_t containingAppId = NO_APP_ID;
174 if (aAppFrameOwnerApp) {
175 nsresult rv = aAppFrameOwnerApp->GetLocalId(&containingAppId);
176 NS_ENSURE_SUCCESS(rv, false);
177 NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
178 }
179
180 mInitialized = true;
181 mIsBrowser = false;
182 mOwnAppId = ownAppId;
183 mContainingAppId = containingAppId;
184 mScrollingBehavior = aRequestedBehavior;
185 mOwnApp = aOwnApp;
186 mContainingApp = aAppFrameOwnerApp;
187 return true;
188 }
189
190 bool
191 TabContext::SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp,
192 ScrollingBehavior aRequestedBehavior)
193 {
194 NS_ENSURE_FALSE(mInitialized, false);
195
196 uint32_t containingAppId = NO_APP_ID;
197 if (aBrowserFrameOwnerApp) {
198 nsresult rv = aBrowserFrameOwnerApp->GetLocalId(&containingAppId);
199 NS_ENSURE_SUCCESS(rv, false);
200 NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
201 }
202
203 mInitialized = true;
204 mIsBrowser = true;
205 mOwnAppId = NO_APP_ID;
206 mContainingAppId = containingAppId;
207 mScrollingBehavior = aRequestedBehavior;
208 mContainingApp = aBrowserFrameOwnerApp;
209 return true;
210 }
211
212 bool
213 TabContext::SetTabContextForNormalFrame(ScrollingBehavior aRequestedBehavior)
214 {
215 NS_ENSURE_FALSE(mInitialized, false);
216
217 mInitialized = true;
218 mScrollingBehavior = aRequestedBehavior;
219 return true;
220 }
221
222 IPCTabContext
223 TabContext::AsIPCTabContext() const
224 {
225 if (mIsBrowser) {
226 return IPCTabContext(BrowserFrameIPCTabContext(mContainingAppId),
227 mScrollingBehavior);
228 }
229
230 return IPCTabContext(AppFrameIPCTabContext(mOwnAppId, mContainingAppId),
231 mScrollingBehavior);
232 }
233
234 static already_AddRefed<mozIApplication>
235 GetAppForId(uint32_t aAppId)
236 {
237 nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
238 NS_ENSURE_TRUE(appsService, nullptr);
239
240 nsCOMPtr<mozIApplication> app;
241 appsService->GetAppByLocalId(aAppId, getter_AddRefs(app));
242
243 return app.forget();
244 }
245
246 MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
247 : mInvalidReason(nullptr)
248 {
249 bool isBrowser = false;
250 uint32_t ownAppId = NO_APP_ID;
251 uint32_t containingAppId = NO_APP_ID;
252
253 const IPCTabAppBrowserContext& appBrowser = aParams.appBrowserContext();
254 switch(appBrowser.type()) {
255 case IPCTabAppBrowserContext::TPopupIPCTabContext: {
256 const PopupIPCTabContext &ipcContext = appBrowser.get_PopupIPCTabContext();
257
258 TabContext *context;
259 if (ipcContext.openerParent()) {
260 context = static_cast<TabParent*>(ipcContext.openerParent());
261 if (context->IsBrowserElement() && !ipcContext.isBrowserElement()) {
262 // If the TabParent corresponds to a browser element, then it can only
263 // open other browser elements, for security reasons. We should have
264 // checked this before calling the TabContext constructor, so this is
265 // a fatal error.
266 mInvalidReason = "Child is-browser process tried to "
267 "open a non-browser tab.";
268 return;
269 }
270 } else if (ipcContext.openerChild()) {
271 context = static_cast<TabChild*>(ipcContext.openerChild());
272 } else {
273 // This should be unreachable because PopupIPCTabContext::opener is not a
274 // nullable field.
275 mInvalidReason = "PopupIPCTabContext::opener was null (?!).";
276 return;
277 }
278
279 // Browser elements can't nest other browser elements. So if
280 // our opener is browser element, we must be a new DOM window
281 // opened by it. In that case we inherit our containing app ID
282 // (if any).
283 //
284 // Otherwise, we're a new app window and we inherit from our
285 // opener app.
286 if (ipcContext.isBrowserElement()) {
287 isBrowser = true;
288 ownAppId = NO_APP_ID;
289 containingAppId = context->OwnOrContainingAppId();
290 } else {
291 isBrowser = false;
292 ownAppId = context->mOwnAppId;
293 containingAppId = context->mContainingAppId;
294 }
295 break;
296 }
297 case IPCTabAppBrowserContext::TAppFrameIPCTabContext: {
298 const AppFrameIPCTabContext &ipcContext =
299 appBrowser.get_AppFrameIPCTabContext();
300
301 isBrowser = false;
302 ownAppId = ipcContext.ownAppId();
303 containingAppId = ipcContext.appFrameOwnerAppId();
304 break;
305 }
306 case IPCTabAppBrowserContext::TBrowserFrameIPCTabContext: {
307 const BrowserFrameIPCTabContext &ipcContext =
308 appBrowser.get_BrowserFrameIPCTabContext();
309
310 isBrowser = true;
311 ownAppId = NO_APP_ID;
312 containingAppId = ipcContext.browserFrameOwnerAppId();
313 break;
314 }
315 case IPCTabAppBrowserContext::TVanillaFrameIPCTabContext: {
316 isBrowser = false;
317 ownAppId = NO_APP_ID;
318 containingAppId = NO_APP_ID;
319 break;
320 }
321 default: {
322 MOZ_CRASH();
323 }
324 }
325
326 nsCOMPtr<mozIApplication> ownApp = GetAppForId(ownAppId);
327 if ((ownApp == nullptr) != (ownAppId == NO_APP_ID)) {
328 mInvalidReason = "Got an ownAppId that didn't correspond to an app.";
329 return;
330 }
331
332 nsCOMPtr<mozIApplication> containingApp = GetAppForId(containingAppId);
333 if ((containingApp == nullptr) != (containingAppId == NO_APP_ID)) {
334 mInvalidReason = "Got a containingAppId that didn't correspond to an app.";
335 return;
336 }
337
338 bool rv;
339 if (isBrowser) {
340 rv = mTabContext.SetTabContextForBrowserFrame(containingApp,
341 aParams.scrollingBehavior());
342 } else {
343 rv = mTabContext.SetTabContextForAppFrame(ownApp,
344 containingApp,
345 aParams.scrollingBehavior());
346 }
347
348 if (!rv) {
349 mInvalidReason = "Couldn't initialize TabContext.";
350 }
351 }
352
353 bool
354 MaybeInvalidTabContext::IsValid()
355 {
356 return mInvalidReason == nullptr;
357 }
358
359 const char*
360 MaybeInvalidTabContext::GetInvalidReason()
361 {
362 return mInvalidReason;
363 }
364
365 const TabContext&
366 MaybeInvalidTabContext::GetTabContext()
367 {
368 if (!IsValid()) {
369 MOZ_CRASH("Can't GetTabContext() if !IsValid().");
370 }
371
372 return mTabContext;
373 }
374
375 } // namespace dom
376 } // namespace mozilla

mercurial