Chromium Code Reviews| 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 NavigationEntryImpl::TreeNode* NavigationEntryImpl::TreeNode::Clone() const { | 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 | |
| 47 NavigationEntryImpl::TreeNode* NavigationEntryImpl::TreeNode::CloneAndReplace( | |
| 48 FrameTreeNode* frame_tree_node, | |
| 49 FrameNavigationEntry* frame_navigation_entry) const { | |
| 50 if (frame_tree_node && MatchesFrame(frame_tree_node)) { | |
| 51 // Replace this node in the cloned tree and prune its children. | |
| 52 return new NavigationEntryImpl::TreeNode(frame_navigation_entry); | |
| 53 } | |
| 54 | |
| 37 // Clone the tree using a copy of the FrameNavigationEntry, without sharing. | 55 // Clone the tree using a copy of the FrameNavigationEntry, without sharing. |
| 56 // TODO(creis): Share FNEs unless it's for another tab. | |
| 38 NavigationEntryImpl::TreeNode* copy = | 57 NavigationEntryImpl::TreeNode* copy = |
| 39 new NavigationEntryImpl::TreeNode(frame_entry->Clone()); | 58 new NavigationEntryImpl::TreeNode(frame_entry->Clone()); |
| 40 | 59 |
| 41 // TODO(creis): Clone children once we add them. | 60 // Recursively clone the children. |
| 61 for (auto& child : children) { | |
| 62 copy->children.push_back( | |
| 63 child->CloneAndReplace(frame_tree_node, frame_navigation_entry)); | |
| 64 } | |
| 65 | |
| 42 return copy; | 66 return copy; |
| 43 } | 67 } |
| 44 | 68 |
| 45 NavigationEntry* NavigationEntry::Create() { | 69 NavigationEntry* NavigationEntry::Create() { |
| 46 return new NavigationEntryImpl(); | 70 return new NavigationEntryImpl(); |
| 47 } | 71 } |
| 48 | 72 |
| 49 NavigationEntryImpl* NavigationEntryImpl::FromNavigationEntry( | 73 NavigationEntryImpl* NavigationEntryImpl::FromNavigationEntry( |
| 50 NavigationEntry* entry) { | 74 NavigationEntry* entry) { |
| 51 return static_cast<NavigationEntryImpl*>(entry); | 75 return static_cast<NavigationEntryImpl*>(entry); |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 return false; | 352 return false; |
| 329 *data = iter->second; | 353 *data = iter->second; |
| 330 return true; | 354 return true; |
| 331 } | 355 } |
| 332 | 356 |
| 333 void NavigationEntryImpl::ClearExtraData(const std::string& key) { | 357 void NavigationEntryImpl::ClearExtraData(const std::string& key) { |
| 334 extra_data_.erase(key); | 358 extra_data_.erase(key); |
| 335 } | 359 } |
| 336 | 360 |
| 337 NavigationEntryImpl* NavigationEntryImpl::Clone() const { | 361 NavigationEntryImpl* NavigationEntryImpl::Clone() const { |
| 362 return NavigationEntryImpl::CloneAndReplace(nullptr, nullptr); | |
| 363 } | |
| 364 | |
| 365 NavigationEntryImpl* NavigationEntryImpl::CloneAndReplace( | |
| 366 FrameTreeNode* frame_tree_node, | |
| 367 FrameNavigationEntry* frame_navigation_entry) const { | |
| 338 NavigationEntryImpl* copy = new NavigationEntryImpl(); | 368 NavigationEntryImpl* copy = new NavigationEntryImpl(); |
| 339 | 369 |
| 340 // TODO(creis): Only share the same FrameNavigationEntries if cloning within | 370 // TODO(creis): Only share the same FrameNavigationEntries if cloning within |
| 341 // the same tab. | 371 // the same tab. |
| 342 copy->frame_tree_.reset(frame_tree_->Clone()); | 372 copy->frame_tree_.reset( |
| 373 frame_tree_->CloneAndReplace(frame_tree_node, frame_navigation_entry)); | |
| 343 | 374 |
| 344 // Copy all state over, unless cleared in ResetForCommit. | 375 // Copy all state over, unless cleared in ResetForCommit. |
| 345 copy->unique_id_ = unique_id_; | 376 copy->unique_id_ = unique_id_; |
| 346 copy->bindings_ = bindings_; | 377 copy->bindings_ = bindings_; |
| 347 copy->page_type_ = page_type_; | 378 copy->page_type_ = page_type_; |
| 348 copy->virtual_url_ = virtual_url_; | 379 copy->virtual_url_ = virtual_url_; |
| 349 copy->update_virtual_url_with_url_ = update_virtual_url_with_url_; | 380 copy->update_virtual_url_with_url_ = update_virtual_url_with_url_; |
| 350 copy->title_ = title_; | 381 copy->title_ = title_; |
| 351 copy->favicon_ = favicon_; | 382 copy->favicon_ = favicon_; |
| 352 copy->page_state_ = page_state_; | 383 copy->page_state_ = page_state_; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 465 #endif | 496 #endif |
| 466 } | 497 } |
| 467 | 498 |
| 468 void NavigationEntryImpl::AddOrUpdateFrameEntry(FrameTreeNode* frame_tree_node, | 499 void NavigationEntryImpl::AddOrUpdateFrameEntry(FrameTreeNode* frame_tree_node, |
| 469 SiteInstanceImpl* site_instance, | 500 SiteInstanceImpl* site_instance, |
| 470 const GURL& url, | 501 const GURL& url, |
| 471 const Referrer& referrer) { | 502 const Referrer& referrer) { |
| 472 // We should already have a TreeNode for the parent node by the time this node | 503 // We should already have a TreeNode for the parent node by the time this node |
| 473 // commits. Find it first. | 504 // commits. Find it first. |
| 474 DCHECK(frame_tree_node->parent()); | 505 DCHECK(frame_tree_node->parent()); |
| 475 int parent_ftn_id = frame_tree_node->parent()->frame_tree_node_id(); | |
| 476 bool found = false; | 506 bool found = false; |
| 477 NavigationEntryImpl::TreeNode* parent_node = nullptr; | 507 NavigationEntryImpl::TreeNode* parent_node = nullptr; |
| 478 std::queue<NavigationEntryImpl::TreeNode*> work_queue; | 508 std::queue<NavigationEntryImpl::TreeNode*> work_queue; |
| 479 work_queue.push(root_node()); | 509 work_queue.push(root_node()); |
| 480 while (!found && !work_queue.empty()) { | 510 while (!found && !work_queue.empty()) { |
| 481 parent_node = work_queue.front(); | 511 parent_node = work_queue.front(); |
| 482 work_queue.pop(); | 512 work_queue.pop(); |
| 483 // The root FNE will have an ID of -1, so check for that as well. | 513 if (parent_node->MatchesFrame(frame_tree_node->parent())) { |
| 484 if (parent_node->frame_entry->frame_tree_node_id() == parent_ftn_id || | 514 // Only the root TreeNode should have a FTN ID of -1. |
| 485 (parent_node->frame_entry->frame_tree_node_id() == -1 && | 515 DCHECK_IMPLIES(parent_node->frame_entry->frame_tree_node_id() == -1, |
| 486 parent_node == root_node() && | 516 parent_node == root_node()); |
|
Avi (use Gerrit)
2015/05/19 16:34:13
I <3 DCHECK_IMPLIES.
| |
| 487 frame_tree_node->parent()->IsMainFrame())) { | |
| 488 found = true; | 517 found = true; |
| 489 break; | 518 break; |
| 490 } | 519 } |
| 491 // Enqueue any children and keep looking. | 520 // Enqueue any children and keep looking. |
| 492 for (auto& child : parent_node->children) | 521 for (auto& child : parent_node->children) |
| 493 work_queue.push(child); | 522 work_queue.push(child); |
| 494 } | 523 } |
| 495 if (!found) { | 524 if (!found) { |
| 496 // The renderer should not send a commit for a subframe before its parent. | 525 // The renderer should not send a commit for a subframe before its parent. |
| 497 // TODO(creis): This can currently happen because we don't yet clone the | 526 // TODO(creis): Kill the renderer if we get here. |
| 498 // FrameNavigationEntry tree on manual subframe navigations. Once that's | 527 NOTREACHED() << "Shouldn't see a commit for a subframe before parent."; |
| 499 // added, we should kill the renderer if we get here. | |
| 500 return; | 528 return; |
| 501 } | 529 } |
| 502 | 530 |
| 503 // Now check whether we have a TreeNode for the node itself. | 531 // Now check whether we have a TreeNode for the node itself. |
| 504 int frame_tree_node_id = frame_tree_node->frame_tree_node_id(); | 532 int frame_tree_node_id = frame_tree_node->frame_tree_node_id(); |
| 505 for (TreeNode* child : parent_node->children) { | 533 for (TreeNode* child : parent_node->children) { |
| 506 if (child->frame_entry->frame_tree_node_id() == frame_tree_node_id) { | 534 if (child->frame_entry->frame_tree_node_id() == frame_tree_node_id) { |
| 507 // Update the existing FrameNavigationEntry. | 535 // Update the existing FrameNavigationEntry (e.g., for replaceState). |
| 508 child->frame_entry->UpdateEntry(site_instance, url, referrer); | 536 child->frame_entry->UpdateEntry(site_instance, url, referrer); |
| 509 return; | 537 return; |
| 510 } | 538 } |
| 511 } | 539 } |
| 512 | 540 |
| 513 // No entry exists yet, so create a new one. Unordered list, since we expect | 541 // No entry exists yet, so create a new one. Unordered list, since we expect |
| 514 // to look up entries by frame sequence number or unique name. | 542 // to look up entries by frame sequence number or unique name. |
| 515 FrameNavigationEntry* frame_entry = new FrameNavigationEntry( | 543 FrameNavigationEntry* frame_entry = new FrameNavigationEntry( |
| 516 frame_tree_node_id, site_instance, url, referrer); | 544 frame_tree_node_id, site_instance, url, referrer); |
| 517 parent_node->children.push_back( | 545 parent_node->children.push_back( |
| 518 new NavigationEntryImpl::TreeNode(frame_entry)); | 546 new NavigationEntryImpl::TreeNode(frame_entry)); |
| 519 } | 547 } |
| 520 | 548 |
| 521 void NavigationEntryImpl::SetScreenshotPNGData( | 549 void NavigationEntryImpl::SetScreenshotPNGData( |
| 522 scoped_refptr<base::RefCountedBytes> png_data) { | 550 scoped_refptr<base::RefCountedBytes> png_data) { |
| 523 screenshot_ = png_data; | 551 screenshot_ = png_data; |
| 524 if (screenshot_.get()) | 552 if (screenshot_.get()) |
| 525 UMA_HISTOGRAM_MEMORY_KB("Overscroll.ScreenshotSize", screenshot_->size()); | 553 UMA_HISTOGRAM_MEMORY_KB("Overscroll.ScreenshotSize", screenshot_->size()); |
| 526 } | 554 } |
| 527 | 555 |
| 528 GURL NavigationEntryImpl::GetHistoryURLForDataURL() const { | 556 GURL NavigationEntryImpl::GetHistoryURLForDataURL() const { |
| 529 return GetBaseURLForDataURL().is_empty() ? GURL() : GetVirtualURL(); | 557 return GetBaseURLForDataURL().is_empty() ? GURL() : GetVirtualURL(); |
| 530 } | 558 } |
| 531 | 559 |
| 532 } // namespace content | 560 } // namespace content |
| OLD | NEW |