Port Android relocation packer to chromium build
[chromium-blink-merge.git] / mojo / services / html_viewer / html_document.cc
blob2d56d142c7f88ff40e012a6ea89938d1fb59a92d
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 "mojo/services/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 "media/blink/webencryptedmediaclient_impl.h"
16 #include "media/cdm/default_cdm_factory.h"
17 #include "media/filters/default_media_permission.h"
18 #include "mojo/services/html_viewer/blink_input_events_type_converters.h"
19 #include "mojo/services/html_viewer/blink_url_request_type_converters.h"
20 #include "mojo/services/html_viewer/weblayertreeview_impl.h"
21 #include "mojo/services/html_viewer/webmediaplayer_factory.h"
22 #include "mojo/services/html_viewer/webstoragenamespace_impl.h"
23 #include "mojo/services/html_viewer/weburlloader_impl.h"
24 #include "skia/ext/refptr.h"
25 #include "third_party/WebKit/public/platform/Platform.h"
26 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
27 #include "third_party/WebKit/public/platform/WebSize.h"
28 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
29 #include "third_party/WebKit/public/web/WebDocument.h"
30 #include "third_party/WebKit/public/web/WebElement.h"
31 #include "third_party/WebKit/public/web/WebInputEvent.h"
32 #include "third_party/WebKit/public/web/WebLocalFrame.h"
33 #include "third_party/WebKit/public/web/WebScriptSource.h"
34 #include "third_party/WebKit/public/web/WebSettings.h"
35 #include "third_party/WebKit/public/web/WebView.h"
36 #include "third_party/mojo/src/mojo/public/cpp/application/connect.h"
37 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h"
38 #include "third_party/mojo/src/mojo/public/interfaces/application/shell.mojom.h"
39 #include "third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom.h"
40 #include "third_party/mojo_services/src/view_manager/public/cpp/view.h"
41 #include "third_party/skia/include/core/SkCanvas.h"
42 #include "third_party/skia/include/core/SkColor.h"
43 #include "third_party/skia/include/core/SkDevice.h"
44 #include "ui/gfx/geometry/dip_util.h"
46 using mojo::AxProvider;
47 using mojo::Rect;
48 using mojo::ServiceProviderPtr;
49 using mojo::URLResponsePtr;
50 using mojo::View;
51 using mojo::ViewManager;
52 using mojo::WeakBindToRequest;
54 namespace html_viewer {
55 namespace {
57 void ConfigureSettings(blink::WebSettings* settings) {
58 settings->setCookieEnabled(true);
59 settings->setDefaultFixedFontSize(13);
60 settings->setDefaultFontSize(16);
61 settings->setLoadsImagesAutomatically(true);
62 settings->setJavaScriptEnabled(true);
65 mojo::Target WebNavigationPolicyToNavigationTarget(
66 blink::WebNavigationPolicy policy) {
67 switch (policy) {
68 case blink::WebNavigationPolicyCurrentTab:
69 return mojo::TARGET_SOURCE_NODE;
70 case blink::WebNavigationPolicyNewBackgroundTab:
71 case blink::WebNavigationPolicyNewForegroundTab:
72 case blink::WebNavigationPolicyNewWindow:
73 case blink::WebNavigationPolicyNewPopup:
74 return mojo::TARGET_NEW_NODE;
75 default:
76 return mojo::TARGET_DEFAULT;
80 bool CanNavigateLocally(blink::WebFrame* frame,
81 const blink::WebURLRequest& request) {
82 // For now, we just load child frames locally.
83 // TODO(aa): In the future, this should use embedding to connect to a
84 // different instance of Blink if the frame is cross-origin.
85 if (frame->parent())
86 return true;
88 // If we have extraData() it means we already have the url response
89 // (presumably because we are being called via Navigate()). In that case we
90 // can go ahead and navigate locally.
91 if (request.extraData())
92 return true;
94 // Otherwise we don't know if we're the right app to handle this request. Ask
95 // host to do the navigation for us.
96 return false;
99 } // namespace
101 HTMLDocument::HTMLDocument(
102 mojo::InterfaceRequest<mojo::ServiceProvider> services,
103 URLResponsePtr response,
104 mojo::Shell* shell,
105 scoped_refptr<base::MessageLoopProxy> compositor_thread,
106 WebMediaPlayerFactory* web_media_player_factory,
107 bool is_headless)
108 : response_(response.Pass()),
109 shell_(shell),
110 web_view_(nullptr),
111 root_(nullptr),
112 view_manager_client_factory_(shell_, this),
113 compositor_thread_(compositor_thread),
114 web_media_player_factory_(web_media_player_factory),
115 is_headless_(is_headless) {
116 exported_services_.AddService(this);
117 exported_services_.AddService(&view_manager_client_factory_);
118 exported_services_.Bind(services.Pass());
119 Load(response_.Pass());
122 HTMLDocument::~HTMLDocument() {
123 STLDeleteElements(&ax_provider_impls_);
125 if (web_view_)
126 web_view_->close();
127 if (root_)
128 root_->RemoveObserver(this);
131 void HTMLDocument::OnEmbed(
132 View* root,
133 mojo::InterfaceRequest<mojo::ServiceProvider> services,
134 mojo::ServiceProviderPtr exposed_services) {
135 DCHECK(!is_headless_);
136 root_ = root;
137 embedder_service_provider_ = exposed_services.Pass();
138 navigator_host_.set_service_provider(embedder_service_provider_.get());
139 UpdateWebviewSizeFromViewSize();
140 web_layer_tree_view_impl_->set_view(root_);
141 root_->AddObserver(this);
144 void HTMLDocument::Create(mojo::ApplicationConnection* connection,
145 mojo::InterfaceRequest<AxProvider> request) {
146 if (!web_view_)
147 return;
148 ax_provider_impls_.insert(
149 WeakBindToRequest(new AxProviderImpl(web_view_), &request));
152 void HTMLDocument::OnViewManagerDisconnected(ViewManager* view_manager) {
153 // TODO(aa): Need to figure out how shutdown works.
156 void HTMLDocument::Load(URLResponsePtr response) {
157 web_view_ = blink::WebView::create(this);
158 web_layer_tree_view_impl_->set_widget(web_view_);
159 ConfigureSettings(web_view_->settings());
160 web_view_->setMainFrame(blink::WebLocalFrame::create(this));
162 GURL url(response->url);
164 WebURLRequestExtraData* extra_data = new WebURLRequestExtraData;
165 extra_data->synthetic_response = response.Pass();
167 blink::WebURLRequest web_request;
168 web_request.initialize();
169 web_request.setURL(url);
170 web_request.setExtraData(extra_data);
172 web_view_->mainFrame()->loadRequest(web_request);
175 void HTMLDocument::UpdateWebviewSizeFromViewSize() {
176 web_view_->setDeviceScaleFactor(root_->viewport_metrics().device_pixel_ratio);
177 const gfx::Size size_in_pixels(root_->bounds().width, root_->bounds().height);
178 const gfx::Size size_in_dips = gfx::ConvertSizeToDIP(
179 root_->viewport_metrics().device_pixel_ratio, size_in_pixels);
180 web_view_->resize(
181 blink::WebSize(size_in_dips.width(), size_in_dips.height()));
182 web_layer_tree_view_impl_->setViewportSize(size_in_pixels);
185 blink::WebStorageNamespace* HTMLDocument::createSessionStorageNamespace() {
186 return new WebStorageNamespaceImpl();
189 void HTMLDocument::initializeLayerTreeView() {
190 if (is_headless_) {
191 web_layer_tree_view_impl_.reset(
192 new WebLayerTreeViewImpl(compositor_thread_, nullptr, nullptr));
193 return;
196 ServiceProviderPtr surfaces_service_provider;
197 shell_->ConnectToApplication("mojo:surfaces_service",
198 GetProxy(&surfaces_service_provider), nullptr);
199 mojo::SurfacePtr surface;
200 ConnectToService(surfaces_service_provider.get(), &surface);
202 ServiceProviderPtr gpu_service_provider;
203 // TODO(jamesr): Should be mojo:gpu_service
204 shell_->ConnectToApplication("mojo:native_viewport_service",
205 GetProxy(&gpu_service_provider), nullptr);
206 mojo::GpuPtr gpu_service;
207 ConnectToService(gpu_service_provider.get(), &gpu_service);
208 web_layer_tree_view_impl_.reset(new WebLayerTreeViewImpl(
209 compositor_thread_, surface.Pass(), gpu_service.Pass()));
212 blink::WebLayerTreeView* HTMLDocument::layerTreeView() {
213 return web_layer_tree_view_impl_.get();
216 blink::WebMediaPlayer* HTMLDocument::createMediaPlayer(
217 blink::WebLocalFrame* frame,
218 const blink::WebURL& url,
219 blink::WebMediaPlayerClient* client) {
220 return createMediaPlayer(frame, url, client, nullptr);
223 blink::WebMediaPlayer* HTMLDocument::createMediaPlayer(
224 blink::WebLocalFrame* frame,
225 const blink::WebURL& url,
226 blink::WebMediaPlayerClient* client,
227 blink::WebContentDecryptionModule* initial_cdm) {
228 if (!media_permission_)
229 media_permission_.reset(new media::DefaultMediaPermission(true));
231 blink::WebMediaPlayer* player =
232 web_media_player_factory_
233 ? web_media_player_factory_->CreateMediaPlayer(
234 frame, url, client, media_permission_.get(), initial_cdm,
235 shell_)
236 : nullptr;
237 return player;
240 blink::WebFrame* HTMLDocument::createChildFrame(
241 blink::WebLocalFrame* parent,
242 const blink::WebString& frameName,
243 blink::WebSandboxFlags sandboxFlags) {
244 blink::WebLocalFrame* web_frame = blink::WebLocalFrame::create(this);
245 parent->appendChild(web_frame);
246 return web_frame;
249 void HTMLDocument::frameDetached(blink::WebFrame* frame) {
250 if (frame->parent())
251 frame->parent()->removeChild(frame);
253 // |frame| is invalid after here.
254 frame->close();
257 blink::WebCookieJar* HTMLDocument::cookieJar(blink::WebLocalFrame* frame) {
258 // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar.
259 // Either it should, as it once did, or we should find another solution here.
260 return blink::Platform::current()->cookieJar();
263 blink::WebNavigationPolicy HTMLDocument::decidePolicyForNavigation(
264 blink::WebLocalFrame* frame,
265 blink::WebDataSource::ExtraData* data,
266 const blink::WebURLRequest& request,
267 blink::WebNavigationType nav_type,
268 blink::WebNavigationPolicy default_policy,
269 bool is_redirect) {
270 if (CanNavigateLocally(frame, request))
271 return default_policy;
273 if (navigator_host_.get()) {
274 navigator_host_->RequestNavigate(
275 WebNavigationPolicyToNavigationTarget(default_policy),
276 mojo::URLRequest::From(request).Pass());
279 return blink::WebNavigationPolicyIgnore;
282 void HTMLDocument::didAddMessageToConsole(
283 const blink::WebConsoleMessage& message,
284 const blink::WebString& source_name,
285 unsigned source_line,
286 const blink::WebString& stack_trace) {
287 VLOG(1) << "[" << source_name.utf8() << "(" << source_line << ")] "
288 << message.text.utf8();
291 void HTMLDocument::didNavigateWithinPage(
292 blink::WebLocalFrame* frame,
293 const blink::WebHistoryItem& history_item,
294 blink::WebHistoryCommitType commit_type) {
295 if (navigator_host_.get())
296 navigator_host_->DidNavigateLocally(history_item.urlString().utf8());
299 blink::WebEncryptedMediaClient* HTMLDocument::encryptedMediaClient() {
300 if (!web_encrypted_media_client_) {
301 if (!media_permission_)
302 media_permission_.reset(new media::DefaultMediaPermission(true));
303 web_encrypted_media_client_.reset(new media::WebEncryptedMediaClientImpl(
304 make_scoped_ptr(new media::DefaultCdmFactory()),
305 media_permission_.get()));
307 return web_encrypted_media_client_.get();
310 void HTMLDocument::OnViewBoundsChanged(View* view,
311 const Rect& old_bounds,
312 const Rect& new_bounds) {
313 DCHECK_EQ(view, root_);
314 UpdateWebviewSizeFromViewSize();
317 void HTMLDocument::OnViewDestroyed(View* view) {
318 DCHECK_EQ(view, root_);
319 root_ = nullptr;
322 void HTMLDocument::OnViewInputEvent(View* view, const mojo::EventPtr& event) {
323 scoped_ptr<blink::WebInputEvent> web_event =
324 event.To<scoped_ptr<blink::WebInputEvent>>();
325 if (web_event)
326 web_view_->handleInputEvent(*web_event);
329 } // namespace html_viewer