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/devtools_service/public/cpp/switches.h"
14 #include "components/html_viewer/blink_url_request_type_converters.h"
15 #include "components/html_viewer/devtools_agent_impl.h"
16 #include "components/html_viewer/document_resource_waiter.h"
17 #include "components/html_viewer/global_state.h"
18 #include "components/html_viewer/html_frame.h"
19 #include "components/html_viewer/html_frame_tree_manager.h"
20 #include "components/html_viewer/test_html_viewer_impl.h"
21 #include "components/html_viewer/web_url_loader_impl.h"
22 #include "components/view_manager/ids.h"
23 #include "components/view_manager/public/cpp/view.h"
24 #include "components/view_manager/public/cpp/view_manager.h"
25 #include "mojo/application/public/cpp/application_impl.h"
26 #include "mojo/application/public/cpp/connect.h"
27 #include "mojo/application/public/interfaces/shell.mojom.h"
28 #include "mojo/converters/geometry/geometry_type_converters.h"
29 #include "third_party/WebKit/public/web/WebLocalFrame.h"
30 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h"
31 #include "ui/gfx/geometry/dip_util.h"
32 #include "ui/gfx/geometry/size.h"
34 using mojo::AxProvider
;
37 namespace html_viewer
{
40 const char kEnableTestInterface
[] = "enable-html-viewer-test-interface";
42 bool IsTestInterfaceEnabled() {
43 return base::CommandLine::ForCurrentProcess()->HasSwitch(
44 kEnableTestInterface
);
47 bool EnableRemoteDebugging() {
48 return base::CommandLine::ForCurrentProcess()->HasSwitch(
49 devtools_service::kRemoteDebuggingPort
);
54 HTMLDocumentOOPIF::BeforeLoadCache::BeforeLoadCache() {
57 HTMLDocumentOOPIF::BeforeLoadCache::~BeforeLoadCache() {
58 STLDeleteElements(&ax_provider_requests
);
59 STLDeleteElements(&test_interface_requests
);
62 HTMLDocumentOOPIF::HTMLDocumentOOPIF(mojo::ApplicationImpl
* html_document_app
,
63 mojo::ApplicationConnection
* connection
,
64 mojo::URLResponsePtr response
,
65 GlobalState
* global_state
,
66 const DeleteCallback
& delete_callback
)
67 : app_refcount_(html_document_app
->app_lifetime_helper()
68 ->CreateAppRefCount()),
69 html_document_app_(html_document_app
),
70 connection_(connection
),
71 view_manager_client_factory_(html_document_app
->shell(), this),
72 global_state_(global_state
),
74 delete_callback_(delete_callback
) {
75 // TODO(sky): nuke headless. We're not going to care about it anymore.
76 DCHECK(!global_state_
->is_headless());
78 connection
->AddService(
79 static_cast<mojo::InterfaceFactory
<mandoline::FrameTreeClient
>*>(this));
80 connection
->AddService(static_cast<InterfaceFactory
<AxProvider
>*>(this));
81 connection
->AddService(&view_manager_client_factory_
);
82 if (IsTestInterfaceEnabled()) {
83 connection
->AddService(
84 static_cast<mojo::InterfaceFactory
<TestHTMLViewer
>*>(this));
87 resource_waiter_
.reset(
88 new DocumentResourceWaiter(global_state_
, response
.Pass(), this));
92 void HTMLDocumentOOPIF::Destroy() {
93 if (resource_waiter_
) {
94 mojo::View
* root
= resource_waiter_
->root();
96 root
->RemoveObserver(this);
97 resource_waiter_
.reset();
98 delete root
->view_manager();
103 // Closing the frame ends up destroying the ViewManager, which triggers
104 // deleting this (OnViewManagerDestroyed()).
109 HTMLDocumentOOPIF::~HTMLDocumentOOPIF() {
110 delete_callback_
.Run(this);
112 STLDeleteElements(&ax_providers_
);
115 void HTMLDocumentOOPIF::LoadIfNecessary() {
116 if (!frame_
&& resource_waiter_
->IsReady())
120 void HTMLDocumentOOPIF::Load() {
121 DCHECK(resource_waiter_
&& resource_waiter_
->IsReady());
123 mojo::View
* view
= resource_waiter_
->root();
124 global_state_
->InitIfNecessary(
125 view
->viewport_metrics().size_in_pixels
.To
<gfx::Size
>(),
126 view
->viewport_metrics().device_pixel_ratio
);
128 view
->RemoveObserver(this);
130 WebURLRequestExtraData
* extra_data
= new WebURLRequestExtraData
;
131 extra_data
->synthetic_response
=
132 resource_waiter_
->ReleaseURLResponse().Pass();
134 frame_
= HTMLFrameTreeManager::CreateFrameAndAttachToTree(
135 global_state_
, html_document_app_
, view
, resource_waiter_
.Pass(), this);
137 // TODO(yzshen): http://crbug.com/498986 Creating DevToolsAgentImpl instances
138 // causes html_viewer_apptests flakiness currently. Before we fix that we
139 // cannot enable remote debugging (which is required by Telemetry tests) on
141 if (EnableRemoteDebugging() && !frame_
->parent()) {
142 devtools_agent_
.reset(new DevToolsAgentImpl(
143 frame_
->web_frame()->toWebLocalFrame(), html_document_app_
->shell()));
146 const GURL
url(extra_data
->synthetic_response
->url
);
148 blink::WebURLRequest web_request
;
149 web_request
.initialize();
150 web_request
.setURL(url
);
151 web_request
.setExtraData(extra_data
);
153 frame_
->web_frame()->toWebLocalFrame()->loadRequest(web_request
);
156 HTMLDocumentOOPIF::BeforeLoadCache
* HTMLDocumentOOPIF::GetBeforeLoadCache() {
157 CHECK(!did_finish_local_frame_load_
);
158 if (!before_load_cache_
.get())
159 before_load_cache_
.reset(new BeforeLoadCache
);
160 return before_load_cache_
.get();
163 void HTMLDocumentOOPIF::OnEmbed(View
* root
) {
164 // We're an observer until the document is loaded.
165 root
->AddObserver(this);
166 resource_waiter_
->set_root(root
);
171 void HTMLDocumentOOPIF::OnViewManagerDestroyed(
172 mojo::ViewManager
* view_manager
) {
176 void HTMLDocumentOOPIF::OnViewViewportMetricsChanged(
178 const mojo::ViewportMetrics
& old_metrics
,
179 const mojo::ViewportMetrics
& new_metrics
) {
183 void HTMLDocumentOOPIF::OnViewDestroyed(View
* view
) {
184 resource_waiter_
->root()->RemoveObserver(this);
185 resource_waiter_
->set_root(nullptr);
188 bool HTMLDocumentOOPIF::ShouldNavigateLocallyInMainFrame() {
189 return devtools_agent_
&& devtools_agent_
->handling_page_navigate_request();
192 void HTMLDocumentOOPIF::OnFrameDidFinishLoad() {
193 did_finish_local_frame_load_
= true;
194 scoped_ptr
<BeforeLoadCache
> before_load_cache
= before_load_cache_
.Pass();
195 if (!before_load_cache
)
198 // Bind any pending AxProvider and TestHTMLViewer interface requests.
199 for (auto it
: before_load_cache
->ax_provider_requests
) {
200 ax_providers_
.insert(new AxProviderImpl(
201 frame_
->frame_tree_manager()->GetWebView(), it
->Pass()));
203 for (auto it
: before_load_cache
->test_interface_requests
) {
204 CHECK(IsTestInterfaceEnabled());
205 test_html_viewers_
.push_back(new TestHTMLViewerImpl(
206 frame_
->web_frame()->toWebLocalFrame(), it
->Pass()));
210 mojo::ApplicationImpl
* HTMLDocumentOOPIF::GetApp() {
211 return html_document_app_
;
214 void HTMLDocumentOOPIF::Create(mojo::ApplicationConnection
* connection
,
215 mojo::InterfaceRequest
<AxProvider
> request
) {
216 if (!did_finish_local_frame_load_
) {
217 // Cache AxProvider interface requests until the document finishes loading.
218 auto cached_request
= new mojo::InterfaceRequest
<AxProvider
>();
219 *cached_request
= request
.Pass();
220 GetBeforeLoadCache()->ax_provider_requests
.insert(cached_request
);
222 ax_providers_
.insert(
223 new AxProviderImpl(frame_
->web_view(), request
.Pass()));
227 void HTMLDocumentOOPIF::Create(mojo::ApplicationConnection
* connection
,
228 mojo::InterfaceRequest
<TestHTMLViewer
> request
) {
229 CHECK(IsTestInterfaceEnabled());
230 if (!did_finish_local_frame_load_
) {
231 auto cached_request
= new mojo::InterfaceRequest
<TestHTMLViewer
>();
232 *cached_request
= request
.Pass();
233 GetBeforeLoadCache()->test_interface_requests
.insert(cached_request
);
235 test_html_viewers_
.push_back(new TestHTMLViewerImpl(
236 frame_
->web_frame()->toWebLocalFrame(), request
.Pass()));
240 void HTMLDocumentOOPIF::Create(
241 mojo::ApplicationConnection
* connection
,
242 mojo::InterfaceRequest
<mandoline::FrameTreeClient
> request
) {
244 DVLOG(1) << "Request for FrameTreeClient after one already vended.";
247 resource_waiter_
->Bind(request
.Pass());
250 } // namespace html_viewer