ContentProcessManager.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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 "ContentProcessManager.h"
  6. #include "ContentParent.h"
  7. #include "mozilla/dom/TabParent.h"
  8. #include "mozilla/StaticPtr.h"
  9. #include "mozilla/ClearOnShutdown.h"
  10. #include "nsPrintfCString.h"
  11. #include "nsIScriptSecurityManager.h"
  12. // XXX need another bug to move this to a common header.
  13. #ifdef DISABLE_ASSERTS_FOR_FUZZING
  14. #define ASSERT_UNLESS_FUZZING(...) do { } while (0)
  15. #else
  16. #define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
  17. #endif
  18. namespace mozilla {
  19. namespace dom {
  20. static uint64_t gTabId = 0;
  21. /* static */
  22. StaticAutoPtr<ContentProcessManager>
  23. ContentProcessManager::sSingleton;
  24. /* static */ ContentProcessManager*
  25. ContentProcessManager::GetSingleton()
  26. {
  27. MOZ_ASSERT(XRE_IsParentProcess());
  28. if (!sSingleton) {
  29. sSingleton = new ContentProcessManager();
  30. ClearOnShutdown(&sSingleton);
  31. }
  32. return sSingleton;
  33. }
  34. void
  35. ContentProcessManager::AddContentProcess(ContentParent* aChildCp,
  36. const ContentParentId& aParentCpId)
  37. {
  38. MOZ_ASSERT(NS_IsMainThread());
  39. MOZ_ASSERT(aChildCp);
  40. ContentProcessInfo info;
  41. info.mCp = aChildCp;
  42. info.mParentCpId = aParentCpId;
  43. mContentParentMap[aChildCp->ChildID()] = info;
  44. }
  45. void
  46. ContentProcessManager::RemoveContentProcess(const ContentParentId& aChildCpId)
  47. {
  48. MOZ_ASSERT(NS_IsMainThread());
  49. MOZ_ASSERT(mContentParentMap.find(aChildCpId) != mContentParentMap.end());
  50. mContentParentMap.erase(aChildCpId);
  51. for (auto iter = mContentParentMap.begin();
  52. iter != mContentParentMap.end();
  53. ++iter) {
  54. if (!iter->second.mChildrenCpId.empty()) {
  55. iter->second.mChildrenCpId.erase(aChildCpId);
  56. }
  57. }
  58. }
  59. bool
  60. ContentProcessManager::AddGrandchildProcess(const ContentParentId& aParentCpId,
  61. const ContentParentId& aChildCpId)
  62. {
  63. MOZ_ASSERT(NS_IsMainThread());
  64. auto iter = mContentParentMap.find(aParentCpId);
  65. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  66. ASSERT_UNLESS_FUZZING("Parent process should be already in map!");
  67. return false;
  68. }
  69. iter->second.mChildrenCpId.insert(aChildCpId);
  70. return true;
  71. }
  72. bool
  73. ContentProcessManager::GetParentProcessId(const ContentParentId& aChildCpId,
  74. /*out*/ ContentParentId* aParentCpId)
  75. {
  76. MOZ_ASSERT(NS_IsMainThread());
  77. auto iter = mContentParentMap.find(aChildCpId);
  78. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  79. ASSERT_UNLESS_FUZZING();
  80. return false;
  81. }
  82. *aParentCpId = iter->second.mParentCpId;
  83. return true;
  84. }
  85. ContentParent*
  86. ContentProcessManager::GetContentProcessById(const ContentParentId& aChildCpId)
  87. {
  88. MOZ_ASSERT(NS_IsMainThread());
  89. auto iter = mContentParentMap.find(aChildCpId);
  90. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  91. ASSERT_UNLESS_FUZZING();
  92. return nullptr;
  93. }
  94. return iter->second.mCp;
  95. }
  96. nsTArray<ContentParentId>
  97. ContentProcessManager::GetAllChildProcessById(const ContentParentId& aParentCpId)
  98. {
  99. MOZ_ASSERT(NS_IsMainThread());
  100. nsTArray<ContentParentId> cpIdArray;
  101. auto iter = mContentParentMap.find(aParentCpId);
  102. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  103. ASSERT_UNLESS_FUZZING();
  104. return Move(cpIdArray);
  105. }
  106. for (auto cpIter = iter->second.mChildrenCpId.begin();
  107. cpIter != iter->second.mChildrenCpId.end();
  108. ++cpIter) {
  109. cpIdArray.AppendElement(*cpIter);
  110. }
  111. return Move(cpIdArray);
  112. }
  113. TabId
  114. ContentProcessManager::AllocateTabId(const TabId& aOpenerTabId,
  115. const IPCTabContext& aContext,
  116. const ContentParentId& aChildCpId)
  117. {
  118. MOZ_ASSERT(NS_IsMainThread());
  119. auto iter = mContentParentMap.find(aChildCpId);
  120. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  121. ASSERT_UNLESS_FUZZING();
  122. return TabId(0);
  123. }
  124. struct RemoteFrameInfo info;
  125. // If it's a PopupIPCTabContext, it's the case that a TabChild want to
  126. // open a new tab. aOpenerTabId has to be it's parent frame's opener id.
  127. if (aContext.type() == IPCTabContext::TPopupIPCTabContext) {
  128. auto remoteFrameIter = iter->second.mRemoteFrames.find(aOpenerTabId);
  129. if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
  130. ASSERT_UNLESS_FUZZING("Failed to find parent frame's opener id.");
  131. return TabId(0);
  132. }
  133. info.mOpenerTabId = remoteFrameIter->second.mOpenerTabId;
  134. const PopupIPCTabContext &ipcContext = aContext.get_PopupIPCTabContext();
  135. MOZ_ASSERT(ipcContext.opener().type() == PBrowserOrId::TTabId);
  136. remoteFrameIter = iter->second.mRemoteFrames.find(ipcContext.opener().get_TabId());
  137. if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
  138. ASSERT_UNLESS_FUZZING("Failed to find tab id.");
  139. return TabId(0);
  140. }
  141. info.mContext = remoteFrameIter->second.mContext;
  142. }
  143. else {
  144. MaybeInvalidTabContext tc(aContext);
  145. if (!tc.IsValid()) {
  146. NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
  147. "the child process. (%s)",
  148. tc.GetInvalidReason()).get());
  149. return TabId(0);
  150. }
  151. info.mOpenerTabId = aOpenerTabId;
  152. info.mContext = tc.GetTabContext();
  153. }
  154. mUniqueId = ++gTabId;
  155. iter->second.mRemoteFrames[mUniqueId] = info;
  156. return mUniqueId;
  157. }
  158. void
  159. ContentProcessManager::DeallocateTabId(const ContentParentId& aChildCpId,
  160. const TabId& aChildTabId)
  161. {
  162. MOZ_ASSERT(NS_IsMainThread());
  163. auto iter = mContentParentMap.find(aChildCpId);
  164. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  165. ASSERT_UNLESS_FUZZING();
  166. return;
  167. }
  168. auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
  169. if (remoteFrameIter != iter->second.mRemoteFrames.end()) {
  170. iter->second.mRemoteFrames.erase(aChildTabId);
  171. }
  172. }
  173. bool
  174. ContentProcessManager::GetTabContextByProcessAndTabId(const ContentParentId& aChildCpId,
  175. const TabId& aChildTabId,
  176. /*out*/ TabContext* aTabContext)
  177. {
  178. MOZ_ASSERT(NS_IsMainThread());
  179. MOZ_ASSERT(aTabContext);
  180. auto iter = mContentParentMap.find(aChildCpId);
  181. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  182. ASSERT_UNLESS_FUZZING();
  183. return false;
  184. }
  185. auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
  186. if (NS_WARN_IF(remoteFrameIter == iter->second.mRemoteFrames.end())) {
  187. ASSERT_UNLESS_FUZZING();
  188. return false;
  189. }
  190. *aTabContext = remoteFrameIter->second.mContext;
  191. return true;
  192. }
  193. nsTArray<TabContext>
  194. ContentProcessManager::GetTabContextByContentProcess(const ContentParentId& aChildCpId)
  195. {
  196. MOZ_ASSERT(NS_IsMainThread());
  197. nsTArray<TabContext> tabContextArray;
  198. auto iter = mContentParentMap.find(aChildCpId);
  199. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  200. ASSERT_UNLESS_FUZZING();
  201. return Move(tabContextArray);
  202. }
  203. for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
  204. remoteFrameIter != iter->second.mRemoteFrames.end();
  205. ++remoteFrameIter) {
  206. tabContextArray.AppendElement(remoteFrameIter->second.mContext);
  207. }
  208. return Move(tabContextArray);
  209. }
  210. bool
  211. ContentProcessManager::GetRemoteFrameOpenerTabId(const ContentParentId& aChildCpId,
  212. const TabId& aChildTabId,
  213. /*out*/TabId* aOpenerTabId)
  214. {
  215. MOZ_ASSERT(NS_IsMainThread());
  216. auto iter = mContentParentMap.find(aChildCpId);
  217. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  218. ASSERT_UNLESS_FUZZING();
  219. return false;
  220. }
  221. auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
  222. if (NS_WARN_IF(remoteFrameIter == iter->second.mRemoteFrames.end())) {
  223. ASSERT_UNLESS_FUZZING();
  224. return false;
  225. }
  226. *aOpenerTabId = remoteFrameIter->second.mOpenerTabId;
  227. return true;
  228. }
  229. already_AddRefed<TabParent>
  230. ContentProcessManager::GetTabParentByProcessAndTabId(const ContentParentId& aChildCpId,
  231. const TabId& aChildTabId)
  232. {
  233. MOZ_ASSERT(NS_IsMainThread());
  234. auto iter = mContentParentMap.find(aChildCpId);
  235. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  236. ASSERT_UNLESS_FUZZING();
  237. return nullptr;
  238. }
  239. const ManagedContainer<PBrowserParent>& browsers = iter->second.mCp->ManagedPBrowserParent();
  240. for (auto iter = browsers.ConstIter(); !iter.Done(); iter.Next()) {
  241. RefPtr<TabParent> tab = TabParent::GetFrom(iter.Get()->GetKey());
  242. if (tab->GetTabId() == aChildTabId) {
  243. return tab.forget();
  244. }
  245. }
  246. return nullptr;
  247. }
  248. already_AddRefed<TabParent>
  249. ContentProcessManager::GetTopLevelTabParentByProcessAndTabId(const ContentParentId& aChildCpId,
  250. const TabId& aChildTabId)
  251. {
  252. MOZ_ASSERT(NS_IsMainThread());
  253. // Used to keep the current ContentParentId and the current TabId
  254. // in the iteration(do-while loop below)
  255. ContentParentId currentCpId;
  256. TabId currentTabId;
  257. // To get the ContentParentId and the TabParentId on upper level
  258. ContentParentId parentCpId = aChildCpId;
  259. TabId openerTabId = aChildTabId;
  260. // Stop this loop when the upper ContentParentId of
  261. // the current ContentParentId is chrome(ContentParentId = 0).
  262. do {
  263. // Update the current ContentParentId and TabId in iteration
  264. currentCpId = parentCpId;
  265. currentTabId = openerTabId;
  266. // Get the ContentParentId and TabId on upper level
  267. if (!GetParentProcessId(currentCpId, &parentCpId) ||
  268. !GetRemoteFrameOpenerTabId(currentCpId, currentTabId, &openerTabId)) {
  269. return nullptr;
  270. }
  271. } while (parentCpId);
  272. // Get the top level TabParent by the current ContentParentId and TabId
  273. return GetTabParentByProcessAndTabId(currentCpId, currentTabId);
  274. }
  275. nsTArray<TabId>
  276. ContentProcessManager::GetTabParentsByProcessId(const ContentParentId& aChildCpId)
  277. {
  278. MOZ_ASSERT(NS_IsMainThread());
  279. nsTArray<TabId> tabIdList;
  280. auto iter = mContentParentMap.find(aChildCpId);
  281. if (NS_WARN_IF(iter == mContentParentMap.end())) {
  282. ASSERT_UNLESS_FUZZING();
  283. return Move(tabIdList);
  284. }
  285. for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
  286. remoteFrameIter != iter->second.mRemoteFrames.end();
  287. ++remoteFrameIter) {
  288. tabIdList.AppendElement(remoteFrameIter->first);
  289. }
  290. return Move(tabIdList);
  291. }
  292. uint32_t
  293. ContentProcessManager::GetAppIdByProcessAndTabId(const ContentParentId& aChildCpId,
  294. const TabId& aChildTabId)
  295. {
  296. uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
  297. if (aChildCpId && aChildTabId) {
  298. TabContext tabContext;
  299. if (GetTabContextByProcessAndTabId(aChildCpId, aChildTabId, &tabContext)) {
  300. appId = tabContext.OwnOrContainingAppId();
  301. }
  302. }
  303. return appId;
  304. }
  305. } // namespace dom
  306. } // namespace mozilla