frame_node_impl.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/performance_manager/graph/frame_node_impl.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/containers/contains.h"
  8. #include "components/performance_manager/graph/graph_impl.h"
  9. #include "components/performance_manager/graph/graph_impl_util.h"
  10. #include "components/performance_manager/graph/page_node_impl.h"
  11. #include "components/performance_manager/graph/process_node_impl.h"
  12. #include "components/performance_manager/graph/worker_node_impl.h"
  13. #include "components/performance_manager/public/v8_memory/web_memory.h"
  14. namespace performance_manager {
  15. // static
  16. constexpr char FrameNodeImpl::kDefaultPriorityReason[] =
  17. "default frame priority";
  18. using PriorityAndReason = execution_context_priority::PriorityAndReason;
  19. FrameNodeImpl::FrameNodeImpl(ProcessNodeImpl* process_node,
  20. PageNodeImpl* page_node,
  21. FrameNodeImpl* parent_frame_node,
  22. int render_frame_id,
  23. const blink::LocalFrameToken& frame_token,
  24. content::BrowsingInstanceId browsing_instance_id,
  25. content::SiteInstanceId site_instance_id)
  26. : parent_frame_node_(parent_frame_node),
  27. page_node_(page_node),
  28. process_node_(process_node),
  29. render_frame_id_(render_frame_id),
  30. frame_token_(frame_token),
  31. browsing_instance_id_(browsing_instance_id),
  32. site_instance_id_(site_instance_id),
  33. render_frame_host_proxy_(content::GlobalRenderFrameHostId(
  34. process_node->render_process_host_proxy()
  35. .render_process_host_id()
  36. .value(),
  37. render_frame_id)) {
  38. weak_this_ = weak_factory_.GetWeakPtr();
  39. DCHECK(process_node);
  40. DCHECK(page_node);
  41. DETACH_FROM_SEQUENCE(sequence_checker_);
  42. }
  43. FrameNodeImpl::~FrameNodeImpl() {
  44. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  45. DCHECK(child_worker_nodes_.empty());
  46. DCHECK(opened_page_nodes_.empty());
  47. DCHECK(embedded_page_nodes_.empty());
  48. DCHECK(!execution_context_);
  49. }
  50. void FrameNodeImpl::Bind(
  51. mojo::PendingReceiver<mojom::DocumentCoordinationUnit> receiver) {
  52. // It is possible to receive a mojo::PendingReceiver<DocumentCoordinationUnit>
  53. // when |receiver_| is already bound in these cases:
  54. // - Navigation from the initial empty document to the first real document.
  55. // - Navigation rejected by RenderFrameHostImpl::ValidateDidCommitParams().
  56. // See discussion:
  57. // https://chromium-review.googlesource.com/c/chromium/src/+/1572459/6#message-bd31f3e73f96bd9f7721be81ba6ac0076d053147
  58. receiver_.reset();
  59. receiver_.Bind(std::move(receiver));
  60. }
  61. void FrameNodeImpl::SetNetworkAlmostIdle() {
  62. document_.network_almost_idle.SetAndMaybeNotify(this, true);
  63. }
  64. void FrameNodeImpl::SetLifecycleState(mojom::LifecycleState state) {
  65. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  66. lifecycle_state_.SetAndMaybeNotify(this, state);
  67. }
  68. void FrameNodeImpl::SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload) {
  69. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  70. document_.has_nonempty_beforeunload = has_nonempty_beforeunload;
  71. }
  72. void FrameNodeImpl::SetIsAdFrame(bool is_ad_frame) {
  73. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  74. is_ad_frame_.SetAndMaybeNotify(this, is_ad_frame);
  75. }
  76. void FrameNodeImpl::SetHadFormInteraction() {
  77. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  78. document_.had_form_interaction.SetAndMaybeNotify(this, true);
  79. }
  80. void FrameNodeImpl::OnNonPersistentNotificationCreated() {
  81. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  82. for (auto* observer : GetObservers())
  83. observer->OnNonPersistentNotificationCreated(this);
  84. }
  85. void FrameNodeImpl::OnFirstContentfulPaint(
  86. base::TimeDelta time_since_navigation_start) {
  87. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  88. for (auto* observer : GetObservers())
  89. observer->OnFirstContentfulPaint(this, time_since_navigation_start);
  90. }
  91. const RenderFrameHostProxy& FrameNodeImpl::GetRenderFrameHostProxy() const {
  92. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  93. return render_frame_host_proxy();
  94. }
  95. bool FrameNodeImpl::IsMainFrame() const {
  96. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  97. return !parent_frame_node_;
  98. }
  99. FrameNodeImpl* FrameNodeImpl::parent_frame_node() const {
  100. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  101. return parent_frame_node_;
  102. }
  103. PageNodeImpl* FrameNodeImpl::page_node() const {
  104. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  105. return page_node_;
  106. }
  107. ProcessNodeImpl* FrameNodeImpl::process_node() const {
  108. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  109. return process_node_;
  110. }
  111. int FrameNodeImpl::render_frame_id() const {
  112. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  113. return render_frame_id_;
  114. }
  115. const blink::LocalFrameToken& FrameNodeImpl::frame_token() const {
  116. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  117. return frame_token_;
  118. }
  119. content::BrowsingInstanceId FrameNodeImpl::browsing_instance_id() const {
  120. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  121. return browsing_instance_id_;
  122. }
  123. content::SiteInstanceId FrameNodeImpl::site_instance_id() const {
  124. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  125. return site_instance_id_;
  126. }
  127. const RenderFrameHostProxy& FrameNodeImpl::render_frame_host_proxy() const {
  128. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  129. return render_frame_host_proxy_;
  130. }
  131. const base::flat_set<FrameNodeImpl*>& FrameNodeImpl::child_frame_nodes() const {
  132. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  133. return child_frame_nodes_;
  134. }
  135. const base::flat_set<PageNodeImpl*>& FrameNodeImpl::opened_page_nodes() const {
  136. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  137. return opened_page_nodes_;
  138. }
  139. const base::flat_set<PageNodeImpl*>& FrameNodeImpl::embedded_page_nodes()
  140. const {
  141. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  142. return embedded_page_nodes_;
  143. }
  144. mojom::LifecycleState FrameNodeImpl::lifecycle_state() const {
  145. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  146. return lifecycle_state_.value();
  147. }
  148. bool FrameNodeImpl::has_nonempty_beforeunload() const {
  149. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  150. return document_.has_nonempty_beforeunload;
  151. }
  152. const GURL& FrameNodeImpl::url() const {
  153. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  154. return document_.url.value();
  155. }
  156. bool FrameNodeImpl::is_current() const {
  157. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  158. return is_current_.value();
  159. }
  160. bool FrameNodeImpl::network_almost_idle() const {
  161. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  162. return document_.network_almost_idle.value();
  163. }
  164. bool FrameNodeImpl::is_ad_frame() const {
  165. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  166. return is_ad_frame_.value();
  167. }
  168. bool FrameNodeImpl::is_holding_weblock() const {
  169. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  170. return is_holding_weblock_.value();
  171. }
  172. bool FrameNodeImpl::is_holding_indexeddb_lock() const {
  173. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  174. return is_holding_indexeddb_lock_.value();
  175. }
  176. const base::flat_set<WorkerNodeImpl*>& FrameNodeImpl::child_worker_nodes()
  177. const {
  178. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  179. return child_worker_nodes_;
  180. }
  181. const PriorityAndReason& FrameNodeImpl::priority_and_reason() const {
  182. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  183. return priority_and_reason_.value();
  184. }
  185. bool FrameNodeImpl::had_form_interaction() const {
  186. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  187. return document_.had_form_interaction.value();
  188. }
  189. bool FrameNodeImpl::is_audible() const {
  190. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  191. return is_audible_.value();
  192. }
  193. const absl::optional<gfx::Rect>& FrameNodeImpl::viewport_intersection() const {
  194. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  195. // The viewport intersection of the main frame is not tracked.
  196. DCHECK(!IsMainFrame());
  197. return viewport_intersection_.value();
  198. }
  199. FrameNode::Visibility FrameNodeImpl::visibility() const {
  200. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  201. return visibility_.value();
  202. }
  203. void FrameNodeImpl::SetIsCurrent(bool is_current) {
  204. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  205. is_current_.SetAndMaybeNotify(this, is_current);
  206. // TODO(crbug.com/1211368): We maintain an invariant that of all sibling
  207. // frame nodes in the same FrameTreeNode, at most one may be current. We used
  208. // to save the RenderFrameHost's `frame_tree_node_id` at FrameNode creation
  209. // time to check this invariant, but prerendering RenderFrameHost's can be
  210. // moved to a new FrameTreeNode when they're activated so the
  211. // `frame_tree_node_id` can go out of date. Because of this,
  212. // RenderFrameHost::GetFrameTreeNodeId() is being deprecated. (See the
  213. // discussion at crbug.com/1179502 and in the comment thread at
  214. // https://chromium-review.googlesource.com/c/chromium/src/+/2966195/comments/58550eac_5795f790
  215. // for more details.) We need to find another way to check this invariant
  216. // here. (altimin suggests simply relying on RFH::GetLifecycleState to
  217. // correctly track "active" frame nodes instead of using "current", and not
  218. // checking this invariant.)
  219. }
  220. void FrameNodeImpl::SetIsHoldingWebLock(bool is_holding_weblock) {
  221. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  222. DCHECK_NE(is_holding_weblock, is_holding_weblock_.value());
  223. is_holding_weblock_.SetAndMaybeNotify(this, is_holding_weblock);
  224. }
  225. void FrameNodeImpl::SetIsHoldingIndexedDBLock(bool is_holding_indexeddb_lock) {
  226. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  227. DCHECK_NE(is_holding_indexeddb_lock, is_holding_indexeddb_lock_.value());
  228. is_holding_indexeddb_lock_.SetAndMaybeNotify(this, is_holding_indexeddb_lock);
  229. }
  230. void FrameNodeImpl::SetIsAudible(bool is_audible) {
  231. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  232. DCHECK_NE(is_audible, is_audible_.value());
  233. is_audible_.SetAndMaybeNotify(this, is_audible);
  234. }
  235. void FrameNodeImpl::SetViewportIntersection(
  236. const gfx::Rect& viewport_intersection) {
  237. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  238. // The viewport intersection of the main frame is not tracked.
  239. DCHECK(!IsMainFrame());
  240. viewport_intersection_.SetAndMaybeNotify(this, viewport_intersection);
  241. }
  242. void FrameNodeImpl::SetVisibility(Visibility visibility) {
  243. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  244. visibility_.SetAndMaybeNotify(this, visibility);
  245. }
  246. void FrameNodeImpl::OnNavigationCommitted(const GURL& url, bool same_document) {
  247. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  248. if (same_document) {
  249. document_.url.SetAndMaybeNotify(this, url);
  250. return;
  251. }
  252. // Close |receiver_| to ensure that messages queued by the previous document
  253. // before the navigation commit are dropped.
  254. //
  255. // Note: It is guaranteed that |receiver_| isn't yet bound to the new
  256. // document.
  257. // This is important because it would be incorrect to close the new
  258. // document's binding.
  259. //
  260. // Renderer: blink::DocumentLoader::DidCommitNavigation
  261. // ... content::RenderFrameImpl::DidCommitProvisionalLoad
  262. // ... mojom::FrameHost::DidCommitProvisionalLoad
  263. // Browser: RenderFrameHostImpl::DidCommitNavigation
  264. // Bind the new document's interface provider [A]
  265. // PMTabHelper::DidFinishNavigation
  266. // (async) FrameNodeImpl::OnNavigationCommitted [B]
  267. // Renderer: Request DocumentCoordinationUnit interface
  268. // Browser: PMTabHelper::OnInterfaceRequestFromFrame [C]
  269. // (async) FrameNodeImpl::Bind [D]
  270. //
  271. // A happens before C, because no interface request can be processed
  272. // before the interface provider is bound. A posts B to PM sequence and
  273. // C posts D to PM sequence, therefore B happens before D.
  274. receiver_.reset();
  275. // Reset properties.
  276. document_.Reset(this, url);
  277. }
  278. void FrameNodeImpl::AddChildWorker(WorkerNodeImpl* worker_node) {
  279. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  280. bool inserted = child_worker_nodes_.insert(worker_node).second;
  281. DCHECK(inserted);
  282. }
  283. void FrameNodeImpl::RemoveChildWorker(WorkerNodeImpl* worker_node) {
  284. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  285. size_t removed = child_worker_nodes_.erase(worker_node);
  286. DCHECK_EQ(1u, removed);
  287. }
  288. void FrameNodeImpl::SetPriorityAndReason(
  289. const PriorityAndReason& priority_and_reason) {
  290. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  291. priority_and_reason_.SetAndMaybeNotify(this, priority_and_reason);
  292. }
  293. base::WeakPtr<FrameNodeImpl> FrameNodeImpl::GetWeakPtrOnUIThread() {
  294. // TODO(siggi): Validate the thread context here.
  295. return weak_this_;
  296. }
  297. base::WeakPtr<FrameNodeImpl> FrameNodeImpl::GetWeakPtr() {
  298. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  299. return weak_factory_.GetWeakPtr();
  300. }
  301. void FrameNodeImpl::AddOpenedPage(base::PassKey<PageNodeImpl>,
  302. PageNodeImpl* page_node) {
  303. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  304. DCHECK(page_node);
  305. DCHECK_NE(page_node_, page_node);
  306. DCHECK(graph()->NodeInGraph(page_node));
  307. DCHECK_EQ(this, page_node->opener_frame_node());
  308. bool inserted = opened_page_nodes_.insert(page_node).second;
  309. DCHECK(inserted);
  310. }
  311. void FrameNodeImpl::RemoveOpenedPage(base::PassKey<PageNodeImpl>,
  312. PageNodeImpl* page_node) {
  313. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  314. DCHECK(page_node);
  315. DCHECK_NE(page_node_, page_node);
  316. DCHECK(graph()->NodeInGraph(page_node));
  317. DCHECK_EQ(this, page_node->opener_frame_node());
  318. size_t removed = opened_page_nodes_.erase(page_node);
  319. DCHECK_EQ(1u, removed);
  320. }
  321. void FrameNodeImpl::AddEmbeddedPage(base::PassKey<PageNodeImpl>,
  322. PageNodeImpl* page_node) {
  323. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  324. DCHECK(page_node);
  325. DCHECK_NE(page_node_, page_node);
  326. DCHECK(graph()->NodeInGraph(page_node));
  327. DCHECK_EQ(this, page_node->embedder_frame_node());
  328. bool inserted = embedded_page_nodes_.insert(page_node).second;
  329. DCHECK(inserted);
  330. }
  331. void FrameNodeImpl::RemoveEmbeddedPage(base::PassKey<PageNodeImpl>,
  332. PageNodeImpl* page_node) {
  333. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  334. DCHECK(page_node);
  335. DCHECK_NE(page_node_, page_node);
  336. DCHECK(graph()->NodeInGraph(page_node));
  337. DCHECK_EQ(this, page_node->embedder_frame_node());
  338. size_t removed = embedded_page_nodes_.erase(page_node);
  339. DCHECK_EQ(1u, removed);
  340. }
  341. const FrameNode* FrameNodeImpl::GetParentFrameNode() const {
  342. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  343. return parent_frame_node();
  344. }
  345. const PageNode* FrameNodeImpl::GetPageNode() const {
  346. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  347. return page_node();
  348. }
  349. const ProcessNode* FrameNodeImpl::GetProcessNode() const {
  350. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  351. return process_node();
  352. }
  353. const blink::LocalFrameToken& FrameNodeImpl::GetFrameToken() const {
  354. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  355. return frame_token();
  356. }
  357. content::BrowsingInstanceId FrameNodeImpl::GetBrowsingInstanceId() const {
  358. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  359. return browsing_instance_id();
  360. }
  361. content::SiteInstanceId FrameNodeImpl::GetSiteInstanceId() const {
  362. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  363. return site_instance_id();
  364. }
  365. bool FrameNodeImpl::VisitChildFrameNodes(
  366. const FrameNodeVisitor& visitor) const {
  367. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  368. for (auto* frame_impl : child_frame_nodes()) {
  369. const FrameNode* frame = frame_impl;
  370. if (!visitor.Run(frame))
  371. return false;
  372. }
  373. return true;
  374. }
  375. const base::flat_set<const FrameNode*> FrameNodeImpl::GetChildFrameNodes()
  376. const {
  377. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  378. return UpcastNodeSet<FrameNode>(child_frame_nodes());
  379. }
  380. bool FrameNodeImpl::VisitOpenedPageNodes(const PageNodeVisitor& visitor) const {
  381. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  382. for (auto* page_impl : opened_page_nodes()) {
  383. const PageNode* page = page_impl;
  384. if (!visitor.Run(page))
  385. return false;
  386. }
  387. return true;
  388. }
  389. const base::flat_set<const PageNode*> FrameNodeImpl::GetOpenedPageNodes()
  390. const {
  391. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  392. return UpcastNodeSet<PageNode>(opened_page_nodes());
  393. }
  394. bool FrameNodeImpl::VisitEmbeddedPageNodes(
  395. const PageNodeVisitor& visitor) const {
  396. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  397. for (auto* page_impl : embedded_page_nodes()) {
  398. const PageNode* page = page_impl;
  399. if (!visitor.Run(page))
  400. return false;
  401. }
  402. return true;
  403. }
  404. const base::flat_set<const PageNode*> FrameNodeImpl::GetEmbeddedPageNodes()
  405. const {
  406. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  407. return UpcastNodeSet<PageNode>(embedded_page_nodes());
  408. }
  409. FrameNodeImpl::LifecycleState FrameNodeImpl::GetLifecycleState() const {
  410. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  411. return lifecycle_state();
  412. }
  413. bool FrameNodeImpl::HasNonemptyBeforeUnload() const {
  414. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  415. return has_nonempty_beforeunload();
  416. }
  417. const GURL& FrameNodeImpl::GetURL() const {
  418. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  419. return url();
  420. }
  421. bool FrameNodeImpl::IsCurrent() const {
  422. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  423. return is_current();
  424. }
  425. bool FrameNodeImpl::GetNetworkAlmostIdle() const {
  426. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  427. return network_almost_idle();
  428. }
  429. bool FrameNodeImpl::IsAdFrame() const {
  430. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  431. return is_ad_frame();
  432. }
  433. bool FrameNodeImpl::IsHoldingWebLock() const {
  434. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  435. return is_holding_weblock();
  436. }
  437. bool FrameNodeImpl::IsHoldingIndexedDBLock() const {
  438. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  439. return is_holding_indexeddb_lock();
  440. }
  441. const base::flat_set<const WorkerNode*> FrameNodeImpl::GetChildWorkerNodes()
  442. const {
  443. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  444. return UpcastNodeSet<WorkerNode>(child_worker_nodes());
  445. }
  446. bool FrameNodeImpl::VisitChildDedicatedWorkers(
  447. const WorkerNodeVisitor& visitor) const {
  448. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  449. for (auto* worker_node_impl : child_worker_nodes()) {
  450. const WorkerNode* node = worker_node_impl;
  451. if (node->GetWorkerType() == WorkerNode::WorkerType::kDedicated &&
  452. !visitor.Run(node))
  453. return false;
  454. }
  455. return true;
  456. }
  457. const PriorityAndReason& FrameNodeImpl::GetPriorityAndReason() const {
  458. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  459. return priority_and_reason();
  460. }
  461. bool FrameNodeImpl::HadFormInteraction() const {
  462. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  463. return had_form_interaction();
  464. }
  465. bool FrameNodeImpl::IsAudible() const {
  466. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  467. return is_audible();
  468. }
  469. const absl::optional<gfx::Rect>& FrameNodeImpl::GetViewportIntersection()
  470. const {
  471. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  472. return viewport_intersection();
  473. }
  474. FrameNode::Visibility FrameNodeImpl::GetVisibility() const {
  475. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  476. return visibility();
  477. }
  478. void FrameNodeImpl::AddChildFrame(FrameNodeImpl* child_frame_node) {
  479. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  480. DCHECK(child_frame_node);
  481. DCHECK_EQ(this, child_frame_node->parent_frame_node());
  482. DCHECK_NE(this, child_frame_node);
  483. DCHECK(graph()->NodeInGraph(child_frame_node));
  484. DCHECK(!HasFrameNodeInAncestors(child_frame_node) &&
  485. !child_frame_node->HasFrameNodeInDescendants(this));
  486. bool inserted = child_frame_nodes_.insert(child_frame_node).second;
  487. DCHECK(inserted);
  488. }
  489. void FrameNodeImpl::RemoveChildFrame(FrameNodeImpl* child_frame_node) {
  490. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  491. DCHECK(child_frame_node);
  492. DCHECK_EQ(this, child_frame_node->parent_frame_node());
  493. DCHECK_NE(this, child_frame_node);
  494. DCHECK(graph()->NodeInGraph(child_frame_node));
  495. size_t removed = child_frame_nodes_.erase(child_frame_node);
  496. DCHECK_EQ(1u, removed);
  497. }
  498. void FrameNodeImpl::OnJoiningGraph() {
  499. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  500. // Enable querying this node using process and frame routing ids.
  501. graph()->RegisterFrameNodeForId(process_node_->GetRenderProcessId(),
  502. render_frame_id_, this);
  503. // Set the initial frame visibility. This is done on the graph because the
  504. // page node must be accessed. OnFrameNodeAdded() has not been called yet for
  505. // this frame, so it is important to avoid sending a notification for this
  506. // property change.
  507. visibility_.Set(this, GetInitialFrameVisibility());
  508. // Wire this up to the other nodes in the graph.
  509. if (parent_frame_node_)
  510. parent_frame_node_->AddChildFrame(this);
  511. page_node_->AddFrame(base::PassKey<FrameNodeImpl>(), this);
  512. process_node_->AddFrame(this);
  513. }
  514. void FrameNodeImpl::OnBeforeLeavingGraph() {
  515. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  516. DCHECK(child_frame_nodes_.empty());
  517. SeverPageRelationshipsAndMaybeReparent();
  518. // Leave the page.
  519. DCHECK(graph()->NodeInGraph(page_node_));
  520. page_node_->RemoveFrame(base::PassKey<FrameNodeImpl>(), this);
  521. // Leave the frame hierarchy.
  522. if (parent_frame_node_) {
  523. DCHECK(graph()->NodeInGraph(parent_frame_node_));
  524. parent_frame_node_->RemoveChildFrame(this);
  525. }
  526. // And leave the process.
  527. DCHECK(graph()->NodeInGraph(process_node_));
  528. process_node_->RemoveFrame(this);
  529. // Disable querying this node using process and frame routing ids.
  530. graph()->UnregisterFrameNodeForId(process_node_->GetRenderProcessId(),
  531. render_frame_id_, this);
  532. }
  533. void FrameNodeImpl::RemoveNodeAttachedData() {
  534. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  535. execution_context_.reset();
  536. }
  537. void FrameNodeImpl::SeverPageRelationshipsAndMaybeReparent() {
  538. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  539. // Be careful when iterating: when we call
  540. // PageNodeImpl::(Set|Clear)(Opener|Embedder)FrameNode() this will call
  541. // back into this frame node and call Remove(Opened|Embedded)Page(), which
  542. // modifies |opened_page_nodes_| and |embedded_page_nodes_|.
  543. //
  544. // We also reparent related pages to this frame's parent to maintain the
  545. // relationship between the distinct frame trees for bookkeeping. For the
  546. // relationship to be finally severed one of the frame trees must completely
  547. // disappear, or it must be explicitly severed (this can happen with
  548. // portals).
  549. while (!opened_page_nodes_.empty()) {
  550. auto* opened_node = *opened_page_nodes_.begin();
  551. if (parent_frame_node_) {
  552. opened_node->SetOpenerFrameNode(parent_frame_node_);
  553. } else {
  554. opened_node->ClearOpenerFrameNode();
  555. }
  556. DCHECK(!base::Contains(opened_page_nodes_, opened_node));
  557. }
  558. while (!embedded_page_nodes_.empty()) {
  559. auto* embedded_node = *embedded_page_nodes_.begin();
  560. auto embedding_type = embedded_node->embedding_type();
  561. if (parent_frame_node_) {
  562. embedded_node->SetEmbedderFrameNodeAndEmbeddingType(parent_frame_node_,
  563. embedding_type);
  564. } else {
  565. embedded_node->ClearEmbedderFrameNodeAndEmbeddingType();
  566. }
  567. DCHECK(!base::Contains(embedded_page_nodes_, embedded_node));
  568. }
  569. // Expect each page node to have called RemoveEmbeddedPage(), and for this to
  570. // now be empty.
  571. DCHECK(opened_page_nodes_.empty());
  572. DCHECK(embedded_page_nodes_.empty());
  573. }
  574. FrameNodeImpl* FrameNodeImpl::GetFrameTreeRoot() const {
  575. FrameNodeImpl* root = const_cast<FrameNodeImpl*>(this);
  576. while (root->parent_frame_node())
  577. root = parent_frame_node();
  578. DCHECK_NE(nullptr, root);
  579. return root;
  580. }
  581. bool FrameNodeImpl::HasFrameNodeInAncestors(FrameNodeImpl* frame_node) const {
  582. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  583. if (parent_frame_node_ == frame_node ||
  584. (parent_frame_node_ &&
  585. parent_frame_node_->HasFrameNodeInAncestors(frame_node))) {
  586. return true;
  587. }
  588. return false;
  589. }
  590. bool FrameNodeImpl::HasFrameNodeInDescendants(FrameNodeImpl* frame_node) const {
  591. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  592. for (FrameNodeImpl* child : child_frame_nodes_) {
  593. if (child == frame_node || child->HasFrameNodeInDescendants(frame_node)) {
  594. return true;
  595. }
  596. }
  597. return false;
  598. }
  599. bool FrameNodeImpl::HasFrameNodeInTree(FrameNodeImpl* frame_node) const {
  600. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  601. return GetFrameTreeRoot() == frame_node->GetFrameTreeRoot();
  602. }
  603. FrameNode::Visibility FrameNodeImpl::GetInitialFrameVisibility() const {
  604. DCHECK(!viewport_intersection_.value());
  605. // If the page hosting this frame is not visible, then the frame is also not
  606. // visible.
  607. if (!page_node()->is_visible())
  608. return FrameNode::Visibility::kNotVisible;
  609. // The visibility of the frame depends on the viewport intersection of said
  610. // frame. Since a main frame has no viewport intersection, it is always
  611. // visible in the page.
  612. if (IsMainFrame())
  613. return FrameNode::Visibility::kVisible;
  614. // Since the viewport intersection of a frame is not initially available, the
  615. // visibility of a child frame is initially unknown.
  616. return FrameNode::Visibility::kUnknown;
  617. }
  618. FrameNodeImpl::DocumentProperties::DocumentProperties() = default;
  619. FrameNodeImpl::DocumentProperties::~DocumentProperties() = default;
  620. void FrameNodeImpl::DocumentProperties::Reset(FrameNodeImpl* frame_node,
  621. const GURL& url_in) {
  622. url.SetAndMaybeNotify(frame_node, url_in);
  623. has_nonempty_beforeunload = false;
  624. // Network is busy on navigation.
  625. network_almost_idle.SetAndMaybeNotify(frame_node, false);
  626. had_form_interaction.SetAndMaybeNotify(frame_node, false);
  627. }
  628. void FrameNodeImpl::OnWebMemoryMeasurementRequested(
  629. mojom::WebMemoryMeasurement::Mode mode,
  630. OnWebMemoryMeasurementRequestedCallback callback) {
  631. v8_memory::WebMeasureMemory(
  632. this, mode, v8_memory::WebMeasureMemorySecurityChecker::Create(),
  633. std::move(callback), mojo::GetBadMessageCallback());
  634. }
  635. } // namespace performance_manager