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
;
36 namespace html_viewer
{
39 const char kEnableTestInterface
[] = "enable-html-viewer-test-interface";
41 bool IsTestInterfaceEnabled() {
42 return base::CommandLine::ForCurrentProcess()->HasSwitch(
43 kEnableTestInterface
);
48 HTMLDocumentOOPIF::BeforeLoadCache::BeforeLoadCache() {
51 HTMLDocumentOOPIF::BeforeLoadCache::~BeforeLoadCache() {
52 STLDeleteElements(&ax_provider_requests
);
53 STLDeleteElements(&test_interface_requests
);
56 HTMLDocumentOOPIF::HTMLDocumentOOPIF(mojo::ApplicationImpl
* html_document_app
,
57 mojo::ApplicationConnection
* connection
,
58 mojo::URLResponsePtr response
,
59 GlobalState
* global_state
,
60 const DeleteCallback
& delete_callback
,
62 : app_refcount_(html_document_app
->app_lifetime_helper()
63 ->CreateAppRefCount()),
64 html_document_app_(html_document_app
),
65 connection_(connection
),
66 global_state_(global_state
),
68 delete_callback_(delete_callback
),
71 // TODO(sky): nuke headless. We're not going to care about it anymore.
72 DCHECK(!global_state_
->is_headless());
74 connection
->AddService
<mandoline::FrameTreeClient
>(this);
75 connection
->AddService
<AxProvider
>(this);
76 connection
->AddService
<mojo::ViewTreeClient
>(this);
77 connection
->AddService
<devtools_service::DevToolsAgent
>(this);
78 if (IsTestInterfaceEnabled())
79 connection
->AddService
<TestHTMLViewer
>(this);
81 resource_waiter_
.reset(
82 new DocumentResourceWaiter(global_state_
, response
.Pass(), this));
86 void HTMLDocumentOOPIF::Destroy() {
87 if (resource_waiter_
) {
88 mojo::View
* root
= resource_waiter_
->root();
90 root
->RemoveObserver(this);
91 resource_waiter_
.reset();
92 delete root
->connection();
97 // Closing the frame ends up destroying the ViewManager, which triggers
98 // deleting this (OnViewManagerDestroyed()).
104 HTMLDocumentOOPIF::~HTMLDocumentOOPIF() {
105 delete_callback_
.Run(this);
107 STLDeleteElements(&ax_providers_
);
110 void HTMLDocumentOOPIF::LoadIfNecessary() {
111 if (!frame_
&& resource_waiter_
->IsReady())
115 void HTMLDocumentOOPIF::Load() {
116 DCHECK(resource_waiter_
&& resource_waiter_
->IsReady());
118 mojo::View
* view
= resource_waiter_
->root();
119 global_state_
->InitIfNecessary(
120 view
->viewport_metrics().size_in_pixels
.To
<gfx::Size
>(),
121 view
->viewport_metrics().device_pixel_ratio
);
123 scoped_ptr
<WebURLRequestExtraData
> extra_data(new WebURLRequestExtraData
);
124 extra_data
->synthetic_response
=
125 resource_waiter_
->ReleaseURLResponse().Pass();
127 frame_
= HTMLFrameTreeManager::CreateFrameAndAttachToTree(
128 global_state_
, view
, resource_waiter_
.Pass(), this);
130 // If the frame wasn't created we can destroy the connection.
132 root_
->RemoveObserver(this);
133 // This triggers deleting us.
134 delete root_
->connection();
138 view
->RemoveObserver(this);
140 if (devtools_agent_request_
.is_pending()) {
141 if (frame_
->devtools_agent()) {
142 frame_
->devtools_agent()->BindToRequest(devtools_agent_request_
.Pass());
144 devtools_agent_request_
=
145 mojo::InterfaceRequest
<devtools_service::DevToolsAgent
>();
149 const GURL
url(extra_data
->synthetic_response
->url
);
151 blink::WebURLRequest web_request
;
152 web_request
.initialize();
153 web_request
.setURL(url
);
154 web_request
.setExtraData(extra_data
.release());
156 frame_
->web_frame()->toWebLocalFrame()->loadRequest(web_request
);
159 HTMLDocumentOOPIF::BeforeLoadCache
* HTMLDocumentOOPIF::GetBeforeLoadCache() {
160 CHECK(!did_finish_local_frame_load_
);
161 if (!before_load_cache_
.get())
162 before_load_cache_
.reset(new BeforeLoadCache
);
163 return before_load_cache_
.get();
166 void HTMLDocumentOOPIF::OnEmbed(View
* root
) {
169 // We're an observer until the document is loaded.
170 root
->AddObserver(this);
171 resource_waiter_
->set_root(root
);
176 void HTMLDocumentOOPIF::OnConnectionLost(mojo::ViewTreeConnection
* connection
) {
180 void HTMLDocumentOOPIF::OnViewViewportMetricsChanged(
182 const mojo::ViewportMetrics
& old_metrics
,
183 const mojo::ViewportMetrics
& new_metrics
) {
187 void HTMLDocumentOOPIF::OnViewDestroyed(View
* view
) {
188 if (resource_waiter_
) {
189 resource_waiter_
->root()->RemoveObserver(this);
190 resource_waiter_
->set_root(nullptr);
194 void HTMLDocumentOOPIF::OnFrameDidFinishLoad() {
195 did_finish_local_frame_load_
= true;
196 scoped_ptr
<BeforeLoadCache
> before_load_cache
= before_load_cache_
.Pass();
197 if (!before_load_cache
)
200 // Bind any pending AxProvider and TestHTMLViewer interface requests.
201 for (auto it
: before_load_cache
->ax_provider_requests
) {
202 ax_providers_
.insert(new AxProviderImpl(
203 frame_
->frame_tree_manager()->GetWebView(), it
->Pass()));
205 for (auto it
: before_load_cache
->test_interface_requests
) {
206 CHECK(IsTestInterfaceEnabled());
207 test_html_viewers_
.push_back(new TestHTMLViewerImpl(
208 frame_
->web_frame()->toWebLocalFrame(), it
->Pass()));
212 mojo::ApplicationImpl
* HTMLDocumentOOPIF::GetApp() {
213 return html_document_app_
;
216 HTMLFactory
* HTMLDocumentOOPIF::GetHTMLFactory() {
220 void HTMLDocumentOOPIF::OnFrameSwappedToRemote() {
221 // When the frame becomes remote HTMLDocumentOOPIF is no longer needed.
222 // Deleting the ViewManager triggers deleting us.
223 delete root_
->connection();
226 void HTMLDocumentOOPIF::Create(mojo::ApplicationConnection
* connection
,
227 mojo::InterfaceRequest
<AxProvider
> request
) {
228 if (!did_finish_local_frame_load_
) {
229 // Cache AxProvider interface requests until the document finishes loading.
230 auto cached_request
= new mojo::InterfaceRequest
<AxProvider
>();
231 *cached_request
= request
.Pass();
232 GetBeforeLoadCache()->ax_provider_requests
.insert(cached_request
);
234 ax_providers_
.insert(
235 new AxProviderImpl(frame_
->web_view(), request
.Pass()));
239 void HTMLDocumentOOPIF::Create(mojo::ApplicationConnection
* connection
,
240 mojo::InterfaceRequest
<TestHTMLViewer
> request
) {
241 CHECK(IsTestInterfaceEnabled());
242 if (!did_finish_local_frame_load_
) {
243 auto cached_request
= new mojo::InterfaceRequest
<TestHTMLViewer
>();
244 *cached_request
= request
.Pass();
245 GetBeforeLoadCache()->test_interface_requests
.insert(cached_request
);
247 test_html_viewers_
.push_back(new TestHTMLViewerImpl(
248 frame_
->web_frame()->toWebLocalFrame(), request
.Pass()));
252 void HTMLDocumentOOPIF::Create(
253 mojo::ApplicationConnection
* connection
,
254 mojo::InterfaceRequest
<mandoline::FrameTreeClient
> request
) {
256 DVLOG(1) << "Request for FrameTreeClient after one already vended.";
259 resource_waiter_
->Bind(request
.Pass());
262 void HTMLDocumentOOPIF::Create(
263 mojo::ApplicationConnection
* connection
,
264 mojo::InterfaceRequest
<devtools_service::DevToolsAgent
> request
) {
266 if (frame_
->devtools_agent())
267 frame_
->devtools_agent()->BindToRequest(request
.Pass());
269 devtools_agent_request_
= request
.Pass();
273 void HTMLDocumentOOPIF::Create(
274 mojo::ApplicationConnection
* connection
,
275 mojo::InterfaceRequest
<mojo::ViewTreeClient
> request
) {
276 mojo::ViewTreeConnection::Create(this, request
.Pass());
279 } // namespace html_viewer