|
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 |