| 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 "services/sky/document_view.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/location.h" | |
| 9 #include "base/single_thread_task_runner.h" | |
| 10 #include "base/strings/string_util.h" | |
| 11 #include "base/thread_task_runner_handle.h" | |
| 12 #include "mojo/converters/geometry/geometry_type_converters.h" | |
| 13 #include "mojo/converters/input_events/input_events_type_converters.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/view_manager/public/cpp/view.h" | |
| 18 #include "mojo/services/view_manager/public/cpp/view_manager.h" | |
| 19 #include "mojo/services/view_manager/public/interfaces/view_manager.mojom.h" | |
| 20 #include "services/sky/compositor/layer.h" | |
| 21 #include "services/sky/compositor/layer_host.h" | |
| 22 #include "services/sky/compositor/rasterizer_bitmap.h" | |
| 23 #include "services/sky/compositor/rasterizer_ganesh.h" | |
| 24 #include "services/sky/converters/input_event_types.h" | |
| 25 #include "services/sky/dart_library_provider_impl.h" | |
| 26 #include "services/sky/internals.h" | |
| 27 #include "services/sky/runtime_flags.h" | |
| 28 #include "skia/ext/refptr.h" | |
| 29 #include "sky/engine/public/platform/Platform.h" | |
| 30 #include "sky/engine/public/platform/WebInputEvent.h" | |
| 31 #include "sky/engine/public/platform/WebScreenInfo.h" | |
| 32 #include "sky/engine/public/web/Sky.h" | |
| 33 #include "third_party/skia/include/core/SkCanvas.h" | |
| 34 #include "third_party/skia/include/core/SkColor.h" | |
| 35 #include "third_party/skia/include/core/SkDevice.h" | |
| 36 #include "ui/events/gestures/gesture_recognizer.h" | |
| 37 | |
| 38 namespace sky { | |
| 39 namespace { | |
| 40 | |
| 41 ui::EventType ConvertEventTypeToUIEventType(blink::WebInputEvent::Type type) { | |
| 42 if (type == blink::WebInputEvent::PointerDown) | |
| 43 return ui::ET_TOUCH_PRESSED; | |
| 44 if (type == blink::WebInputEvent::PointerUp) | |
| 45 return ui::ET_TOUCH_RELEASED; | |
| 46 if (type == blink::WebInputEvent::PointerMove) | |
| 47 return ui::ET_TOUCH_MOVED; | |
| 48 DCHECK(type == blink::WebInputEvent::PointerCancel); | |
| 49 return ui::ET_TOUCH_CANCELLED; | |
| 50 } | |
| 51 | |
| 52 scoped_ptr<ui::TouchEvent> ConvertToUITouchEvent( | |
| 53 const blink::WebInputEvent& event, | |
| 54 float device_pixel_ratio) { | |
| 55 if (!blink::WebInputEvent::isPointerEventType(event.type)) | |
| 56 return nullptr; | |
| 57 const blink::WebPointerEvent& pointer_event = | |
| 58 static_cast<const blink::WebPointerEvent&>(event); | |
| 59 return make_scoped_ptr(new ui::TouchEvent( | |
| 60 ConvertEventTypeToUIEventType(event.type), | |
| 61 gfx::PointF(pointer_event.x * device_pixel_ratio, | |
| 62 pointer_event.y * device_pixel_ratio), | |
| 63 pointer_event.pointer, | |
| 64 base::TimeDelta::FromMillisecondsD(pointer_event.timeStampMS))); | |
| 65 } | |
| 66 | |
| 67 scoped_ptr<DartLibraryProviderImpl::PrefetchedLibrary> | |
| 68 CreatePrefetchedLibraryIfNeeded(const String& name, | |
| 69 mojo::URLResponsePtr response) { | |
| 70 scoped_ptr<DartLibraryProviderImpl::PrefetchedLibrary> prefetched; | |
| 71 if (response->status_code == 200) { | |
| 72 prefetched.reset(new DartLibraryProviderImpl::PrefetchedLibrary()); | |
| 73 prefetched->name = name.toUTF8(); | |
| 74 prefetched->pipe = response->body.Pass(); | |
| 75 } | |
| 76 return prefetched.Pass(); | |
| 77 } | |
| 78 | |
| 79 } // namespace | |
| 80 | |
| 81 DocumentView::DocumentView( | |
| 82 mojo::InterfaceRequest<mojo::ServiceProvider> services, | |
| 83 mojo::ServiceProviderPtr exported_services, | |
| 84 mojo::URLResponsePtr response, | |
| 85 mojo::Shell* shell) | |
| 86 : response_(response.Pass()), | |
| 87 exported_services_(services.Pass()), | |
| 88 imported_services_(exported_services.Pass()), | |
| 89 shell_(shell), | |
| 90 root_(nullptr), | |
| 91 view_manager_client_factory_(shell_, this), | |
| 92 bitmap_rasterizer_(nullptr), | |
| 93 weak_factory_(this) { | |
| 94 exported_services_.AddService(&view_manager_client_factory_); | |
| 95 InitServiceRegistry(); | |
| 96 mojo::ServiceProviderPtr network_service_provider; | |
| 97 shell->ConnectToApplication("mojo:authenticated_network_service", | |
| 98 mojo::GetProxy(&network_service_provider), | |
| 99 nullptr); | |
| 100 mojo::ConnectToService(network_service_provider.get(), &network_service_); | |
| 101 } | |
| 102 | |
| 103 DocumentView::~DocumentView() { | |
| 104 if (root_) | |
| 105 root_->RemoveObserver(this); | |
| 106 ui::GestureRecognizer::Get()->CleanupStateForConsumer(this); | |
| 107 } | |
| 108 | |
| 109 base::WeakPtr<DocumentView> DocumentView::GetWeakPtr() { | |
| 110 return weak_factory_.GetWeakPtr(); | |
| 111 } | |
| 112 | |
| 113 void DocumentView::OnEmbed( | |
| 114 mojo::View* root, | |
| 115 mojo::InterfaceRequest<mojo::ServiceProvider> services_provided_to_embedder, | |
| 116 mojo::ServiceProviderPtr services_provided_by_embedder) { | |
| 117 root_ = root; | |
| 118 | |
| 119 if (services_provided_by_embedder.get()) { | |
| 120 mojo::ConnectToService(services_provided_by_embedder.get(), | |
| 121 &navigator_host_); | |
| 122 } | |
| 123 | |
| 124 services_provided_to_embedder_ = services_provided_to_embedder.Pass(); | |
| 125 services_provided_by_embedder_ = services_provided_by_embedder.Pass(); | |
| 126 | |
| 127 Load(response_.Pass()); | |
| 128 | |
| 129 UpdateRootSizeAndViewportMetrics(root_->bounds()); | |
| 130 | |
| 131 root_->AddObserver(this); | |
| 132 } | |
| 133 | |
| 134 void DocumentView::OnViewManagerDisconnected(mojo::ViewManager* view_manager) { | |
| 135 // TODO(aa): Need to figure out how shutdown works. | |
| 136 } | |
| 137 void DocumentView::Load(mojo::URLResponsePtr response) { | |
| 138 String name = String::fromUTF8(response->url); | |
| 139 library_provider_.reset(new DartLibraryProviderImpl( | |
| 140 network_service_.get(), | |
| 141 CreatePrefetchedLibraryIfNeeded(name, response.Pass()))); | |
| 142 sky_view_ = blink::SkyView::Create(this); | |
| 143 layer_host_.reset(new LayerHost(this)); | |
| 144 root_layer_ = make_scoped_refptr(new Layer(this)); | |
| 145 root_layer_->set_rasterizer(CreateRasterizer()); | |
| 146 layer_host_->SetRootLayer(root_layer_); | |
| 147 | |
| 148 sky_view_->RunFromLibrary(name, library_provider_.get()); | |
| 149 } | |
| 150 | |
| 151 scoped_ptr<Rasterizer> DocumentView::CreateRasterizer() { | |
| 152 if (!RuntimeFlags::Get().testing()) | |
| 153 return make_scoped_ptr(new RasterizerGanesh(layer_host_.get())); | |
| 154 // TODO(abarth): If we have more than one layer, we'll need to re-think how | |
| 155 // we capture pixels for testing; | |
| 156 DCHECK(!bitmap_rasterizer_); | |
| 157 bitmap_rasterizer_ = new RasterizerBitmap(layer_host_.get()); | |
| 158 return make_scoped_ptr(bitmap_rasterizer_); | |
| 159 } | |
| 160 | |
| 161 void DocumentView::GetPixelsForTesting(std::vector<unsigned char>* pixels) { | |
| 162 DCHECK(RuntimeFlags::Get().testing()) << "Requires testing runtime flag"; | |
| 163 DCHECK(root_layer_) << "The root layer owns the rasterizer"; | |
| 164 return bitmap_rasterizer_->GetPixelsForTesting(pixels); | |
| 165 } | |
| 166 | |
| 167 mojo::ScopedMessagePipeHandle DocumentView::TakeServicesProvidedToEmbedder() { | |
| 168 return services_provided_to_embedder_.PassMessagePipe(); | |
| 169 } | |
| 170 | |
| 171 mojo::ScopedMessagePipeHandle DocumentView::TakeServicesProvidedByEmbedder() { | |
| 172 return services_provided_by_embedder_.PassInterface().PassHandle(); | |
| 173 } | |
| 174 | |
| 175 mojo::ScopedMessagePipeHandle DocumentView::TakeServiceRegistry() { | |
| 176 return service_registry_.PassInterface().PassHandle(); | |
| 177 } | |
| 178 | |
| 179 mojo::Shell* DocumentView::GetShell() { | |
| 180 return shell_; | |
| 181 } | |
| 182 | |
| 183 void DocumentView::BeginFrame(base::TimeTicks frame_time) { | |
| 184 if (sky_view_) { | |
| 185 sky_view_->BeginFrame(frame_time); | |
| 186 root_layer_->SetSize(sky_view_->display_metrics().physical_size); | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 void DocumentView::OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) { | |
| 191 if (root_) | |
| 192 root_->SetSurfaceId(surface_id.Pass()); | |
| 193 } | |
| 194 | |
| 195 void DocumentView::PaintContents(SkCanvas* canvas, const gfx::Rect& clip) { | |
| 196 blink::WebRect rect(clip.x(), clip.y(), clip.width(), clip.height()); | |
| 197 | |
| 198 if (sky_view_) { | |
| 199 skia::RefPtr<SkPicture> picture = sky_view_->Paint(); | |
| 200 canvas->clear(SK_ColorBLACK); | |
| 201 canvas->scale(GetDevicePixelRatio(), GetDevicePixelRatio()); | |
| 202 if (picture) | |
| 203 canvas->drawPicture(picture.get()); | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 float DocumentView::GetDevicePixelRatio() const { | |
| 208 if (root_) | |
| 209 return root_->viewport_metrics().device_pixel_ratio; | |
| 210 return 1.f; | |
| 211 } | |
| 212 | |
| 213 void DocumentView::DidCreateIsolate(Dart_Isolate isolate) { | |
| 214 Internals::Create(isolate, this); | |
| 215 } | |
| 216 | |
| 217 mojo::NavigatorHost* DocumentView::NavigatorHost() { | |
| 218 return navigator_host_.get(); | |
| 219 } | |
| 220 | |
| 221 void DocumentView::OnViewBoundsChanged(mojo::View* view, | |
| 222 const mojo::Rect& old_bounds, | |
| 223 const mojo::Rect& new_bounds) { | |
| 224 DCHECK_EQ(view, root_); | |
| 225 UpdateRootSizeAndViewportMetrics(new_bounds); | |
| 226 } | |
| 227 | |
| 228 void DocumentView::OnViewViewportMetricsChanged( | |
| 229 mojo::View* view, | |
| 230 const mojo::ViewportMetrics& old_metrics, | |
| 231 const mojo::ViewportMetrics& new_metrics) { | |
| 232 DCHECK_EQ(view, root_); | |
| 233 | |
| 234 UpdateRootSizeAndViewportMetrics(root_->bounds()); | |
| 235 } | |
| 236 | |
| 237 void DocumentView::UpdateRootSizeAndViewportMetrics( | |
| 238 const mojo::Rect& new_bounds) { | |
| 239 float device_pixel_ratio = GetDevicePixelRatio(); | |
| 240 | |
| 241 if (sky_view_) { | |
| 242 blink::SkyDisplayMetrics metrics; | |
| 243 mojo::Rect bounds = root_->bounds(); | |
| 244 metrics.physical_size = blink::WebSize(bounds.width, bounds.height); | |
| 245 metrics.device_pixel_ratio = device_pixel_ratio; | |
| 246 sky_view_->SetDisplayMetrics(metrics); | |
| 247 return; | |
| 248 } | |
| 249 } | |
| 250 | |
| 251 void DocumentView::OnViewFocusChanged(mojo::View* gained_focus, | |
| 252 mojo::View* lost_focus) { | |
| 253 } | |
| 254 | |
| 255 void DocumentView::OnViewDestroyed(mojo::View* view) { | |
| 256 DCHECK_EQ(view, root_); | |
| 257 | |
| 258 root_ = nullptr; | |
| 259 } | |
| 260 | |
| 261 void DocumentView::OnViewInputEvent( | |
| 262 mojo::View* view, const mojo::EventPtr& event) { | |
| 263 float device_pixel_ratio = GetDevicePixelRatio(); | |
| 264 scoped_ptr<blink::WebInputEvent> web_event = | |
| 265 ConvertEvent(event, device_pixel_ratio); | |
| 266 if (!web_event) | |
| 267 return; | |
| 268 | |
| 269 ui::GestureRecognizer* recognizer = ui::GestureRecognizer::Get(); | |
| 270 scoped_ptr<ui::TouchEvent> touch_event = | |
| 271 ConvertToUITouchEvent(*web_event, device_pixel_ratio); | |
| 272 if (touch_event) | |
| 273 recognizer->ProcessTouchEventPreDispatch(*touch_event, this); | |
| 274 | |
| 275 bool handled = false; | |
| 276 | |
| 277 if (sky_view_) | |
| 278 sky_view_->HandleInputEvent(*web_event); | |
| 279 | |
| 280 if (touch_event) { | |
| 281 ui::EventResult result = handled ? ui::ER_UNHANDLED : ui::ER_UNHANDLED; | |
| 282 if (auto gestures = recognizer->ProcessTouchEventPostDispatch( | |
| 283 *touch_event, result, this)) { | |
| 284 for (auto& gesture : *gestures) { | |
| 285 scoped_ptr<blink::WebInputEvent> gesture_event = | |
| 286 ConvertEvent(*gesture, device_pixel_ratio); | |
| 287 if (gesture_event) { | |
| 288 if (sky_view_) | |
| 289 sky_view_->HandleInputEvent(*gesture_event); | |
| 290 } | |
| 291 } | |
| 292 } | |
| 293 } | |
| 294 } | |
| 295 | |
| 296 void DocumentView::StartDebuggerInspectorBackend() { | |
| 297 // FIXME: Do we need this for dart? | |
| 298 } | |
| 299 | |
| 300 void DocumentView::InitServiceRegistry() { | |
| 301 mojo::ConnectToService(imported_services_.get(), &service_registry_); | |
| 302 mojo::Array<mojo::String> interface_names(1); | |
| 303 interface_names[0] = mojo::ViewManagerClient::Name_; | |
| 304 mojo::ServiceProviderImpl* sp_impl(new mojo::ServiceProviderImpl()); | |
| 305 sp_impl->AddService(&view_manager_client_factory_); | |
| 306 mojo::ServiceProviderPtr sp; | |
| 307 service_registry_service_provider_binding_.reset( | |
| 308 new mojo::StrongBinding<mojo::ServiceProvider>(sp_impl, &sp)); | |
| 309 service_registry_->AddServices(interface_names.Pass(), sp.Pass()); | |
| 310 } | |
| 311 | |
| 312 void DocumentView::ScheduleFrame() { | |
| 313 DCHECK(sky_view_); | |
| 314 layer_host_->SetNeedsAnimate(); | |
| 315 } | |
| 316 | |
| 317 } // namespace sky | |
| OLD | NEW |