nsIContentParent.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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 file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsIContentParent.h"
  6. #include "mozilla/AppProcessChecker.h"
  7. #include "mozilla/Preferences.h"
  8. #include "mozilla/dom/File.h"
  9. #include "mozilla/dom/ContentParent.h"
  10. #include "mozilla/dom/ContentBridgeParent.h"
  11. #include "mozilla/dom/PTabContext.h"
  12. #include "mozilla/dom/PermissionMessageUtils.h"
  13. #include "mozilla/dom/TabParent.h"
  14. #include "mozilla/dom/ipc/BlobParent.h"
  15. #include "mozilla/dom/ipc/StructuredCloneData.h"
  16. #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
  17. #include "mozilla/ipc/FileDescriptorSetParent.h"
  18. #include "mozilla/ipc/PFileDescriptorSetParent.h"
  19. #include "mozilla/ipc/SendStreamAlloc.h"
  20. #include "mozilla/Unused.h"
  21. #include "nsFrameMessageManager.h"
  22. #include "nsIWebBrowserChrome.h"
  23. #include "nsPrintfCString.h"
  24. #include "xpcpublic.h"
  25. using namespace mozilla::ipc;
  26. using namespace mozilla::jsipc;
  27. // XXX need another bug to move this to a common header.
  28. #ifdef DISABLE_ASSERTS_FOR_FUZZING
  29. #define ASSERT_UNLESS_FUZZING(...) do { } while (0)
  30. #else
  31. #define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
  32. #endif
  33. namespace mozilla {
  34. namespace dom {
  35. nsIContentParent::nsIContentParent()
  36. {
  37. mMessageManager = nsFrameMessageManager::NewProcessMessageManager(true);
  38. }
  39. ContentParent*
  40. nsIContentParent::AsContentParent()
  41. {
  42. MOZ_ASSERT(IsContentParent());
  43. return static_cast<ContentParent*>(this);
  44. }
  45. ContentBridgeParent*
  46. nsIContentParent::AsContentBridgeParent()
  47. {
  48. MOZ_ASSERT(IsContentBridgeParent());
  49. return static_cast<ContentBridgeParent*>(this);
  50. }
  51. PJavaScriptParent*
  52. nsIContentParent::AllocPJavaScriptParent()
  53. {
  54. return NewJavaScriptParent();
  55. }
  56. bool
  57. nsIContentParent::DeallocPJavaScriptParent(PJavaScriptParent* aParent)
  58. {
  59. ReleaseJavaScriptParent(aParent);
  60. return true;
  61. }
  62. bool
  63. nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
  64. {
  65. // (PopupIPCTabContext lets the child process prove that it has access to
  66. // the app it's trying to open.)
  67. // On e10s we also allow UnsafeTabContext to allow service workers to open
  68. // windows. This is enforced in MaybeInvalidTabContext.
  69. if (aContext.type() != IPCTabContext::TPopupIPCTabContext &&
  70. aContext.type() != IPCTabContext::TUnsafeIPCTabContext) {
  71. ASSERT_UNLESS_FUZZING("Unexpected IPCTabContext type. Aborting AllocPBrowserParent.");
  72. return false;
  73. }
  74. if (aContext.type() == IPCTabContext::TPopupIPCTabContext) {
  75. const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext();
  76. if (popupContext.opener().type() != PBrowserOrId::TPBrowserParent) {
  77. ASSERT_UNLESS_FUZZING("Unexpected PopupIPCTabContext type. Aborting AllocPBrowserParent.");
  78. return false;
  79. }
  80. auto opener = TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
  81. if (!opener) {
  82. ASSERT_UNLESS_FUZZING("Got null opener from child; aborting AllocPBrowserParent.");
  83. return false;
  84. }
  85. // Popup windows of isMozBrowserElement frames must be isMozBrowserElement if
  86. // the parent isMozBrowserElement. Allocating a !isMozBrowserElement frame with
  87. // same app ID would allow the content to access data it's not supposed to.
  88. if (!popupContext.isMozBrowserElement() && opener->IsMozBrowserElement()) {
  89. ASSERT_UNLESS_FUZZING("Child trying to escalate privileges! Aborting AllocPBrowserParent.");
  90. return false;
  91. }
  92. }
  93. MaybeInvalidTabContext tc(aContext);
  94. if (!tc.IsValid()) {
  95. NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext. (%s) "
  96. "Aborting AllocPBrowserParent.",
  97. tc.GetInvalidReason()).get());
  98. return false;
  99. }
  100. return true;
  101. }
  102. PBrowserParent*
  103. nsIContentParent::AllocPBrowserParent(const TabId& aTabId,
  104. const IPCTabContext& aContext,
  105. const uint32_t& aChromeFlags,
  106. const ContentParentId& aCpId,
  107. const bool& aIsForApp,
  108. const bool& aIsForBrowser)
  109. {
  110. Unused << aCpId;
  111. Unused << aIsForApp;
  112. Unused << aIsForBrowser;
  113. if (!CanOpenBrowser(aContext)) {
  114. return nullptr;
  115. }
  116. uint32_t chromeFlags = aChromeFlags;
  117. if (aContext.type() == IPCTabContext::TPopupIPCTabContext) {
  118. // CanOpenBrowser has ensured that the IPCTabContext is of
  119. // type PopupIPCTabContext, and that the opener TabParent is
  120. // reachable.
  121. const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext();
  122. auto opener = TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
  123. // We must ensure that the private browsing and remoteness flags
  124. // match those of the opener.
  125. nsCOMPtr<nsILoadContext> loadContext = opener->GetLoadContext();
  126. if (!loadContext) {
  127. return nullptr;
  128. }
  129. bool isPrivate;
  130. loadContext->GetUsePrivateBrowsing(&isPrivate);
  131. if (isPrivate) {
  132. chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
  133. }
  134. }
  135. // And because we're allocating a remote browser, of course the
  136. // window is remote.
  137. chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
  138. MaybeInvalidTabContext tc(aContext);
  139. MOZ_ASSERT(tc.IsValid());
  140. TabParent* parent = new TabParent(this, aTabId, tc.GetTabContext(), chromeFlags);
  141. // We release this ref in DeallocPBrowserParent()
  142. NS_ADDREF(parent);
  143. return parent;
  144. }
  145. bool
  146. nsIContentParent::DeallocPBrowserParent(PBrowserParent* aFrame)
  147. {
  148. TabParent* parent = TabParent::GetFrom(aFrame);
  149. NS_RELEASE(parent);
  150. return true;
  151. }
  152. PBlobParent*
  153. nsIContentParent::AllocPBlobParent(const BlobConstructorParams& aParams)
  154. {
  155. return BlobParent::Create(this, aParams);
  156. }
  157. bool
  158. nsIContentParent::DeallocPBlobParent(PBlobParent* aActor)
  159. {
  160. BlobParent::Destroy(aActor);
  161. return true;
  162. }
  163. BlobParent*
  164. nsIContentParent::GetOrCreateActorForBlob(Blob* aBlob)
  165. {
  166. MOZ_ASSERT(NS_IsMainThread());
  167. MOZ_ASSERT(aBlob);
  168. RefPtr<BlobImpl> blobImpl = aBlob->Impl();
  169. MOZ_ASSERT(blobImpl);
  170. return GetOrCreateActorForBlobImpl(blobImpl);
  171. }
  172. BlobParent*
  173. nsIContentParent::GetOrCreateActorForBlobImpl(BlobImpl* aImpl)
  174. {
  175. MOZ_ASSERT(NS_IsMainThread());
  176. MOZ_ASSERT(aImpl);
  177. BlobParent* actor = BlobParent::GetOrCreate(this, aImpl);
  178. NS_ENSURE_TRUE(actor, nullptr);
  179. return actor;
  180. }
  181. bool
  182. nsIContentParent::RecvSyncMessage(const nsString& aMsg,
  183. const ClonedMessageData& aData,
  184. InfallibleTArray<CpowEntry>&& aCpows,
  185. const IPC::Principal& aPrincipal,
  186. nsTArray<ipc::StructuredCloneData>* aRetvals)
  187. {
  188. // FIXME Permission check in Content process
  189. nsIPrincipal* principal = aPrincipal;
  190. if (IsContentParent()) {
  191. ContentParent* parent = AsContentParent();
  192. if (!ContentParent::IgnoreIPCPrincipal() &&
  193. parent && principal && !AssertAppPrincipal(parent, principal)) {
  194. return false;
  195. }
  196. }
  197. RefPtr<nsFrameMessageManager> ppm = mMessageManager;
  198. if (ppm) {
  199. ipc::StructuredCloneData data;
  200. ipc::UnpackClonedMessageDataForParent(aData, data);
  201. CrossProcessCpowHolder cpows(this, aCpows);
  202. ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr,
  203. aMsg, true, &data, &cpows, aPrincipal, aRetvals);
  204. }
  205. return true;
  206. }
  207. bool
  208. nsIContentParent::RecvRpcMessage(const nsString& aMsg,
  209. const ClonedMessageData& aData,
  210. InfallibleTArray<CpowEntry>&& aCpows,
  211. const IPC::Principal& aPrincipal,
  212. nsTArray<ipc::StructuredCloneData>* aRetvals)
  213. {
  214. // FIXME Permission check in Content process
  215. nsIPrincipal* principal = aPrincipal;
  216. if (IsContentParent()) {
  217. ContentParent* parent = AsContentParent();
  218. if (!ContentParent::IgnoreIPCPrincipal() &&
  219. parent && principal && !AssertAppPrincipal(parent, principal)) {
  220. return false;
  221. }
  222. }
  223. RefPtr<nsFrameMessageManager> ppm = mMessageManager;
  224. if (ppm) {
  225. ipc::StructuredCloneData data;
  226. ipc::UnpackClonedMessageDataForParent(aData, data);
  227. CrossProcessCpowHolder cpows(this, aCpows);
  228. ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr,
  229. aMsg, true, &data, &cpows, aPrincipal, aRetvals);
  230. }
  231. return true;
  232. }
  233. PFileDescriptorSetParent*
  234. nsIContentParent::AllocPFileDescriptorSetParent(const FileDescriptor& aFD)
  235. {
  236. return new FileDescriptorSetParent(aFD);
  237. }
  238. bool
  239. nsIContentParent::DeallocPFileDescriptorSetParent(PFileDescriptorSetParent* aActor)
  240. {
  241. delete static_cast<FileDescriptorSetParent*>(aActor);
  242. return true;
  243. }
  244. PSendStreamParent*
  245. nsIContentParent::AllocPSendStreamParent()
  246. {
  247. return mozilla::ipc::AllocPSendStreamParent();
  248. }
  249. bool
  250. nsIContentParent::DeallocPSendStreamParent(PSendStreamParent* aActor)
  251. {
  252. delete aActor;
  253. return true;
  254. }
  255. bool
  256. nsIContentParent::RecvAsyncMessage(const nsString& aMsg,
  257. InfallibleTArray<CpowEntry>&& aCpows,
  258. const IPC::Principal& aPrincipal,
  259. const ClonedMessageData& aData)
  260. {
  261. // FIXME Permission check in Content process
  262. nsIPrincipal* principal = aPrincipal;
  263. if (IsContentParent()) {
  264. ContentParent* parent = AsContentParent();
  265. if (!ContentParent::IgnoreIPCPrincipal() &&
  266. parent && principal && !AssertAppPrincipal(parent, principal)) {
  267. return false;
  268. }
  269. }
  270. RefPtr<nsFrameMessageManager> ppm = mMessageManager;
  271. if (ppm) {
  272. ipc::StructuredCloneData data;
  273. ipc::UnpackClonedMessageDataForParent(aData, data);
  274. CrossProcessCpowHolder cpows(this, aCpows);
  275. ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr,
  276. aMsg, false, &data, &cpows, aPrincipal, nullptr);
  277. }
  278. return true;
  279. }
  280. } // namespace dom
  281. } // namespace mozilla