Don't preload rarely seen large images
[chromium-blink-merge.git] / components / html_viewer / html_document_oopif.cc
blob1dfc61b6f82f1a1f3b21c12b5f3f1a17b104bfea
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/frame.h"
18 #include "components/html_viewer/frame_tree_manager.h"
19 #include "components/html_viewer/global_state.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;
35 using mojo::View;
37 namespace html_viewer {
38 namespace {
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);
52 } // namespace
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_(
68 html_document_app->app_lifetime_helper()->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),
73 delete_callback_(delete_callback) {
74 // TODO(sky): nuke headless. We're not going to care about it anymore.
75 DCHECK(!global_state_->is_headless());
77 connection->AddService(
78 static_cast<mojo::InterfaceFactory<mandoline::FrameTreeClient>*>(this));
79 connection->AddService(static_cast<InterfaceFactory<AxProvider>*>(this));
80 connection->AddService(&view_manager_client_factory_);
81 if (IsTestInterfaceEnabled()) {
82 connection->AddService(
83 static_cast<mojo::InterfaceFactory<TestHTMLViewer>*>(this));
86 resource_waiter_.reset(
87 new DocumentResourceWaiter(global_state_, response.Pass(), this));
88 LoadIfNecessary();
91 void HTMLDocumentOOPIF::Destroy() {
92 if (resource_waiter_) {
93 mojo::View* root = resource_waiter_->root();
94 if (root) {
95 root->RemoveObserver(this);
96 resource_waiter_.reset();
97 delete root->view_manager();
98 } else {
99 delete this;
101 } else {
102 DCHECK(frame_tree_manager_);
103 mojo::ViewManager* view_manager =
104 frame_tree_manager_->GetLocalFrame()->view()->view_manager();
105 frame_tree_manager_.reset();
107 // Delete the ViewManager, which will trigger deleting us.
108 delete view_manager;
112 HTMLDocumentOOPIF::~HTMLDocumentOOPIF() {
113 delete_callback_.Run(this);
115 STLDeleteElements(&ax_providers_);
118 void HTMLDocumentOOPIF::LoadIfNecessary() {
119 if (!frame_tree_manager_ && resource_waiter_->IsReady())
120 Load();
123 void HTMLDocumentOOPIF::Load() {
124 DCHECK(resource_waiter_ && resource_waiter_->IsReady());
126 mojo::View* view = resource_waiter_->root();
127 global_state_->InitIfNecessary(
128 view->viewport_metrics().size_in_pixels.To<gfx::Size>(),
129 view->viewport_metrics().device_pixel_ratio);
131 mojo::InterfaceRequest<mandoline::FrameTreeClient> frame_tree_client_request;
132 mandoline::FrameTreeServerPtr frame_tree_server;
133 mojo::Array<mandoline::FrameDataPtr> frame_data;
134 mojo::URLResponsePtr response;
135 resource_waiter_->Release(&frame_tree_client_request, &frame_tree_server,
136 &frame_data, &response);
137 resource_waiter_.reset();
139 view->RemoveObserver(this);
141 frame_tree_manager_.reset(
142 new FrameTreeManager(global_state_, html_document_app_, connection_,
143 view->id(), frame_tree_server.Pass()));
144 frame_tree_manager_->set_delegate(this);
145 frame_tree_manager_binding_.reset(
146 new mojo::Binding<mandoline::FrameTreeClient>(
147 frame_tree_manager_.get(), frame_tree_client_request.Pass()));
148 frame_tree_manager_->Init(view, frame_data.Pass());
150 // TODO(yzshen): http://crbug.com/498986 Creating DevToolsAgentImpl instances
151 // causes html_viewer_apptests flakiness currently. Before we fix that we
152 // cannot enable remote debugging (which is required by Telemetry tests) on
153 // the bots.
154 if (EnableRemoteDebugging()) {
155 Frame* frame = frame_tree_manager_->GetLocalFrame();
156 if (!frame->parent()) {
157 devtools_agent_.reset(new DevToolsAgentImpl(
158 frame->web_frame()->toWebLocalFrame(), html_document_app_->shell()));
162 WebURLRequestExtraData* extra_data = new WebURLRequestExtraData;
163 extra_data->synthetic_response = response.Pass();
165 const GURL url(extra_data->synthetic_response->url);
167 blink::WebURLRequest web_request;
168 web_request.initialize();
169 web_request.setURL(url);
170 web_request.setExtraData(extra_data);
172 frame_tree_manager_->GetLocalWebFrame()->loadRequest(web_request);
175 HTMLDocumentOOPIF::BeforeLoadCache* HTMLDocumentOOPIF::GetBeforeLoadCache() {
176 CHECK(!did_finish_local_frame_load_);
177 if (!before_load_cache_.get())
178 before_load_cache_.reset(new BeforeLoadCache);
179 return before_load_cache_.get();
182 void HTMLDocumentOOPIF::OnEmbed(View* root) {
183 // We're an observer until the document is loaded.
184 root->AddObserver(this);
185 resource_waiter_->set_root(root);
187 LoadIfNecessary();
190 void HTMLDocumentOOPIF::OnViewManagerDestroyed(
191 mojo::ViewManager* view_manager) {
192 delete this;
195 void HTMLDocumentOOPIF::OnViewViewportMetricsChanged(
196 mojo::View* view,
197 const mojo::ViewportMetrics& old_metrics,
198 const mojo::ViewportMetrics& new_metrics) {
199 LoadIfNecessary();
202 void HTMLDocumentOOPIF::OnViewDestroyed(View* view) {
203 resource_waiter_->root()->RemoveObserver(this);
204 resource_waiter_->set_root(nullptr);
207 bool HTMLDocumentOOPIF::ShouldNavigateLocallyInMainFrame() {
208 return devtools_agent_ && devtools_agent_->handling_page_navigate_request();
211 void HTMLDocumentOOPIF::OnFrameDidFinishLoad(Frame* frame) {
212 // TODO(msw): Notify AxProvider clients of updates on child frame loads.
213 if (frame_tree_manager_ &&
214 frame != frame_tree_manager_->GetLocalFrame()) {
215 return;
218 did_finish_local_frame_load_ = true;
219 scoped_ptr<BeforeLoadCache> before_load_cache = before_load_cache_.Pass();
220 if (!before_load_cache)
221 return;
223 // Bind any pending AxProvider and TestHTMLViewer interface requests.
224 for (auto it : before_load_cache->ax_provider_requests) {
225 ax_providers_.insert(
226 new AxProviderImpl(frame_tree_manager_->GetWebView(), it->Pass()));
228 for (auto it : before_load_cache->test_interface_requests) {
229 CHECK(IsTestInterfaceEnabled());
230 test_html_viewers_.push_back(new TestHTMLViewerImpl(
231 frame_tree_manager_->GetLocalWebFrame(), it->Pass()));
235 void HTMLDocumentOOPIF::Create(mojo::ApplicationConnection* connection,
236 mojo::InterfaceRequest<AxProvider> request) {
237 if (!did_finish_local_frame_load_) {
238 // Cache AxProvider interface requests until the document finishes loading.
239 auto cached_request = new mojo::InterfaceRequest<AxProvider>();
240 *cached_request = request.Pass();
241 GetBeforeLoadCache()->ax_provider_requests.insert(cached_request);
242 } else {
243 ax_providers_.insert(new AxProviderImpl(
244 frame_tree_manager_->GetLocalFrame()->web_view(), request.Pass()));
248 void HTMLDocumentOOPIF::Create(mojo::ApplicationConnection* connection,
249 mojo::InterfaceRequest<TestHTMLViewer> request) {
250 CHECK(IsTestInterfaceEnabled());
251 if (!did_finish_local_frame_load_) {
252 auto cached_request = new mojo::InterfaceRequest<TestHTMLViewer>();
253 *cached_request = request.Pass();
254 GetBeforeLoadCache()->test_interface_requests.insert(cached_request);
255 } else {
256 test_html_viewers_.push_back(new TestHTMLViewerImpl(
257 frame_tree_manager_->GetLocalWebFrame(), request.Pass()));
261 void HTMLDocumentOOPIF::Create(
262 mojo::ApplicationConnection* connection,
263 mojo::InterfaceRequest<mandoline::FrameTreeClient> request) {
264 if (frame_tree_manager_.get() || frame_tree_manager_binding_.get()) {
265 DVLOG(1) << "Request for FrameTreeClient after one already vended.";
266 return;
268 resource_waiter_->Bind(request.Pass());
271 } // namespace html_viewer