Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / components / html_viewer / html_document_oopif.cc
blob045a3e44f4757622e5e3b881ba0ac585298a4545
1 // Copyright 2014 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_document_oopif.h"
7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/stl_util.h"
11 #include "base/strings/string_util.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "components/html_viewer/blink_url_request_type_converters.h"
14 #include "components/html_viewer/devtools_agent_impl.h"
15 #include "components/html_viewer/document_resource_waiter.h"
16 #include "components/html_viewer/global_state.h"
17 #include "components/html_viewer/html_frame.h"
18 #include "components/html_viewer/html_frame_tree_manager.h"
19 #include "components/html_viewer/test_html_viewer_impl.h"
20 #include "components/html_viewer/web_url_loader_impl.h"
21 #include "components/view_manager/ids.h"
22 #include "components/view_manager/public/cpp/view.h"
23 #include "components/view_manager/public/cpp/view_tree_connection.h"
24 #include "mojo/application/public/cpp/application_impl.h"
25 #include "mojo/application/public/cpp/connect.h"
26 #include "mojo/application/public/interfaces/shell.mojom.h"
27 #include "mojo/converters/geometry/geometry_type_converters.h"
28 #include "third_party/WebKit/public/web/WebLocalFrame.h"
29 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h"
30 #include "ui/gfx/geometry/dip_util.h"
31 #include "ui/gfx/geometry/size.h"
33 using mojo::AxProvider;
34 using mojo::View;
36 namespace html_viewer {
37 namespace {
39 const char kEnableTestInterface[] = "enable-html-viewer-test-interface";
41 bool IsTestInterfaceEnabled() {
42 return base::CommandLine::ForCurrentProcess()->HasSwitch(
43 kEnableTestInterface);
46 } // namespace
48 // A ViewTreeDelegate implementation that delegates to a (swappable) delegate.
49 // This is used when one HTMLDocumentOOPIF takes over for another delegate
50 // (OnSwap()).
51 class ViewTreeDelegateImpl : public mojo::ViewTreeDelegate {
52 public:
53 explicit ViewTreeDelegateImpl(mojo::ViewTreeDelegate* delegate)
54 : delegate_(delegate) {}
55 ~ViewTreeDelegateImpl() override {}
57 void set_delegate(mojo::ViewTreeDelegate* delegate) { delegate_ = delegate; }
59 private:
60 // ViewTreeDelegate:
61 void OnEmbed(mojo::View* root) override { delegate_->OnEmbed(root); }
62 void OnUnembed() override { delegate_->OnUnembed(); }
63 void OnConnectionLost(mojo::ViewTreeConnection* connection) override {
64 delegate_->OnConnectionLost(connection);
67 mojo::ViewTreeDelegate* delegate_;
69 DISALLOW_COPY_AND_ASSIGN(ViewTreeDelegateImpl);
72 HTMLDocumentOOPIF::BeforeLoadCache::BeforeLoadCache() {
75 HTMLDocumentOOPIF::BeforeLoadCache::~BeforeLoadCache() {
76 STLDeleteElements(&ax_provider_requests);
77 STLDeleteElements(&test_interface_requests);
80 HTMLDocumentOOPIF::TransferableState::TransferableState()
81 : owns_view_tree_connection(false), root(nullptr) {}
83 HTMLDocumentOOPIF::TransferableState::~TransferableState() {}
85 void HTMLDocumentOOPIF::TransferableState::Move(TransferableState* other) {
86 owns_view_tree_connection = other->owns_view_tree_connection;
87 root = other->root;
88 view_tree_delegate_impl = other->view_tree_delegate_impl.Pass();
90 other->root = nullptr;
91 other->owns_view_tree_connection = false;
94 HTMLDocumentOOPIF::HTMLDocumentOOPIF(mojo::ApplicationImpl* html_document_app,
95 mojo::ApplicationConnection* connection,
96 mojo::URLResponsePtr response,
97 GlobalState* global_state,
98 const DeleteCallback& delete_callback,
99 HTMLFactory* factory)
100 : app_refcount_(html_document_app->app_lifetime_helper()
101 ->CreateAppRefCount()),
102 html_document_app_(html_document_app),
103 connection_(connection),
104 global_state_(global_state),
105 frame_(nullptr),
106 delete_callback_(delete_callback),
107 factory_(factory) {
108 // TODO(sky): nuke headless. We're not going to care about it anymore.
109 DCHECK(!global_state_->is_headless());
111 connection->AddService<web_view::FrameTreeClient>(this);
112 connection->AddService<AxProvider>(this);
113 connection->AddService<mojo::ViewTreeClient>(this);
114 connection->AddService<devtools_service::DevToolsAgent>(this);
115 if (IsTestInterfaceEnabled())
116 connection->AddService<TestHTMLViewer>(this);
118 resource_waiter_.reset(
119 new DocumentResourceWaiter(global_state_, response.Pass(), this));
122 void HTMLDocumentOOPIF::Destroy() {
123 if (resource_waiter_) {
124 mojo::View* root = resource_waiter_->root();
125 if (root) {
126 resource_waiter_.reset();
127 delete root->connection();
128 } else {
129 delete this;
131 } else if (frame_) {
132 // Closing the frame ends up destroying the ViewManager, which triggers
133 // deleting this (OnConnectionLost()).
134 frame_->Close();
135 } else if (transferable_state_.root) {
136 // This triggers deleting us.
137 if (transferable_state_.owns_view_tree_connection)
138 delete transferable_state_.root->connection();
139 else
140 delete this;
141 } else {
142 delete this;
146 HTMLDocumentOOPIF::~HTMLDocumentOOPIF() {
147 delete_callback_.Run(this);
149 STLDeleteElements(&ax_providers_);
152 void HTMLDocumentOOPIF::Load() {
153 DCHECK(resource_waiter_ && resource_waiter_->is_ready());
155 // Note: |view| is null if we're taking over for an existing frame.
156 mojo::View* view = resource_waiter_->root();
157 if (view) {
158 global_state_->InitIfNecessary(
159 view->viewport_metrics().size_in_pixels.To<gfx::Size>(),
160 view->viewport_metrics().device_pixel_ratio);
163 scoped_ptr<WebURLRequestExtraData> extra_data(new WebURLRequestExtraData);
164 extra_data->synthetic_response =
165 resource_waiter_->ReleaseURLResponse().Pass();
167 frame_ = HTMLFrameTreeManager::CreateFrameAndAttachToTree(
168 global_state_, view, resource_waiter_.Pass(), this);
170 // If the frame wasn't created we can destroy ourself.
171 if (!frame_) {
172 Destroy();
173 return;
176 if (devtools_agent_request_.is_pending()) {
177 if (frame_->devtools_agent()) {
178 frame_->devtools_agent()->BindToRequest(devtools_agent_request_.Pass());
179 } else {
180 devtools_agent_request_ =
181 mojo::InterfaceRequest<devtools_service::DevToolsAgent>();
185 const GURL url(extra_data->synthetic_response->url);
187 blink::WebURLRequest web_request;
188 web_request.initialize();
189 web_request.setURL(url);
190 web_request.setExtraData(extra_data.release());
192 frame_->web_frame()->toWebLocalFrame()->loadRequest(web_request);
195 HTMLDocumentOOPIF::BeforeLoadCache* HTMLDocumentOOPIF::GetBeforeLoadCache() {
196 CHECK(!did_finish_local_frame_load_);
197 if (!before_load_cache_.get())
198 before_load_cache_.reset(new BeforeLoadCache);
199 return before_load_cache_.get();
202 void HTMLDocumentOOPIF::OnEmbed(View* root) {
203 transferable_state_.root = root;
204 resource_waiter_->SetRoot(root);
207 void HTMLDocumentOOPIF::OnConnectionLost(mojo::ViewTreeConnection* connection) {
208 delete this;
211 void HTMLDocumentOOPIF::OnFrameDidFinishLoad() {
212 did_finish_local_frame_load_ = true;
213 scoped_ptr<BeforeLoadCache> before_load_cache = before_load_cache_.Pass();
214 if (!before_load_cache)
215 return;
217 // Bind any pending AxProvider and TestHTMLViewer interface requests.
218 for (auto it : before_load_cache->ax_provider_requests) {
219 ax_providers_.insert(new AxProviderImpl(
220 frame_->frame_tree_manager()->GetWebView(), it->Pass()));
222 for (auto it : before_load_cache->test_interface_requests) {
223 CHECK(IsTestInterfaceEnabled());
224 test_html_viewers_.push_back(new TestHTMLViewerImpl(
225 frame_->web_frame()->toWebLocalFrame(), it->Pass()));
229 mojo::ApplicationImpl* HTMLDocumentOOPIF::GetApp() {
230 return html_document_app_;
233 HTMLFactory* HTMLDocumentOOPIF::GetHTMLFactory() {
234 return factory_;
237 void HTMLDocumentOOPIF::OnFrameSwappedToRemote() {
238 // When the frame becomes remote HTMLDocumentOOPIF is no longer needed.
239 frame_ = nullptr;
240 Destroy();
243 void HTMLDocumentOOPIF::OnSwap(HTMLFrame* frame,
244 HTMLFrameDelegate* old_delegate) {
245 DCHECK(frame->IsLocal());
246 DCHECK(frame->view());
247 DCHECK(!frame_);
248 DCHECK(!transferable_state_.root);
249 if (!old_delegate) {
250 // We're taking over a child of a local root that isn't associated with a
251 // delegate. In this case the frame's view is not the root of the
252 // ViewTreeConnection.
253 transferable_state_.owns_view_tree_connection = false;
254 transferable_state_.root = frame->view();
255 } else {
256 HTMLDocumentOOPIF* old_document =
257 static_cast<HTMLDocumentOOPIF*>(old_delegate);
258 transferable_state_.Move(&old_document->transferable_state_);
259 if (transferable_state_.view_tree_delegate_impl)
260 transferable_state_.view_tree_delegate_impl->set_delegate(this);
261 old_document->frame_ = nullptr;
262 old_document->Destroy();
266 void HTMLDocumentOOPIF::OnFrameDestroyed() {
267 if (!transferable_state_.owns_view_tree_connection)
268 delete this;
271 void HTMLDocumentOOPIF::Create(mojo::ApplicationConnection* connection,
272 mojo::InterfaceRequest<AxProvider> request) {
273 if (!did_finish_local_frame_load_) {
274 // Cache AxProvider interface requests until the document finishes loading.
275 auto cached_request = new mojo::InterfaceRequest<AxProvider>();
276 *cached_request = request.Pass();
277 GetBeforeLoadCache()->ax_provider_requests.insert(cached_request);
278 } else {
279 ax_providers_.insert(
280 new AxProviderImpl(frame_->web_view(), request.Pass()));
284 void HTMLDocumentOOPIF::Create(mojo::ApplicationConnection* connection,
285 mojo::InterfaceRequest<TestHTMLViewer> request) {
286 CHECK(IsTestInterfaceEnabled());
287 if (!did_finish_local_frame_load_) {
288 auto cached_request = new mojo::InterfaceRequest<TestHTMLViewer>();
289 *cached_request = request.Pass();
290 GetBeforeLoadCache()->test_interface_requests.insert(cached_request);
291 } else {
292 test_html_viewers_.push_back(new TestHTMLViewerImpl(
293 frame_->web_frame()->toWebLocalFrame(), request.Pass()));
297 void HTMLDocumentOOPIF::Create(
298 mojo::ApplicationConnection* connection,
299 mojo::InterfaceRequest<web_view::FrameTreeClient> request) {
300 if (frame_) {
301 DVLOG(1) << "Request for FrameTreeClient after one already vended.";
302 return;
304 resource_waiter_->Bind(request.Pass());
307 void HTMLDocumentOOPIF::Create(
308 mojo::ApplicationConnection* connection,
309 mojo::InterfaceRequest<devtools_service::DevToolsAgent> request) {
310 if (frame_) {
311 if (frame_->devtools_agent())
312 frame_->devtools_agent()->BindToRequest(request.Pass());
313 } else {
314 devtools_agent_request_ = request.Pass();
318 void HTMLDocumentOOPIF::Create(
319 mojo::ApplicationConnection* connection,
320 mojo::InterfaceRequest<mojo::ViewTreeClient> request) {
321 DCHECK(!transferable_state_.view_tree_delegate_impl);
322 transferable_state_.view_tree_delegate_impl.reset(
323 new ViewTreeDelegateImpl(this));
324 transferable_state_.owns_view_tree_connection = true;
325 mojo::ViewTreeConnection::Create(
326 transferable_state_.view_tree_delegate_impl.get(), request.Pass());
329 } // namespace html_viewer