1 // Copyright (c) 2012 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 "content/browser/renderer_host/render_widget_host_view_base.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/unguessable_token.h"
10 #include "build/build_config.h"
11 #include "components/viz/common/features.h"
12 #include "components/viz/host/host_frame_sink_manager.h"
13 #include "content/browser/compositor/surface_utils.h"
14 #include "content/browser/gpu/gpu_data_manager_impl.h"
15 #include "content/browser/renderer_host/delegated_frame_host.h"
16 #include "content/browser/renderer_host/display_util.h"
17 #include "content/browser/renderer_host/event_with_latency_info.h"
18 #include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
19 #include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
20 #include "content/browser/renderer_host/render_process_host_impl.h"
21 #include "content/browser/renderer_host/render_widget_host_delegate.h"
22 #include "content/browser/renderer_host/render_widget_host_impl.h"
23 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
24 #include "content/browser/renderer_host/render_widget_host_owner_delegate.h"
25 #include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
26 #include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
27 #include "content/browser/renderer_host/text_input_manager.h"
28 #include "content/common/content_switches_internal.h"
29 #include "third_party/blink/public/mojom/page/record_content_to_visible_time_request.mojom.h"
30 #include "ui/base/layout.h"
31 #include "ui/base/ui_base_types.h"
32 #include "ui/display/screen.h"
33 #include "ui/events/event.h"
34 #include "ui/events/keycodes/dom/dom_code.h"
35 #include "ui/gfx/geometry/dip_util.h"
36 #include "ui/gfx/geometry/point_conversions.h"
37 #include "ui/gfx/geometry/size_conversions.h"
38 #include "ui/gfx/geometry/size_f.h"
39
40 namespace content {
41
RenderWidgetHostViewBase(RenderWidgetHost * host)42 RenderWidgetHostViewBase::RenderWidgetHostViewBase(RenderWidgetHost* host)
43 : host_(RenderWidgetHostImpl::From(host)) {
44 }
45
~RenderWidgetHostViewBase()46 RenderWidgetHostViewBase::~RenderWidgetHostViewBase() {
47 DCHECK(!keyboard_locked_);
48 DCHECK(!IsMouseLocked());
49 // We call this here to guarantee that observers are notified before we go
50 // away. However, some subclasses may wish to call this earlier in their
51 // shutdown process, e.g. to force removal from
52 // RenderWidgetHostInputEventRouter's surface map before relinquishing a
53 // host pointer. There is no harm in calling NotifyObserversAboutShutdown()
54 // twice, as the observers are required to de-register on the first call, and
55 // so the second call does nothing.
56 NotifyObserversAboutShutdown();
57 // If we have a live reference to |text_input_manager_|, we should unregister
58 // so that the |text_input_manager_| will free its state.
59 if (text_input_manager_)
60 text_input_manager_->Unregister(this);
61 }
62
GetFocusedWidget() const63 RenderWidgetHostImpl* RenderWidgetHostViewBase::GetFocusedWidget() const {
64 return host() && host()->delegate()
65 ? host()->delegate()->GetFocusedRenderWidgetHost(host())
66 : nullptr;
67 }
68
GetRenderWidgetHost()69 RenderWidgetHost* RenderWidgetHostViewBase::GetRenderWidgetHost() {
70 return host();
71 }
72
SetContentBackgroundColor(SkColor color)73 void RenderWidgetHostViewBase::SetContentBackgroundColor(SkColor color) {
74 if (content_background_color_ == color)
75 return;
76
77 content_background_color_ = color;
78 UpdateBackgroundColor();
79 }
80
NotifyObserversAboutShutdown()81 void RenderWidgetHostViewBase::NotifyObserversAboutShutdown() {
82 // Note: RenderWidgetHostInputEventRouter is an observer, and uses the
83 // following notification to remove this view from its surface owners map.
84 for (auto& observer : observers_)
85 observer.OnRenderWidgetHostViewBaseDestroyed(this);
86 // All observers are required to disconnect after they are notified.
87 DCHECK(!observers_.might_have_observers());
88 }
89
GetMouseWheelPhaseHandler()90 MouseWheelPhaseHandler* RenderWidgetHostViewBase::GetMouseWheelPhaseHandler() {
91 return nullptr;
92 }
93
StopFlingingIfNecessary(const blink::WebGestureEvent & event,blink::mojom::InputEventResultState ack_result)94 void RenderWidgetHostViewBase::StopFlingingIfNecessary(
95 const blink::WebGestureEvent& event,
96 blink::mojom::InputEventResultState ack_result) {
97 // Reset view_stopped_flinging_for_test_ at the beginning of the scroll
98 // sequence.
99 if (event.GetType() == blink::WebInputEvent::Type::kGestureScrollBegin)
100 view_stopped_flinging_for_test_ = false;
101
102 bool processed = blink::mojom::InputEventResultState::kConsumed == ack_result;
103 if (!processed &&
104 event.GetType() == blink::WebInputEvent::Type::kGestureScrollUpdate &&
105 event.data.scroll_update.inertial_phase ==
106 blink::WebGestureEvent::InertialPhaseState::kMomentum &&
107 event.SourceDevice() != blink::WebGestureDevice::kSyntheticAutoscroll) {
108 StopFling();
109 view_stopped_flinging_for_test_ = true;
110 }
111 }
112
UpdateIntrinsicSizingInfo(blink::mojom::IntrinsicSizingInfoPtr sizing_info)113 void RenderWidgetHostViewBase::UpdateIntrinsicSizingInfo(
114 blink::mojom::IntrinsicSizingInfoPtr sizing_info) {}
115
GetCompositorViewportPixelSize()116 gfx::Size RenderWidgetHostViewBase::GetCompositorViewportPixelSize() {
117 return gfx::ScaleToCeiledSize(GetRequestedRendererSize(),
118 GetDeviceScaleFactor());
119 }
120
SelectionBoundsChanged(const gfx::Rect & anchor_rect,base::i18n::TextDirection anchor_dir,const gfx::Rect & focus_rect,base::i18n::TextDirection focus_dir,bool is_anchor_first)121 void RenderWidgetHostViewBase::SelectionBoundsChanged(
122 const gfx::Rect& anchor_rect,
123 base::i18n::TextDirection anchor_dir,
124 const gfx::Rect& focus_rect,
125 base::i18n::TextDirection focus_dir,
126 bool is_anchor_first) {
127 #if !defined(OS_ANDROID)
128 if (GetTextInputManager())
129 GetTextInputManager()->SelectionBoundsChanged(
130 this, anchor_rect, anchor_dir, focus_rect, focus_dir, is_anchor_first);
131 #else
132 NOTREACHED() << "Selection bounds should be routed through the compositor.";
133 #endif
134 }
135
GetMouseWheelMinimumGranularity() const136 int RenderWidgetHostViewBase::GetMouseWheelMinimumGranularity() const {
137 // Most platforms can specify the floating-point delta in the wheel event so
138 // they don't have a minimum granularity. Android is currently the only
139 // platform that overrides this.
140 return 0;
141 }
142
GetRootView()143 RenderWidgetHostViewBase* RenderWidgetHostViewBase::GetRootView() {
144 return this;
145 }
146
SelectionChanged(const base::string16 & text,size_t offset,const gfx::Range & range)147 void RenderWidgetHostViewBase::SelectionChanged(const base::string16& text,
148 size_t offset,
149 const gfx::Range& range) {
150 if (GetTextInputManager())
151 GetTextInputManager()->SelectionChanged(this, text, offset, range);
152 }
153
GetRequestedRendererSize()154 gfx::Size RenderWidgetHostViewBase::GetRequestedRendererSize() {
155 return GetViewBounds().size();
156 }
157
GetCaptureSequenceNumber() const158 uint32_t RenderWidgetHostViewBase::GetCaptureSequenceNumber() const {
159 // TODO(vmpstr): Implement this for overrides other than aura and child frame.
160 NOTIMPLEMENTED_LOG_ONCE();
161 return 0u;
162 }
163
GetTextInputClient()164 ui::TextInputClient* RenderWidgetHostViewBase::GetTextInputClient() {
165 NOTREACHED();
166 return nullptr;
167 }
168
SetIsInVR(bool is_in_vr)169 void RenderWidgetHostViewBase::SetIsInVR(bool is_in_vr) {
170 NOTIMPLEMENTED_LOG_ONCE();
171 }
172
IsInVR() const173 bool RenderWidgetHostViewBase::IsInVR() const {
174 return false;
175 }
176
GetRootFrameSinkId()177 viz::FrameSinkId RenderWidgetHostViewBase::GetRootFrameSinkId() {
178 return viz::FrameSinkId();
179 }
180
IsSurfaceAvailableForCopy()181 bool RenderWidgetHostViewBase::IsSurfaceAvailableForCopy() {
182 return false;
183 }
184
CopyMainAndPopupFromSurface(base::WeakPtr<RenderWidgetHostImpl> main_host,base::WeakPtr<DelegatedFrameHost> main_frame_host,base::WeakPtr<RenderWidgetHostImpl> popup_host,base::WeakPtr<DelegatedFrameHost> popup_frame_host,const gfx::Rect & src_subrect,const gfx::Size & dst_size,float scale_factor,base::OnceCallback<void (const SkBitmap &)> callback)185 void RenderWidgetHostViewBase::CopyMainAndPopupFromSurface(
186 base::WeakPtr<RenderWidgetHostImpl> main_host,
187 base::WeakPtr<DelegatedFrameHost> main_frame_host,
188 base::WeakPtr<RenderWidgetHostImpl> popup_host,
189 base::WeakPtr<DelegatedFrameHost> popup_frame_host,
190 const gfx::Rect& src_subrect,
191 const gfx::Size& dst_size,
192 float scale_factor,
193 base::OnceCallback<void(const SkBitmap&)> callback) {
194 if (!main_host || !main_frame_host)
195 return;
196
197 #if defined(OS_ANDROID)
198 NOTREACHED()
199 << "RenderWidgetHostViewAndroid::CopyFromSurface calls "
200 "DelegatedFrameHostAndroid::CopyFromCompositingSurface directly, "
201 "and popups are not supported.";
202 return;
203 #else
204 if (!popup_host || !popup_frame_host) {
205 // No popup - just call CopyFromCompositingSurface once.
206 main_frame_host->CopyFromCompositingSurface(src_subrect, dst_size,
207 std::move(callback));
208 return;
209 }
210
211 // First locate the popup relative to the main page, in DIPs
212 const gfx::Point parent_location =
213 main_host->GetView()->GetBoundsInRootWindow().origin();
214 const gfx::Point popup_location =
215 popup_host->GetView()->GetBoundsInRootWindow().origin();
216 const gfx::Point offset_dips =
217 PointAtOffsetFromOrigin(popup_location - parent_location);
218 const gfx::Vector2d offset_physical =
219 ScaleToFlooredPoint(offset_dips, scale_factor).OffsetFromOrigin();
220
221 // Queue up the request for the MAIN frame image first, but with a
222 // callback that launches a second request for the popup image.
223 // 1. Call CopyFromCompositingSurface for the main frame, with callback
224 // |main_image_done_callback|. Inside |main_image_done_callback|:
225 // a. Call CopyFromCompositingSurface again, this time on the popup
226 // frame. For this call, build a new callback, |popup_done_callback|,
227 // which:
228 // i. Takes the main image as a parameter, combines the main image with
229 // the just-acquired popup image, and then calls the original
230 // (outer) callback with the combined image.
231 auto main_image_done_callback = base::BindOnce(
232 [](base::OnceCallback<void(const SkBitmap&)> final_callback,
233 const gfx::Vector2d offset,
234 base::WeakPtr<DelegatedFrameHost> popup_frame_host,
235 const gfx::Rect src_subrect, const gfx::Size dst_size,
236 const SkBitmap& main_image) {
237 if (!popup_frame_host)
238 return;
239
240 // Build a new callback that actually combines images.
241 auto popup_done_callback = base::BindOnce(
242 [](base::OnceCallback<void(const SkBitmap&)> final_callback,
243 const gfx::Vector2d offset, const SkBitmap& main_image,
244 const SkBitmap& popup_image) {
245 // Draw popup_image into main_image.
246 SkCanvas canvas(main_image, SkSurfaceProps{});
247 canvas.drawBitmap(popup_image, offset.x(), offset.y());
248 std::move(final_callback).Run(main_image);
249 },
250 std::move(final_callback), offset, std::move(main_image));
251
252 // Second, request the popup image.
253 gfx::Rect popup_subrect(src_subrect - offset);
254 popup_frame_host->CopyFromCompositingSurface(
255 popup_subrect, dst_size, std::move(popup_done_callback));
256 },
257 std::move(callback), offset_physical, popup_frame_host, src_subrect,
258 dst_size);
259
260 // Request the main image (happens first).
261 main_frame_host->CopyFromCompositingSurface(
262 src_subrect, dst_size, std::move(main_image_done_callback));
263 #endif
264 }
265
CopyFromSurface(const gfx::Rect & src_rect,const gfx::Size & output_size,base::OnceCallback<void (const SkBitmap &)> callback)266 void RenderWidgetHostViewBase::CopyFromSurface(
267 const gfx::Rect& src_rect,
268 const gfx::Size& output_size,
269 base::OnceCallback<void(const SkBitmap&)> callback) {
270 NOTIMPLEMENTED_LOG_ONCE();
271 std::move(callback).Run(SkBitmap());
272 }
273
274 std::unique_ptr<viz::ClientFrameSinkVideoCapturer>
CreateVideoCapturer()275 RenderWidgetHostViewBase::CreateVideoCapturer() {
276 std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer =
277 GetHostFrameSinkManager()->CreateVideoCapturer();
278 video_capturer->ChangeTarget(GetFrameSinkId());
279 return video_capturer;
280 }
281
GetSelectedText()282 base::string16 RenderWidgetHostViewBase::GetSelectedText() {
283 if (!GetTextInputManager())
284 return base::string16();
285 return GetTextInputManager()->GetTextSelection(this)->selected_text();
286 }
287
SetBackgroundColor(SkColor color)288 void RenderWidgetHostViewBase::SetBackgroundColor(SkColor color) {
289 // TODO(danakj): OPAQUE colors only make sense for main frame widgets,
290 // as child frames are always transparent background. We should move this to
291 // RenderView instead.
292 DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
293 SkColorGetA(color) == SK_AlphaTRANSPARENT);
294 if (default_background_color_ == color)
295 return;
296
297 bool opaque = default_background_color_
298 ? SkColorGetA(*default_background_color_)
299 : SK_AlphaOPAQUE;
300 default_background_color_ = color;
301 UpdateBackgroundColor();
302 if (opaque != (SkColorGetA(color) == SK_AlphaOPAQUE)) {
303 if (host()->owner_delegate()) {
304 host()->owner_delegate()->SetBackgroundOpaque(SkColorGetA(color) ==
305 SK_AlphaOPAQUE);
306 }
307 }
308 }
309
GetBackgroundColor()310 base::Optional<SkColor> RenderWidgetHostViewBase::GetBackgroundColor() {
311 if (content_background_color_)
312 return content_background_color_;
313 return default_background_color_;
314 }
315
IsMouseLocked()316 bool RenderWidgetHostViewBase::IsMouseLocked() {
317 return false;
318 }
319
GetIsMouseLockedUnadjustedMovementForTesting()320 bool RenderWidgetHostViewBase::GetIsMouseLockedUnadjustedMovementForTesting() {
321 return false;
322 }
323
LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes)324 bool RenderWidgetHostViewBase::LockKeyboard(
325 base::Optional<base::flat_set<ui::DomCode>> codes) {
326 NOTIMPLEMENTED_LOG_ONCE();
327 return false;
328 }
329
UnlockKeyboard()330 void RenderWidgetHostViewBase::UnlockKeyboard() {
331 NOTIMPLEMENTED_LOG_ONCE();
332 }
333
IsKeyboardLocked()334 bool RenderWidgetHostViewBase::IsKeyboardLocked() {
335 return keyboard_locked_;
336 }
337
338 base::flat_map<std::string, std::string>
GetKeyboardLayoutMap()339 RenderWidgetHostViewBase::GetKeyboardLayoutMap() {
340 NOTIMPLEMENTED_LOG_ONCE();
341 return base::flat_map<std::string, std::string>();
342 }
343
FilterInputEvent(const blink::WebInputEvent & input_event)344 blink::mojom::InputEventResultState RenderWidgetHostViewBase::FilterInputEvent(
345 const blink::WebInputEvent& input_event) {
346 // By default, input events are simply forwarded to the renderer.
347 return blink::mojom::InputEventResultState::kNotConsumed;
348 }
349
WheelEventAck(const blink::WebMouseWheelEvent & event,blink::mojom::InputEventResultState ack_result)350 void RenderWidgetHostViewBase::WheelEventAck(
351 const blink::WebMouseWheelEvent& event,
352 blink::mojom::InputEventResultState ack_result) {}
353
GestureEventAck(const blink::WebGestureEvent & event,blink::mojom::InputEventResultState ack_result)354 void RenderWidgetHostViewBase::GestureEventAck(
355 const blink::WebGestureEvent& event,
356 blink::mojom::InputEventResultState ack_result) {}
357
ChildDidAckGestureEvent(const blink::WebGestureEvent & event,blink::mojom::InputEventResultState ack_result)358 void RenderWidgetHostViewBase::ChildDidAckGestureEvent(
359 const blink::WebGestureEvent& event,
360 blink::mojom::InputEventResultState ack_result) {}
361
ForwardTouchpadZoomEventIfNecessary(const blink::WebGestureEvent & event,blink::mojom::InputEventResultState ack_result)362 void RenderWidgetHostViewBase::ForwardTouchpadZoomEventIfNecessary(
363 const blink::WebGestureEvent& event,
364 blink::mojom::InputEventResultState ack_result) {
365 if (!event.IsTouchpadZoomEvent())
366 return;
367 if (!event.NeedsWheelEvent())
368 return;
369
370 switch (event.GetType()) {
371 case blink::WebInputEvent::Type::kGesturePinchBegin:
372 // Don't send the begin event until we get the first unconsumed update, so
373 // that we elide pinch gesture steams consisting of only a begin and end.
374 pending_touchpad_pinch_begin_ = event;
375 pending_touchpad_pinch_begin_->SetNeedsWheelEvent(false);
376 break;
377 case blink::WebInputEvent::Type::kGesturePinchUpdate:
378 if (ack_result != blink::mojom::InputEventResultState::kConsumed &&
379 !event.data.pinch_update.zoom_disabled) {
380 if (pending_touchpad_pinch_begin_) {
381 host()->ForwardGestureEvent(*pending_touchpad_pinch_begin_);
382 pending_touchpad_pinch_begin_.reset();
383 }
384 // Now that the synthetic wheel event has gone unconsumed, we have the
385 // pinch event actually change the page scale.
386 blink::WebGestureEvent pinch_event(event);
387 pinch_event.SetNeedsWheelEvent(false);
388 host()->ForwardGestureEvent(pinch_event);
389 }
390 break;
391 case blink::WebInputEvent::Type::kGesturePinchEnd:
392 if (pending_touchpad_pinch_begin_) {
393 pending_touchpad_pinch_begin_.reset();
394 } else {
395 blink::WebGestureEvent pinch_end_event(event);
396 pinch_end_event.SetNeedsWheelEvent(false);
397 host()->ForwardGestureEvent(pinch_end_event);
398 }
399 break;
400 case blink::WebInputEvent::Type::kGestureDoubleTap:
401 if (ack_result != blink::mojom::InputEventResultState::kConsumed) {
402 blink::WebGestureEvent double_tap(event);
403 double_tap.SetNeedsWheelEvent(false);
404 // TODO(mcnee): Support double-tap zoom gesture for OOPIFs. For now,
405 // we naively send this to the main frame. If this is over an OOPIF,
406 // then the iframe element will incorrectly be used for the scale
407 // calculation rather than the element in the OOPIF.
408 // https://crbug.com/758348
409 host()->ForwardGestureEvent(double_tap);
410 }
411 break;
412 default:
413 NOTREACHED();
414 }
415 }
416
HasFallbackSurface() const417 bool RenderWidgetHostViewBase::HasFallbackSurface() const {
418 NOTREACHED();
419 return false;
420 }
421
SetWidgetType(WidgetType widget_type)422 void RenderWidgetHostViewBase::SetWidgetType(WidgetType widget_type) {
423 widget_type_ = widget_type;
424 }
425
GetWidgetType()426 WidgetType RenderWidgetHostViewBase::GetWidgetType() {
427 return widget_type_;
428 }
429
430 BrowserAccessibilityManager*
CreateBrowserAccessibilityManager(BrowserAccessibilityDelegate * delegate,bool for_root_frame)431 RenderWidgetHostViewBase::CreateBrowserAccessibilityManager(
432 BrowserAccessibilityDelegate* delegate,
433 bool for_root_frame) {
434 NOTREACHED();
435 return nullptr;
436 }
437
438 gfx::AcceleratedWidget
AccessibilityGetAcceleratedWidget()439 RenderWidgetHostViewBase::AccessibilityGetAcceleratedWidget() {
440 return gfx::kNullAcceleratedWidget;
441 }
442
443 gfx::NativeViewAccessible
AccessibilityGetNativeViewAccessible()444 RenderWidgetHostViewBase::AccessibilityGetNativeViewAccessible() {
445 return nullptr;
446 }
447
448 gfx::NativeViewAccessible
AccessibilityGetNativeViewAccessibleForWindow()449 RenderWidgetHostViewBase::AccessibilityGetNativeViewAccessibleForWindow() {
450 return nullptr;
451 }
452
RequestRepaintForTesting()453 bool RenderWidgetHostViewBase::RequestRepaintForTesting() {
454 return false;
455 }
456
ProcessAckedTouchEvent(const TouchEventWithLatencyInfo & touch,blink::mojom::InputEventResultState ack_result)457 void RenderWidgetHostViewBase::ProcessAckedTouchEvent(
458 const TouchEventWithLatencyInfo& touch,
459 blink::mojom::InputEventResultState ack_result) {
460 NOTREACHED();
461 }
462
UpdateScreenInfo(gfx::NativeView view)463 void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) {
464 if (host() && host()->delegate())
465 host()->delegate()->SendScreenRects();
466
467 if (HasDisplayPropertyChanged(view) && host()) {
468 OnSynchronizedDisplayPropertiesChanged();
469 host()->NotifyScreenInfoChanged();
470 }
471 }
472
HasDisplayPropertyChanged(gfx::NativeView view)473 bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view) {
474 display::Display display =
475 display::Screen::GetScreen()->GetDisplayNearestView(view);
476 if (current_display_area_ == display.work_area() &&
477 current_device_scale_factor_ == display.device_scale_factor() &&
478 current_display_rotation_ == display.rotation() &&
479 current_display_color_spaces_ == display.color_spaces()) {
480 return false;
481 }
482
483 current_display_area_ = display.work_area();
484 current_device_scale_factor_ = display.device_scale_factor();
485 current_display_rotation_ = display.rotation();
486 current_display_color_spaces_ = display.color_spaces();
487 return true;
488 }
489
DidUnregisterFromTextInputManager(TextInputManager * text_input_manager)490 void RenderWidgetHostViewBase::DidUnregisterFromTextInputManager(
491 TextInputManager* text_input_manager) {
492 DCHECK(text_input_manager && text_input_manager_ == text_input_manager);
493
494 text_input_manager_ = nullptr;
495 }
496
EnableAutoResize(const gfx::Size & min_size,const gfx::Size & max_size)497 void RenderWidgetHostViewBase::EnableAutoResize(const gfx::Size& min_size,
498 const gfx::Size& max_size) {
499 host()->SetAutoResize(true, min_size, max_size);
500 host()->SynchronizeVisualProperties();
501 }
502
DisableAutoResize(const gfx::Size & new_size)503 void RenderWidgetHostViewBase::DisableAutoResize(const gfx::Size& new_size) {
504 if (!new_size.IsEmpty())
505 SetSize(new_size);
506 host()->SetAutoResize(false, gfx::Size(), gfx::Size());
507 host()->SynchronizeVisualProperties();
508 }
509
510 viz::ScopedSurfaceIdAllocator
DidUpdateVisualProperties(const cc::RenderFrameMetadata & metadata)511 RenderWidgetHostViewBase::DidUpdateVisualProperties(
512 const cc::RenderFrameMetadata& metadata) {
513 // This doesn't suppress allocation. Derived classes that need suppression
514 // should override this function.
515 base::OnceCallback<void()> allocation_task =
516 base::BindOnce(&RenderWidgetHostViewBase::SynchronizeVisualProperties,
517 weak_factory_.GetWeakPtr());
518 return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
519 }
520
GetWeakPtr()521 base::WeakPtr<RenderWidgetHostViewBase> RenderWidgetHostViewBase::GetWeakPtr() {
522 return weak_factory_.GetWeakPtr();
523 }
524
GetScreenInfo(blink::ScreenInfo * screen_info)525 void RenderWidgetHostViewBase::GetScreenInfo(blink::ScreenInfo* screen_info) {
526 DisplayUtil::GetNativeViewScreenInfo(screen_info, GetNativeView());
527 }
528
GetDeviceScaleFactor()529 float RenderWidgetHostViewBase::GetDeviceScaleFactor() {
530 blink::ScreenInfo screen_info;
531 GetScreenInfo(&screen_info);
532 return screen_info.device_scale_factor;
533 }
534
OnAutoscrollStart()535 void RenderWidgetHostViewBase::OnAutoscrollStart() {
536 if (!GetMouseWheelPhaseHandler())
537 return;
538
539 // End the current scrolling seqeunce when autoscrolling starts.
540 GetMouseWheelPhaseHandler()->DispatchPendingWheelEndEvent();
541 }
542
GetVisibleViewportSize()543 gfx::Size RenderWidgetHostViewBase::GetVisibleViewportSize() {
544 return GetViewBounds().size();
545 }
546
SetInsets(const gfx::Insets & insets)547 void RenderWidgetHostViewBase::SetInsets(const gfx::Insets& insets) {
548 NOTIMPLEMENTED_LOG_ONCE();
549 }
550
DisplayCursor(const WebCursor & cursor)551 void RenderWidgetHostViewBase::DisplayCursor(const WebCursor& cursor) {
552 return;
553 }
554
GetCursorManager()555 CursorManager* RenderWidgetHostViewBase::GetCursorManager() {
556 return nullptr;
557 }
558
TransformPointToRootSurface(gfx::PointF * point)559 void RenderWidgetHostViewBase::TransformPointToRootSurface(gfx::PointF* point) {
560 return;
561 }
562
OnDidNavigateMainFrameToNewPage()563 void RenderWidgetHostViewBase::OnDidNavigateMainFrameToNewPage() {
564 }
565
OnFrameTokenChangedForView(uint32_t frame_token)566 void RenderWidgetHostViewBase::OnFrameTokenChangedForView(
567 uint32_t frame_token) {
568 if (host())
569 host()->DidProcessFrame(frame_token);
570 }
571
ScreenRectIsUnstableFor(const blink::WebInputEvent & event)572 bool RenderWidgetHostViewBase::ScreenRectIsUnstableFor(
573 const blink::WebInputEvent& event) {
574 return false;
575 }
576
ProcessMouseEvent(const blink::WebMouseEvent & event,const ui::LatencyInfo & latency)577 void RenderWidgetHostViewBase::ProcessMouseEvent(
578 const blink::WebMouseEvent& event,
579 const ui::LatencyInfo& latency) {
580 // TODO(crbug.com/814674): Figure out the reason |host| is null here in all
581 // Process* functions.
582 if (!host())
583 return;
584
585 PreProcessMouseEvent(event);
586 host()->ForwardMouseEventWithLatencyInfo(event, latency);
587 }
588
ProcessMouseWheelEvent(const blink::WebMouseWheelEvent & event,const ui::LatencyInfo & latency)589 void RenderWidgetHostViewBase::ProcessMouseWheelEvent(
590 const blink::WebMouseWheelEvent& event,
591 const ui::LatencyInfo& latency) {
592 if (!host())
593 return;
594 host()->ForwardWheelEventWithLatencyInfo(event, latency);
595 }
596
ProcessTouchEvent(const blink::WebTouchEvent & event,const ui::LatencyInfo & latency)597 void RenderWidgetHostViewBase::ProcessTouchEvent(
598 const blink::WebTouchEvent& event,
599 const ui::LatencyInfo& latency) {
600 if (!host())
601 return;
602
603 PreProcessTouchEvent(event);
604 host()->ForwardTouchEventWithLatencyInfo(event, latency);
605 }
606
ProcessGestureEvent(const blink::WebGestureEvent & event,const ui::LatencyInfo & latency)607 void RenderWidgetHostViewBase::ProcessGestureEvent(
608 const blink::WebGestureEvent& event,
609 const ui::LatencyInfo& latency) {
610 if (!host())
611 return;
612 host()->ForwardGestureEventWithLatencyInfo(event, latency);
613 }
614
TransformPointToRootCoordSpaceF(const gfx::PointF & point)615 gfx::PointF RenderWidgetHostViewBase::TransformPointToRootCoordSpaceF(
616 const gfx::PointF& point) {
617 return point;
618 }
619
TransformRootPointToViewCoordSpace(const gfx::PointF & point)620 gfx::PointF RenderWidgetHostViewBase::TransformRootPointToViewCoordSpace(
621 const gfx::PointF& point) {
622 return point;
623 }
624
TransformPointToCoordSpaceForView(const gfx::PointF & point,RenderWidgetHostViewBase * target_view,gfx::PointF * transformed_point)625 bool RenderWidgetHostViewBase::TransformPointToCoordSpaceForView(
626 const gfx::PointF& point,
627 RenderWidgetHostViewBase* target_view,
628 gfx::PointF* transformed_point) {
629 NOTREACHED();
630 return true;
631 }
632
IsRenderWidgetHostViewChildFrame()633 bool RenderWidgetHostViewBase::IsRenderWidgetHostViewChildFrame() {
634 return false;
635 }
636
HasSize() const637 bool RenderWidgetHostViewBase::HasSize() const {
638 return true;
639 }
640
Destroy()641 void RenderWidgetHostViewBase::Destroy() {
642 host_ = nullptr;
643 }
644
CanSynchronizeVisualProperties()645 bool RenderWidgetHostViewBase::CanSynchronizeVisualProperties() {
646 return true;
647 }
648
649 std::vector<std::unique_ptr<ui::TouchEvent>>
ExtractAndCancelActiveTouches()650 RenderWidgetHostViewBase::ExtractAndCancelActiveTouches() {
651 return {};
652 }
653
TextInputStateChanged(const ui::mojom::TextInputState & text_input_state)654 void RenderWidgetHostViewBase::TextInputStateChanged(
655 const ui::mojom::TextInputState& text_input_state) {
656 if (GetTextInputManager())
657 GetTextInputManager()->UpdateTextInputState(this, text_input_state);
658 }
659
ImeCancelComposition()660 void RenderWidgetHostViewBase::ImeCancelComposition() {
661 if (GetTextInputManager())
662 GetTextInputManager()->ImeCancelComposition(this);
663 }
664
ImeCompositionRangeChanged(const gfx::Range & range,const std::vector<gfx::Rect> & character_bounds)665 void RenderWidgetHostViewBase::ImeCompositionRangeChanged(
666 const gfx::Range& range,
667 const std::vector<gfx::Rect>& character_bounds) {
668 if (GetTextInputManager()) {
669 GetTextInputManager()->ImeCompositionRangeChanged(this, range,
670 character_bounds);
671 }
672 }
673
GetTextInputManager()674 TextInputManager* RenderWidgetHostViewBase::GetTextInputManager() {
675 if (text_input_manager_)
676 return text_input_manager_;
677
678 if (!host() || !host()->delegate())
679 return nullptr;
680
681 // This RWHV needs to be registered with the TextInputManager so that the
682 // TextInputManager starts tracking its state, and observing its lifetime.
683 text_input_manager_ = host()->delegate()->GetTextInputManager();
684 if (text_input_manager_)
685 text_input_manager_->Register(this);
686
687 return text_input_manager_;
688 }
689
StopFling()690 void RenderWidgetHostViewBase::StopFling() {
691 if (!host())
692 return;
693
694 host()->StopFling();
695
696 // In case of scroll bubbling tells the child's fling controller which is in
697 // charge of generating GSUs to stop flinging.
698 if (host()->delegate() && host()->delegate()->GetInputEventRouter()) {
699 host()->delegate()->GetInputEventRouter()->StopFling();
700 }
701 }
702
AddObserver(RenderWidgetHostViewBaseObserver * observer)703 void RenderWidgetHostViewBase::AddObserver(
704 RenderWidgetHostViewBaseObserver* observer) {
705 observers_.AddObserver(observer);
706 }
707
RemoveObserver(RenderWidgetHostViewBaseObserver * observer)708 void RenderWidgetHostViewBase::RemoveObserver(
709 RenderWidgetHostViewBaseObserver* observer) {
710 observers_.RemoveObserver(observer);
711 }
712
713 TouchSelectionControllerClientManager*
GetTouchSelectionControllerClientManager()714 RenderWidgetHostViewBase::GetTouchSelectionControllerClientManager() {
715 return nullptr;
716 }
717
SetRecordContentToVisibleTimeRequest(base::TimeTicks start_time,bool destination_is_loaded,bool show_reason_tab_switching,bool show_reason_unoccluded,bool show_reason_bfcache_restore)718 void RenderWidgetHostViewBase::SetRecordContentToVisibleTimeRequest(
719 base::TimeTicks start_time,
720 bool destination_is_loaded,
721 bool show_reason_tab_switching,
722 bool show_reason_unoccluded,
723 bool show_reason_bfcache_restore) {
724 auto record_tab_switch_time_request =
725 blink::mojom::RecordContentToVisibleTimeRequest::New(
726 start_time, destination_is_loaded, show_reason_tab_switching,
727 show_reason_unoccluded, show_reason_bfcache_restore);
728
729 if (last_record_tab_switch_time_request_) {
730 blink::UpdateRecordContentToVisibleTimeRequest(
731 *record_tab_switch_time_request, *last_record_tab_switch_time_request_);
732 } else {
733 last_record_tab_switch_time_request_ =
734 std::move(record_tab_switch_time_request);
735 }
736 }
737
738 blink::mojom::RecordContentToVisibleTimeRequestPtr
TakeRecordContentToVisibleTimeRequest()739 RenderWidgetHostViewBase::TakeRecordContentToVisibleTimeRequest() {
740 return std::move(last_record_tab_switch_time_request_);
741 }
742
SynchronizeVisualProperties()743 void RenderWidgetHostViewBase::SynchronizeVisualProperties() {
744 if (host())
745 host()->SynchronizeVisualProperties();
746 }
747
DidNavigate()748 void RenderWidgetHostViewBase::DidNavigate() {
749 if (host())
750 host()->SynchronizeVisualProperties();
751 }
752
753 // TODO(wjmaclean): Would it simplify this function if we re-implemented it
754 // using GetTransformToViewCoordSpace()?
TransformPointToTargetCoordSpace(RenderWidgetHostViewBase * original_view,RenderWidgetHostViewBase * target_view,const gfx::PointF & point,gfx::PointF * transformed_point) const755 bool RenderWidgetHostViewBase::TransformPointToTargetCoordSpace(
756 RenderWidgetHostViewBase* original_view,
757 RenderWidgetHostViewBase* target_view,
758 const gfx::PointF& point,
759 gfx::PointF* transformed_point) const {
760 DCHECK(original_view);
761 DCHECK(target_view);
762 viz::FrameSinkId root_frame_sink_id = original_view->GetRootFrameSinkId();
763 if (!root_frame_sink_id.is_valid())
764 return false;
765 const auto& display_hit_test_query_map =
766 GetHostFrameSinkManager()->display_hit_test_query();
767 const auto iter = display_hit_test_query_map.find(root_frame_sink_id);
768 if (iter == display_hit_test_query_map.end())
769 return false;
770 viz::HitTestQuery* query = iter->second.get();
771
772 std::vector<viz::FrameSinkId> target_ancestors;
773 target_ancestors.push_back(target_view->GetFrameSinkId());
774
775 RenderWidgetHostViewBase* cur_view = target_view;
776 while (cur_view->IsRenderWidgetHostViewChildFrame()) {
777 cur_view =
778 static_cast<RenderWidgetHostViewChildFrame*>(cur_view)->GetParentView();
779 if (!cur_view)
780 return false;
781 target_ancestors.push_back(cur_view->GetFrameSinkId());
782 }
783 target_ancestors.push_back(root_frame_sink_id);
784
785 float device_scale_factor = original_view->GetDeviceScaleFactor();
786 DCHECK_GT(device_scale_factor, 0.0f);
787 gfx::Point3F point_in_pixels =
788 gfx::Point3F(gfx::ConvertPointToPixels(point, device_scale_factor));
789 // TODO(crbug.com/966995): Optimize so that |point_in_pixels| doesn't need to
790 // be in the coordinate space of the root surface in HitTestQuery.
791 gfx::Transform transform_root_to_original;
792 query->GetTransformToTarget(original_view->GetFrameSinkId(),
793 &transform_root_to_original);
794 if (!transform_root_to_original.TransformPointReverse(&point_in_pixels))
795 return false;
796 gfx::PointF transformed_point_in_physical_pixels;
797 if (!query->TransformLocationForTarget(
798 target_ancestors, point_in_pixels.AsPointF(),
799 &transformed_point_in_physical_pixels)) {
800 return false;
801 }
802 *transformed_point = gfx::ConvertPointToDips(
803 transformed_point_in_physical_pixels, device_scale_factor);
804 return true;
805 }
806
GetTransformToViewCoordSpace(RenderWidgetHostViewBase * target_view,gfx::Transform * transform)807 bool RenderWidgetHostViewBase::GetTransformToViewCoordSpace(
808 RenderWidgetHostViewBase* target_view,
809 gfx::Transform* transform) {
810 DCHECK(transform);
811 if (target_view == this) {
812 transform->MakeIdentity();
813 return true;
814 }
815
816 viz::FrameSinkId root_frame_sink_id = GetRootFrameSinkId();
817 if (!root_frame_sink_id.is_valid())
818 return false;
819
820 const auto& display_hit_test_query_map =
821 GetHostFrameSinkManager()->display_hit_test_query();
822 const auto iter = display_hit_test_query_map.find(root_frame_sink_id);
823 if (iter == display_hit_test_query_map.end())
824 return false;
825 viz::HitTestQuery* query = iter->second.get();
826
827 gfx::Transform transform_this_to_root;
828 if (GetFrameSinkId() != root_frame_sink_id) {
829 gfx::Transform transform_root_to_this;
830 if (!query->GetTransformToTarget(GetFrameSinkId(), &transform_root_to_this))
831 return false;
832 if (!transform_root_to_this.GetInverse(&transform_this_to_root))
833 return false;
834 }
835 gfx::Transform transform_root_to_target;
836 if (!query->GetTransformToTarget(target_view->GetFrameSinkId(),
837 &transform_root_to_target)) {
838 return false;
839 }
840
841 // TODO(wjmaclean): In TransformPointToTargetCoordSpace the device scale
842 // factor is taken from the original view ... does that matter? Presumably
843 // all the views have the same dsf.
844 float device_scale_factor = GetDeviceScaleFactor();
845 gfx::Transform transform_to_pixel;
846 transform_to_pixel.Scale(device_scale_factor, device_scale_factor);
847 gfx::Transform transform_from_pixel;
848 transform_from_pixel.Scale(1.f / device_scale_factor,
849 1.f / device_scale_factor);
850
851 // Note: gfx::Transform includes optimizations to early-out for scale = 1 or
852 // concatenating an identity matrix, so we don't add those checks here.
853 transform->MakeIdentity();
854
855 transform->ConcatTransform(transform_to_pixel);
856 transform->ConcatTransform(transform_this_to_root);
857 transform->ConcatTransform(transform_root_to_target);
858 transform->ConcatTransform(transform_from_pixel);
859
860 return true;
861 }
862
TransformPointToLocalCoordSpace(const gfx::PointF & point,const viz::SurfaceId & original_surface,gfx::PointF * transformed_point)863 bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
864 const gfx::PointF& point,
865 const viz::SurfaceId& original_surface,
866 gfx::PointF* transformed_point) {
867 viz::FrameSinkId original_frame_sink_id = original_surface.frame_sink_id();
868 viz::FrameSinkId target_frame_sink_id = GetFrameSinkId();
869 if (!original_frame_sink_id.is_valid() || !target_frame_sink_id.is_valid())
870 return false;
871 if (original_frame_sink_id == target_frame_sink_id)
872 return true;
873 if (!host() || !host()->delegate())
874 return false;
875 auto* router = host()->delegate()->GetInputEventRouter();
876 if (!router)
877 return false;
878 *transformed_point = point;
879 return TransformPointToTargetCoordSpace(
880 router->FindViewFromFrameSinkId(original_frame_sink_id),
881 router->FindViewFromFrameSinkId(target_frame_sink_id), point,
882 transformed_point);
883 }
884
885 } // namespace content
886