Stack sampling profiler: add fire-and-forget interface
[chromium-blink-merge.git] / components / html_viewer / html_frame_tree_manager.cc
blobe7252b6c071b709a391a5ab15bf67a1602e4d388
1 // Copyright 2015 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.
5 #include "components/html_viewer/html_frame_tree_manager.h"
7 #include <algorithm>
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "components/html_viewer/blink_basic_type_converters.h"
12 #include "components/html_viewer/blink_url_request_type_converters.h"
13 #include "components/html_viewer/document_resource_waiter.h"
14 #include "components/html_viewer/global_state.h"
15 #include "components/html_viewer/html_frame.h"
16 #include "components/html_viewer/html_frame_delegate.h"
17 #include "components/html_viewer/html_viewer_switches.h"
18 #include "components/view_manager/public/cpp/view_manager.h"
19 #include "mojo/application/public/cpp/application_impl.h"
20 #include "third_party/WebKit/public/web/WebLocalFrame.h"
21 #include "third_party/WebKit/public/web/WebRemoteFrame.h"
22 #include "third_party/WebKit/public/web/WebTreeScopeType.h"
23 #include "third_party/WebKit/public/web/WebView.h"
24 #include "ui/gfx/geometry/dip_util.h"
25 #include "ui/gfx/geometry/size.h"
27 namespace html_viewer {
28 namespace {
30 // Returns the index of the FrameData with the id of |frame_id| in |index|. On
31 // success returns true, otherwise false.
32 bool FindFrameDataIndex(const mojo::Array<mandoline::FrameDataPtr>& frame_data,
33 uint32_t frame_id,
34 size_t* index) {
35 for (size_t i = 0; i < frame_data.size(); ++i) {
36 if (frame_data[i]->frame_id == frame_id) {
37 *index = i;
38 return true;
41 return false;
44 } // namespace
46 // static
47 HTMLFrameTreeManager::TreeMap* HTMLFrameTreeManager::instances_ = nullptr;
49 // static
50 HTMLFrame* HTMLFrameTreeManager::CreateFrameAndAttachToTree(
51 GlobalState* global_state,
52 mojo::ApplicationImpl* app,
53 mojo::View* view,
54 scoped_ptr<DocumentResourceWaiter> resource_waiter,
55 HTMLFrameDelegate* delegate) {
56 if (!instances_)
57 instances_ = new TreeMap;
59 mojo::InterfaceRequest<mandoline::FrameTreeClient> frame_tree_client_request;
60 mandoline::FrameTreeServerPtr frame_tree_server;
61 mojo::Array<mandoline::FrameDataPtr> frame_data;
62 resource_waiter->Release(&frame_tree_client_request, &frame_tree_server,
63 &frame_data);
64 resource_waiter.reset();
66 HTMLFrameTreeManager* frame_tree = nullptr;
68 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
69 switches::kOOPIFAlwaysCreateNewFrameTree)) {
70 if (instances_->count(frame_data[0]->frame_id))
71 frame_tree = (*instances_)[frame_data[0]->frame_id];
74 if (!frame_tree) {
75 frame_tree = new HTMLFrameTreeManager(global_state);
76 frame_tree->Init(delegate, view, frame_data);
77 if (frame_data[0]->frame_id == view->id())
78 (*instances_)[frame_data[0]->frame_id] = frame_tree;
79 } else {
80 // We're going to share a frame tree. There are two possibilities:
81 // . We already know about the frame, in which case we swap it to local.
82 // . We don't know about the frame (most likely because of timing issues),
83 // but we better know about the parent. Create a new frame for it.
84 CHECK(view->id() != frame_data[0]->frame_id);
85 HTMLFrame* existing_frame = frame_tree->root_->FindFrame(view->id());
86 size_t frame_data_index = 0u;
87 CHECK(FindFrameDataIndex(frame_data, view->id(), &frame_data_index));
88 const mandoline::FrameDataPtr& data = frame_data[frame_data_index];
89 if (existing_frame) {
90 CHECK(!existing_frame->IsLocal());
91 existing_frame->set_delegate(delegate);
92 existing_frame->SwapToLocal(view, data->name.To<blink::WebString>());
93 } else {
94 HTMLFrame* parent = frame_tree->root_->FindFrame(data->parent_id);
95 CHECK(parent);
96 HTMLFrame::CreateParams params(frame_tree, parent, view->id());
97 HTMLFrame* frame = new HTMLFrame(params);
98 frame->set_delegate(delegate);
99 frame->Init(view, data->name.To<blink::WebString>(),
100 data->origin.To<blink::WebString>());
104 HTMLFrame* frame = frame_tree->root_->FindFrame(view->id());
105 DCHECK(frame);
106 frame->Bind(frame_tree_server.Pass(), frame_tree_client_request.Pass());
107 return frame;
110 blink::WebView* HTMLFrameTreeManager::GetWebView() {
111 return root_->web_view();
114 void HTMLFrameTreeManager::OnFrameDestroyed(HTMLFrame* frame) {
115 if (frame == root_)
116 root_ = nullptr;
118 if (frame == local_root_)
119 local_root_ = nullptr;
121 if (!local_root_ || !local_root_->HasLocalDescendant())
122 delete this;
125 HTMLFrameTreeManager::HTMLFrameTreeManager(GlobalState* global_state)
126 : global_state_(global_state), root_(nullptr), local_root_(nullptr) {}
128 HTMLFrameTreeManager::~HTMLFrameTreeManager() {
129 DCHECK(!root_);
130 DCHECK(!local_root_);
131 RemoveFromInstances();
134 void HTMLFrameTreeManager::Init(
135 HTMLFrameDelegate* delegate,
136 mojo::View* local_view,
137 const mojo::Array<mandoline::FrameDataPtr>& frame_data) {
138 root_ = BuildFrameTree(delegate, frame_data, local_view->id(), local_view);
139 local_root_ = root_->FindFrame(local_view->id());
140 CHECK(local_root_);
141 local_root_->UpdateFocus();
144 HTMLFrame* HTMLFrameTreeManager::BuildFrameTree(
145 HTMLFrameDelegate* delegate,
146 const mojo::Array<mandoline::FrameDataPtr>& frame_data,
147 uint32_t local_frame_id,
148 mojo::View* local_view) {
149 std::vector<HTMLFrame*> parents;
150 HTMLFrame* root = nullptr;
151 HTMLFrame* last_frame = nullptr;
152 for (size_t i = 0; i < frame_data.size(); ++i) {
153 if (last_frame && frame_data[i]->parent_id == last_frame->id()) {
154 parents.push_back(last_frame);
155 } else if (!parents.empty()) {
156 while (parents.back()->id() != frame_data[i]->parent_id)
157 parents.pop_back();
159 HTMLFrame::CreateParams params(this,
160 !parents.empty() ? parents.back() : nullptr,
161 frame_data[i]->frame_id);
162 HTMLFrame* frame = new HTMLFrame(params);
163 if (!last_frame)
164 root = frame;
165 else
166 DCHECK(frame->parent());
167 last_frame = frame;
169 if (frame_data[i]->frame_id == local_frame_id)
170 frame->set_delegate(delegate);
172 frame->Init(local_view, frame_data[i]->name.To<blink::WebString>(),
173 frame_data[i]->origin.To<blink::WebString>());
175 return root;
178 void HTMLFrameTreeManager::RemoveFromInstances() {
179 for (auto pair : *instances_) {
180 if (pair.second == this) {
181 instances_->erase(pair.first);
182 return;
187 void HTMLFrameTreeManager::ProcessOnFrameAdded(
188 HTMLFrame* source,
189 mandoline::FrameDataPtr frame_data) {
190 if (source != local_root_)
191 return;
193 HTMLFrame* parent = root_->FindFrame(frame_data->parent_id);
194 if (!parent) {
195 DVLOG(1) << "Received invalid parent in OnFrameAdded "
196 << frame_data->parent_id;
197 return;
199 if (root_->FindFrame(frame_data->frame_id)) {
200 DVLOG(1) << "Child with id already exists in OnFrameAdded "
201 << frame_data->frame_id;
202 return;
205 HTMLFrame::CreateParams params(this, parent, frame_data->frame_id);
206 // |parent| takes ownership of |frame|.
207 HTMLFrame* frame = new HTMLFrame(params);
208 frame->Init(nullptr, frame_data->name.To<blink::WebString>(),
209 frame_data->origin.To<blink::WebString>());
212 void HTMLFrameTreeManager::ProcessOnFrameRemoved(HTMLFrame* source,
213 uint32_t frame_id) {
214 if (source != local_root_)
215 return;
217 HTMLFrame* frame = root_->FindFrame(frame_id);
218 if (!frame) {
219 DVLOG(1) << "OnFrameRemoved with unknown frame " << frame_id;
220 return;
223 // We shouldn't see requests to remove the root.
224 if (frame == root_) {
225 DVLOG(1) << "OnFrameRemoved supplied root; ignoring";
226 return;
229 // Requests to remove local frames are followed by the View being destroyed.
230 // We handle destruction there.
231 if (frame->IsLocal())
232 return;
234 frame->Close();
237 void HTMLFrameTreeManager::ProcessOnFrameNameChanged(HTMLFrame* source,
238 uint32_t frame_id,
239 const mojo::String& name) {
240 if (source != root_)
241 return;
243 HTMLFrame* frame = root_->FindFrame(frame_id);
244 if (frame)
245 frame->SetRemoteFrameName(name);
248 } // namespace mojo