OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/frame_host/navigation_entry_impl.h" | 5 #include "content/browser/frame_host/navigation_entry_impl.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 | 8 |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 | 26 |
27 int NavigationEntryImpl::kInvalidBindings = -1; | 27 int NavigationEntryImpl::kInvalidBindings = -1; |
28 | 28 |
29 NavigationEntryImpl::TreeNode::TreeNode(FrameNavigationEntry* frame_entry) | 29 NavigationEntryImpl::TreeNode::TreeNode(FrameNavigationEntry* frame_entry) |
30 : frame_entry(frame_entry) { | 30 : frame_entry(frame_entry) { |
31 } | 31 } |
32 | 32 |
33 NavigationEntryImpl::TreeNode::~TreeNode() { | 33 NavigationEntryImpl::TreeNode::~TreeNode() { |
34 } | 34 } |
35 | 35 |
| 36 bool NavigationEntryImpl::TreeNode::MatchesFrame( |
| 37 FrameTreeNode* frame_tree_node) const { |
| 38 if (frame_tree_node->frame_tree_node_id() == |
| 39 frame_entry->frame_tree_node_id()) |
| 40 return true; |
| 41 |
| 42 // For now, we set the root FNE's FrameTreeNode ID to -1. |
| 43 return frame_tree_node->IsMainFrame() && |
| 44 frame_entry->frame_tree_node_id() == -1; |
| 45 } |
| 46 |
36 NavigationEntryImpl::TreeNode* NavigationEntryImpl::TreeNode::Clone() const { | 47 NavigationEntryImpl::TreeNode* NavigationEntryImpl::TreeNode::Clone() const { |
37 // Clone the tree using a copy of the FrameNavigationEntry, without sharing. | 48 // Clone the tree using a copy of the FrameNavigationEntry, without sharing. |
38 NavigationEntryImpl::TreeNode* copy = | 49 NavigationEntryImpl::TreeNode* copy = |
39 new NavigationEntryImpl::TreeNode(frame_entry->Clone()); | 50 new NavigationEntryImpl::TreeNode(frame_entry->Clone()); |
40 | 51 |
41 // TODO(creis): Clone children once we add them. | 52 // TODO(creis): Clone children once we add them. |
42 return copy; | 53 return copy; |
43 } | 54 } |
44 | 55 |
45 NavigationEntry* NavigationEntry::Create() { | 56 NavigationEntry* NavigationEntry::Create() { |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 } | 423 } |
413 | 424 |
414 return StartNavigationParams( | 425 return StartNavigationParams( |
415 GetHasPostData(), extra_headers(), browser_initiated_post_data, | 426 GetHasPostData(), extra_headers(), browser_initiated_post_data, |
416 should_replace_entry(), transferred_global_request_id().child_id, | 427 should_replace_entry(), transferred_global_request_id().child_id, |
417 transferred_global_request_id().request_id); | 428 transferred_global_request_id().request_id); |
418 } | 429 } |
419 | 430 |
420 RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams( | 431 RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams( |
421 base::TimeTicks navigation_start, | 432 base::TimeTicks navigation_start, |
| 433 bool has_committed_real_load, |
422 bool intended_as_new_entry, | 434 bool intended_as_new_entry, |
423 int pending_history_list_offset, | 435 int pending_history_list_offset, |
424 int current_history_list_offset, | 436 int current_history_list_offset, |
425 int current_history_list_length) const { | 437 int current_history_list_length) const { |
426 // Set the redirect chain to the navigation's redirects, unless returning to a | 438 // Set the redirect chain to the navigation's redirects, unless returning to a |
427 // completed navigation (whose previous redirects don't apply). | 439 // completed navigation (whose previous redirects don't apply). |
428 std::vector<GURL> redirects; | 440 std::vector<GURL> redirects; |
429 if (ui::PageTransitionIsNewNavigation(GetTransitionType())) { | 441 if (ui::PageTransitionIsNewNavigation(GetTransitionType())) { |
430 redirects = GetRedirectChain(); | 442 redirects = GetRedirectChain(); |
431 } | 443 } |
432 | 444 |
433 int pending_offset_to_send = pending_history_list_offset; | 445 int pending_offset_to_send = pending_history_list_offset; |
434 int current_offset_to_send = current_history_list_offset; | 446 int current_offset_to_send = current_history_list_offset; |
435 int current_length_to_send = current_history_list_length; | 447 int current_length_to_send = current_history_list_length; |
436 if (should_clear_history_list()) { | 448 if (should_clear_history_list()) { |
437 // Set the history list related parameters to the same values a | 449 // Set the history list related parameters to the same values a |
438 // NavigationController would return before its first navigation. This will | 450 // NavigationController would return before its first navigation. This will |
439 // fully clear the RenderView's view of the session history. | 451 // fully clear the RenderView's view of the session history. |
440 pending_offset_to_send = -1; | 452 pending_offset_to_send = -1; |
441 current_offset_to_send = -1; | 453 current_offset_to_send = -1; |
442 current_length_to_send = 0; | 454 current_length_to_send = 0; |
443 } | 455 } |
444 return RequestNavigationParams( | 456 return RequestNavigationParams( |
445 GetIsOverridingUserAgent(), navigation_start, redirects, | 457 GetIsOverridingUserAgent(), navigation_start, redirects, |
446 GetCanLoadLocalResources(), base::Time::Now(), GetPageState(), | 458 GetCanLoadLocalResources(), base::Time::Now(), GetPageState(), |
447 GetPageID(), GetUniqueID(), intended_as_new_entry, pending_offset_to_send, | 459 GetPageID(), GetUniqueID(), has_committed_real_load, |
448 current_offset_to_send, current_length_to_send, | 460 intended_as_new_entry, pending_offset_to_send, current_offset_to_send, |
449 should_clear_history_list()); | 461 current_length_to_send, should_clear_history_list()); |
450 } | 462 } |
451 | 463 |
452 void NavigationEntryImpl::ResetForCommit() { | 464 void NavigationEntryImpl::ResetForCommit() { |
453 // Any state that only matters when a navigation entry is pending should be | 465 // Any state that only matters when a navigation entry is pending should be |
454 // cleared here. | 466 // cleared here. |
455 // TODO(creis): This state should be moved to NavigationRequest once | 467 // TODO(creis): This state should be moved to NavigationRequest once |
456 // PlzNavigate is enabled. | 468 // PlzNavigate is enabled. |
457 SetBrowserInitiatedPostData(nullptr); | 469 SetBrowserInitiatedPostData(nullptr); |
458 set_source_site_instance(nullptr); | 470 set_source_site_instance(nullptr); |
459 set_is_renderer_initiated(false); | 471 set_is_renderer_initiated(false); |
(...skipping 10 matching lines...) Expand all Loading... |
470 #endif | 482 #endif |
471 } | 483 } |
472 | 484 |
473 void NavigationEntryImpl::AddOrUpdateFrameEntry(FrameTreeNode* frame_tree_node, | 485 void NavigationEntryImpl::AddOrUpdateFrameEntry(FrameTreeNode* frame_tree_node, |
474 SiteInstanceImpl* site_instance, | 486 SiteInstanceImpl* site_instance, |
475 const GURL& url, | 487 const GURL& url, |
476 const Referrer& referrer) { | 488 const Referrer& referrer) { |
477 // We should already have a TreeNode for the parent node by the time this node | 489 // We should already have a TreeNode for the parent node by the time this node |
478 // commits. Find it first. | 490 // commits. Find it first. |
479 DCHECK(frame_tree_node->parent()); | 491 DCHECK(frame_tree_node->parent()); |
480 int parent_ftn_id = frame_tree_node->parent()->frame_tree_node_id(); | 492 NavigationEntryImpl::TreeNode* parent_node = |
481 bool found = false; | 493 FindFrameEntry(frame_tree_node->parent()); |
482 NavigationEntryImpl::TreeNode* parent_node = nullptr; | 494 if (!parent_node) { |
483 std::queue<NavigationEntryImpl::TreeNode*> work_queue; | |
484 work_queue.push(root_node()); | |
485 while (!found && !work_queue.empty()) { | |
486 parent_node = work_queue.front(); | |
487 work_queue.pop(); | |
488 // The root FNE will have an ID of -1, so check for that as well. | |
489 if (parent_node->frame_entry->frame_tree_node_id() == parent_ftn_id || | |
490 (parent_node->frame_entry->frame_tree_node_id() == -1 && | |
491 parent_node == root_node() && | |
492 frame_tree_node->parent()->IsMainFrame())) { | |
493 found = true; | |
494 break; | |
495 } | |
496 // Enqueue any children and keep looking. | |
497 for (auto& child : parent_node->children) | |
498 work_queue.push(child); | |
499 } | |
500 if (!found) { | |
501 // The renderer should not send a commit for a subframe before its parent. | 495 // The renderer should not send a commit for a subframe before its parent. |
502 // TODO(creis): This can currently happen because we don't yet clone the | 496 // TODO(creis): This can currently happen because we don't yet clone the |
503 // FrameNavigationEntry tree on manual subframe navigations. Once that's | 497 // FrameNavigationEntry tree on manual subframe navigations. Once that's |
504 // added, we should kill the renderer if we get here. | 498 // added, we should kill the renderer if we get here. |
505 return; | 499 return; |
506 } | 500 } |
507 | 501 |
508 // Now check whether we have a TreeNode for the node itself. | 502 // Now check whether we have a TreeNode for the node itself. |
509 int frame_tree_node_id = frame_tree_node->frame_tree_node_id(); | 503 int frame_tree_node_id = frame_tree_node->frame_tree_node_id(); |
510 for (TreeNode* child : parent_node->children) { | 504 for (TreeNode* child : parent_node->children) { |
511 if (child->frame_entry->frame_tree_node_id() == frame_tree_node_id) { | 505 if (child->frame_entry->frame_tree_node_id() == frame_tree_node_id) { |
512 // Update the existing FrameNavigationEntry. | 506 // Update the existing FrameNavigationEntry. |
513 child->frame_entry->UpdateEntry(site_instance, url, referrer); | 507 child->frame_entry->UpdateEntry(site_instance, url, referrer); |
514 return; | 508 return; |
515 } | 509 } |
516 } | 510 } |
517 | 511 |
518 // No entry exists yet, so create a new one. Unordered list, since we expect | 512 // No entry exists yet, so create a new one unless it's for about:blank. |
519 // to look up entries by frame sequence number or unique name. | 513 // Unordered list, since we expect to look up entries by frame sequence number |
| 514 // or unique name. |
| 515 if (url == GURL(url::kAboutBlankURL)) |
| 516 return; |
520 FrameNavigationEntry* frame_entry = new FrameNavigationEntry( | 517 FrameNavigationEntry* frame_entry = new FrameNavigationEntry( |
521 frame_tree_node_id, site_instance, url, referrer); | 518 frame_tree_node_id, site_instance, url, referrer); |
522 parent_node->children.push_back( | 519 parent_node->children.push_back( |
523 new NavigationEntryImpl::TreeNode(frame_entry)); | 520 new NavigationEntryImpl::TreeNode(frame_entry)); |
524 } | 521 } |
525 | 522 |
| 523 bool NavigationEntryImpl::HasFrameEntry(FrameTreeNode* frame_tree_node) const { |
| 524 return FindFrameEntry(frame_tree_node) != nullptr; |
| 525 } |
| 526 |
526 void NavigationEntryImpl::SetScreenshotPNGData( | 527 void NavigationEntryImpl::SetScreenshotPNGData( |
527 scoped_refptr<base::RefCountedBytes> png_data) { | 528 scoped_refptr<base::RefCountedBytes> png_data) { |
528 screenshot_ = png_data; | 529 screenshot_ = png_data; |
529 if (screenshot_.get()) | 530 if (screenshot_.get()) |
530 UMA_HISTOGRAM_MEMORY_KB("Overscroll.ScreenshotSize", screenshot_->size()); | 531 UMA_HISTOGRAM_MEMORY_KB("Overscroll.ScreenshotSize", screenshot_->size()); |
531 } | 532 } |
532 | 533 |
533 GURL NavigationEntryImpl::GetHistoryURLForDataURL() const { | 534 GURL NavigationEntryImpl::GetHistoryURLForDataURL() const { |
534 return GetBaseURLForDataURL().is_empty() ? GURL() : GetVirtualURL(); | 535 return GetBaseURLForDataURL().is_empty() ? GURL() : GetVirtualURL(); |
535 } | 536 } |
536 | 537 |
| 538 NavigationEntryImpl::TreeNode* NavigationEntryImpl::FindFrameEntry( |
| 539 FrameTreeNode* frame_tree_node) const { |
| 540 NavigationEntryImpl::TreeNode* node = nullptr; |
| 541 std::queue<NavigationEntryImpl::TreeNode*> work_queue; |
| 542 work_queue.push(root_node()); |
| 543 while (!work_queue.empty()) { |
| 544 node = work_queue.front(); |
| 545 work_queue.pop(); |
| 546 if (node->MatchesFrame(frame_tree_node)) { |
| 547 // Only the root TreeNode should have a FTN ID of -1. |
| 548 DCHECK_IMPLIES(node->frame_entry->frame_tree_node_id() == -1, |
| 549 node == root_node()); |
| 550 return node; |
| 551 } |
| 552 // Enqueue any children and keep looking. |
| 553 for (auto& child : node->children) |
| 554 work_queue.push(child); |
| 555 } |
| 556 return nullptr; |
| 557 } |
| 558 |
537 } // namespace content | 559 } // namespace content |
OLD | NEW |