1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/ipc/TabContext.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,376 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set sw=2 ts=8 et tw=80 : */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "mozilla/dom/TabContext.h" 1.11 +#include "mozilla/dom/PTabContext.h" 1.12 +#include "mozilla/dom/TabParent.h" 1.13 +#include "mozilla/dom/TabChild.h" 1.14 +#include "nsIAppsService.h" 1.15 +#include "nsIScriptSecurityManager.h" 1.16 +#include "nsServiceManagerUtils.h" 1.17 + 1.18 +#define NO_APP_ID (nsIScriptSecurityManager::NO_APP_ID) 1.19 + 1.20 +using namespace mozilla::dom::ipc; 1.21 +using namespace mozilla::layout; 1.22 + 1.23 +namespace mozilla { 1.24 +namespace dom { 1.25 + 1.26 +TabContext::TabContext() 1.27 + : mInitialized(false) 1.28 + , mOwnAppId(NO_APP_ID) 1.29 + , mContainingAppId(NO_APP_ID) 1.30 + , mScrollingBehavior(DEFAULT_SCROLLING) 1.31 + , mIsBrowser(false) 1.32 +{ 1.33 +} 1.34 + 1.35 +bool 1.36 +TabContext::IsBrowserElement() const 1.37 +{ 1.38 + return mIsBrowser; 1.39 +} 1.40 + 1.41 +bool 1.42 +TabContext::IsBrowserOrApp() const 1.43 +{ 1.44 + return HasOwnApp() || IsBrowserElement(); 1.45 +} 1.46 + 1.47 +uint32_t 1.48 +TabContext::OwnAppId() const 1.49 +{ 1.50 + return mOwnAppId; 1.51 +} 1.52 + 1.53 +already_AddRefed<mozIApplication> 1.54 +TabContext::GetOwnApp() const 1.55 +{ 1.56 + nsCOMPtr<mozIApplication> ownApp = mOwnApp; 1.57 + return ownApp.forget(); 1.58 +} 1.59 + 1.60 +bool 1.61 +TabContext::HasOwnApp() const 1.62 +{ 1.63 + nsCOMPtr<mozIApplication> ownApp = GetOwnApp(); 1.64 + return !!ownApp; 1.65 +} 1.66 + 1.67 +uint32_t 1.68 +TabContext::BrowserOwnerAppId() const 1.69 +{ 1.70 + if (IsBrowserElement()) { 1.71 + return mContainingAppId; 1.72 + } 1.73 + return NO_APP_ID; 1.74 +} 1.75 + 1.76 +already_AddRefed<mozIApplication> 1.77 +TabContext::GetBrowserOwnerApp() const 1.78 +{ 1.79 + nsCOMPtr<mozIApplication> ownerApp; 1.80 + if (IsBrowserElement()) { 1.81 + ownerApp = mContainingApp; 1.82 + } 1.83 + return ownerApp.forget(); 1.84 +} 1.85 + 1.86 +bool 1.87 +TabContext::HasBrowserOwnerApp() const 1.88 +{ 1.89 + nsCOMPtr<mozIApplication> ownerApp = GetBrowserOwnerApp(); 1.90 + return !!ownerApp; 1.91 +} 1.92 + 1.93 +uint32_t 1.94 +TabContext::AppOwnerAppId() const 1.95 +{ 1.96 + if (HasOwnApp()) { 1.97 + return mContainingAppId; 1.98 + } 1.99 + return NO_APP_ID; 1.100 +} 1.101 + 1.102 +already_AddRefed<mozIApplication> 1.103 +TabContext::GetAppOwnerApp() const 1.104 +{ 1.105 + nsCOMPtr<mozIApplication> ownerApp; 1.106 + if (HasOwnApp()) { 1.107 + ownerApp = mContainingApp; 1.108 + } 1.109 + return ownerApp.forget(); 1.110 +} 1.111 + 1.112 +bool 1.113 +TabContext::HasAppOwnerApp() const 1.114 +{ 1.115 + nsCOMPtr<mozIApplication> ownerApp = GetAppOwnerApp(); 1.116 + return !!ownerApp; 1.117 +} 1.118 + 1.119 +uint32_t 1.120 +TabContext::OwnOrContainingAppId() const 1.121 +{ 1.122 + if (HasOwnApp()) { 1.123 + return mOwnAppId; 1.124 + } 1.125 + 1.126 + return mContainingAppId; 1.127 +} 1.128 + 1.129 +already_AddRefed<mozIApplication> 1.130 +TabContext::GetOwnOrContainingApp() const 1.131 +{ 1.132 + nsCOMPtr<mozIApplication> ownOrContainingApp; 1.133 + if (HasOwnApp()) { 1.134 + ownOrContainingApp = mOwnApp; 1.135 + } else { 1.136 + ownOrContainingApp = mContainingApp; 1.137 + } 1.138 + 1.139 + return ownOrContainingApp.forget(); 1.140 +} 1.141 + 1.142 +bool 1.143 +TabContext::HasOwnOrContainingApp() const 1.144 +{ 1.145 + nsCOMPtr<mozIApplication> ownOrContainingApp = GetOwnOrContainingApp(); 1.146 + return !!ownOrContainingApp; 1.147 +} 1.148 + 1.149 +bool 1.150 +TabContext::SetTabContext(const TabContext& aContext) 1.151 +{ 1.152 + NS_ENSURE_FALSE(mInitialized, false); 1.153 + 1.154 + *this = aContext; 1.155 + mInitialized = true; 1.156 + 1.157 + return true; 1.158 +} 1.159 + 1.160 +bool 1.161 +TabContext::SetTabContextForAppFrame(mozIApplication* aOwnApp, 1.162 + mozIApplication* aAppFrameOwnerApp, 1.163 + ScrollingBehavior aRequestedBehavior) 1.164 +{ 1.165 + NS_ENSURE_FALSE(mInitialized, false); 1.166 + 1.167 + // Get ids for both apps and only write to our member variables after we've 1.168 + // verified that this worked. 1.169 + uint32_t ownAppId = NO_APP_ID; 1.170 + if (aOwnApp) { 1.171 + nsresult rv = aOwnApp->GetLocalId(&ownAppId); 1.172 + NS_ENSURE_SUCCESS(rv, false); 1.173 + NS_ENSURE_TRUE(ownAppId != NO_APP_ID, false); 1.174 + } 1.175 + 1.176 + uint32_t containingAppId = NO_APP_ID; 1.177 + if (aAppFrameOwnerApp) { 1.178 + nsresult rv = aAppFrameOwnerApp->GetLocalId(&containingAppId); 1.179 + NS_ENSURE_SUCCESS(rv, false); 1.180 + NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false); 1.181 + } 1.182 + 1.183 + mInitialized = true; 1.184 + mIsBrowser = false; 1.185 + mOwnAppId = ownAppId; 1.186 + mContainingAppId = containingAppId; 1.187 + mScrollingBehavior = aRequestedBehavior; 1.188 + mOwnApp = aOwnApp; 1.189 + mContainingApp = aAppFrameOwnerApp; 1.190 + return true; 1.191 +} 1.192 + 1.193 +bool 1.194 +TabContext::SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp, 1.195 + ScrollingBehavior aRequestedBehavior) 1.196 +{ 1.197 + NS_ENSURE_FALSE(mInitialized, false); 1.198 + 1.199 + uint32_t containingAppId = NO_APP_ID; 1.200 + if (aBrowserFrameOwnerApp) { 1.201 + nsresult rv = aBrowserFrameOwnerApp->GetLocalId(&containingAppId); 1.202 + NS_ENSURE_SUCCESS(rv, false); 1.203 + NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false); 1.204 + } 1.205 + 1.206 + mInitialized = true; 1.207 + mIsBrowser = true; 1.208 + mOwnAppId = NO_APP_ID; 1.209 + mContainingAppId = containingAppId; 1.210 + mScrollingBehavior = aRequestedBehavior; 1.211 + mContainingApp = aBrowserFrameOwnerApp; 1.212 + return true; 1.213 +} 1.214 + 1.215 +bool 1.216 +TabContext::SetTabContextForNormalFrame(ScrollingBehavior aRequestedBehavior) 1.217 +{ 1.218 + NS_ENSURE_FALSE(mInitialized, false); 1.219 + 1.220 + mInitialized = true; 1.221 + mScrollingBehavior = aRequestedBehavior; 1.222 + return true; 1.223 +} 1.224 + 1.225 +IPCTabContext 1.226 +TabContext::AsIPCTabContext() const 1.227 +{ 1.228 + if (mIsBrowser) { 1.229 + return IPCTabContext(BrowserFrameIPCTabContext(mContainingAppId), 1.230 + mScrollingBehavior); 1.231 + } 1.232 + 1.233 + return IPCTabContext(AppFrameIPCTabContext(mOwnAppId, mContainingAppId), 1.234 + mScrollingBehavior); 1.235 +} 1.236 + 1.237 +static already_AddRefed<mozIApplication> 1.238 +GetAppForId(uint32_t aAppId) 1.239 +{ 1.240 + nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); 1.241 + NS_ENSURE_TRUE(appsService, nullptr); 1.242 + 1.243 + nsCOMPtr<mozIApplication> app; 1.244 + appsService->GetAppByLocalId(aAppId, getter_AddRefs(app)); 1.245 + 1.246 + return app.forget(); 1.247 +} 1.248 + 1.249 +MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams) 1.250 + : mInvalidReason(nullptr) 1.251 +{ 1.252 + bool isBrowser = false; 1.253 + uint32_t ownAppId = NO_APP_ID; 1.254 + uint32_t containingAppId = NO_APP_ID; 1.255 + 1.256 + const IPCTabAppBrowserContext& appBrowser = aParams.appBrowserContext(); 1.257 + switch(appBrowser.type()) { 1.258 + case IPCTabAppBrowserContext::TPopupIPCTabContext: { 1.259 + const PopupIPCTabContext &ipcContext = appBrowser.get_PopupIPCTabContext(); 1.260 + 1.261 + TabContext *context; 1.262 + if (ipcContext.openerParent()) { 1.263 + context = static_cast<TabParent*>(ipcContext.openerParent()); 1.264 + if (context->IsBrowserElement() && !ipcContext.isBrowserElement()) { 1.265 + // If the TabParent corresponds to a browser element, then it can only 1.266 + // open other browser elements, for security reasons. We should have 1.267 + // checked this before calling the TabContext constructor, so this is 1.268 + // a fatal error. 1.269 + mInvalidReason = "Child is-browser process tried to " 1.270 + "open a non-browser tab."; 1.271 + return; 1.272 + } 1.273 + } else if (ipcContext.openerChild()) { 1.274 + context = static_cast<TabChild*>(ipcContext.openerChild()); 1.275 + } else { 1.276 + // This should be unreachable because PopupIPCTabContext::opener is not a 1.277 + // nullable field. 1.278 + mInvalidReason = "PopupIPCTabContext::opener was null (?!)."; 1.279 + return; 1.280 + } 1.281 + 1.282 + // Browser elements can't nest other browser elements. So if 1.283 + // our opener is browser element, we must be a new DOM window 1.284 + // opened by it. In that case we inherit our containing app ID 1.285 + // (if any). 1.286 + // 1.287 + // Otherwise, we're a new app window and we inherit from our 1.288 + // opener app. 1.289 + if (ipcContext.isBrowserElement()) { 1.290 + isBrowser = true; 1.291 + ownAppId = NO_APP_ID; 1.292 + containingAppId = context->OwnOrContainingAppId(); 1.293 + } else { 1.294 + isBrowser = false; 1.295 + ownAppId = context->mOwnAppId; 1.296 + containingAppId = context->mContainingAppId; 1.297 + } 1.298 + break; 1.299 + } 1.300 + case IPCTabAppBrowserContext::TAppFrameIPCTabContext: { 1.301 + const AppFrameIPCTabContext &ipcContext = 1.302 + appBrowser.get_AppFrameIPCTabContext(); 1.303 + 1.304 + isBrowser = false; 1.305 + ownAppId = ipcContext.ownAppId(); 1.306 + containingAppId = ipcContext.appFrameOwnerAppId(); 1.307 + break; 1.308 + } 1.309 + case IPCTabAppBrowserContext::TBrowserFrameIPCTabContext: { 1.310 + const BrowserFrameIPCTabContext &ipcContext = 1.311 + appBrowser.get_BrowserFrameIPCTabContext(); 1.312 + 1.313 + isBrowser = true; 1.314 + ownAppId = NO_APP_ID; 1.315 + containingAppId = ipcContext.browserFrameOwnerAppId(); 1.316 + break; 1.317 + } 1.318 + case IPCTabAppBrowserContext::TVanillaFrameIPCTabContext: { 1.319 + isBrowser = false; 1.320 + ownAppId = NO_APP_ID; 1.321 + containingAppId = NO_APP_ID; 1.322 + break; 1.323 + } 1.324 + default: { 1.325 + MOZ_CRASH(); 1.326 + } 1.327 + } 1.328 + 1.329 + nsCOMPtr<mozIApplication> ownApp = GetAppForId(ownAppId); 1.330 + if ((ownApp == nullptr) != (ownAppId == NO_APP_ID)) { 1.331 + mInvalidReason = "Got an ownAppId that didn't correspond to an app."; 1.332 + return; 1.333 + } 1.334 + 1.335 + nsCOMPtr<mozIApplication> containingApp = GetAppForId(containingAppId); 1.336 + if ((containingApp == nullptr) != (containingAppId == NO_APP_ID)) { 1.337 + mInvalidReason = "Got a containingAppId that didn't correspond to an app."; 1.338 + return; 1.339 + } 1.340 + 1.341 + bool rv; 1.342 + if (isBrowser) { 1.343 + rv = mTabContext.SetTabContextForBrowserFrame(containingApp, 1.344 + aParams.scrollingBehavior()); 1.345 + } else { 1.346 + rv = mTabContext.SetTabContextForAppFrame(ownApp, 1.347 + containingApp, 1.348 + aParams.scrollingBehavior()); 1.349 + } 1.350 + 1.351 + if (!rv) { 1.352 + mInvalidReason = "Couldn't initialize TabContext."; 1.353 + } 1.354 +} 1.355 + 1.356 +bool 1.357 +MaybeInvalidTabContext::IsValid() 1.358 +{ 1.359 + return mInvalidReason == nullptr; 1.360 +} 1.361 + 1.362 +const char* 1.363 +MaybeInvalidTabContext::GetInvalidReason() 1.364 +{ 1.365 + return mInvalidReason; 1.366 +} 1.367 + 1.368 +const TabContext& 1.369 +MaybeInvalidTabContext::GetTabContext() 1.370 +{ 1.371 + if (!IsValid()) { 1.372 + MOZ_CRASH("Can't GetTabContext() if !IsValid()."); 1.373 + } 1.374 + 1.375 + return mTabContext; 1.376 +} 1.377 + 1.378 +} // namespace dom 1.379 +} // namespace mozilla