| 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 |