TabContext.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/dom/TabContext.h"
  6. #include "mozilla/dom/PTabContext.h"
  7. #include "mozilla/dom/TabParent.h"
  8. #include "mozilla/dom/TabChild.h"
  9. #include "nsIAppsService.h"
  10. #include "nsIScriptSecurityManager.h"
  11. #include "nsServiceManagerUtils.h"
  12. #define NO_APP_ID (nsIScriptSecurityManager::NO_APP_ID)
  13. using namespace mozilla::dom::ipc;
  14. using namespace mozilla::layout;
  15. namespace mozilla {
  16. namespace dom {
  17. TabContext::TabContext()
  18. : mIsPrerendered(false)
  19. , mInitialized(false)
  20. , mIsMozBrowserElement(false)
  21. , mContainingAppId(NO_APP_ID)
  22. , mShowAccelerators(UIStateChangeType_NoChange)
  23. , mShowFocusRings(UIStateChangeType_NoChange)
  24. {
  25. }
  26. bool
  27. TabContext::IsMozBrowserElement() const
  28. {
  29. return mIsMozBrowserElement;
  30. }
  31. bool
  32. TabContext::IsIsolatedMozBrowserElement() const
  33. {
  34. return mOriginAttributes.mInIsolatedMozBrowser;
  35. }
  36. bool
  37. TabContext::IsMozBrowserOrApp() const
  38. {
  39. return HasOwnApp() || IsMozBrowserElement();
  40. }
  41. uint32_t
  42. TabContext::OwnAppId() const
  43. {
  44. return mOriginAttributes.mAppId;
  45. }
  46. already_AddRefed<mozIApplication>
  47. TabContext::GetOwnApp() const
  48. {
  49. nsCOMPtr<mozIApplication> ownApp = mOwnApp;
  50. return ownApp.forget();
  51. }
  52. bool
  53. TabContext::HasOwnApp() const
  54. {
  55. nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
  56. return !!ownApp;
  57. }
  58. uint32_t
  59. TabContext::BrowserOwnerAppId() const
  60. {
  61. if (IsMozBrowserElement()) {
  62. return mContainingAppId;
  63. }
  64. return NO_APP_ID;
  65. }
  66. already_AddRefed<mozIApplication>
  67. TabContext::GetBrowserOwnerApp() const
  68. {
  69. nsCOMPtr<mozIApplication> ownerApp;
  70. if (IsMozBrowserElement()) {
  71. ownerApp = mContainingApp;
  72. }
  73. return ownerApp.forget();
  74. }
  75. bool
  76. TabContext::HasBrowserOwnerApp() const
  77. {
  78. nsCOMPtr<mozIApplication> ownerApp = GetBrowserOwnerApp();
  79. return !!ownerApp;
  80. }
  81. uint32_t
  82. TabContext::AppOwnerAppId() const
  83. {
  84. if (HasOwnApp()) {
  85. return mContainingAppId;
  86. }
  87. return NO_APP_ID;
  88. }
  89. already_AddRefed<mozIApplication>
  90. TabContext::GetAppOwnerApp() const
  91. {
  92. nsCOMPtr<mozIApplication> ownerApp;
  93. if (HasOwnApp()) {
  94. ownerApp = mContainingApp;
  95. }
  96. return ownerApp.forget();
  97. }
  98. bool
  99. TabContext::HasAppOwnerApp() const
  100. {
  101. nsCOMPtr<mozIApplication> ownerApp = GetAppOwnerApp();
  102. return !!ownerApp;
  103. }
  104. uint32_t
  105. TabContext::OwnOrContainingAppId() const
  106. {
  107. if (HasOwnApp()) {
  108. return mOriginAttributes.mAppId;
  109. }
  110. return mContainingAppId;
  111. }
  112. already_AddRefed<mozIApplication>
  113. TabContext::GetOwnOrContainingApp() const
  114. {
  115. nsCOMPtr<mozIApplication> ownOrContainingApp;
  116. if (HasOwnApp()) {
  117. ownOrContainingApp = mOwnApp;
  118. } else {
  119. ownOrContainingApp = mContainingApp;
  120. }
  121. return ownOrContainingApp.forget();
  122. }
  123. bool
  124. TabContext::HasOwnOrContainingApp() const
  125. {
  126. nsCOMPtr<mozIApplication> ownOrContainingApp = GetOwnOrContainingApp();
  127. return !!ownOrContainingApp;
  128. }
  129. bool
  130. TabContext::SetTabContext(const TabContext& aContext)
  131. {
  132. NS_ENSURE_FALSE(mInitialized, false);
  133. *this = aContext;
  134. mInitialized = true;
  135. return true;
  136. }
  137. void
  138. TabContext::SetPrivateBrowsingAttributes(bool aIsPrivateBrowsing)
  139. {
  140. mOriginAttributes.SyncAttributesWithPrivateBrowsing(aIsPrivateBrowsing);
  141. }
  142. bool
  143. TabContext::UpdateTabContextAfterSwap(const TabContext& aContext)
  144. {
  145. // This is only used after already initialized.
  146. MOZ_ASSERT(mInitialized);
  147. // The only permissable change is to `mIsMozBrowserElement`. All other fields
  148. // must match for the change to be accepted.
  149. if (aContext.OwnAppId() != OwnAppId() ||
  150. aContext.mContainingAppId != mContainingAppId ||
  151. aContext.mOriginAttributes != mOriginAttributes) {
  152. return false;
  153. }
  154. mIsMozBrowserElement = aContext.mIsMozBrowserElement;
  155. return true;
  156. }
  157. const DocShellOriginAttributes&
  158. TabContext::OriginAttributesRef() const
  159. {
  160. return mOriginAttributes;
  161. }
  162. UIStateChangeType
  163. TabContext::ShowAccelerators() const
  164. {
  165. return mShowAccelerators;
  166. }
  167. UIStateChangeType
  168. TabContext::ShowFocusRings() const
  169. {
  170. return mShowFocusRings;
  171. }
  172. bool
  173. TabContext::SetTabContext(bool aIsMozBrowserElement,
  174. bool aIsPrerendered,
  175. mozIApplication* aOwnApp,
  176. mozIApplication* aAppFrameOwnerApp,
  177. UIStateChangeType aShowAccelerators,
  178. UIStateChangeType aShowFocusRings,
  179. const DocShellOriginAttributes& aOriginAttributes)
  180. {
  181. NS_ENSURE_FALSE(mInitialized, false);
  182. // Get ids for both apps and only write to our member variables after we've
  183. // verified that this worked.
  184. uint32_t ownAppId = NO_APP_ID;
  185. if (aOwnApp) {
  186. nsresult rv = aOwnApp->GetLocalId(&ownAppId);
  187. NS_ENSURE_SUCCESS(rv, false);
  188. NS_ENSURE_TRUE(ownAppId != NO_APP_ID, false);
  189. }
  190. uint32_t containingAppId = NO_APP_ID;
  191. if (aAppFrameOwnerApp) {
  192. nsresult rv = aAppFrameOwnerApp->GetLocalId(&containingAppId);
  193. NS_ENSURE_SUCCESS(rv, false);
  194. NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
  195. }
  196. // Veryify that app id matches mAppId passed in originAttributes
  197. MOZ_RELEASE_ASSERT((aOwnApp && aOriginAttributes.mAppId == ownAppId) ||
  198. (aAppFrameOwnerApp && aOriginAttributes.mAppId == containingAppId) ||
  199. aOriginAttributes.mAppId == NO_APP_ID);
  200. mInitialized = true;
  201. mIsMozBrowserElement = aIsMozBrowserElement;
  202. mIsPrerendered = aIsPrerendered;
  203. mOriginAttributes = aOriginAttributes;
  204. mContainingAppId = containingAppId;
  205. mOwnApp = aOwnApp;
  206. mContainingApp = aAppFrameOwnerApp;
  207. mShowAccelerators = aShowAccelerators;
  208. mShowFocusRings = aShowFocusRings;
  209. return true;
  210. }
  211. IPCTabContext
  212. TabContext::AsIPCTabContext() const
  213. {
  214. return IPCTabContext(FrameIPCTabContext(mOriginAttributes,
  215. mContainingAppId,
  216. mIsMozBrowserElement,
  217. mIsPrerendered,
  218. mShowAccelerators,
  219. mShowFocusRings));
  220. }
  221. static already_AddRefed<mozIApplication>
  222. GetAppForId(uint32_t aAppId)
  223. {
  224. nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
  225. NS_ENSURE_TRUE(appsService, nullptr);
  226. nsCOMPtr<mozIApplication> app;
  227. appsService->GetAppByLocalId(aAppId, getter_AddRefs(app));
  228. return app.forget();
  229. }
  230. MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
  231. : mInvalidReason(nullptr)
  232. {
  233. bool isMozBrowserElement = false;
  234. bool isPrerendered = false;
  235. uint32_t containingAppId = NO_APP_ID;
  236. DocShellOriginAttributes originAttributes;
  237. UIStateChangeType showAccelerators = UIStateChangeType_NoChange;
  238. UIStateChangeType showFocusRings = UIStateChangeType_NoChange;
  239. switch(aParams.type()) {
  240. case IPCTabContext::TPopupIPCTabContext: {
  241. const PopupIPCTabContext &ipcContext = aParams.get_PopupIPCTabContext();
  242. TabContext *context;
  243. if (ipcContext.opener().type() == PBrowserOrId::TPBrowserParent) {
  244. context = TabParent::GetFrom(ipcContext.opener().get_PBrowserParent());
  245. if (!context) {
  246. mInvalidReason = "Child is-browser process tried to "
  247. "open a null tab.";
  248. return;
  249. }
  250. if (context->IsMozBrowserElement() &&
  251. !ipcContext.isMozBrowserElement()) {
  252. // If the TabParent corresponds to a browser element, then it can only
  253. // open other browser elements, for security reasons. We should have
  254. // checked this before calling the TabContext constructor, so this is
  255. // a fatal error.
  256. mInvalidReason = "Child is-browser process tried to "
  257. "open a non-browser tab.";
  258. return;
  259. }
  260. } else if (ipcContext.opener().type() == PBrowserOrId::TPBrowserChild) {
  261. context = static_cast<TabChild*>(ipcContext.opener().get_PBrowserChild());
  262. } else if (ipcContext.opener().type() == PBrowserOrId::TTabId) {
  263. // We should never get here because this PopupIPCTabContext is only
  264. // used for allocating a new tab id, not for allocating a PBrowser.
  265. mInvalidReason = "Child process tried to open an tab without the opener information.";
  266. return;
  267. } else {
  268. // This should be unreachable because PopupIPCTabContext::opener is not a
  269. // nullable field.
  270. mInvalidReason = "PopupIPCTabContext::opener was null (?!).";
  271. return;
  272. }
  273. // Browser elements can't nest other browser elements. So if
  274. // our opener is browser element, we must be a new DOM window
  275. // opened by it. In that case we inherit our containing app ID
  276. // (if any).
  277. //
  278. // Otherwise, we're a new app window and we inherit from our
  279. // opener app.
  280. isMozBrowserElement = ipcContext.isMozBrowserElement();
  281. originAttributes = context->mOriginAttributes;
  282. if (isMozBrowserElement) {
  283. containingAppId = context->OwnOrContainingAppId();
  284. } else {
  285. containingAppId = context->mContainingAppId;
  286. }
  287. break;
  288. }
  289. case IPCTabContext::TFrameIPCTabContext: {
  290. const FrameIPCTabContext &ipcContext =
  291. aParams.get_FrameIPCTabContext();
  292. isMozBrowserElement = ipcContext.isMozBrowserElement();
  293. isPrerendered = ipcContext.isPrerendered();
  294. containingAppId = ipcContext.frameOwnerAppId();
  295. showAccelerators = ipcContext.showAccelerators();
  296. showFocusRings = ipcContext.showFocusRings();
  297. originAttributes = ipcContext.originAttributes();
  298. break;
  299. }
  300. case IPCTabContext::TUnsafeIPCTabContext: {
  301. // XXXcatalinb: This used *only* by ServiceWorkerClients::OpenWindow.
  302. // It is meant as a temporary solution until service workers can
  303. // provide a TabChild equivalent.
  304. if (!Preferences::GetBool("dom.serviceWorkers.enabled", false)) {
  305. mInvalidReason = "ServiceWorkers should be enabled.";
  306. return;
  307. }
  308. containingAppId = NO_APP_ID;
  309. break;
  310. }
  311. default: {
  312. MOZ_CRASH();
  313. }
  314. }
  315. nsCOMPtr<mozIApplication> ownApp;
  316. if (!isMozBrowserElement) {
  317. // mAppId corresponds to OwnOrContainingAppId; if isMozBrowserElement is
  318. // false then it's ownApp otherwise it's containingApp
  319. ownApp = GetAppForId(originAttributes.mAppId);
  320. if ((ownApp == nullptr) != (originAttributes.mAppId == NO_APP_ID)) {
  321. mInvalidReason = "Got an ownAppId that didn't correspond to an app.";
  322. return;
  323. }
  324. }
  325. nsCOMPtr<mozIApplication> containingApp = GetAppForId(containingAppId);
  326. if ((containingApp == nullptr) != (containingAppId == NO_APP_ID)) {
  327. mInvalidReason = "Got a containingAppId that didn't correspond to an app.";
  328. return;
  329. }
  330. bool rv;
  331. rv = mTabContext.SetTabContext(isMozBrowserElement,
  332. isPrerendered,
  333. ownApp,
  334. containingApp,
  335. showAccelerators,
  336. showFocusRings,
  337. originAttributes);
  338. if (!rv) {
  339. mInvalidReason = "Couldn't initialize TabContext.";
  340. }
  341. }
  342. bool
  343. MaybeInvalidTabContext::IsValid()
  344. {
  345. return mInvalidReason == nullptr;
  346. }
  347. const char*
  348. MaybeInvalidTabContext::GetInvalidReason()
  349. {
  350. return mInvalidReason;
  351. }
  352. const TabContext&
  353. MaybeInvalidTabContext::GetTabContext()
  354. {
  355. if (!IsValid()) {
  356. MOZ_CRASH("Can't GetTabContext() if !IsValid().");
  357. }
  358. return mTabContext;
  359. }
  360. } // namespace dom
  361. } // namespace mozilla