NaCl: Increase validation cache size.
[chromium-blink-merge.git] / components / html_viewer / html_document.cc
blob96ebb8a3980bc9587692df55fbc55b06e0579c44
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.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_util.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "components/html_viewer/blink_input_events_type_converters.h"
16 #include "components/html_viewer/blink_url_request_type_converters.h"
17 #include "components/html_viewer/setup.h"
18 #include "components/html_viewer/web_layer_tree_view_impl.h"
19 #include "components/html_viewer/web_media_player_factory.h"
20 #include "components/html_viewer/web_storage_namespace_impl.h"
21 #include "components/html_viewer/web_url_loader_impl.h"
22 #include "components/view_manager/public/cpp/view.h"
23 #include "components/view_manager/public/interfaces/surfaces.mojom.h"
24 #include "media/blink/webencryptedmediaclient_impl.h"
25 #include "media/cdm/default_cdm_factory.h"
26 #include "media/filters/default_media_permission.h"
27 #include "mojo/application/public/cpp/application_impl.h"
28 #include "mojo/application/public/cpp/connect.h"
29 #include "mojo/application/public/interfaces/shell.mojom.h"
30 #include "skia/ext/refptr.h"
31 #include "third_party/WebKit/public/platform/Platform.h"
32 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
33 #include "third_party/WebKit/public/platform/WebSize.h"
34 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
35 #include "third_party/WebKit/public/web/WebDocument.h"
36 #include "third_party/WebKit/public/web/WebElement.h"
37 #include "third_party/WebKit/public/web/WebInputEvent.h"
38 #include "third_party/WebKit/public/web/WebLocalFrame.h"
39 #include "third_party/WebKit/public/web/WebScriptSource.h"
40 #include "third_party/WebKit/public/web/WebSettings.h"
41 #include "third_party/WebKit/public/web/WebView.h"
42 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h"
43 #include "third_party/skia/include/core/SkCanvas.h"
44 #include "third_party/skia/include/core/SkColor.h"
45 #include "third_party/skia/include/core/SkDevice.h"
46 #include "ui/gfx/geometry/dip_util.h"
47 #include "ui/gfx/geometry/size.h"
49 using blink::WebString;
50 using mojo::AxProvider;
51 using mojo::Rect;
52 using mojo::ServiceProviderPtr;
53 using mojo::URLResponsePtr;
54 using mojo::View;
55 using mojo::ViewManager;
56 using mojo::WeakBindToRequest;
58 namespace html_viewer {
59 namespace {
61 void ConfigureSettings(blink::WebSettings* settings) {
62 settings->setCookieEnabled(true);
63 settings->setDefaultFixedFontSize(13);
64 settings->setDefaultFontSize(16);
65 settings->setLoadsImagesAutomatically(true);
66 settings->setJavaScriptEnabled(true);
69 mojo::Target WebNavigationPolicyToNavigationTarget(
70 blink::WebNavigationPolicy policy) {
71 switch (policy) {
72 case blink::WebNavigationPolicyCurrentTab:
73 return mojo::TARGET_SOURCE_NODE;
74 case blink::WebNavigationPolicyNewBackgroundTab:
75 case blink::WebNavigationPolicyNewForegroundTab:
76 case blink::WebNavigationPolicyNewWindow:
77 case blink::WebNavigationPolicyNewPopup:
78 return mojo::TARGET_NEW_NODE;
79 default:
80 return mojo::TARGET_DEFAULT;
84 bool CanNavigateLocally(blink::WebFrame* frame,
85 const blink::WebURLRequest& request) {
86 // For now, we just load child frames locally.
87 // TODO(aa): In the future, this should use embedding to connect to a
88 // different instance of Blink if the frame is cross-origin.
89 if (frame->parent())
90 return true;
92 // If we have extraData() it means we already have the url response
93 // (presumably because we are being called via Navigate()). In that case we
94 // can go ahead and navigate locally.
95 if (request.extraData())
96 return true;
98 // Otherwise we don't know if we're the right app to handle this request. Ask
99 // host to do the navigation for us.
100 return false;
103 bool AreSecureCodecsSupported() {
104 // Hardware-secure codecs are not currently supported by HTML Viewer on any
105 // platform.
106 return false;
109 } // namespace
111 HTMLDocument::HTMLDocument(
112 mojo::InterfaceRequest<mojo::ServiceProvider> services,
113 URLResponsePtr response,
114 mojo::Shell* shell,
115 Setup* setup)
116 : response_(response.Pass()),
117 shell_(shell),
118 web_view_(nullptr),
119 root_(nullptr),
120 view_manager_client_factory_(shell_, this),
121 setup_(setup) {
122 exported_services_.AddService(this);
123 exported_services_.AddService(&view_manager_client_factory_);
124 exported_services_.Bind(services.Pass());
125 if (setup_->did_init())
126 Load(response_.Pass());
129 HTMLDocument::~HTMLDocument() {
130 STLDeleteElements(&ax_providers_);
131 STLDeleteElements(&ax_provider_requests_);
133 if (web_view_)
134 web_view_->close();
135 if (root_)
136 root_->RemoveObserver(this);
139 void HTMLDocument::OnEmbed(
140 View* root,
141 mojo::InterfaceRequest<mojo::ServiceProvider> services,
142 mojo::ServiceProviderPtr exposed_services) {
143 DCHECK(!setup_->is_headless());
144 root_ = root;
145 root_->AddObserver(this);
146 embedder_service_provider_ = exposed_services.Pass();
147 navigator_host_.set_service_provider(embedder_service_provider_.get());
149 InitSetupAndLoadIfNecessary();
152 void HTMLDocument::OnViewManagerDisconnected(ViewManager* view_manager) {
153 // TODO(aa): Need to figure out how shutdown works.
156 void HTMLDocument::Create(mojo::ApplicationConnection* connection,
157 mojo::InterfaceRequest<AxProvider> request) {
158 if (!did_finish_load_) {
159 // Cache AxProvider interface requests until the document finishes loading.
160 auto cached_request = new mojo::InterfaceRequest<AxProvider>();
161 *cached_request = request.Pass();
162 ax_provider_requests_.insert(cached_request);
163 } else {
164 ax_providers_.insert(
165 WeakBindToRequest(new AxProviderImpl(web_view_), &request));
169 void HTMLDocument::Load(URLResponsePtr response) {
170 DCHECK(!web_view_);
171 web_view_ = blink::WebView::create(this);
172 touch_handler_.reset(new TouchHandler(web_view_));
173 web_layer_tree_view_impl_->set_widget(web_view_);
174 ConfigureSettings(web_view_->settings());
175 web_view_->setMainFrame(
176 blink::WebLocalFrame::create(blink::WebTreeScopeType::Document, this));
178 GURL url(response->url);
180 WebURLRequestExtraData* extra_data = new WebURLRequestExtraData;
181 extra_data->synthetic_response = response.Pass();
183 blink::WebURLRequest web_request;
184 web_request.initialize();
185 web_request.setURL(url);
186 web_request.setExtraData(extra_data);
188 web_view_->mainFrame()->loadRequest(web_request);
191 void HTMLDocument::UpdateWebviewSizeFromViewSize() {
192 web_view_->setDeviceScaleFactor(setup_->device_pixel_ratio());
193 const gfx::Size size_in_pixels(root_->bounds().width, root_->bounds().height);
194 const gfx::Size size_in_dips = gfx::ConvertSizeToDIP(
195 root_->viewport_metrics().device_pixel_ratio, size_in_pixels);
196 web_view_->resize(
197 blink::WebSize(size_in_dips.width(), size_in_dips.height()));
198 web_layer_tree_view_impl_->setViewportSize(size_in_pixels);
201 void HTMLDocument::InitSetupAndLoadIfNecessary() {
202 DCHECK(root_);
203 if (web_view_ || root_->viewport_metrics().device_pixel_ratio == 0.f)
204 return;
206 setup_->InitIfNecessary(gfx::Size(root_->viewport_metrics().size->width,
207 root_->viewport_metrics().size->height),
208 root_->viewport_metrics().device_pixel_ratio);
209 Load(response_.Pass());
211 UpdateWebviewSizeFromViewSize();
212 web_layer_tree_view_impl_->set_view(root_);
215 blink::WebStorageNamespace* HTMLDocument::createSessionStorageNamespace() {
216 return new WebStorageNamespaceImpl();
219 void HTMLDocument::initializeLayerTreeView() {
220 if (setup_->is_headless()) {
221 web_layer_tree_view_impl_.reset(new WebLayerTreeViewImpl(
222 setup_->compositor_thread(), nullptr, nullptr));
223 return;
226 mojo::URLRequestPtr request(mojo::URLRequest::New());
227 request->url = mojo::String::From("mojo:surfaces_service");
228 mojo::SurfacePtr surface;
229 setup_->app()->ConnectToService(request.Pass(), &surface);
231 // TODO(jamesr): Should be mojo:gpu_service
232 mojo::URLRequestPtr request2(mojo::URLRequest::New());
233 request2->url = mojo::String::From("mojo:view_manager");
234 mojo::GpuPtr gpu_service;
235 setup_->app()->ConnectToService(request2.Pass(), &gpu_service);
236 web_layer_tree_view_impl_.reset(new WebLayerTreeViewImpl(
237 setup_->compositor_thread(), surface.Pass(), gpu_service.Pass()));
240 blink::WebLayerTreeView* HTMLDocument::layerTreeView() {
241 return web_layer_tree_view_impl_.get();
244 blink::WebMediaPlayer* HTMLDocument::createMediaPlayer(
245 blink::WebLocalFrame* frame,
246 const blink::WebURL& url,
247 blink::WebMediaPlayerClient* client) {
248 return createMediaPlayer(frame, url, client, nullptr);
251 blink::WebMediaPlayer* HTMLDocument::createMediaPlayer(
252 blink::WebLocalFrame* frame,
253 const blink::WebURL& url,
254 blink::WebMediaPlayerClient* client,
255 blink::WebContentDecryptionModule* initial_cdm) {
256 blink::WebMediaPlayer* player =
257 setup_->web_media_player_factory()
258 ? setup_->web_media_player_factory()->CreateMediaPlayer(
259 frame, url, client, GetMediaPermission(), GetCdmFactory(),
260 initial_cdm, shell_)
261 : nullptr;
262 return player;
265 blink::WebFrame* HTMLDocument::createChildFrame(
266 blink::WebLocalFrame* parent,
267 blink::WebTreeScopeType scope,
268 const blink::WebString& frameName,
269 blink::WebSandboxFlags sandboxFlags) {
270 blink::WebLocalFrame* web_frame = blink::WebLocalFrame::create(scope, this);
271 parent->appendChild(web_frame);
272 return web_frame;
275 void HTMLDocument::frameDetached(blink::WebFrame* frame) {
276 if (frame->parent())
277 frame->parent()->removeChild(frame);
279 // |frame| is invalid after here.
280 frame->close();
283 blink::WebCookieJar* HTMLDocument::cookieJar(blink::WebLocalFrame* frame) {
284 // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar.
285 // Either it should, as it once did, or we should find another solution here.
286 return blink::Platform::current()->cookieJar();
289 blink::WebNavigationPolicy HTMLDocument::decidePolicyForNavigation(
290 blink::WebLocalFrame* frame,
291 blink::WebDataSource::ExtraData* data,
292 const blink::WebURLRequest& request,
293 blink::WebNavigationType nav_type,
294 blink::WebNavigationPolicy default_policy,
295 bool is_redirect) {
296 if (CanNavigateLocally(frame, request))
297 return default_policy;
299 if (navigator_host_.get()) {
300 mojo::URLRequestPtr url_request = mojo::URLRequest::From(request);
301 navigator_host_->RequestNavigate(
302 WebNavigationPolicyToNavigationTarget(default_policy),
303 url_request.Pass());
306 return blink::WebNavigationPolicyIgnore;
309 void HTMLDocument::didAddMessageToConsole(
310 const blink::WebConsoleMessage& message,
311 const blink::WebString& source_name,
312 unsigned source_line,
313 const blink::WebString& stack_trace) {
314 VLOG(1) << "[" << source_name.utf8() << "(" << source_line << ")] "
315 << message.text.utf8();
318 void HTMLDocument::didFinishLoad(blink::WebLocalFrame* frame) {
319 // TODO(msw): Notify AxProvider clients of updates on child frame loads.
320 did_finish_load_ = true;
321 // Bind any pending AxProviderImpl interface requests.
322 for (auto it : ax_provider_requests_)
323 ax_providers_.insert(WeakBindToRequest(new AxProviderImpl(web_view_), it));
324 STLDeleteElements(&ax_provider_requests_);
327 void HTMLDocument::didNavigateWithinPage(
328 blink::WebLocalFrame* frame,
329 const blink::WebHistoryItem& history_item,
330 blink::WebHistoryCommitType commit_type) {
331 if (navigator_host_.get())
332 navigator_host_->DidNavigateLocally(history_item.urlString().utf8());
335 blink::WebEncryptedMediaClient* HTMLDocument::encryptedMediaClient() {
336 if (!web_encrypted_media_client_) {
337 web_encrypted_media_client_.reset(new media::WebEncryptedMediaClientImpl(
338 base::Bind(&AreSecureCodecsSupported), GetCdmFactory(),
339 GetMediaPermission()));
341 return web_encrypted_media_client_.get();
344 void HTMLDocument::OnViewBoundsChanged(View* view,
345 const Rect& old_bounds,
346 const Rect& new_bounds) {
347 DCHECK_EQ(view, root_);
348 UpdateWebviewSizeFromViewSize();
351 void HTMLDocument::OnViewViewportMetricsChanged(
352 mojo::View* view,
353 const mojo::ViewportMetrics& old_metrics,
354 const mojo::ViewportMetrics& new_metrics) {
355 InitSetupAndLoadIfNecessary();
358 void HTMLDocument::OnViewDestroyed(View* view) {
359 DCHECK_EQ(view, root_);
360 root_ = nullptr;
361 setup_->app()->Terminate();
362 delete this;
365 void HTMLDocument::OnViewInputEvent(View* view, const mojo::EventPtr& event) {
366 if (event->pointer_data) {
367 // Blink expects coordintes to be in DIPs.
368 event->pointer_data->x /= setup_->device_pixel_ratio();
369 event->pointer_data->y /= setup_->device_pixel_ratio();
370 event->pointer_data->screen_x /= setup_->device_pixel_ratio();
371 event->pointer_data->screen_y /= setup_->device_pixel_ratio();
374 if ((event->action == mojo::EVENT_TYPE_POINTER_DOWN ||
375 event->action == mojo::EVENT_TYPE_POINTER_UP ||
376 event->action == mojo::EVENT_TYPE_POINTER_CANCEL ||
377 event->action == mojo::EVENT_TYPE_POINTER_MOVE) &&
378 event->pointer_data->kind == mojo::POINTER_KIND_TOUCH) {
379 touch_handler_->OnTouchEvent(*event);
380 return;
382 scoped_ptr<blink::WebInputEvent> web_event =
383 event.To<scoped_ptr<blink::WebInputEvent>>();
384 if (web_event)
385 web_view_->handleInputEvent(*web_event);
388 media::MediaPermission* HTMLDocument::GetMediaPermission() {
389 if (!media_permission_)
390 media_permission_.reset(new media::DefaultMediaPermission(true));
391 return media_permission_.get();
394 media::CdmFactory* HTMLDocument::GetCdmFactory() {
395 if (!cdm_factory_)
396 cdm_factory_.reset(new media::DefaultCdmFactory());
397 return cdm_factory_.get();
400 } // namespace html_viewer