summaryrefslogtreecommitdiffstats
path: root/components/html_viewer/html_frame_tree_manager.cc
diff options
context:
space:
mode:
authoryzshen <yzshen@chromium.org>2015-09-30 15:08:35 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-30 22:09:21 +0000
commit27cebfb9d21017f13f4af86d4a7b1dc4fdb2d913 (patch)
tree3788f07cb76bedf424845b57a704ba297d994cf8 /components/html_viewer/html_frame_tree_manager.cc
parent47ac70588e80993b22cdc6737baec8057ebd965d (diff)
downloadchromium_src-27cebfb9d21017f13f4af86d4a7b1dc4fdb2d913.zip
chromium_src-27cebfb9d21017f13f4af86d4a7b1dc4fdb2d913.tar.gz
chromium_src-27cebfb9d21017f13f4af86d4a7b1dc4fdb2d913.tar.bz2
Don't delete HTMLFrameTreeManager when the local root is removed but we still have local frames that are not descendants of this local root.
In that case, we need to select a new local root. BUG=None Review URL: https://codereview.chromium.org/1383603002 Cr-Commit-Position: refs/heads/master@{#351654}
Diffstat (limited to 'components/html_viewer/html_frame_tree_manager.cc')
-rw-r--r--components/html_viewer/html_frame_tree_manager.cc65
1 files changed, 51 insertions, 14 deletions
diff --git a/components/html_viewer/html_frame_tree_manager.cc b/components/html_viewer/html_frame_tree_manager.cc
index bae5b7b..2cefb66 100644
--- a/components/html_viewer/html_frame_tree_manager.cc
+++ b/components/html_viewer/html_frame_tree_manager.cc
@@ -178,29 +178,39 @@ void HTMLFrameTreeManager::RemoveObserver(
}
void HTMLFrameTreeManager::OnFrameDestroyed(HTMLFrame* frame) {
- if (frame == root_)
- root_ = nullptr;
-
- if (frame == local_root_)
- local_root_ = nullptr;
-
if (!in_process_on_frame_removed_)
pending_remove_ids_.insert(frame->id());
- if (!local_root_ || !local_root_->HasLocalDescendant())
+ if (frame == root_) {
+ // If |root_| is removed before |local_frame_|, we don't have a way to
+ // select a new local frame when |local_frame_| is removed. On the other
+ // hand, it is impossible to remove |root_| after all local frames are gone,
+ // because by that time this object has already been deleted.
+ CHECK_EQ(root_, local_frame_);
+ root_ = nullptr;
+ }
+
+ if (frame != local_frame_)
+ return;
+
+ // |local_frame_| is being removed. We need to find out whether we have local
+ // frames that are not descendants of |local_frame_|, and if yes select a new
+ // |local_frame_|.
+ local_frame_ = FindNewLocalFrame();
+ if (!local_frame_)
delete this;
}
HTMLFrameTreeManager::HTMLFrameTreeManager(GlobalState* global_state)
: global_state_(global_state),
root_(nullptr),
- local_root_(nullptr),
+ local_frame_(nullptr),
change_id_(0u),
in_process_on_frame_removed_(false),
weak_factory_(this) {}
HTMLFrameTreeManager::~HTMLFrameTreeManager() {
- DCHECK(!root_ || !local_root_);
+ DCHECK(!local_frame_);
RemoveFromInstances();
FOR_EACH_OBSERVER(HTMLFrameTreeManagerObserver, observers_,
@@ -214,9 +224,9 @@ void HTMLFrameTreeManager::Init(
uint32_t change_id) {
change_id_ = change_id;
root_ = BuildFrameTree(delegate, frame_data, local_view->id(), local_view);
- local_root_ = root_->FindFrame(local_view->id());
- CHECK(local_root_);
- local_root_->UpdateFocus();
+ local_frame_ = root_->FindFrame(local_view->id());
+ CHECK(local_frame_);
+ local_frame_->UpdateFocus();
}
HTMLFrame* HTMLFrameTreeManager::BuildFrameTree(
@@ -268,7 +278,7 @@ bool HTMLFrameTreeManager::PrepareForStructureChange(HTMLFrame* source,
return false;
// We only process changes for the topmost local root.
- if (source != local_root_)
+ if (source != local_frame_)
return false;
// Update the id as the change is going to be applied (or we can assume it
@@ -359,7 +369,7 @@ void HTMLFrameTreeManager::ProcessOnFrameClientPropertyChanged(
uint32_t frame_id,
const mojo::String& name,
mojo::Array<uint8_t> new_data) {
- if (source != local_root_)
+ if (source != local_frame_)
return;
HTMLFrame* frame = root_->FindFrame(frame_id);
@@ -367,4 +377,31 @@ void HTMLFrameTreeManager::ProcessOnFrameClientPropertyChanged(
frame->SetValueFromClientProperty(name, new_data.Pass());
}
+HTMLFrame* HTMLFrameTreeManager::FindNewLocalFrame() {
+ HTMLFrame* new_local_frame = nullptr;
+
+ if (root_) {
+ std::queue<HTMLFrame*> nodes;
+ nodes.push(root_);
+
+ while (!nodes.empty()) {
+ HTMLFrame* node = nodes.front();
+ nodes.pop();
+
+ if (node == local_frame_)
+ continue;
+
+ if (node->IsLocal()) {
+ new_local_frame = node;
+ break;
+ }
+
+ for (const auto& child : node->children())
+ nodes.push(child);
+ }
+ }
+
+ return new_local_frame;
+}
+
} // namespace mojo