OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "mojo/services/html_viewer/html_document_view.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/location.h" | |
9 #include "base/message_loop/message_loop_proxy.h" | |
10 #include "base/single_thread_task_runner.h" | |
11 #include "base/stl_util.h" | |
12 #include "base/strings/string_util.h" | |
13 #include "base/thread_task_runner_handle.h" | |
14 #include "mojo/public/cpp/application/connect.h" | |
15 #include "mojo/public/cpp/system/data_pipe.h" | |
16 #include "mojo/public/interfaces/application/shell.mojom.h" | |
17 #include "mojo/services/html_viewer/blink_input_events_type_converters.h" | |
18 #include "mojo/services/html_viewer/blink_url_request_type_converters.h" | |
19 #include "mojo/services/html_viewer/weblayertreeview_impl.h" | |
20 #include "mojo/services/html_viewer/webmediaplayer_factory.h" | |
21 #include "mojo/services/html_viewer/webstoragenamespace_impl.h" | |
22 #include "mojo/services/html_viewer/weburlloader_impl.h" | |
23 #include "mojo/services/public/cpp/view_manager/view.h" | |
24 #include "mojo/services/public/interfaces/surfaces/surfaces_service.mojom.h" | |
25 #include "skia/ext/refptr.h" | |
26 #include "third_party/WebKit/public/platform/Platform.h" | |
27 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" | |
28 #include "third_party/WebKit/public/platform/WebSize.h" | |
29 #include "third_party/WebKit/public/web/WebConsoleMessage.h" | |
30 #include "third_party/WebKit/public/web/WebDocument.h" | |
31 #include "third_party/WebKit/public/web/WebElement.h" | |
32 #include "third_party/WebKit/public/web/WebInputEvent.h" | |
33 #include "third_party/WebKit/public/web/WebLocalFrame.h" | |
34 #include "third_party/WebKit/public/web/WebScriptSource.h" | |
35 #include "third_party/WebKit/public/web/WebSettings.h" | |
36 #include "third_party/WebKit/public/web/WebView.h" | |
37 #include "third_party/skia/include/core/SkCanvas.h" | |
38 #include "third_party/skia/include/core/SkColor.h" | |
39 #include "third_party/skia/include/core/SkDevice.h" | |
40 | |
41 namespace mojo { | |
42 namespace { | |
43 | |
44 void ConfigureSettings(blink::WebSettings* settings) { | |
45 settings->setCookieEnabled(true); | |
46 settings->setDefaultFixedFontSize(13); | |
47 settings->setDefaultFontSize(16); | |
48 settings->setLoadsImagesAutomatically(true); | |
49 settings->setJavaScriptEnabled(true); | |
50 } | |
51 | |
52 Target WebNavigationPolicyToNavigationTarget( | |
53 blink::WebNavigationPolicy policy) { | |
54 switch (policy) { | |
55 case blink::WebNavigationPolicyCurrentTab: | |
56 return TARGET_SOURCE_NODE; | |
57 case blink::WebNavigationPolicyNewBackgroundTab: | |
58 case blink::WebNavigationPolicyNewForegroundTab: | |
59 case blink::WebNavigationPolicyNewWindow: | |
60 case blink::WebNavigationPolicyNewPopup: | |
61 return TARGET_NEW_NODE; | |
62 default: | |
63 return TARGET_DEFAULT; | |
64 } | |
65 } | |
66 | |
67 bool CanNavigateLocally(blink::WebFrame* frame, | |
68 const blink::WebURLRequest& request) { | |
69 // For now, we just load child frames locally. | |
70 // TODO(aa): In the future, this should use embedding to connect to a | |
71 // different instance of Blink if the frame is cross-origin. | |
72 if (frame->parent()) | |
73 return true; | |
74 | |
75 // If we have extraData() it means we already have the url response | |
76 // (presumably because we are being called via Navigate()). In that case we | |
77 // can go ahead and navigate locally. | |
78 if (request.extraData()) | |
79 return true; | |
80 | |
81 // Otherwise we don't know if we're the right app to handle this request. Ask | |
82 // host to do the navigation for us. | |
83 return false; | |
84 } | |
85 | |
86 } // namespace | |
87 | |
88 HTMLDocumentView::HTMLDocumentView( | |
89 URLResponsePtr response, | |
90 ShellPtr shell, | |
91 scoped_refptr<base::MessageLoopProxy> compositor_thread, | |
92 WebMediaPlayerFactory* web_media_player_factory) | |
93 : response_(response.Pass()), | |
94 shell_(shell.Pass()), | |
95 web_view_(NULL), | |
96 root_(NULL), | |
97 view_manager_client_factory_(shell_.get(), this), | |
98 compositor_thread_(compositor_thread), | |
99 web_media_player_factory_(web_media_player_factory) { | |
100 shell_.set_client(this); | |
101 } | |
102 | |
103 HTMLDocumentView::~HTMLDocumentView() { | |
104 STLDeleteElements(&ax_provider_impls_); | |
105 | |
106 if (web_view_) | |
107 web_view_->close(); | |
108 if (root_) | |
109 root_->RemoveObserver(this); | |
110 } | |
111 | |
112 void HTMLDocumentView::AcceptConnection(const String& requestor_url, | |
113 ServiceProviderPtr provider) { | |
114 exported_services_.AddService(this); | |
115 exported_services_.AddService(&view_manager_client_factory_); | |
116 WeakBindToPipe(&exported_services_, provider.PassMessagePipe()); | |
117 Load(response_.Pass()); | |
118 } | |
119 | |
120 void HTMLDocumentView::Initialize(Array<String> args) { | |
121 } | |
122 | |
123 void HTMLDocumentView::OnEmbed( | |
124 ViewManager* view_manager, | |
125 View* root, | |
126 ServiceProviderImpl* embedee_service_provider_impl, | |
127 scoped_ptr<ServiceProvider> embedder_service_provider) { | |
128 root_ = root; | |
129 embedder_service_provider_ = embedder_service_provider.Pass(); | |
130 navigator_host_.set_service_provider(embedder_service_provider_.get()); | |
131 | |
132 blink::WebSize root_size(root_->bounds().width, root_->bounds().height); | |
133 web_view_->resize(root_size); | |
134 web_layer_tree_view_impl_->setViewportSize(root_size); | |
135 web_layer_tree_view_impl_->set_view(root_); | |
136 root_->AddObserver(this); | |
137 } | |
138 | |
139 void HTMLDocumentView::Create(ApplicationConnection* connection, | |
140 InterfaceRequest<AxProvider> request) { | |
141 if (!web_view_) | |
142 return; | |
143 ax_provider_impls_.insert( | |
144 WeakBindToRequest(new AxProviderImpl(web_view_), &request)); | |
145 } | |
146 | |
147 void HTMLDocumentView::OnViewManagerDisconnected(ViewManager* view_manager) { | |
148 // TODO(aa): Need to figure out how shutdown works. | |
149 } | |
150 | |
151 void HTMLDocumentView::Load(URLResponsePtr response) { | |
152 web_view_ = blink::WebView::create(this); | |
153 web_layer_tree_view_impl_->set_widget(web_view_); | |
154 ConfigureSettings(web_view_->settings()); | |
155 web_view_->setMainFrame(blink::WebLocalFrame::create(this)); | |
156 | |
157 GURL url(response->url); | |
158 | |
159 WebURLRequestExtraData* extra_data = new WebURLRequestExtraData; | |
160 extra_data->synthetic_response = response.Pass(); | |
161 | |
162 blink::WebURLRequest web_request; | |
163 web_request.initialize(); | |
164 web_request.setURL(url); | |
165 web_request.setExtraData(extra_data); | |
166 | |
167 web_view_->mainFrame()->loadRequest(web_request); | |
168 } | |
169 | |
170 blink::WebStorageNamespace* HTMLDocumentView::createSessionStorageNamespace() { | |
171 return new WebStorageNamespaceImpl(); | |
172 } | |
173 | |
174 void HTMLDocumentView::initializeLayerTreeView() { | |
175 ServiceProviderPtr surfaces_service_provider; | |
176 shell_->ConnectToApplication("mojo:surfaces_service", | |
177 GetProxy(&surfaces_service_provider)); | |
178 SurfacesServicePtr surfaces_service; | |
179 ConnectToService(surfaces_service_provider.get(), &surfaces_service); | |
180 | |
181 ServiceProviderPtr gpu_service_provider; | |
182 // TODO(jamesr): Should be mojo:gpu_service | |
183 shell_->ConnectToApplication("mojo:native_viewport_service", | |
184 GetProxy(&gpu_service_provider)); | |
185 GpuPtr gpu_service; | |
186 ConnectToService(gpu_service_provider.get(), &gpu_service); | |
187 web_layer_tree_view_impl_.reset(new WebLayerTreeViewImpl( | |
188 compositor_thread_, surfaces_service.Pass(), gpu_service.Pass())); | |
189 } | |
190 | |
191 blink::WebLayerTreeView* HTMLDocumentView::layerTreeView() { | |
192 return web_layer_tree_view_impl_.get(); | |
193 } | |
194 | |
195 blink::WebMediaPlayer* HTMLDocumentView::createMediaPlayer( | |
196 blink::WebLocalFrame* frame, | |
197 const blink::WebURL& url, | |
198 blink::WebMediaPlayerClient* client) { | |
199 return web_media_player_factory_->CreateMediaPlayer( | |
200 frame, url, client, shell_.get()); | |
201 } | |
202 | |
203 blink::WebMediaPlayer* HTMLDocumentView::createMediaPlayer( | |
204 blink::WebLocalFrame* frame, | |
205 const blink::WebURL& url, | |
206 blink::WebMediaPlayerClient* client, | |
207 blink::WebContentDecryptionModule* initial_cdm) { | |
208 return createMediaPlayer(frame, url, client); | |
209 } | |
210 | |
211 blink::WebFrame* HTMLDocumentView::createChildFrame( | |
212 blink::WebLocalFrame* parent, | |
213 const blink::WebString& frameName) { | |
214 blink::WebLocalFrame* web_frame = blink::WebLocalFrame::create(this); | |
215 parent->appendChild(web_frame); | |
216 return web_frame; | |
217 } | |
218 | |
219 void HTMLDocumentView::frameDetached(blink::WebFrame* frame) { | |
220 if (frame->parent()) | |
221 frame->parent()->removeChild(frame); | |
222 | |
223 // |frame| is invalid after here. | |
224 frame->close(); | |
225 } | |
226 | |
227 blink::WebCookieJar* HTMLDocumentView::cookieJar(blink::WebLocalFrame* frame) { | |
228 // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar. | |
229 // Either it should, as it once did, or we should find another solution here. | |
230 return blink::Platform::current()->cookieJar(); | |
231 } | |
232 | |
233 blink::WebNavigationPolicy HTMLDocumentView::decidePolicyForNavigation( | |
234 blink::WebLocalFrame* frame, blink::WebDataSource::ExtraData* data, | |
235 const blink::WebURLRequest& request, blink::WebNavigationType nav_type, | |
236 blink::WebNavigationPolicy default_policy, bool is_redirect) { | |
237 if (CanNavigateLocally(frame, request)) | |
238 return default_policy; | |
239 | |
240 navigator_host_->RequestNavigate( | |
241 WebNavigationPolicyToNavigationTarget(default_policy), | |
242 URLRequest::From(request).Pass()); | |
243 | |
244 return blink::WebNavigationPolicyIgnore; | |
245 } | |
246 | |
247 void HTMLDocumentView::didAddMessageToConsole( | |
248 const blink::WebConsoleMessage& message, | |
249 const blink::WebString& source_name, | |
250 unsigned source_line, | |
251 const blink::WebString& stack_trace) { | |
252 } | |
253 | |
254 void HTMLDocumentView::didNavigateWithinPage( | |
255 blink::WebLocalFrame* frame, const blink::WebHistoryItem& history_item, | |
256 blink::WebHistoryCommitType commit_type) { | |
257 navigator_host_->DidNavigateLocally(history_item.urlString().utf8()); | |
258 } | |
259 | |
260 void HTMLDocumentView::OnViewBoundsChanged(View* view, | |
261 const Rect& old_bounds, | |
262 const Rect& new_bounds) { | |
263 DCHECK_EQ(view, root_); | |
264 web_view_->resize( | |
265 blink::WebSize(view->bounds().width, view->bounds().height)); | |
266 } | |
267 | |
268 void HTMLDocumentView::OnViewDestroyed(View* view) { | |
269 DCHECK_EQ(view, root_); | |
270 view->RemoveObserver(this); | |
271 root_ = NULL; | |
272 } | |
273 | |
274 void HTMLDocumentView::OnViewInputEvent(View* view, const EventPtr& event) { | |
275 scoped_ptr<blink::WebInputEvent> web_event = | |
276 event.To<scoped_ptr<blink::WebInputEvent> >(); | |
277 if (web_event) | |
278 web_view_->handleInputEvent(*web_event); | |
279 } | |
280 | |
281 } // namespace mojo | |
OLD | NEW |