summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc4301
1 files changed, 3830 insertions, 471 deletions
diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index eaa7e12154b..e3e764c59b0 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -33,62 +33,112 @@
#include <memory>
#include <utility>
-#include "base/auto_reset.h"
-#include "base/optional.h"
+#include "base/debug/crash_logging.h"
+#include "base/debug/dump_without_crashing.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
#include "build/build_config.h"
-#include "cc/layers/picture_layer.h"
-#include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
+#include "cc/trees/compositor_commit_data.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/swap_promise.h"
+#include "cc/trees/ukm_manager.h"
+#include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h"
+#include "third_party/blink/public/mojom/input/touch_event.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
#include "third_party/blink/public/web/web_autofill_client.h"
-#include "third_party/blink/public/web/web_element.h"
-#include "third_party/blink/public/web/web_frame_widget.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
+#include "third_party/blink/public/web/web_non_composited_widget_client.h"
+#include "third_party/blink/public/web/web_performance.h"
#include "third_party/blink/public/web/web_plugin.h"
-#include "third_party/blink/public/web/web_range.h"
-#include "third_party/blink/public/web/web_widget_client.h"
-#include "third_party/blink/renderer/core/editing/editing_utilities.h"
-#include "third_party/blink/renderer/core/editing/editor.h"
-#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/public/web/web_settings.h"
+#include "third_party/blink/public/web/web_view_client.h"
+#include "third_party/blink/renderer/core/content_capture/content_capture_manager.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
-#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
-#include "third_party/blink/renderer/core/editing/plain_text_range.h"
-#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/events/current_input_event.h"
#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
+#include "third_party/blink/renderer/core/events/wheel_event.h"
#include "third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h"
-#include "third_party/blink/renderer/core/exported/web_page_popup_impl.h"
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
+#include "third_party/blink/renderer/core/exported/web_settings_impl.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/frame/remote_frame.h"
+#include "third_party/blink/renderer/core/frame/remote_frame_client.h"
+#include "third_party/blink/renderer/core/frame/screen.h"
+#include "third_party/blink/renderer/core/frame/screen_metrics_emulator.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
-#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
+#include "third_party/blink/renderer/core/html/battery_savings.h"
+#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
+#include "third_party/blink/renderer/core/html/portal/document_portals.h"
+#include "third_party/blink/renderer/core/html/portal/portal_contents.h"
#include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/hit_test_location.h"
+#include "third_party/blink/renderer/core/layout/hit_test_request.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/core/loader/interactive_detector.h"
#include "third_party/blink/renderer/core/page/context_menu_controller.h"
+#include "third_party/blink/renderer/core/page/drag_actions.h"
+#include "third_party/blink/renderer/core/page/drag_controller.h"
+#include "third_party/blink/renderer/core/page/drag_data.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
+#include "third_party/blink/renderer/core/page/link_highlight.h"
#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/page/page_popup.h"
#include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
-#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
+#include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
+#include "third_party/blink/renderer/core/page/validation_message_client.h"
+#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
+#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
-#include "third_party/blink/renderer/platform/graphics/color.h"
-#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
+#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
+#include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
+#include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h"
+#include "third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h"
#include "third_party/blink/renderer/platform/widget/widget_base.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-blink.h"
+#include "ui/gfx/geometry/point_conversions.h"
+
+#if defined(OS_MAC)
+#include "third_party/blink/renderer/core/editing/substring_util.h"
+#include "third_party/blink/renderer/platform/fonts/mac/attributed_string_type_converter.h"
+#include "ui/base/mojom/attributed_string.mojom-blink.h"
+#include "ui/gfx/geometry/point.h"
+#endif
+
+namespace WTF {
+template <>
+struct CrossThreadCopier<blink::WebReportTimeCallback>
+ : public CrossThreadCopierByValuePassThrough<blink::WebReportTimeCallback> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+
+} // namespace WTF
namespace blink {
+
namespace {
+
+using ::ui::mojom::blink::DragOperation;
+
const int kCaretPadding = 10;
const float kIdealPaddingRatio = 0.3f;
@@ -102,104 +152,80 @@ FloatRect NormalizeRect(const IntRect& to_normalize, const IntRect& base_rect) {
return result;
}
-} // namespace
-
-// WebFrameWidget ------------------------------------------------------------
+void ForEachLocalFrameControlledByWidget(
+ LocalFrame* frame,
+ const base::RepeatingCallback<void(WebLocalFrameImpl*)>& callback) {
+ callback.Run(WebLocalFrameImpl::FromFrame(frame));
+ for (Frame* child = frame->FirstChild(); child;
+ child = child->NextSibling()) {
+ if (child->IsLocalFrame()) {
+ ForEachLocalFrameControlledByWidget(DynamicTo<LocalFrame>(child),
+ callback);
+ }
+ }
+}
-static CreateWebViewFrameWidgetFunction g_create_web_view_frame_widget =
- nullptr;
+// Iterate the remote children that will be controlled by the widget. Skip over
+// any RemoteFrames have have another LocalFrame root as their parent.
+void ForEachRemoteFrameChildrenControlledByWidget(
+ Frame* frame,
+ const base::RepeatingCallback<void(RemoteFrame*)>& callback) {
+ for (Frame* child = frame->Tree().FirstChild(); child;
+ child = child->Tree().NextSibling()) {
+ if (auto* remote_frame = DynamicTo<RemoteFrame>(child)) {
+ callback.Run(remote_frame);
+ ForEachRemoteFrameChildrenControlledByWidget(remote_frame, callback);
+ } else if (auto* local_frame = DynamicTo<LocalFrame>(child)) {
+ // If iteration arrives at a local root then don't descend as it will be
+ // controlled by another widget.
+ if (!local_frame->IsLocalRoot()) {
+ ForEachRemoteFrameChildrenControlledByWidget(local_frame, callback);
+ }
+ }
+ }
-void InstallCreateWebViewFrameWidgetHook(
- CreateWebViewFrameWidgetFunction create_widget) {
- g_create_web_view_frame_widget = create_widget;
+ // Iterate on any portals owned by a local frame.
+ if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
+ if (Document* document = local_frame->GetDocument()) {
+ for (PortalContents* portal :
+ DocumentPortals::From(*document).GetPortals()) {
+ if (RemoteFrame* remote_frame = portal->GetFrame())
+ callback.Run(remote_frame);
+ }
+ }
+ }
}
-WebFrameWidget* WebFrameWidget::CreateForMainFrame(
- WebWidgetClient* client,
- WebLocalFrame* main_frame,
- CrossVariantMojoAssociatedRemote<mojom::blink::FrameWidgetHostInterfaceBase>
- mojo_frame_widget_host,
- CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
- mojo_frame_widget,
- CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
- mojo_widget_host,
- CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
- mojo_widget,
- const viz::FrameSinkId& frame_sink_id,
- bool is_for_nested_main_frame,
- bool hidden,
- bool never_composited) {
- DCHECK(client) << "A valid WebWidgetClient must be supplied.";
- DCHECK(!main_frame->Parent()); // This is the main frame.
-
- // Grabs the WebViewImpl associated with the |main_frame|, which will then
- // be wrapped by the WebViewFrameWidget, with calls being forwarded to the
- // |main_frame|'s WebViewImpl.
- // Note: this can't DCHECK that the view's main frame points to
- // |main_frame|, as provisional frames violate this precondition.
- WebLocalFrameImpl& main_frame_impl = To<WebLocalFrameImpl>(*main_frame);
- DCHECK(main_frame_impl.ViewImpl());
- WebViewImpl& web_view_impl = *main_frame_impl.ViewImpl();
-
- WebViewFrameWidget* widget = nullptr;
- if (g_create_web_view_frame_widget) {
- widget = g_create_web_view_frame_widget(
- util::PassKey<WebFrameWidget>(), *client, web_view_impl,
- std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
- std::move(mojo_widget_host), std::move(mojo_widget),
- main_frame->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
- frame_sink_id, is_for_nested_main_frame, hidden, never_composited);
- } else {
- // Note: this isn't a leak, as the object has a self-reference that the
- // caller needs to release by calling Close().
- // TODO(dcheng): Remove the special bridge class for main frame widgets.
- widget = MakeGarbageCollected<WebViewFrameWidget>(
- util::PassKey<WebFrameWidget>(), *client, web_view_impl,
- std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
- std::move(mojo_widget_host), std::move(mojo_widget),
- main_frame->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
- frame_sink_id, is_for_nested_main_frame, hidden, never_composited);
- }
- widget->BindLocalRoot(*main_frame);
- return widget;
-}
-
-WebFrameWidget* WebFrameWidget::CreateForChildLocalRoot(
- WebWidgetClient* client,
- WebLocalFrame* local_root,
- CrossVariantMojoAssociatedRemote<mojom::blink::FrameWidgetHostInterfaceBase>
- mojo_frame_widget_host,
- CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
- mojo_frame_widget,
- CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
- mojo_widget_host,
- CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
- mojo_widget,
- const viz::FrameSinkId& frame_sink_id,
- bool hidden,
- bool never_composited) {
- DCHECK(client) << "A valid WebWidgetClient must be supplied.";
- DCHECK(local_root->Parent()); // This is not the main frame.
- // Frames whose direct ancestor is a remote frame are local roots. Verify this
- // is one. Other frames should be using the widget for their nearest local
- // root.
- DCHECK(local_root->Parent()->IsWebRemoteFrame());
+viz::FrameSinkId GetRemoteFrameSinkId(const HitTestResult& result) {
+ Node* node = result.InnerNode();
+ auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node);
+ if (!frame_owner || !frame_owner->ContentFrame() ||
+ !frame_owner->ContentFrame()->IsRemoteFrame())
+ return viz::FrameSinkId();
- // Note: this isn't a leak, as the object has a self-reference that the
- // caller needs to release by calling Close().
- auto* widget = MakeGarbageCollected<WebFrameWidgetImpl>(
- util::PassKey<WebFrameWidget>(), *client,
- std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
- std::move(mojo_widget_host), std::move(mojo_widget),
- local_root->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
- frame_sink_id, hidden, never_composited);
- widget->BindLocalRoot(*local_root);
- return widget;
+ RemoteFrame* remote_frame = To<RemoteFrame>(frame_owner->ContentFrame());
+ if (remote_frame->IsIgnoredForHitTest())
+ return viz::FrameSinkId();
+ LayoutObject* object = node->GetLayoutObject();
+ DCHECK(object);
+ if (!object->IsBox())
+ return viz::FrameSinkId();
+
+ IntPoint local_point = RoundedIntPoint(result.LocalPoint());
+ if (!To<LayoutBox>(object)->ComputedCSSContentBoxRect().Contains(local_point))
+ return viz::FrameSinkId();
+
+ return remote_frame->GetFrameSinkId();
}
+} // namespace
+
+// WebFrameWidget ------------------------------------------------------------
+
+bool WebFrameWidgetImpl::ignore_input_events_ = false;
+
WebFrameWidgetImpl::WebFrameWidgetImpl(
- util::PassKey<WebFrameWidget>,
- WebWidgetClient& client,
+ base::PassKey<WebLocalFrame>,
CrossVariantMojoAssociatedRemote<mojom::blink::FrameWidgetHostInterfaceBase>
frame_widget_host,
CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
@@ -211,30 +237,1684 @@ WebFrameWidgetImpl::WebFrameWidgetImpl(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const viz::FrameSinkId& frame_sink_id,
bool hidden,
- bool never_composited)
- : WebFrameWidgetBase(client,
- std::move(frame_widget_host),
- std::move(frame_widget),
- std::move(widget_host),
- std::move(widget),
- std::move(task_runner),
- frame_sink_id,
- hidden,
- never_composited,
- /*is_for_child_local_root=*/true),
- self_keep_alive_(PERSISTENT_FROM_HERE, this) {}
+ bool never_composited,
+ bool is_for_child_local_root,
+ bool is_for_nested_main_frame)
+ : widget_base_(std::make_unique<WidgetBase>(/*widget_base_client=*/this,
+ std::move(widget_host),
+ std::move(widget),
+ task_runner,
+ hidden,
+ never_composited,
+ is_for_child_local_root)),
+ frame_sink_id_(frame_sink_id),
+ is_for_child_local_root_(is_for_child_local_root) {
+ DCHECK(task_runner);
+ if (is_for_nested_main_frame)
+ main_data().is_for_nested_main_frame = is_for_nested_main_frame;
+ frame_widget_host_.Bind(std::move(frame_widget_host), task_runner);
+ receiver_.Bind(std::move(frame_widget), task_runner);
+}
+
+WebFrameWidgetImpl::~WebFrameWidgetImpl() {
+ // Ensure that Close is called and we aren't releasing |widget_base_| in the
+ // destructor.
+ // TODO(crbug.com/1139104): This CHECK can be changed to a DCHECK once
+ // the issue is solved.
+ CHECK(!widget_base_);
+}
+
+void WebFrameWidgetImpl::BindLocalRoot(WebLocalFrame& local_root) {
+ local_root_ = To<WebLocalFrameImpl>(local_root);
+}
+
+bool WebFrameWidgetImpl::ForTopMostMainFrame() const {
+ return ForMainFrame() && !main_data().is_for_nested_main_frame;
+}
+
+void WebFrameWidgetImpl::SetIsNestedMainFrameWidget(bool is_nested) {
+ main_data().is_for_nested_main_frame = is_nested;
+}
+
+void WebFrameWidgetImpl::Close() {
+ LocalFrameView* frame_view;
+ if (is_for_child_local_root_) {
+ frame_view = LocalRootImpl()->GetFrame()->View();
+ } else {
+ // Scrolling for the root frame is special we need to pass null indicating
+ // we are at the top of the tree when setting up the Animation. Which will
+ // cause ownership of the timeline and animation host.
+ // See ScrollingCoordinator::AnimationHostInitialized.
+ frame_view = nullptr;
+ }
+ GetPage()->WillCloseAnimationHost(frame_view);
+
+ if (ForMainFrame()) {
+ // Closing the WebFrameWidgetImpl happens in response to the local main
+ // frame being detached from the Page/WebViewImpl.
+ View()->SetMainFrameViewWidget(nullptr);
+ }
+
+ mutator_dispatcher_ = nullptr;
+ local_root_ = nullptr;
+ widget_base_->Shutdown();
+ widget_base_.reset();
+ // These WeakPtrs must be invalidated for WidgetInputHandlerManager at the
+ // same time as the WidgetBase is.
+ input_handler_weak_ptr_factory_.InvalidateWeakPtrs();
+ receiver_.reset();
+ input_target_receiver_.reset();
+}
+
+WebLocalFrame* WebFrameWidgetImpl::LocalRoot() const {
+ return local_root_;
+}
+
+gfx::Rect WebFrameWidgetImpl::ComputeBlockBound(
+ const gfx::Point& point_in_root_frame,
+ bool ignore_clipping) const {
+ HitTestLocation location(local_root_->GetFrameView()->ConvertFromRootFrame(
+ PhysicalOffset(IntPoint(point_in_root_frame))));
+ HitTestRequest::HitTestRequestType hit_type =
+ HitTestRequest::kReadOnly | HitTestRequest::kActive |
+ (ignore_clipping ? HitTestRequest::kIgnoreClipping : 0);
+ HitTestResult result =
+ local_root_->GetFrame()->GetEventHandler().HitTestResultAtLocation(
+ location, hit_type);
+ result.SetToShadowHostIfInRestrictedShadowRoot();
+
+ Node* node = result.InnerNodeOrImageMapImage();
+ if (!node)
+ return gfx::Rect();
+
+ // Find the block type node based on the hit node.
+ // FIXME: This wants to walk flat tree with
+ // LayoutTreeBuilderTraversal::parent().
+ while (node &&
+ (!node->GetLayoutObject() || node->GetLayoutObject()->IsInline()))
+ node = LayoutTreeBuilderTraversal::Parent(*node);
+
+ // Return the bounding box in the root frame's coordinate space.
+ if (node) {
+ IntRect absolute_rect = node->GetLayoutObject()->AbsoluteBoundingBoxRect();
+ LocalFrame* frame = node->GetDocument().GetFrame();
+ return frame->View()->ConvertToRootFrame(absolute_rect);
+ }
+ return gfx::Rect();
+}
+
+void WebFrameWidgetImpl::DragTargetDragEnter(
+ const WebDragData& web_drag_data,
+ const gfx::PointF& point_in_viewport,
+ const gfx::PointF& screen_point,
+ DragOperationsMask operations_allowed,
+ uint32_t key_modifiers,
+ DragTargetDragEnterCallback callback) {
+ DCHECK(!current_drag_data_);
+
+ current_drag_data_ = DataObject::Create(web_drag_data);
+ operations_allowed_ = operations_allowed;
+
+ DragOperation operation = DragTargetDragEnterOrOver(
+ point_in_viewport, screen_point, kDragEnter, key_modifiers);
+ std::move(callback).Run(operation);
+}
+
+void WebFrameWidgetImpl::DragTargetDragOver(
+ const gfx::PointF& point_in_viewport,
+ const gfx::PointF& screen_point,
+ DragOperationsMask operations_allowed,
+ uint32_t key_modifiers,
+ DragTargetDragOverCallback callback) {
+ operations_allowed_ = operations_allowed;
+
+ DragOperation operation = DragTargetDragEnterOrOver(
+ point_in_viewport, screen_point, kDragOver, key_modifiers);
+ std::move(callback).Run(operation);
+}
+
+void WebFrameWidgetImpl::DragTargetDragLeave(
+ const gfx::PointF& point_in_viewport,
+ const gfx::PointF& screen_point) {
+ DCHECK(current_drag_data_);
+
+ // TODO(paulmeyer): It shouldn't be possible for |current_drag_data_| to be
+ // null here, but this is somehow happening (rarely). This suggests that in
+ // some cases drag-leave is happening before drag-enter, which should be
+ // impossible. This needs to be investigated further. Once fixed, the extra
+ // check for |!current_drag_data_| should be removed. (crbug.com/671152)
+ if (IgnoreInputEvents() || !current_drag_data_) {
+ CancelDrag();
+ return;
+ }
+
+ gfx::PointF point_in_root_frame(ViewportToRootFrame(point_in_viewport));
+ DragData drag_data(current_drag_data_.Get(), FloatPoint(point_in_root_frame),
+ FloatPoint(screen_point), operations_allowed_);
+
+ GetPage()->GetDragController().DragExited(&drag_data,
+ *local_root_->GetFrame());
+
+ // FIXME: why is the drag scroll timer not stopped here?
+
+ drag_operation_ = DragOperation::kNone;
+ current_drag_data_ = nullptr;
+}
+
+void WebFrameWidgetImpl::DragTargetDrop(const WebDragData& web_drag_data,
+ const gfx::PointF& point_in_viewport,
+ const gfx::PointF& screen_point,
+ uint32_t key_modifiers) {
+ gfx::PointF point_in_root_frame(ViewportToRootFrame(point_in_viewport));
+
+ DCHECK(current_drag_data_);
+ current_drag_data_ = DataObject::Create(web_drag_data);
+
+ // If this webview transitions from the "drop accepting" state to the "not
+ // accepting" state, then our IPC message reply indicating that may be in-
+ // flight, or else delayed by javascript processing in this webview. If a
+ // drop happens before our IPC reply has reached the browser process, then
+ // the browser forwards the drop to this webview. So only allow a drop to
+ // proceed if our webview drag_operation_ state is not DragOperation::kNone.
+
+ if (drag_operation_ == DragOperation::kNone) {
+ // IPC RACE CONDITION: do not allow this drop.
+ DragTargetDragLeave(point_in_viewport, screen_point);
+ return;
+ }
+
+ if (!IgnoreInputEvents()) {
+ current_drag_data_->SetModifiers(key_modifiers);
+ DragData drag_data(current_drag_data_.Get(),
+ FloatPoint(point_in_root_frame),
+ FloatPoint(screen_point), operations_allowed_);
+
+ GetPage()->GetDragController().PerformDrag(&drag_data,
+ *local_root_->GetFrame());
+ }
+ drag_operation_ = DragOperation::kNone;
+ current_drag_data_ = nullptr;
+}
+
+void WebFrameWidgetImpl::DragSourceEndedAt(const gfx::PointF& point_in_viewport,
+ const gfx::PointF& screen_point,
+ DragOperation operation) {
+ if (!local_root_) {
+ // We should figure out why |local_root_| could be nullptr
+ // (https://crbug.com/792345).
+ return;
+ }
+
+ if (IgnoreInputEvents()) {
+ CancelDrag();
+ return;
+ }
+ gfx::PointF point_in_root_frame(
+ GetPage()->GetVisualViewport().ViewportToRootFrame(
+ FloatPoint(point_in_viewport)));
+
+ WebMouseEvent fake_mouse_move(
+ WebInputEvent::Type::kMouseMove, point_in_root_frame, screen_point,
+ WebPointerProperties::Button::kLeft, 0, WebInputEvent::kNoModifiers,
+ base::TimeTicks::Now());
+ fake_mouse_move.SetFrameScale(1);
+ local_root_->GetFrame()->GetEventHandler().DragSourceEndedAt(fake_mouse_move,
+ operation);
+}
+
+void WebFrameWidgetImpl::DragSourceSystemDragEnded() {
+ CancelDrag();
+}
+
+void WebFrameWidgetImpl::SetBackgroundOpaque(bool opaque) {
+ if (opaque) {
+ View()->ClearBaseBackgroundColorOverride();
+ View()->ClearBackgroundColorOverride();
+ } else {
+ View()->SetBaseBackgroundColorOverride(SK_ColorTRANSPARENT);
+ View()->SetBackgroundColorOverride(SK_ColorTRANSPARENT);
+ }
+}
+
+void WebFrameWidgetImpl::SetTextDirection(base::i18n::TextDirection direction) {
+ LocalFrame* focusedFrame = FocusedLocalFrameInWidget();
+ if (focusedFrame)
+ focusedFrame->SetTextDirection(direction);
+}
+
+void WebFrameWidgetImpl::SetInheritedEffectiveTouchActionForSubFrame(
+ TouchAction touch_action) {
+ DCHECK(ForSubframe());
+ LocalRootImpl()->GetFrame()->SetInheritedEffectiveTouchAction(touch_action);
+}
+
+void WebFrameWidgetImpl::UpdateRenderThrottlingStatusForSubFrame(
+ bool is_throttled,
+ bool subtree_throttled,
+ bool display_locked) {
+ DCHECK(ForSubframe());
+ // TODO(szager,vmpstr): The parent render process currently rolls up
+ // display_locked into the value of subtree throttled here; display_locked
+ // should be maintained as a separate bit and transmitted between render
+ // processes.
+ LocalRootImpl()->GetFrameView()->UpdateRenderThrottlingStatus(
+ is_throttled, subtree_throttled, display_locked, /*recurse=*/true);
+}
+
+#if defined(OS_MAC)
+void WebFrameWidgetImpl::GetStringAtPoint(const gfx::Point& point_in_local_root,
+ GetStringAtPointCallback callback) {
+ gfx::Point baseline_point;
+ ui::mojom::blink::AttributedStringPtr attributed_string = nullptr;
+ NSAttributedString* string = SubstringUtil::AttributedWordAtPoint(
+ this, point_in_local_root, baseline_point);
+ if (string)
+ attributed_string = ui::mojom::blink::AttributedString::From(string);
+
+ std::move(callback).Run(std::move(attributed_string), baseline_point);
+}
+#endif
+
+void WebFrameWidgetImpl::BindWidgetCompositor(
+ mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) {
+ widget_base_->BindWidgetCompositor(std::move(receiver));
+}
+
+void WebFrameWidgetImpl::BindInputTargetClient(
+ mojo::PendingReceiver<viz::mojom::blink::InputTargetClient> receiver) {
+ DCHECK(!input_target_receiver_.is_bound());
+ input_target_receiver_.Bind(
+ std::move(receiver),
+ local_root_->GetTaskRunner(TaskType::kInternalDefault));
+}
+
+void WebFrameWidgetImpl::FrameSinkIdAt(const gfx::PointF& point,
+ const uint64_t trace_id,
+ FrameSinkIdAtCallback callback) {
+ TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Event.Pipeline",
+ TRACE_ID_GLOBAL(trace_id),
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "step", "FrameSinkIdAt");
+
+ gfx::PointF local_point;
+ viz::FrameSinkId id = GetFrameSinkIdAtPoint(point, &local_point);
+ std::move(callback).Run(id, local_point);
+}
+
+viz::FrameSinkId WebFrameWidgetImpl::GetFrameSinkIdAtPoint(
+ const gfx::PointF& point_in_dips,
+ gfx::PointF* local_point_in_dips) {
+ HitTestResult result =
+ CoreHitTestResultAt(widget_base_->DIPsToBlinkSpace(point_in_dips));
+
+ Node* result_node = result.InnerNode();
+ *local_point_in_dips = gfx::PointF(point_in_dips);
+
+ // TODO(crbug.com/797828): When the node is null the caller may
+ // need to do extra checks. Like maybe update the layout and then
+ // call the hit-testing API. Either way it might be better to have
+ // a DCHECK for the node rather than a null check here.
+ if (!result_node) {
+ return frame_sink_id_;
+ }
+
+ viz::FrameSinkId remote_frame_sink_id = GetRemoteFrameSinkId(result);
+ if (remote_frame_sink_id.is_valid()) {
+ FloatPoint local_point = FloatPoint(result.LocalPoint());
+ LayoutObject* object = result_node->GetLayoutObject();
+ if (auto* box = DynamicTo<LayoutBox>(object))
+ local_point.MoveBy(-FloatPoint(box->PhysicalContentBoxOffset()));
+
+ *local_point_in_dips =
+ widget_base_->BlinkSpaceToDIPs(gfx::PointF(local_point));
+ return remote_frame_sink_id;
+ }
+
+ // Return the FrameSinkId for the current widget if the point did not hit
+ // test to a remote frame, or the point is outside of the remote frame's
+ // content box, or the remote frame doesn't have a valid FrameSinkId yet.
+ return frame_sink_id_;
+}
+
+gfx::RectF WebFrameWidgetImpl::BlinkSpaceToDIPs(const gfx::RectF& rect) {
+ return widget_base_->BlinkSpaceToDIPs(rect);
+}
+
+gfx::Rect WebFrameWidgetImpl::BlinkSpaceToEnclosedDIPs(const gfx::Rect& rect) {
+ return widget_base_->BlinkSpaceToEnclosedDIPs(rect);
+}
+
+gfx::Size WebFrameWidgetImpl::BlinkSpaceToFlooredDIPs(const gfx::Size& size) {
+ return widget_base_->BlinkSpaceToFlooredDIPs(size);
+}
+
+gfx::RectF WebFrameWidgetImpl::DIPsToBlinkSpace(const gfx::RectF& rect) {
+ return widget_base_->DIPsToBlinkSpace(rect);
+}
+
+gfx::PointF WebFrameWidgetImpl::DIPsToBlinkSpace(const gfx::PointF& point) {
+ return widget_base_->DIPsToBlinkSpace(point);
+}
+
+gfx::Point WebFrameWidgetImpl::DIPsToRoundedBlinkSpace(
+ const gfx::Point& point) {
+ return widget_base_->DIPsToRoundedBlinkSpace(point);
+}
+
+float WebFrameWidgetImpl::DIPsToBlinkSpace(float scalar) {
+ return widget_base_->DIPsToBlinkSpace(scalar);
+}
+
+gfx::Size WebFrameWidgetImpl::DIPsToCeiledBlinkSpace(const gfx::Size& size) {
+ return widget_base_->DIPsToCeiledBlinkSpace(size);
+}
+
+void WebFrameWidgetImpl::SetActive(bool active) {
+ View()->SetIsActive(active);
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleKeyEvent(
+ const WebKeyboardEvent& event) {
+ DCHECK((event.GetType() == WebInputEvent::Type::kRawKeyDown) ||
+ (event.GetType() == WebInputEvent::Type::kKeyDown) ||
+ (event.GetType() == WebInputEvent::Type::kKeyUp));
+
+ // Please refer to the comments explaining the m_suppressNextKeypressEvent
+ // member.
+ // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
+ // Webkit. A keyDown event is typically associated with a keyPress(char)
+ // event and a keyUp event. We reset this flag here as this is a new keyDown
+ // event.
+ suppress_next_keypress_event_ = false;
+
+ // If there is a popup open, it should be the one processing the event,
+ // not the page.
+ scoped_refptr<WebPagePopupImpl> page_popup = View()->GetPagePopup();
+ if (page_popup) {
+ page_popup->HandleKeyEvent(event);
+ if (event.GetType() == WebInputEvent::Type::kRawKeyDown) {
+ suppress_next_keypress_event_ = true;
+ }
+ return WebInputEventResult::kHandledSystem;
+ }
+
+ auto* frame = DynamicTo<LocalFrame>(FocusedCoreFrame());
+ if (!frame)
+ return WebInputEventResult::kNotHandled;
+
+ WebInputEventResult result = frame->GetEventHandler().KeyEvent(event);
+ if (result != WebInputEventResult::kNotHandled) {
+ if (WebInputEvent::Type::kRawKeyDown == event.GetType()) {
+ // Suppress the next keypress event unless the focused node is a plugin
+ // node. (Flash needs these keypress events to handle non-US keyboards.)
+ Element* element = FocusedElement();
+ if (element && element->GetLayoutObject() &&
+ element->GetLayoutObject()->IsEmbeddedObject()) {
+ if (event.windows_key_code == VKEY_TAB) {
+ // If the plugin supports keyboard focus then we should not send a tab
+ // keypress event.
+ WebPluginContainerImpl* plugin_view =
+ To<LayoutEmbeddedContent>(element->GetLayoutObject())->Plugin();
+ if (plugin_view && plugin_view->SupportsKeyboardFocus()) {
+ suppress_next_keypress_event_ = true;
+ }
+ }
+ } else {
+ suppress_next_keypress_event_ = true;
+ }
+ }
+ return result;
+ }
+
+#if !defined(OS_MAC)
+ const WebInputEvent::Type kContextMenuKeyTriggeringEventType =
+#if defined(OS_WIN)
+ WebInputEvent::Type::kKeyUp;
+#else
+ WebInputEvent::Type::kRawKeyDown;
+#endif
+ const WebInputEvent::Type kShiftF10TriggeringEventType =
+ WebInputEvent::Type::kRawKeyDown;
+
+ bool is_unmodified_menu_key =
+ !(event.GetModifiers() & WebInputEvent::kInputModifiers) &&
+ event.windows_key_code == VKEY_APPS;
+ bool is_shift_f10 = (event.GetModifiers() & WebInputEvent::kInputModifiers) ==
+ WebInputEvent::kShiftKey &&
+ event.windows_key_code == VKEY_F10;
+ if ((is_unmodified_menu_key &&
+ event.GetType() == kContextMenuKeyTriggeringEventType) ||
+ (is_shift_f10 && event.GetType() == kShiftF10TriggeringEventType)) {
+ View()->SendContextMenuEvent();
+ return WebInputEventResult::kHandledSystem;
+ }
+#endif // !defined(OS_MAC)
+
+ return WebInputEventResult::kNotHandled;
+}
+
+void WebFrameWidgetImpl::HandleMouseDown(LocalFrame& local_root,
+ const WebMouseEvent& event) {
+ WebViewImpl* view_impl = View();
+ // If there is a popup open, close it as the user is clicking on the page
+ // (outside of the popup). We also save it so we can prevent a click on an
+ // element from immediately reopening the same popup.
+ scoped_refptr<WebPagePopupImpl> page_popup;
+ if (event.button == WebMouseEvent::Button::kLeft) {
+ page_popup = view_impl->GetPagePopup();
+ view_impl->CancelPagePopup();
+ }
+
+ // Take capture on a mouse down on a plugin so we can send it mouse events.
+ // If the hit node is a plugin but a scrollbar is over it don't start mouse
+ // capture because it will interfere with the scrollbar receiving events.
+ PhysicalOffset point(LayoutUnit(event.PositionInWidget().x()),
+ LayoutUnit(event.PositionInWidget().y()));
+ if (event.button == WebMouseEvent::Button::kLeft) {
+ HitTestLocation location(
+ LocalRootImpl()->GetFrameView()->ConvertFromRootFrame(point));
+ HitTestResult result(
+ LocalRootImpl()->GetFrame()->GetEventHandler().HitTestResultAtLocation(
+ location));
+ result.SetToShadowHostIfInRestrictedShadowRoot();
+ Node* hit_node = result.InnerNode();
+ auto* html_element = DynamicTo<HTMLElement>(hit_node);
+ if (!result.GetScrollbar() && hit_node && hit_node->GetLayoutObject() &&
+ hit_node->GetLayoutObject()->IsEmbeddedObject() && html_element &&
+ html_element->IsPluginElement()) {
+ mouse_capture_element_ = To<HTMLPlugInElement>(hit_node);
+ SetMouseCapture(true);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("input", "capturing mouse",
+ TRACE_ID_LOCAL(this));
+ }
+ }
+
+ PageWidgetEventHandler::HandleMouseDown(local_root, event);
+ // PageWidgetEventHandler may have detached the frame.
+ if (!LocalRootImpl())
+ return;
+
+ if (view_impl->GetPagePopup() && page_popup &&
+ view_impl->GetPagePopup()->HasSamePopupClient(page_popup.get())) {
+ // That click triggered a page popup that is the same as the one we just
+ // closed. It needs to be closed.
+ view_impl->CancelPagePopup();
+ }
+
+ // Dispatch the contextmenu event regardless of if the click was swallowed.
+ if (!GetPage()->GetSettings().GetShowContextMenuOnMouseUp()) {
+#if defined(OS_MAC)
+ if (event.button == WebMouseEvent::Button::kRight ||
+ (event.button == WebMouseEvent::Button::kLeft &&
+ event.GetModifiers() & WebMouseEvent::kControlKey))
+ MouseContextMenu(event);
+#else
+ if (event.button == WebMouseEvent::Button::kRight)
+ MouseContextMenu(event);
+#endif
+ }
+}
+
+void WebFrameWidgetImpl::HandleMouseLeave(LocalFrame& local_root,
+ const WebMouseEvent& event) {
+ View()->SetMouseOverURL(WebURL());
+ PageWidgetEventHandler::HandleMouseLeave(local_root, event);
+ // PageWidgetEventHandler may have detached the frame.
+}
+
+void WebFrameWidgetImpl::MouseContextMenu(const WebMouseEvent& event) {
+ GetPage()->GetContextMenuController().ClearContextMenu();
+
+ WebMouseEvent transformed_event =
+ TransformWebMouseEvent(LocalRootImpl()->GetFrameView(), event);
+ transformed_event.menu_source_type = kMenuSourceMouse;
+
+ // Find the right target frame. See issue 1186900.
+ HitTestResult result = HitTestResultForRootFramePos(
+ FloatPoint(transformed_event.PositionInRootFrame()));
+ Frame* target_frame;
+ if (result.InnerNodeOrImageMapImage())
+ target_frame = result.InnerNodeOrImageMapImage()->GetDocument().GetFrame();
+ else
+ target_frame = GetPage()->GetFocusController().FocusedOrMainFrame();
+
+ // This will need to be changed to a nullptr check when focus control
+ // is refactored, at which point focusedOrMainFrame will never return a
+ // RemoteFrame.
+ // See https://crbug.com/341918.
+ LocalFrame* target_local_frame = DynamicTo<LocalFrame>(target_frame);
+ if (!target_local_frame)
+ return;
+
+ {
+ ContextMenuAllowedScope scope;
+ target_local_frame->GetEventHandler().SendContextMenuEvent(
+ transformed_event);
+ }
+ // Actually showing the context menu is handled by the ContextMenuClient
+ // implementation...
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleMouseUp(
+ LocalFrame& local_root,
+ const WebMouseEvent& event) {
+ WebInputEventResult result =
+ PageWidgetEventHandler::HandleMouseUp(local_root, event);
+ // PageWidgetEventHandler may have detached the frame.
+ if (!LocalRootImpl())
+ return result;
+
+ if (GetPage()->GetSettings().GetShowContextMenuOnMouseUp()) {
+ // Dispatch the contextmenu event regardless of if the click was swallowed.
+ // On Mac/Linux, we handle it on mouse down, not up.
+ if (event.button == WebMouseEvent::Button::kRight)
+ MouseContextMenu(event);
+ }
+ return result;
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleGestureEvent(
+ const WebGestureEvent& event) {
+ WebInputEventResult event_result = WebInputEventResult::kNotHandled;
+
+ // Fling events are not sent to the renderer.
+ CHECK(event.GetType() != WebInputEvent::Type::kGestureFlingStart);
+ CHECK(event.GetType() != WebInputEvent::Type::kGestureFlingCancel);
+
+ WebViewImpl* web_view = View();
+
+ LocalFrame* frame = LocalRootImpl()->GetFrame();
+ WebGestureEvent scaled_event = TransformWebGestureEvent(frame->View(), event);
+
+ // Special handling for double tap and scroll events as we don't want to
+ // hit test for them.
+ switch (event.GetType()) {
+ case WebInputEvent::Type::kGestureDoubleTap:
+ if (web_view->SettingsImpl()->DoubleTapToZoomEnabled() &&
+ web_view->MinimumPageScaleFactor() !=
+ web_view->MaximumPageScaleFactor()) {
+ IntPoint pos_in_local_frame_root =
+ FlooredIntPoint(scaled_event.PositionInRootFrame());
+ auto block_bounds =
+ gfx::Rect(ComputeBlockBound(pos_in_local_frame_root, false));
+
+ if (ForMainFrame()) {
+ web_view->AnimateDoubleTapZoom(pos_in_local_frame_root, block_bounds);
+ } else {
+ // This sends the tap point and bounds to the main frame renderer via
+ // the browser, where their coordinates will be transformed into the
+ // main frame's coordinate space.
+ GetAssociatedFrameWidgetHost()->AnimateDoubleTapZoomInMainFrame(
+ pos_in_local_frame_root, block_bounds);
+ }
+ }
+ event_result = WebInputEventResult::kHandledSystem;
+ DidHandleGestureEvent(event);
+ return event_result;
+ case WebInputEvent::Type::kGestureScrollBegin:
+ case WebInputEvent::Type::kGestureScrollEnd:
+ case WebInputEvent::Type::kGestureScrollUpdate:
+ // If we are getting any scroll toss close any page popup that is open.
+ web_view->CancelPagePopup();
+
+ // Scrolling-related gesture events invoke EventHandler recursively for
+ // each frame down the chain, doing a single-frame hit-test per frame.
+ // This matches handleWheelEvent. Perhaps we could simplify things by
+ // rewriting scroll handling to work inner frame out, and then unify with
+ // other gesture events.
+ event_result =
+ frame->GetEventHandler().HandleGestureScrollEvent(scaled_event);
+ DidHandleGestureEvent(event);
+ return event_result;
+ default:
+ break;
+ }
+
+ // Hit test across all frames and do touch adjustment as necessary for the
+ // event type.
+ GestureEventWithHitTestResults targeted_event =
+ frame->GetEventHandler().TargetGestureEvent(scaled_event);
+
+ // Link highlight animations are only for the main frame.
+ if (ForMainFrame()) {
+ // Handle link highlighting outside the main switch to avoid getting lost in
+ // the complicated set of cases handled below.
+ switch (scaled_event.GetType()) {
+ case WebInputEvent::Type::kGestureShowPress:
+ // Queue a highlight animation, then hand off to regular handler.
+ web_view->EnableTapHighlightAtPoint(targeted_event);
+ break;
+ case WebInputEvent::Type::kGestureTapCancel:
+ case WebInputEvent::Type::kGestureTap:
+ case WebInputEvent::Type::kGestureLongPress:
+ GetPage()->GetLinkHighlight().StartHighlightAnimationIfNeeded();
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (scaled_event.GetType()) {
+ case WebInputEvent::Type::kGestureTap: {
+ {
+ ContextMenuAllowedScope scope;
+ event_result =
+ frame->GetEventHandler().HandleGestureEvent(targeted_event);
+ }
+
+ if (web_view->GetPagePopup() && last_hidden_page_popup_ &&
+ web_view->GetPagePopup()->HasSamePopupClient(
+ last_hidden_page_popup_.get())) {
+ // The tap triggered a page popup that is the same as the one we just
+ // closed. It needs to be closed.
+ web_view->CancelPagePopup();
+ }
+ // Don't have this value persist outside of a single tap gesture, plus
+ // we're done with it now.
+ last_hidden_page_popup_ = nullptr;
+ break;
+ }
+ case WebInputEvent::Type::kGestureTwoFingerTap:
+ case WebInputEvent::Type::kGestureLongPress:
+ case WebInputEvent::Type::kGestureLongTap:
+ if (scaled_event.GetType() == WebInputEvent::Type::kGestureLongTap) {
+ if (LocalFrame* inner_frame =
+ targeted_event.GetHitTestResult().InnerNodeFrame()) {
+ if (!inner_frame->GetEventHandler().LongTapShouldInvokeContextMenu())
+ break;
+ } else if (!frame->GetEventHandler().LongTapShouldInvokeContextMenu()) {
+ break;
+ }
+ }
+
+ GetPage()->GetContextMenuController().ClearContextMenu();
+ {
+ ContextMenuAllowedScope scope;
+ event_result =
+ frame->GetEventHandler().HandleGestureEvent(targeted_event);
+ }
+
+ break;
+ case WebInputEvent::Type::kGestureTapDown:
+ // Touch pinch zoom and scroll on the page (outside of a popup) must hide
+ // the popup. In case of a touch scroll or pinch zoom, this function is
+ // called with GestureTapDown rather than a GSB/GSU/GSE or GPB/GPU/GPE.
+ // When we close a popup because of a GestureTapDown, we also save it so
+ // we can prevent the following GestureTap from immediately reopening the
+ // same popup.
+ // This value should not persist outside of a gesture, so is cleared by
+ // GestureTap (where it is used) and by GestureCancel.
+ last_hidden_page_popup_ = web_view->GetPagePopup();
+ web_view->CancelPagePopup();
+ event_result =
+ frame->GetEventHandler().HandleGestureEvent(targeted_event);
+ break;
+ case WebInputEvent::Type::kGestureTapCancel:
+ // Don't have this value persist outside of a single tap gesture.
+ last_hidden_page_popup_ = nullptr;
+ event_result =
+ frame->GetEventHandler().HandleGestureEvent(targeted_event);
+ break;
+ case WebInputEvent::Type::kGestureShowPress:
+ case WebInputEvent::Type::kGestureTapUnconfirmed:
+ event_result =
+ frame->GetEventHandler().HandleGestureEvent(targeted_event);
+ break;
+ default:
+ NOTREACHED();
+ }
+ DidHandleGestureEvent(event);
+ return event_result;
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleMouseWheel(
+ LocalFrame& frame,
+ const WebMouseWheelEvent& event) {
+ View()->CancelPagePopup();
+ return PageWidgetEventHandler::HandleMouseWheel(frame, event);
+ // PageWidgetEventHandler may have detached the frame.
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleCharEvent(
+ const WebKeyboardEvent& event) {
+ DCHECK_EQ(event.GetType(), WebInputEvent::Type::kChar);
+
+ // Please refer to the comments explaining the m_suppressNextKeypressEvent
+ // member. The m_suppressNextKeypressEvent is set if the KeyDown is
+ // handled by Webkit. A keyDown event is typically associated with a
+ // keyPress(char) event and a keyUp event. We reset this flag here as it
+ // only applies to the current keyPress event.
+ bool suppress = suppress_next_keypress_event_;
+ suppress_next_keypress_event_ = false;
+
+ // If there is a popup open, it should be the one processing the event,
+ // not the page.
+ scoped_refptr<WebPagePopupImpl> page_popup = View()->GetPagePopup();
+ if (page_popup)
+ return page_popup->HandleKeyEvent(event);
+
+ LocalFrame* frame = To<LocalFrame>(FocusedCoreFrame());
+ if (!frame) {
+ return suppress ? WebInputEventResult::kHandledSuppressed
+ : WebInputEventResult::kNotHandled;
+ }
+
+ EventHandler& handler = frame->GetEventHandler();
+
+ if (!event.IsCharacterKey())
+ return WebInputEventResult::kHandledSuppressed;
+
+ // Accesskeys are triggered by char events and can't be suppressed.
+ // It is unclear whether a keypress should be dispatched as well
+ // crbug.com/563507
+ if (handler.HandleAccessKey(event))
+ return WebInputEventResult::kHandledSystem;
+
+ // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
+ // the eventHandler::keyEvent. We mimic this behavior on all platforms since
+ // for now we are converting other platform's key events to windows key
+ // events.
+ if (event.is_system_key)
+ return WebInputEventResult::kNotHandled;
+
+ if (suppress)
+ return WebInputEventResult::kHandledSuppressed;
+
+ WebInputEventResult result = handler.KeyEvent(event);
+ if (result != WebInputEventResult::kNotHandled)
+ return result;
+
+ return WebInputEventResult::kNotHandled;
+}
+
+void WebFrameWidgetImpl::CancelDrag() {
+ // It's possible for this to be called while we're not doing a drag if
+ // it's from a previous page that got unloaded.
+ if (!doing_drag_and_drop_)
+ return;
+ GetPage()->GetDragController().DragEnded();
+ doing_drag_and_drop_ = false;
+}
+
+void WebFrameWidgetImpl::StartDragging(const WebDragData& drag_data,
+ DragOperationsMask operations_allowed,
+ const SkBitmap& drag_image,
+ const gfx::Point& drag_image_offset) {
+ doing_drag_and_drop_ = true;
+ if (drag_and_drop_disabled_) {
+ DragSourceSystemDragEnded();
+ return;
+ }
-WebFrameWidgetImpl::~WebFrameWidgetImpl() = default;
+ gfx::Point offset_in_dips =
+ widget_base_->BlinkSpaceToFlooredDIPs(drag_image_offset);
+ GetAssociatedFrameWidgetHost()->StartDragging(
+ drag_data, operations_allowed, drag_image,
+ gfx::Vector2d(offset_in_dips.x(), offset_in_dips.y()),
+ possible_drag_event_info_.Clone());
+}
+
+DragOperation WebFrameWidgetImpl::DragTargetDragEnterOrOver(
+ const gfx::PointF& point_in_viewport,
+ const gfx::PointF& screen_point,
+ DragAction drag_action,
+ uint32_t key_modifiers) {
+ DCHECK(current_drag_data_);
+ // TODO(paulmeyer): It shouldn't be possible for |m_currentDragData| to be
+ // null here, but this is somehow happening (rarely). This suggests that in
+ // some cases drag-over is happening before drag-enter, which should be
+ // impossible. This needs to be investigated further. Once fixed, the extra
+ // check for |!m_currentDragData| should be removed. (crbug.com/671504)
+ if (IgnoreInputEvents() || !current_drag_data_) {
+ CancelDrag();
+ return DragOperation::kNone;
+ }
+
+ FloatPoint point_in_root_frame(ViewportToRootFrame(point_in_viewport));
+
+ current_drag_data_->SetModifiers(key_modifiers);
+ DragData drag_data(current_drag_data_.Get(), FloatPoint(point_in_root_frame),
+ FloatPoint(screen_point), operations_allowed_);
+
+ DragOperation drag_operation =
+ GetPage()->GetDragController().DragEnteredOrUpdated(
+ &drag_data, *local_root_->GetFrame());
+
+ // Mask the drag operation against the drag source's allowed
+ // operations.
+ if (!(static_cast<int>(drag_operation) &
+ drag_data.DraggingSourceOperationMask()))
+ drag_operation = DragOperation::kNone;
+
+ drag_operation_ = drag_operation;
+
+ return drag_operation_;
+}
+
+void WebFrameWidgetImpl::SendOverscrollEventFromImplSide(
+ const gfx::Vector2dF& overscroll_delta,
+ cc::ElementId scroll_latched_element_id) {
+ if (!RuntimeEnabledFeatures::OverscrollCustomizationEnabled())
+ return;
+
+ Node* target_node = View()->FindNodeFromScrollableCompositorElementId(
+ scroll_latched_element_id);
+ if (target_node) {
+ target_node->GetDocument().EnqueueOverscrollEventForNode(
+ target_node, overscroll_delta.x(), overscroll_delta.y());
+ }
+}
+
+void WebFrameWidgetImpl::SendScrollEndEventFromImplSide(
+ cc::ElementId scroll_latched_element_id) {
+ if (!RuntimeEnabledFeatures::OverscrollCustomizationEnabled())
+ return;
+
+ Node* target_node = View()->FindNodeFromScrollableCompositorElementId(
+ scroll_latched_element_id);
+ if (target_node)
+ target_node->GetDocument().EnqueueScrollEndEventForNode(target_node);
+}
+
+void WebFrameWidgetImpl::UpdateCompositorScrollState(
+ const cc::CompositorCommitData& commit_data) {
+ if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl())
+ devtools->SetPageIsScrolling(commit_data.is_scroll_active);
+
+ RecordManipulationTypeCounts(commit_data.manipulation_info);
+
+ if (commit_data.scroll_latched_element_id == cc::ElementId())
+ return;
+
+ if (!commit_data.overscroll_delta.IsZero()) {
+ SendOverscrollEventFromImplSide(commit_data.overscroll_delta,
+ commit_data.scroll_latched_element_id);
+ }
+
+ // TODO(bokan): If a scroll ended and a new one began in the same Blink frame
+ // (e.g. during a long running main thread task), this will erroneously
+ // dispatch the scroll end to the latter (still-scrolling) element.
+ // https://crbug.com/1116780.
+ if (commit_data.scroll_gesture_did_end)
+ SendScrollEndEventFromImplSide(commit_data.scroll_latched_element_id);
+}
+
+WebInputMethodController*
+WebFrameWidgetImpl::GetActiveWebInputMethodController() const {
+ WebLocalFrameImpl* local_frame =
+ WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
+ return local_frame ? local_frame->GetInputMethodController() : nullptr;
+}
+
+void WebFrameWidgetImpl::DisableDragAndDrop() {
+ drag_and_drop_disabled_ = true;
+}
+
+gfx::PointF WebFrameWidgetImpl::ViewportToRootFrame(
+ const gfx::PointF& point_in_viewport) const {
+ return GetPage()->GetVisualViewport().ViewportToRootFrame(
+ FloatPoint(point_in_viewport));
+}
+
+WebViewImpl* WebFrameWidgetImpl::View() const {
+ return local_root_->ViewImpl();
+}
+
+Page* WebFrameWidgetImpl::GetPage() const {
+ return View()->GetPage();
+}
+
+mojom::blink::FrameWidgetHost*
+WebFrameWidgetImpl::GetAssociatedFrameWidgetHost() const {
+ return frame_widget_host_.get();
+}
+
+void WebFrameWidgetImpl::RequestDecode(
+ const PaintImage& image,
+ base::OnceCallback<void(bool)> callback) {
+ widget_base_->LayerTreeHost()->QueueImageDecode(image, std::move(callback));
+}
+
+void WebFrameWidgetImpl::Trace(Visitor* visitor) const {
+ visitor->Trace(local_root_);
+ visitor->Trace(current_drag_data_);
+ visitor->Trace(frame_widget_host_);
+ visitor->Trace(receiver_);
+ visitor->Trace(input_target_receiver_);
+ visitor->Trace(mouse_capture_element_);
+ visitor->Trace(device_emulator_);
+}
+
+void WebFrameWidgetImpl::SetNeedsRecalculateRasterScales() {
+ if (!View()->does_composite())
+ return;
+ widget_base_->LayerTreeHost()->SetNeedsRecalculateRasterScales();
+}
+
+void WebFrameWidgetImpl::SetBackgroundColor(SkColor color) {
+ if (!View()->does_composite())
+ return;
+ widget_base_->LayerTreeHost()->set_background_color(color);
+}
+
+void WebFrameWidgetImpl::SetOverscrollBehavior(
+ const cc::OverscrollBehavior& overscroll_behavior) {
+ if (!View()->does_composite())
+ return;
+ widget_base_->LayerTreeHost()->SetOverscrollBehavior(overscroll_behavior);
+}
+
+void WebFrameWidgetImpl::RegisterSelection(cc::LayerSelection selection) {
+ if (!View()->does_composite())
+ return;
+ widget_base_->LayerTreeHost()->RegisterSelection(selection);
+}
+
+void WebFrameWidgetImpl::StartPageScaleAnimation(
+ const gfx::Vector2d& destination,
+ bool use_anchor,
+ float new_page_scale,
+ base::TimeDelta duration) {
+ widget_base_->LayerTreeHost()->StartPageScaleAnimation(
+ destination, use_anchor, new_page_scale, duration);
+}
+
+void WebFrameWidgetImpl::RequestBeginMainFrameNotExpected(bool request) {
+ if (!View()->does_composite())
+ return;
+ widget_base_->LayerTreeHost()->RequestBeginMainFrameNotExpected(request);
+}
+
+void WebFrameWidgetImpl::DidCommitAndDrawCompositorFrame() {
+ ForEachLocalFrameControlledByWidget(
+ local_root_->GetFrame(),
+ WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
+ local_frame->Client()->DidCommitAndDrawCompositorFrame();
+ }));
+}
+
+void WebFrameWidgetImpl::DidObserveFirstScrollDelay(
+ base::TimeDelta first_scroll_delay,
+ base::TimeTicks first_scroll_timestamp) {
+ if (!local_root_ || !(local_root_->GetFrame()) ||
+ !(local_root_->GetFrame()->GetDocument())) {
+ return;
+ }
+ InteractiveDetector* interactive_detector =
+ InteractiveDetector::From(*(local_root_->GetFrame()->GetDocument()));
+ if (interactive_detector) {
+ interactive_detector->DidObserveFirstScrollDelay(first_scroll_delay,
+ first_scroll_timestamp);
+ }
+}
+
+std::unique_ptr<cc::LayerTreeFrameSink>
+WebFrameWidgetImpl::AllocateNewLayerTreeFrameSink() {
+ return nullptr;
+}
+
+void WebFrameWidgetImpl::DidBeginMainFrame() {
+ DCHECK(LocalRootImpl()->GetFrame());
+ PageWidgetDelegate::DidBeginFrame(*LocalRootImpl()->GetFrame());
+}
+
+void WebFrameWidgetImpl::UpdateLifecycle(WebLifecycleUpdate requested_update,
+ DocumentUpdateReason reason) {
+ TRACE_EVENT0("blink", "WebFrameWidgetImpl::UpdateLifecycle");
+ if (!LocalRootImpl())
+ return;
+
+ PageWidgetDelegate::UpdateLifecycle(*GetPage(), *LocalRootImpl()->GetFrame(),
+ requested_update, reason);
+ if (requested_update != WebLifecycleUpdate::kAll)
+ return;
+
+ View()->UpdatePagePopup();
+
+ // Meaningful layout events and background colors only apply to main frames.
+ if (ForMainFrame()) {
+ MainFrameData& data = main_data();
+
+ // There is no background color for non-composited WebViews (eg
+ // printing).
+ if (View()->does_composite()) {
+ SkColor background_color = View()->BackgroundColor();
+ SetBackgroundColor(background_color);
+ if (background_color != data.last_background_color) {
+ LocalRootImpl()->GetFrame()->DidChangeBackgroundColor(
+ background_color, false /* color_adjust */);
+ data.last_background_color = background_color;
+ }
+ }
+
+ if (LocalFrameView* view = LocalRootImpl()->GetFrameView()) {
+ LocalFrame* frame = LocalRootImpl()->GetFrame();
+
+ if (data.should_dispatch_first_visually_non_empty_layout &&
+ view->IsVisuallyNonEmpty()) {
+ data.should_dispatch_first_visually_non_empty_layout = false;
+ // TODO(esprehn): Move users of this callback to something
+ // better, the heuristic for "visually non-empty" is bad.
+ DidMeaningfulLayout(WebMeaningfulLayout::kVisuallyNonEmpty);
+ }
+
+ if (data.should_dispatch_first_layout_after_finished_parsing &&
+ frame->GetDocument()->HasFinishedParsing()) {
+ data.should_dispatch_first_layout_after_finished_parsing = false;
+ DidMeaningfulLayout(WebMeaningfulLayout::kFinishedParsing);
+ }
+
+ if (data.should_dispatch_first_layout_after_finished_loading &&
+ frame->GetDocument()->IsLoadCompleted()) {
+ data.should_dispatch_first_layout_after_finished_loading = false;
+ DidMeaningfulLayout(WebMeaningfulLayout::kFinishedLoading);
+ }
+ }
+ }
+}
+
+void WebFrameWidgetImpl::DidCompletePageScaleAnimation() {
+ // Page scale animations only happen on the main frame.
+ DCHECK(ForMainFrame());
+ if (auto* focused_frame = View()->FocusedFrame()) {
+ if (focused_frame->AutofillClient())
+ focused_frame->AutofillClient()->DidCompleteFocusChangeInFrame();
+ }
+}
+
+void WebFrameWidgetImpl::ScheduleAnimation() {
+ if (!View()->does_composite()) {
+ non_composited_client_->ScheduleNonCompositedAnimation();
+ return;
+ }
+ widget_base_->LayerTreeHost()->SetNeedsAnimate();
+}
+
+void WebFrameWidgetImpl::FocusChanged(bool enable) {
+ // TODO(crbug.com/689777): FocusChange events are only sent to the MainFrame
+ // these maybe should goto the local root so that the rest of input messages
+ // sent to those are preserved in order.
+ DCHECK(ForMainFrame());
+ View()->SetPageFocus(enable);
+}
+
+bool WebFrameWidgetImpl::ShouldAckSyntheticInputImmediately() {
+ // TODO(bokan): The RequestPresentation API appears not to function in VR. As
+ // a short term workaround for https://crbug.com/940063, ACK input
+ // immediately rather than using RequestPresentation.
+ if (GetPage()->GetSettings().GetImmersiveModeEnabled())
+ return true;
+ return false;
+}
+
+void WebFrameWidgetImpl::UpdateVisualProperties(
+ const VisualProperties& visual_properties) {
+ SetZoomLevel(visual_properties.zoom_level);
+
+ // TODO(danakj): In order to synchronize updates between local roots, the
+ // display mode should be propagated to RenderFrameProxies and down through
+ // their RenderWidgetHosts to child WebFrameWidgetImpl via the
+ // VisualProperties waterfall, instead of coming to each WebFrameWidgetImpl
+ // independently.
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode
+ SetDisplayMode(visual_properties.display_mode);
+
+ if (ForMainFrame()) {
+ SetAutoResizeMode(visual_properties.auto_resize_enabled,
+ visual_properties.min_size_for_auto_resize,
+ visual_properties.max_size_for_auto_resize,
+ visual_properties.screen_info.device_scale_factor);
+ }
+
+ bool capture_sequence_number_changed =
+ visual_properties.capture_sequence_number !=
+ last_capture_sequence_number_;
+ if (capture_sequence_number_changed) {
+ last_capture_sequence_number_ = visual_properties.capture_sequence_number;
+
+ // Send the capture sequence number to RemoteFrames that are below the
+ // local root for this widget.
+ ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+ [](uint32_t capture_sequence_number, RemoteFrame* remote_frame) {
+ remote_frame->UpdateCaptureSequenceNumber(capture_sequence_number);
+ },
+ visual_properties.capture_sequence_number));
+ }
+
+ if (!View()->AutoResizeMode()) {
+ if (visual_properties.is_fullscreen_granted != is_fullscreen_granted_) {
+ is_fullscreen_granted_ = visual_properties.is_fullscreen_granted;
+ if (is_fullscreen_granted_)
+ View()->DidEnterFullscreen();
+ else
+ View()->DidExitFullscreen();
+ }
+ }
+
+ gfx::Size old_visible_viewport_size_in_dips =
+ widget_base_->VisibleViewportSizeInDIPs();
+ ApplyVisualPropertiesSizing(visual_properties);
+
+ if (old_visible_viewport_size_in_dips !=
+ widget_base_->VisibleViewportSizeInDIPs()) {
+ ForEachLocalFrameControlledByWidget(
+ local_root_->GetFrame(),
+ WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
+ local_frame->ResetHasScrolledFocusedEditableIntoView();
+ }));
+
+ // Propagate changes down to child local root RenderWidgets and
+ // BrowserPlugins in other frame trees/processes.
+ ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+ [](const gfx::Size& visible_viewport_size, RemoteFrame* remote_frame) {
+ remote_frame->DidChangeVisibleViewportSize(visible_viewport_size);
+ },
+ widget_base_->VisibleViewportSizeInDIPs()));
+ }
+
+ // All non-top-level Widgets (child local-root frames, Portals, GuestViews,
+ // etc.) propagate and consume the page scale factor as "external", meaning
+ // that it comes from the top level widget's page scale.
+ if (!ForTopMostMainFrame()) {
+ // The main frame controls the page scale factor, from blink. For other
+ // frame widgets, the page scale from pinch zoom and compositing scale is
+ // received from its parent as part of the visual properties here. While
+ // blink doesn't need to know this page scale factor outside the main frame,
+ // the compositor does in order to produce its output at the correct scale.
+ float combined_scale_factor = visual_properties.page_scale_factor *
+ visual_properties.compositing_scale_factor;
+ widget_base_->LayerTreeHost()->SetExternalPageScaleFactor(
+ combined_scale_factor, visual_properties.is_pinch_gesture_active);
+
+ NotifyPageScaleFactorChanged(visual_properties.page_scale_factor,
+ visual_properties.is_pinch_gesture_active);
+
+ NotifyCompositingScaleFactorChanged(
+ visual_properties.compositing_scale_factor);
+ } else {
+ // Ensure the external scale factor in top-level widgets is reset as it may
+ // be leftover from when a widget was nested and was promoted to top level
+ // (e.g. portal activation).
+ widget_base_->LayerTreeHost()->SetExternalPageScaleFactor(
+ 1.f,
+ /*is_pinch_gesture_active=*/false);
+ }
+
+ // TODO(crbug.com/939118): ScrollFocusedNodeIntoViewForWidget does not work
+ // when the focused node is inside an OOPIF. This code path where
+ // scroll_focused_node_into_view is set is used only for WebView, crbug
+ // 939118 tracks fixing webviews to not use scroll_focused_node_into_view.
+ if (visual_properties.scroll_focused_node_into_view)
+ ScrollFocusedEditableElementIntoView();
+}
+
+void WebFrameWidgetImpl::ApplyVisualPropertiesSizing(
+ const VisualProperties& visual_properties) {
+ gfx::Rect new_compositor_viewport_pixel_rect =
+ visual_properties.compositor_viewport_pixel_rect;
+ if (ForMainFrame()) {
+ if (size_ !=
+ widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size)) {
+ // Only hide popups when the size changes. Eg https://crbug.com/761908.
+ View()->CancelPagePopup();
+ }
+
+ if (auto* device_emulator = DeviceEmulator()) {
+ device_emulator->UpdateVisualProperties(visual_properties);
+ return;
+ }
+
+ if (AutoResizeMode()) {
+ new_compositor_viewport_pixel_rect = gfx::Rect(gfx::ScaleToCeiledSize(
+ widget_base_->BlinkSpaceToFlooredDIPs(size_.value_or(gfx::Size())),
+ visual_properties.screen_info.device_scale_factor));
+ }
+ }
+
+ SetWindowSegments(visual_properties.root_widget_window_segments);
+
+ widget_base_->UpdateSurfaceAndScreenInfo(
+ visual_properties.local_surface_id.value_or(viz::LocalSurfaceId()),
+ new_compositor_viewport_pixel_rect, visual_properties.screen_info);
+
+ // Store this even when auto-resizing, it is the size of the full viewport
+ // used for clipping, and this value is propagated down the Widget
+ // hierarchy via the VisualProperties waterfall.
+ widget_base_->SetVisibleViewportSizeInDIPs(
+ visual_properties.visible_viewport_size);
+
+ if (ForMainFrame()) {
+ if (!AutoResizeMode()) {
+ size_ = widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size);
+
+ View()->ResizeWithBrowserControls(
+ size_.value(),
+ widget_base_->DIPsToCeiledBlinkSpace(
+ widget_base_->VisibleViewportSizeInDIPs()),
+ visual_properties.browser_controls_params);
+ }
+ } else {
+ // Widgets in a WebView's frame tree without a local main frame
+ // set the size of the WebView to be the |visible_viewport_size|, in order
+ // to limit compositing in (out of process) child frames to what is visible.
+ //
+ // Note that child frames in the same process/WebView frame tree as the
+ // main frame do not do this in order to not clobber the source of truth in
+ // the main frame.
+ if (!View()->MainFrameImpl()) {
+ View()->Resize(widget_base_->DIPsToCeiledBlinkSpace(
+ widget_base_->VisibleViewportSizeInDIPs()));
+ }
+
+ Resize(widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size));
+ }
+}
+
+int WebFrameWidgetImpl::GetLayerTreeId() {
+ if (!View()->does_composite())
+ return 0;
+ return widget_base_->LayerTreeHost()->GetId();
+}
+
+const cc::LayerTreeSettings& WebFrameWidgetImpl::GetLayerTreeSettings() {
+ return widget_base_->LayerTreeHost()->GetSettings();
+}
+
+void WebFrameWidgetImpl::UpdateBrowserControlsState(
+ cc::BrowserControlsState constraints,
+ cc::BrowserControlsState current,
+ bool animate) {
+ DCHECK(View()->does_composite());
+ widget_base_->LayerTreeHost()->UpdateBrowserControlsState(constraints,
+ current, animate);
+}
+
+void WebFrameWidgetImpl::SetHaveScrollEventHandlers(bool has_handlers) {
+ widget_base_->LayerTreeHost()->SetHaveScrollEventHandlers(has_handlers);
+}
+
+void WebFrameWidgetImpl::SetEventListenerProperties(
+ cc::EventListenerClass listener_class,
+ cc::EventListenerProperties listener_properties) {
+ widget_base_->LayerTreeHost()->SetEventListenerProperties(
+ listener_class, listener_properties);
+
+ if (listener_class == cc::EventListenerClass::kTouchStartOrMove ||
+ listener_class == cc::EventListenerClass::kTouchEndOrCancel) {
+ bool has_touch_handlers =
+ EventListenerProperties(cc::EventListenerClass::kTouchStartOrMove) !=
+ cc::EventListenerProperties::kNone ||
+ EventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel) !=
+ cc::EventListenerProperties::kNone;
+ if (!has_touch_handlers_ || *has_touch_handlers_ != has_touch_handlers) {
+ has_touch_handlers_ = has_touch_handlers;
+
+ // Can be null when running tests.
+ if (auto* scheduler_state = widget_base_->RendererWidgetSchedulingState())
+ scheduler_state->SetHasTouchHandler(has_touch_handlers);
+ // Set touch event consumers based on whether there are touch event
+ // handlers or the page has hit testable scrollbars.
+ auto touch_event_consumers = mojom::blink::TouchEventConsumers::New(
+ has_touch_handlers, GetPage()->GetScrollbarTheme().AllowsHitTest());
+ frame_widget_host_->SetHasTouchEventConsumers(
+ std::move(touch_event_consumers));
+ }
+ } else if (listener_class == cc::EventListenerClass::kPointerRawUpdate) {
+ SetHasPointerRawUpdateEventHandlers(listener_properties !=
+ cc::EventListenerProperties::kNone);
+ }
+}
+
+cc::EventListenerProperties WebFrameWidgetImpl::EventListenerProperties(
+ cc::EventListenerClass listener_class) const {
+ return widget_base_->LayerTreeHost()->event_listener_properties(
+ listener_class);
+}
-// WebWidget ------------------------------------------------------------------
+mojom::blink::DisplayMode WebFrameWidgetImpl::DisplayMode() const {
+ return display_mode_;
+}
+
+const WebVector<gfx::Rect>& WebFrameWidgetImpl::WindowSegments() const {
+ return window_segments_;
+}
+
+void WebFrameWidgetImpl::StartDeferringCommits(base::TimeDelta timeout) {
+ if (!View()->does_composite())
+ return;
+ widget_base_->LayerTreeHost()->StartDeferringCommits(timeout);
+}
+
+void WebFrameWidgetImpl::StopDeferringCommits(
+ cc::PaintHoldingCommitTrigger triggger) {
+ if (!View()->does_composite())
+ return;
+ widget_base_->LayerTreeHost()->StopDeferringCommits(triggger);
+}
+
+std::unique_ptr<cc::ScopedDeferMainFrameUpdate>
+WebFrameWidgetImpl::DeferMainFrameUpdate() {
+ return widget_base_->LayerTreeHost()->DeferMainFrameUpdate();
+}
+
+void WebFrameWidgetImpl::SetBrowserControlsShownRatio(float top_ratio,
+ float bottom_ratio) {
+ widget_base_->LayerTreeHost()->SetBrowserControlsShownRatio(top_ratio,
+ bottom_ratio);
+}
+
+void WebFrameWidgetImpl::SetBrowserControlsParams(
+ cc::BrowserControlsParams params) {
+ widget_base_->LayerTreeHost()->SetBrowserControlsParams(params);
+}
+
+void WebFrameWidgetImpl::SynchronouslyCompositeForTesting(
+ base::TimeTicks frame_time) {
+ widget_base_->LayerTreeHost()->CompositeForTest(frame_time, false);
+}
+
+void WebFrameWidgetImpl::UseSynchronousResizeModeForTesting(bool enable) {
+ main_data().synchronous_resize_mode_for_testing = enable;
+}
+
+void WebFrameWidgetImpl::SetDeviceColorSpaceForTesting(
+ const gfx::ColorSpace& color_space) {
+ DCHECK(ForMainFrame());
+ // We are changing the device color space from the renderer, so allocate a
+ // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
+ widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
+
+ blink::ScreenInfo info = widget_base_->GetScreenInfo();
+ info.display_color_spaces = gfx::DisplayColorSpaces(color_space);
+ widget_base_->UpdateScreenInfo(info);
+}
+
+// TODO(665924): Remove direct dispatches of mouse events from
+// PointerLockController, instead passing them through EventHandler.
+void WebFrameWidgetImpl::PointerLockMouseEvent(
+ const WebCoalescedInputEvent& coalesced_event) {
+ const WebInputEvent& input_event = coalesced_event.Event();
+ const WebMouseEvent& mouse_event =
+ static_cast<const WebMouseEvent&>(input_event);
+ WebMouseEvent transformed_event =
+ TransformWebMouseEvent(local_root_->GetFrameView(), mouse_event);
+
+ AtomicString event_type;
+ switch (input_event.GetType()) {
+ case WebInputEvent::Type::kMouseDown:
+ event_type = event_type_names::kMousedown;
+ if (!GetPage() || !GetPage()->GetPointerLockController().GetElement())
+ break;
+ LocalFrame::NotifyUserActivation(
+ GetPage()
+ ->GetPointerLockController()
+ .GetElement()
+ ->GetDocument()
+ .GetFrame(),
+ mojom::blink::UserActivationNotificationType::kInteraction);
+ break;
+ case WebInputEvent::Type::kMouseUp:
+ event_type = event_type_names::kMouseup;
+ break;
+ case WebInputEvent::Type::kMouseMove:
+ event_type = event_type_names::kMousemove;
+ break;
+ default:
+ NOTREACHED() << input_event.GetType();
+ }
+
+ if (GetPage()) {
+ GetPage()->GetPointerLockController().DispatchLockedMouseEvent(
+ transformed_event,
+ TransformWebMouseEventVector(
+ local_root_->GetFrameView(),
+ coalesced_event.GetCoalescedEventsPointers()),
+ TransformWebMouseEventVector(
+ local_root_->GetFrameView(),
+ coalesced_event.GetPredictedEventsPointers()),
+ event_type);
+ }
+}
+bool WebFrameWidgetImpl::IsPointerLocked() {
+ if (GetPage()) {
+ return GetPage()->GetPointerLockController().IsPointerLocked();
+ }
+ return false;
+}
+
+void WebFrameWidgetImpl::ShowContextMenu(
+ ui::mojom::blink::MenuSourceType source_type,
+ const gfx::Point& location) {
+ host_context_menu_location_ = location;
+
+ if (!GetPage())
+ return;
+ GetPage()->GetContextMenuController().ClearContextMenu();
+ {
+ ContextMenuAllowedScope scope;
+ if (LocalFrame* focused_frame =
+ GetPage()->GetFocusController().FocusedFrame()) {
+ focused_frame->GetEventHandler().ShowNonLocatedContextMenu(
+ nullptr, static_cast<blink::WebMenuSourceType>(source_type));
+ }
+ }
+ host_context_menu_location_.reset();
+}
+
+void WebFrameWidgetImpl::SetViewportIntersection(
+ mojom::blink::ViewportIntersectionStatePtr intersection_state,
+ const base::Optional<VisualProperties>& visual_properties) {
+ // Remote viewports are only applicable to local frames with remote ancestors.
+ // TODO(https://crbug.com/1148960): Should this deal with portals?
+ DCHECK(ForSubframe());
+
+ if (visual_properties.has_value())
+ UpdateVisualProperties(visual_properties.value());
+ ApplyViewportIntersection(std::move(intersection_state));
+}
+
+void WebFrameWidgetImpl::ApplyViewportIntersectionForTesting(
+ mojom::blink::ViewportIntersectionStatePtr intersection_state) {
+ ApplyViewportIntersection(std::move(intersection_state));
+}
+
+void WebFrameWidgetImpl::ApplyViewportIntersection(
+ mojom::blink::ViewportIntersectionStatePtr intersection_state) {
+ child_data().compositor_visible_rect =
+ intersection_state->compositor_visible_rect;
+ widget_base_->LayerTreeHost()->SetVisualDeviceViewportIntersectionRect(
+ intersection_state->compositor_visible_rect);
+ LocalRootImpl()->GetFrame()->SetViewportIntersectionFromParent(
+ *intersection_state);
+}
+
+void WebFrameWidgetImpl::EnableDeviceEmulation(
+ const DeviceEmulationParams& parameters) {
+ // Device Emaulation is only supported for the main frame.
+ DCHECK(ForMainFrame());
+ if (!device_emulator_) {
+ gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(Size());
+
+ device_emulator_ = MakeGarbageCollected<ScreenMetricsEmulator>(
+ this, widget_base_->GetScreenInfo(), size_in_dips,
+ widget_base_->VisibleViewportSizeInDIPs(),
+ widget_base_->WidgetScreenRect(), widget_base_->WindowScreenRect());
+ }
+ device_emulator_->ChangeEmulationParams(parameters);
+}
+
+void WebFrameWidgetImpl::DisableDeviceEmulation() {
+ if (!device_emulator_)
+ return;
+ device_emulator_->DisableAndApply();
+ device_emulator_ = nullptr;
+}
+
+void WebFrameWidgetImpl::SetIsInertForSubFrame(bool inert) {
+ DCHECK(ForSubframe());
+ LocalRootImpl()->GetFrame()->SetIsInert(inert);
+}
+
+base::Optional<gfx::Point>
+WebFrameWidgetImpl::GetAndResetContextMenuLocation() {
+ return std::move(host_context_menu_location_);
+}
+
+void WebFrameWidgetImpl::SetZoomLevel(double zoom_level) {
+ // Override the zoom level with the testing one if necessary.
+ if (zoom_level_for_testing_ != -INFINITY)
+ zoom_level = zoom_level_for_testing_;
+
+ View()->SetZoomLevel(zoom_level);
+
+ // Part of the UpdateVisualProperties dance we send the zoom level to
+ // RemoteFrames that are below the local root for this widget.
+ ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+ [](double zoom_level, RemoteFrame* remote_frame) {
+ remote_frame->ZoomLevelChanged(zoom_level);
+ },
+ zoom_level));
+}
+
+void WebFrameWidgetImpl::SetAutoResizeMode(bool auto_resize,
+ const gfx::Size& min_window_size,
+ const gfx::Size& max_window_size,
+ float device_scale_factor) {
+ // Auto resize only applies to main frames.
+ DCHECK(ForMainFrame());
+
+ if (auto_resize) {
+ if (!Platform::Current()->IsUseZoomForDSFEnabled())
+ device_scale_factor = 1.f;
+ View()->EnableAutoResizeMode(
+ gfx::ScaleToCeiledSize(min_window_size, device_scale_factor),
+ gfx::ScaleToCeiledSize(max_window_size, device_scale_factor));
+ } else if (AutoResizeMode()) {
+ View()->DisableAutoResizeMode();
+ }
+}
+
+void WebFrameWidgetImpl::DidAutoResize(const gfx::Size& size) {
+ DCHECK(ForMainFrame());
+ gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(size);
+ size_ = size;
+
+ if (main_data().synchronous_resize_mode_for_testing) {
+ gfx::Rect new_pos(widget_base_->WindowRect());
+ new_pos.set_size(size_in_dips);
+ SetScreenRects(new_pos, new_pos);
+ }
+
+ // TODO(ccameron): Note that this destroys any information differentiating
+ // |size| from the compositor's viewport size.
+ gfx::Rect size_with_dsf = gfx::Rect(gfx::ScaleToCeiledSize(
+ gfx::Rect(size_in_dips).size(),
+ widget_base_->GetScreenInfo().device_scale_factor));
+ widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
+ widget_base_->UpdateCompositorViewportRect(size_with_dsf);
+}
+
+LocalFrame* WebFrameWidgetImpl::FocusedLocalFrameInWidget() const {
+ if (!local_root_) {
+ // WebFrameWidget is created in the call to CreateFrame. The corresponding
+ // RenderWidget, however, might not swap in right away (InstallNewDocument()
+ // will lead to it swapping in). During this interval local_root_ is nullptr
+ // (see https://crbug.com/792345).
+ return nullptr;
+ }
+
+ LocalFrame* frame = GetPage()->GetFocusController().FocusedFrame();
+ return (frame && frame->LocalFrameRoot() == local_root_->GetFrame())
+ ? frame
+ : nullptr;
+}
+
+WebLocalFrameImpl* WebFrameWidgetImpl::FocusedWebLocalFrameInWidget() const {
+ return WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
+}
+
+bool WebFrameWidgetImpl::ScrollFocusedEditableElementIntoView() {
+ Element* element = FocusedElement();
+ if (!element || !WebElement(element).IsEditable())
+ return false;
+
+ element->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection);
+
+ if (!element->GetLayoutObject())
+ return false;
+
+ PhysicalRect rect_to_scroll;
+ auto params =
+ GetScrollParamsForFocusedEditableElement(*element, rect_to_scroll);
+ element->GetLayoutObject()->ScrollRectToVisible(rect_to_scroll,
+ std::move(params));
+
+ // Second phase for main frames is to schedule a zoom animation.
+ if (ForMainFrame()) {
+ LocalFrameView* main_frame_view = LocalRootImpl()->GetFrame()->View();
+
+ View()->ZoomAndScrollToFocusedEditableElementRect(
+ main_frame_view->RootFrameToDocument(
+ element->GetDocument().View()->ConvertToRootFrame(
+ element->GetLayoutObject()->AbsoluteBoundingBoxRect())),
+ main_frame_view->RootFrameToDocument(
+ element->GetDocument().View()->ConvertToRootFrame(
+ element->GetDocument()
+ .GetFrame()
+ ->Selection()
+ .ComputeRectToScroll(kDoNotRevealExtent))),
+ View()->ShouldZoomToLegibleScale(*element));
+ }
+
+ return true;
+}
+
+void WebFrameWidgetImpl::ResetMeaningfulLayoutStateForMainFrame() {
+ MainFrameData& data = main_data();
+ data.should_dispatch_first_visually_non_empty_layout = true;
+ data.should_dispatch_first_layout_after_finished_parsing = true;
+ data.should_dispatch_first_layout_after_finished_loading = true;
+}
-void WebFrameWidgetImpl::Close(
- scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) {
- GetPage()->WillCloseAnimationHost(LocalRootImpl()->GetFrame()->View());
+void WebFrameWidgetImpl::InitializeCompositing(
+ scheduler::WebAgentGroupScheduler& agent_group_scheduler,
+ cc::TaskGraphRunner* task_graph_runner,
+ const ScreenInfo& screen_info,
+ std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory,
+ const cc::LayerTreeSettings* settings) {
+ DCHECK(View()->does_composite());
+ DCHECK(!non_composited_client_); // Assure only one initialize is called.
+ widget_base_->InitializeCompositing(
+ agent_group_scheduler, task_graph_runner, is_for_child_local_root_,
+ screen_info, std::move(ukm_recorder_factory), settings,
+ input_handler_weak_ptr_factory_.GetWeakPtr());
- WebFrameWidgetBase::Close(std::move(cleanup_runner));
+ LocalFrameView* frame_view;
+ if (is_for_child_local_root_) {
+ frame_view = LocalRootImpl()->GetFrame()->View();
+ } else {
+ // Scrolling for the root frame is special we need to pass null indicating
+ // we are at the top of the tree when setting up the Animation. Which will
+ // cause ownership of the timeline and animation host.
+ // See ScrollingCoordinator::AnimationHostInitialized.
+ frame_view = nullptr;
+ }
- self_keep_alive_.Clear();
+ GetPage()->AnimationHostInitialized(*AnimationHost(), frame_view);
+}
+
+void WebFrameWidgetImpl::InitializeNonCompositing(
+ WebNonCompositedWidgetClient* client) {
+ DCHECK(!non_composited_client_);
+ DCHECK(client);
+ DCHECK(!View()->does_composite());
+ // Assure only one initialize is called.
+ DCHECK(!widget_base_->IsComposited());
+ non_composited_client_ = client;
+}
+
+void WebFrameWidgetImpl::SetCompositorVisible(bool visible) {
+ widget_base_->SetCompositorVisible(visible);
}
gfx::Size WebFrameWidgetImpl::Size() {
@@ -245,20 +1925,24 @@ void WebFrameWidgetImpl::Resize(const gfx::Size& new_size) {
if (size_ && *size_ == new_size)
return;
- if (did_suspend_parsing_) {
- did_suspend_parsing_ = false;
+ if (ForMainFrame()) {
+ size_ = new_size;
+ View()->Resize(new_size);
+ return;
+ }
+
+ if (child_data().did_suspend_parsing) {
+ child_data().did_suspend_parsing = false;
LocalRootImpl()->GetFrame()->Loader().GetDocumentLoader()->ResumeParser();
}
LocalFrameView* view = LocalRootImpl()->GetFrameView();
- if (!view)
- return;
+ DCHECK(view);
size_ = new_size;
- UpdateMainFrameLayoutSize();
-
- view->Resize(WebSize(*size_));
+ view->SetLayoutSize(IntSize(*size_));
+ view->Resize(IntSize(*size_));
// FIXME: In WebViewImpl this layout was a precursor to setting the minimum
// scale limit. It is not clear if this is necessary for frame-level widget
@@ -277,10 +1961,7 @@ void WebFrameWidgetImpl::Resize(const gfx::Size& new_size) {
// resizeEvent as part of layout. Layout is also responsible for sending
// invalidations to the embedder. This method and all callers may be wrong.
// -- eseidel.
- if (LocalRootImpl()->GetFrameView()) {
- // Enqueues the resize event.
- LocalRootImpl()->GetFrame()->GetDocument()->EnqueueResizeEvent();
- }
+ LocalRootImpl()->GetFrame()->GetDocument()->EnqueueResizeEvent();
// Pass the limits even though this is for subframes, as the limits will
// be needed in setting the raster scale. We set this value when setting
@@ -295,75 +1976,544 @@ void WebFrameWidgetImpl::Resize(const gfx::Size& new_size) {
}
}
-void WebFrameWidgetImpl::UpdateMainFrameLayoutSize() {
+void WebFrameWidgetImpl::BeginMainFrame(base::TimeTicks last_frame_time) {
+ TRACE_EVENT1("blink", "WebFrameWidgetImpl::BeginMainFrame", "frameTime",
+ last_frame_time);
+ DCHECK(!last_frame_time.is_null());
+ CHECK(LocalRootImpl());
+
+ // Dirty bit on MouseEventManager is not cleared in OOPIFs after scroll
+ // or layout changes. Ensure the hover state is recomputed if necessary.
+ LocalRootImpl()
+ ->GetFrame()
+ ->GetEventHandler()
+ .RecomputeMouseHoverStateIfNeeded();
+
+ // Adjusting frame anchor only happens on the main frame.
+ if (ForMainFrame()) {
+ if (LocalFrameView* view = LocalRootImpl()->GetFrameView()) {
+ if (FragmentAnchor* anchor = view->GetFragmentAnchor())
+ anchor->PerformPreRafActions();
+ }
+ }
+
+ base::Optional<LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer> ukm_timer;
+ if (WidgetBase::ShouldRecordBeginMainFrameMetrics()) {
+ ukm_timer.emplace(LocalRootImpl()
+ ->GetFrame()
+ ->View()
+ ->EnsureUkmAggregator()
+ .GetScopedTimer(LocalFrameUkmAggregator::kAnimate));
+ }
+
+ PageWidgetDelegate::Animate(*GetPage(), last_frame_time);
+ // Animate can cause the local frame to detach.
if (!LocalRootImpl())
return;
- LocalFrameView* view = LocalRootImpl()->GetFrameView();
- if (!view)
+ GetPage()->GetValidationMessageClient().LayoutOverlay();
+}
+
+void WebFrameWidgetImpl::BeginCommitCompositorFrame() {
+ commit_compositor_frame_start_time_.emplace(base::TimeTicks::Now());
+}
+
+void WebFrameWidgetImpl::EndCommitCompositorFrame(
+ base::TimeTicks commit_start_time) {
+ DCHECK(commit_compositor_frame_start_time_.has_value());
+ if (ForMainFrame()) {
+ View()->DidCommitCompositorFrameForLocalMainFrame();
+ View()->UpdatePreferredSize();
+ if (!View()->MainFrameImpl()) {
+ // Trying to track down why the view's idea of the main frame varies
+ // from LocalRootImpl's.
+ // TODO(https://crbug.com/1139104): Remove this.
+ std::string reason = View()->GetNullFrameReasonForBug1139104();
+ DCHECK(false) << reason;
+ SCOPED_CRASH_KEY_STRING32("Crbug1139104", "NullFrameReason", reason);
+ base::debug::DumpWithoutCrashing();
+ }
+ }
+
+ LocalRootImpl()
+ ->GetFrame()
+ ->View()
+ ->EnsureUkmAggregator()
+ .RecordImplCompositorSample(commit_compositor_frame_start_time_.value(),
+ commit_start_time, base::TimeTicks::Now());
+ commit_compositor_frame_start_time_.reset();
+}
+
+void WebFrameWidgetImpl::ApplyViewportChanges(
+ const ApplyViewportChangesArgs& args) {
+ // Viewport changes only change the main frame.
+ if (!ForMainFrame())
+ return;
+ WebViewImpl* web_view = View();
+ // TODO(https://crbug.com/1160652): Figure out if View is null.
+ CHECK(widget_base_);
+ CHECK(web_view);
+ web_view->ApplyViewportChanges(args);
+}
+
+void WebFrameWidgetImpl::RecordManipulationTypeCounts(
+ cc::ManipulationInfo info) {
+ // Manipulation counts are only recorded for the main frame.
+ if (!ForMainFrame())
return;
- gfx::Size layout_size = *size_;
+ if ((info & cc::kManipulationInfoWheel) == cc::kManipulationInfoWheel) {
+ UseCounter::Count(LocalRootImpl()->GetDocument(),
+ WebFeature::kScrollByWheel);
+ }
+ if ((info & cc::kManipulationInfoTouch) == cc::kManipulationInfoTouch) {
+ UseCounter::Count(LocalRootImpl()->GetDocument(),
+ WebFeature::kScrollByTouch);
+ }
+ if ((info & cc::kManipulationInfoPinchZoom) ==
+ cc::kManipulationInfoPinchZoom) {
+ UseCounter::Count(LocalRootImpl()->GetDocument(), WebFeature::kPinchZoom);
+ }
+ if ((info & cc::kManipulationInfoPrecisionTouchPad) ==
+ cc::kManipulationInfoPrecisionTouchPad) {
+ UseCounter::Count(LocalRootImpl()->GetDocument(),
+ WebFeature::kScrollByPrecisionTouchPad);
+ }
+}
- view->SetLayoutSize(WebSize(layout_size));
+void WebFrameWidgetImpl::RecordDispatchRafAlignedInputTime(
+ base::TimeTicks raf_aligned_input_start_time) {
+ if (LocalRootImpl()) {
+ LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
+ LocalFrameUkmAggregator::kHandleInputEvents,
+ raf_aligned_input_start_time, base::TimeTicks::Now());
+ }
}
-bool WebFrameWidgetImpl::ShouldHandleImeEvents() {
- // TODO(ekaramad): WebViewWidgetImpl returns true only if it has focus.
- // We track page focus in all RenderViews on the page but
- // the RenderWidgets corresponding to child local roots do not get the
- // update. For now, this method returns true when the RenderWidget is for a
- // child local frame, i.e., IME events will be processed regardless of page
- // focus. We should revisit this after page focus for OOPIFs has been fully
- // resolved (https://crbug.com/689777).
- return LocalRootImpl();
+void WebFrameWidgetImpl::SetSuppressFrameRequestsWorkaroundFor704763Only(
+ bool suppress_frame_requests) {
+ GetPage()->Animator().SetSuppressFrameRequestsWorkaroundFor704763Only(
+ suppress_frame_requests);
}
-void WebFrameWidgetImpl::UpdateLifecycle(WebLifecycleUpdate requested_update,
- DocumentUpdateReason reason) {
- TRACE_EVENT0("blink", "WebFrameWidgetImpl::updateAllLifecyclePhases");
+std::unique_ptr<cc::BeginMainFrameMetrics>
+WebFrameWidgetImpl::GetBeginMainFrameMetrics() {
+ if (!LocalRootImpl())
+ return nullptr;
+
+ return LocalRootImpl()
+ ->GetFrame()
+ ->View()
+ ->EnsureUkmAggregator()
+ .GetBeginMainFrameMetrics();
+}
+
+std::unique_ptr<cc::WebVitalMetrics> WebFrameWidgetImpl::GetWebVitalMetrics() {
+ if (!LocalRootImpl())
+ return nullptr;
+
+ // This class should be called at most once per commit.
+ WebPerformance perf = LocalRootImpl()->Performance();
+ auto metrics = std::make_unique<cc::WebVitalMetrics>();
+ if (perf.FirstInputDelay().has_value()) {
+ metrics->first_input_delay = perf.FirstInputDelay().value();
+ metrics->has_fid = true;
+ }
+
+ base::TimeTicks start = perf.NavigationStartAsMonotonicTime();
+ base::TimeTicks largest_contentful_paint =
+ perf.LargestContentfulPaintAsMonotonicTime();
+ if (largest_contentful_paint >= start) {
+ metrics->largest_contentful_paint = largest_contentful_paint - start;
+ metrics->has_lcp = true;
+ }
+
+ double layout_shift = LocalRootImpl()
+ ->GetFrame()
+ ->View()
+ ->GetLayoutShiftTracker()
+ .WeightedScore();
+ if (layout_shift > 0.f) {
+ metrics->layout_shift = layout_shift;
+ metrics->has_cls = true;
+ }
+
+ if (!metrics->HasValue())
+ return nullptr;
+
+ return metrics;
+}
+
+void WebFrameWidgetImpl::BeginUpdateLayers() {
+ if (LocalRootImpl())
+ update_layers_start_time_.emplace(base::TimeTicks::Now());
+}
+
+void WebFrameWidgetImpl::EndUpdateLayers() {
+ if (LocalRootImpl()) {
+ DCHECK(update_layers_start_time_);
+ LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
+ LocalFrameUkmAggregator::kUpdateLayers,
+ update_layers_start_time_.value(), base::TimeTicks::Now());
+ probe::LayerTreeDidChange(LocalRootImpl()->GetFrame());
+ }
+ update_layers_start_time_.reset();
+}
+
+void WebFrameWidgetImpl::RecordStartOfFrameMetrics() {
if (!LocalRootImpl())
return;
- PageWidgetDelegate::UpdateLifecycle(*GetPage(), *LocalRootImpl()->GetFrame(),
- requested_update, reason);
- View()->UpdatePagePopup();
+ LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().BeginMainFrame();
}
-bool WebFrameWidgetImpl::ScrollFocusedEditableElementIntoView() {
- Element* element = FocusedElement();
- if (!element || !WebElement(element).IsEditable())
- return false;
+void WebFrameWidgetImpl::RecordEndOfFrameMetrics(
+ base::TimeTicks frame_begin_time,
+ cc::ActiveFrameSequenceTrackers trackers) {
+ if (!LocalRootImpl())
+ return;
- if (!element->GetLayoutObject())
- return false;
+ LocalRootImpl()
+ ->GetFrame()
+ ->View()
+ ->EnsureUkmAggregator()
+ .RecordEndOfFrameMetrics(frame_begin_time, base::TimeTicks::Now(),
+ trackers);
+}
- PhysicalRect rect_to_scroll;
- auto params = ScrollAlignment::CreateScrollIntoViewParams();
- GetScrollParamsForFocusedEditableElement(*element, rect_to_scroll, params);
- element->GetLayoutObject()->ScrollRectToVisible(rect_to_scroll,
- std::move(params));
- return true;
+bool WebFrameWidgetImpl::WillHandleGestureEvent(const WebGestureEvent& event) {
+ possible_drag_event_info_.source = ui::mojom::blink::DragEventSource::kTouch;
+ possible_drag_event_info_.location =
+ gfx::ToFlooredPoint(event.PositionInScreen());
+
+ bool move_cursor = false;
+ switch (event.GetType()) {
+ case WebInputEvent::Type::kGestureScrollBegin: {
+ if (event.data.scroll_begin.cursor_control) {
+ swipe_to_move_cursor_activated_ = true;
+ move_cursor = true;
+ }
+ break;
+ }
+ case WebInputEvent::Type::kGestureScrollUpdate: {
+ if (swipe_to_move_cursor_activated_)
+ move_cursor = true;
+ break;
+ }
+ case WebInputEvent::Type::kGestureScrollEnd: {
+ if (swipe_to_move_cursor_activated_) {
+ swipe_to_move_cursor_activated_ = false;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ // TODO(crbug.com/1140106): Place cursor for scroll begin other than just move
+ // cursor.
+ if (move_cursor) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (focused_frame) {
+ gfx::Point base(event.PositionInWidget().x(),
+ event.PositionInWidget().y());
+ focused_frame->MoveCaretSelection(base);
+ }
+ return true;
+ }
+ return false;
}
-void WebFrameWidgetImpl::SetZoomLevelForTesting(double zoom_level) {
- // Zoom level is only controlled for testing on the main frame.
- NOTREACHED();
+void WebFrameWidgetImpl::WillHandleMouseEvent(const WebMouseEvent& event) {
+ possible_drag_event_info_.source = ui::mojom::blink::DragEventSource::kMouse;
+ possible_drag_event_info_.location =
+ gfx::Point(event.PositionInScreen().x(), event.PositionInScreen().y());
}
-void WebFrameWidgetImpl::ResetZoomLevelForTesting() {
- // Zoom level is only controlled for testing on the main frame.
- NOTREACHED();
+void WebFrameWidgetImpl::ObserveGestureEventAndResult(
+ const WebGestureEvent& gesture_event,
+ const gfx::Vector2dF& unused_delta,
+ const cc::OverscrollBehavior& overscroll_behavior,
+ bool event_processed) {
+ if (!widget_base_->LayerTreeHost()->GetSettings().enable_elastic_overscroll)
+ return;
+
+ cc::InputHandlerScrollResult scroll_result;
+ scroll_result.did_scroll = event_processed;
+ scroll_result.did_overscroll_root = !unused_delta.IsZero();
+ scroll_result.unused_scroll_delta = unused_delta;
+ scroll_result.overscroll_behavior = overscroll_behavior;
+
+ widget_base_->widget_input_handler_manager()->ObserveGestureEventOnMainThread(
+ gesture_event, scroll_result);
}
-void WebFrameWidgetImpl::SetDeviceScaleFactorForTesting(float factor) {
- NOTREACHED();
+void WebFrameWidgetImpl::DidHandleKeyEvent() {
+ ClearEditCommands();
}
-void WebFrameWidgetImpl::IntrinsicSizingInfoChanged(
- mojom::blink::IntrinsicSizingInfoPtr sizing_info) {
- GetAssociatedFrameWidgetHost()->IntrinsicSizingInfoChanged(
- std::move(sizing_info));
+WebTextInputType WebFrameWidgetImpl::GetTextInputType() {
+ if (ShouldDispatchImeEventsToPlugin()) {
+ return GetFocusedPluginContainer()->GetPluginTextInputType();
+ }
+
+ WebInputMethodController* controller = GetActiveWebInputMethodController();
+ if (!controller)
+ return WebTextInputType::kWebTextInputTypeNone;
+ return controller->TextInputType();
+}
+
+void WebFrameWidgetImpl::SetCursorVisibilityState(bool is_visible) {
+ GetPage()->SetIsCursorVisible(is_visible);
+}
+
+void WebFrameWidgetImpl::ApplyViewportChangesForTesting(
+ const ApplyViewportChangesArgs& args) {
+ widget_base_->ApplyViewportChanges(args);
+}
+
+void WebFrameWidgetImpl::SetDisplayMode(mojom::blink::DisplayMode mode) {
+ if (mode != display_mode_) {
+ display_mode_ = mode;
+ LocalFrame* frame = LocalRootImpl()->GetFrame();
+ frame->MediaQueryAffectingValueChangedForLocalSubtree(
+ MediaValueChange::kOther);
+ }
+}
+
+void WebFrameWidgetImpl::SetWindowSegments(
+ const std::vector<gfx::Rect>& window_segments_param) {
+ WebVector<gfx::Rect> window_segments(window_segments_param);
+ if (!window_segments_.Equals(window_segments)) {
+ window_segments_ = window_segments;
+ LocalFrame* frame = LocalRootImpl()->GetFrame();
+ frame->WindowSegmentsChanged(window_segments_);
+
+ ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+ [](const std::vector<gfx::Rect>& window_segments,
+ RemoteFrame* remote_frame) {
+ remote_frame->DidChangeRootWindowSegments(window_segments);
+ },
+ window_segments_param));
+ }
+}
+
+void WebFrameWidgetImpl::SetCursor(const ui::Cursor& cursor) {
+ widget_base_->SetCursor(cursor);
+}
+
+bool WebFrameWidgetImpl::HandlingInputEvent() {
+ return widget_base_->input_handler().handling_input_event();
+}
+
+void WebFrameWidgetImpl::SetHandlingInputEvent(bool handling) {
+ widget_base_->input_handler().set_handling_input_event(handling);
+}
+
+void WebFrameWidgetImpl::ProcessInputEventSynchronouslyForTesting(
+ const WebCoalescedInputEvent& event,
+ HandledEventCallback callback) {
+ widget_base_->input_handler().HandleInputEvent(event, nullptr,
+ std::move(callback));
+}
+
+WebInputEventResult WebFrameWidgetImpl::DispatchBufferedTouchEvents() {
+ CHECK(LocalRootImpl());
+
+ if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl())
+ devtools->DispatchBufferedTouchEvents();
+
+ return LocalRootImpl()
+ ->GetFrame()
+ ->GetEventHandler()
+ .DispatchBufferedTouchEvents();
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleInputEvent(
+ const WebCoalescedInputEvent& coalesced_event) {
+ const WebInputEvent& input_event = coalesced_event.Event();
+ TRACE_EVENT1("input,rail", "WebFrameWidgetImpl::HandleInputEvent", "type",
+ WebInputEvent::GetName(input_event.GetType()));
+ DCHECK(!WebInputEvent::IsTouchEventType(input_event.GetType()));
+ CHECK(LocalRootImpl());
+
+ // Only record metrics for the main frame.
+ if (ForMainFrame()) {
+ GetPage()->GetVisualViewport().StartTrackingPinchStats();
+ }
+
+ // If a drag-and-drop operation is in progress, ignore input events except
+ // PointerCancel.
+ if (doing_drag_and_drop_ &&
+ input_event.GetType() != WebInputEvent::Type::kPointerCancel)
+ return WebInputEventResult::kHandledSuppressed;
+
+ // Don't handle events once we've started shutting down.
+ if (!GetPage())
+ return WebInputEventResult::kNotHandled;
+
+ if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl()) {
+ auto result = devtools->HandleInputEvent(input_event);
+ if (result != WebInputEventResult::kNotHandled)
+ return result;
+ }
+
+ // Report the event to be NOT processed by WebKit, so that the browser can
+ // handle it appropriately.
+ if (IgnoreInputEvents())
+ return WebInputEventResult::kNotHandled;
+
+ base::AutoReset<const WebInputEvent*> current_event_change(
+ &CurrentInputEvent::current_input_event_, &input_event);
+ UIEventWithKeyState::ClearNewTabModifierSetFromIsolatedWorld();
+
+ if (GetPage()->GetPointerLockController().IsPointerLocked() &&
+ WebInputEvent::IsMouseEventType(input_event.GetType())) {
+ PointerLockMouseEvent(coalesced_event);
+ return WebInputEventResult::kHandledSystem;
+ }
+
+ /// These metrics are only captured for the main frame.
+ if (ForMainFrame()) {
+ Document& main_frame_document = *LocalRootImpl()->GetFrame()->GetDocument();
+
+ if (input_event.GetType() != WebInputEvent::Type::kMouseMove) {
+ FirstMeaningfulPaintDetector::From(main_frame_document)
+ .NotifyInputEvent();
+ }
+
+ if (input_event.GetType() != WebInputEvent::Type::kMouseMove &&
+ input_event.GetType() != WebInputEvent::Type::kMouseEnter &&
+ input_event.GetType() != WebInputEvent::Type::kMouseLeave) {
+ InteractiveDetector* interactive_detector(
+ InteractiveDetector::From(main_frame_document));
+ if (interactive_detector) {
+ interactive_detector->OnInvalidatingInputEvent(input_event.TimeStamp());
+ }
+ }
+ }
+
+ NotifyInputObservers(coalesced_event);
+
+ // Notify the focus frame of the input. Note that the other frames are not
+ // notified as input is only handled by the focused frame.
+ Frame* frame = FocusedCoreFrame();
+ if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
+ if (auto* content_capture_manager =
+ local_frame->LocalFrameRoot().GetContentCaptureManager()) {
+ content_capture_manager->NotifyInputEvent(input_event.GetType(),
+ *local_frame);
+ }
+ }
+
+ // Skip the pointerrawupdate for mouse capture case.
+ if (mouse_capture_element_ &&
+ input_event.GetType() == WebInputEvent::Type::kPointerRawUpdate)
+ return WebInputEventResult::kHandledSystem;
+
+ if (mouse_capture_element_ &&
+ WebInputEvent::IsMouseEventType(input_event.GetType()))
+ return HandleCapturedMouseEvent(coalesced_event);
+
+ // FIXME: This should take in the intended frame, not the local frame
+ // root.
+ return PageWidgetDelegate::HandleInputEvent(*this, coalesced_event,
+ LocalRootImpl()->GetFrame());
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleCapturedMouseEvent(
+ const WebCoalescedInputEvent& coalesced_event) {
+ const WebInputEvent& input_event = coalesced_event.Event();
+ TRACE_EVENT1("input", "captured mouse event", "type", input_event.GetType());
+ // Save |mouse_capture_element_| since |MouseCaptureLost()| will clear it.
+ HTMLPlugInElement* element = mouse_capture_element_;
+
+ // Not all platforms call mouseCaptureLost() directly.
+ if (input_event.GetType() == WebInputEvent::Type::kMouseUp) {
+ SetMouseCapture(false);
+ MouseCaptureLost();
+ }
+
+ AtomicString event_type;
+ switch (input_event.GetType()) {
+ case WebInputEvent::Type::kMouseEnter:
+ event_type = event_type_names::kMouseover;
+ break;
+ case WebInputEvent::Type::kMouseMove:
+ event_type = event_type_names::kMousemove;
+ break;
+ case WebInputEvent::Type::kPointerRawUpdate:
+ // There will be no mouse event for rawupdate events.
+ event_type = event_type_names::kPointerrawupdate;
+ break;
+ case WebInputEvent::Type::kMouseLeave:
+ event_type = event_type_names::kMouseout;
+ break;
+ case WebInputEvent::Type::kMouseDown:
+ event_type = event_type_names::kMousedown;
+ LocalFrame::NotifyUserActivation(
+ element->GetDocument().GetFrame(),
+ mojom::blink::UserActivationNotificationType::kInteraction);
+ break;
+ case WebInputEvent::Type::kMouseUp:
+ event_type = event_type_names::kMouseup;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ WebMouseEvent transformed_event =
+ TransformWebMouseEvent(LocalRootImpl()->GetFrameView(),
+ static_cast<const WebMouseEvent&>(input_event));
+ if (LocalFrame* frame = element->GetDocument().GetFrame()) {
+ frame->GetEventHandler().HandleTargetedMouseEvent(
+ element, transformed_event, event_type,
+ TransformWebMouseEventVector(
+ LocalRootImpl()->GetFrameView(),
+ coalesced_event.GetCoalescedEventsPointers()),
+ TransformWebMouseEventVector(
+ LocalRootImpl()->GetFrameView(),
+ coalesced_event.GetPredictedEventsPointers()));
+ }
+ return WebInputEventResult::kHandledSystem;
+}
+
+void WebFrameWidgetImpl::UpdateTextInputState() {
+ widget_base_->UpdateTextInputState();
+}
+
+void WebFrameWidgetImpl::UpdateSelectionBounds() {
+ widget_base_->UpdateSelectionBounds();
+}
+
+void WebFrameWidgetImpl::ShowVirtualKeyboard() {
+ widget_base_->ShowVirtualKeyboard();
+}
+
+void WebFrameWidgetImpl::FlushInputProcessedCallback() {
+ widget_base_->FlushInputProcessedCallback();
+}
+
+void WebFrameWidgetImpl::CancelCompositionForPepper() {
+ widget_base_->CancelCompositionForPepper();
+}
+
+void WebFrameWidgetImpl::RequestMouseLock(
+ bool has_transient_user_activation,
+ bool request_unadjusted_movement,
+ mojom::blink::WidgetInputHandlerHost::RequestMouseLockCallback callback) {
+ mojom::blink::WidgetInputHandlerHost* host =
+ widget_base_->widget_input_handler_manager()->GetWidgetInputHandlerHost();
+
+ // If we don't have a host just leave the callback uncalled. This simulates
+ // the browser indefinitely postponing the mouse request which is valid.
+ // Note that |callback| is not a mojo bound callback (until it is passed
+ // into the mojo interface) and can be destructed without invoking the
+ // callback. It does share the same signature as the mojo definition
+ // for simplicity.
+ if (host) {
+ host->RequestMouseLock(has_transient_user_activation,
+ request_unadjusted_movement, std::move(callback));
+ }
}
void WebFrameWidgetImpl::MouseCaptureLost() {
@@ -372,63 +2522,1057 @@ void WebFrameWidgetImpl::MouseCaptureLost() {
mouse_capture_element_ = nullptr;
}
-void WebFrameWidgetImpl::FocusChanged(bool enable) {
- if (enable)
- GetPage()->GetFocusController().SetActive(true);
- GetPage()->GetFocusController().SetFocused(enable);
- if (enable) {
- LocalFrame* focused_frame = GetPage()->GetFocusController().FocusedFrame();
- if (focused_frame) {
- Element* element = focused_frame->GetDocument()->FocusedElement();
- if (element && focused_frame->Selection()
- .ComputeVisibleSelectionInDOMTreeDeprecated()
- .IsNone()) {
- // If the selection was cleared while the WebView was not
- // focused, then the focus element shows with a focus ring but
- // no caret and does respond to keyboard inputs.
- focused_frame->GetDocument()->UpdateStyleAndLayoutTree();
- if (element->IsTextControl()) {
- element->UpdateFocusAppearance(SelectionBehaviorOnFocus::kRestore);
- } else if (HasEditableStyle(*element)) {
- // updateFocusAppearance() selects all the text of
- // contentseditable DIVs. So we set the selection explicitly
- // instead. Note that this has the side effect of moving the
- // caret back to the beginning of the text.
- Position position(element, 0);
- focused_frame->Selection().SetSelectionAndEndTyping(
- SelectionInDOMTree::Builder().Collapse(position).Build());
- }
- }
+void WebFrameWidgetImpl::ApplyVisualProperties(
+ const VisualProperties& visual_properties) {
+ widget_base_->UpdateVisualProperties(visual_properties);
+}
+
+bool WebFrameWidgetImpl::IsFullscreenGranted() {
+ return is_fullscreen_granted_;
+}
+
+bool WebFrameWidgetImpl::PinchGestureActiveInMainFrame() {
+ return is_pinch_gesture_active_in_mainframe_;
+}
+
+float WebFrameWidgetImpl::PageScaleInMainFrame() {
+ return page_scale_factor_in_mainframe_;
+}
+
+void WebFrameWidgetImpl::UpdateSurfaceAndScreenInfo(
+ const viz::LocalSurfaceId& new_local_surface_id,
+ const gfx::Rect& compositor_viewport_pixel_rect,
+ const ScreenInfo& new_screen_info) {
+ widget_base_->UpdateSurfaceAndScreenInfo(
+ new_local_surface_id, compositor_viewport_pixel_rect, new_screen_info);
+}
+
+void WebFrameWidgetImpl::UpdateScreenInfo(const ScreenInfo& new_screen_info) {
+ widget_base_->UpdateScreenInfo(new_screen_info);
+}
+
+void WebFrameWidgetImpl::UpdateSurfaceAndCompositorRect(
+ const viz::LocalSurfaceId& new_local_surface_id,
+ const gfx::Rect& compositor_viewport_pixel_rect) {
+ widget_base_->UpdateSurfaceAndCompositorRect(new_local_surface_id,
+ compositor_viewport_pixel_rect);
+}
+
+void WebFrameWidgetImpl::UpdateCompositorViewportRect(
+ const gfx::Rect& compositor_viewport_pixel_rect) {
+ widget_base_->UpdateCompositorViewportRect(compositor_viewport_pixel_rect);
+}
+
+const ScreenInfo& WebFrameWidgetImpl::GetScreenInfo() {
+ return widget_base_->GetScreenInfo();
+}
+
+gfx::Rect WebFrameWidgetImpl::WindowRect() {
+ return widget_base_->WindowRect();
+}
+
+gfx::Rect WebFrameWidgetImpl::ViewRect() {
+ return widget_base_->ViewRect();
+}
+
+void WebFrameWidgetImpl::SetScreenRects(const gfx::Rect& widget_screen_rect,
+ const gfx::Rect& window_screen_rect) {
+ widget_base_->SetScreenRects(widget_screen_rect, window_screen_rect);
+}
+
+gfx::Size WebFrameWidgetImpl::VisibleViewportSizeInDIPs() {
+ return widget_base_->VisibleViewportSizeInDIPs();
+}
+
+void WebFrameWidgetImpl::SetPendingWindowRect(
+ const gfx::Rect& window_screen_rect) {
+ widget_base_->SetPendingWindowRect(window_screen_rect);
+}
+
+void WebFrameWidgetImpl::AckPendingWindowRect() {
+ widget_base_->AckPendingWindowRect();
+}
+
+bool WebFrameWidgetImpl::IsHidden() const {
+ return widget_base_->is_hidden();
+}
+
+WebString WebFrameWidgetImpl::GetLastToolTipTextForTesting() const {
+ return GetPage()->GetChromeClient().GetLastToolTipTextForTesting();
+}
+
+float WebFrameWidgetImpl::GetEmulatorScale() {
+ if (device_emulator_)
+ return device_emulator_->scale();
+ return 1.0f;
+}
+
+void WebFrameWidgetImpl::IntrinsicSizingInfoChanged(
+ mojom::blink::IntrinsicSizingInfoPtr sizing_info) {
+ DCHECK(ForSubframe());
+ GetAssociatedFrameWidgetHost()->IntrinsicSizingInfoChanged(
+ std::move(sizing_info));
+}
+
+void WebFrameWidgetImpl::AutoscrollStart(const gfx::PointF& position) {
+ GetAssociatedFrameWidgetHost()->AutoscrollStart(std::move(position));
+}
+
+void WebFrameWidgetImpl::AutoscrollFling(const gfx::Vector2dF& velocity) {
+ GetAssociatedFrameWidgetHost()->AutoscrollFling(std::move(velocity));
+}
+
+void WebFrameWidgetImpl::AutoscrollEnd() {
+ GetAssociatedFrameWidgetHost()->AutoscrollEnd();
+}
+
+void WebFrameWidgetImpl::DidMeaningfulLayout(WebMeaningfulLayout layout_type) {
+ if (layout_type == blink::WebMeaningfulLayout::kVisuallyNonEmpty) {
+ NotifySwapAndPresentationTime(
+ base::NullCallback(),
+ WTF::Bind(&WebFrameWidgetImpl::PresentationCallbackForMeaningfulLayout,
+ WrapPersistent(this)));
+ }
+
+ ForEachLocalFrameControlledByWidget(
+ local_root_->GetFrame(),
+ WTF::BindRepeating(
+ [](WebMeaningfulLayout layout_type, WebLocalFrameImpl* local_frame) {
+ local_frame->Client()->DidMeaningfulLayout(layout_type);
+ },
+ layout_type));
+}
+
+void WebFrameWidgetImpl::PresentationCallbackForMeaningfulLayout(
+ blink::WebSwapResult,
+ base::TimeTicks) {
+ GetAssociatedFrameWidgetHost()->DidFirstVisuallyNonEmptyPaint();
+}
+
+void WebFrameWidgetImpl::RequestAnimationAfterDelay(
+ const base::TimeDelta& delay) {
+ widget_base_->RequestAnimationAfterDelay(delay);
+}
+
+void WebFrameWidgetImpl::SetRootLayer(scoped_refptr<cc::Layer> layer) {
+ if (!View()->does_composite()) {
+ DCHECK(ForMainFrame());
+ DCHECK(!layer);
+ return;
+ }
+
+ // Set up some initial state before we are setting the layer.
+ if (ForSubframe() && layer) {
+ // Child local roots will always have a transparent background color.
+ widget_base_->LayerTreeHost()->set_background_color(SK_ColorTRANSPARENT);
+ // Pass the limits even though this is for subframes, as the limits will
+ // be needed in setting the raster scale.
+ SetPageScaleStateAndLimits(1.f, false /* is_pinch_gesture_active */,
+ View()->MinimumPageScaleFactor(),
+ View()->MaximumPageScaleFactor());
+ }
+
+ bool root_layer_exists = !!layer;
+ widget_base_->LayerTreeHost()->SetRootLayer(std::move(layer));
+
+ // Notify the WebView that we did set a layer.
+ if (ForMainFrame()) {
+ View()->DidChangeRootLayer(root_layer_exists);
+ }
+}
+
+base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
+WebFrameWidgetImpl::EnsureCompositorMutatorDispatcher(
+ scoped_refptr<base::SingleThreadTaskRunner> mutator_task_runner) {
+ if (!mutator_task_runner_) {
+ mutator_task_runner_ = std::move(mutator_task_runner);
+ widget_base_->LayerTreeHost()->SetLayerTreeMutator(
+ AnimationWorkletMutatorDispatcherImpl::CreateCompositorThreadClient(
+ mutator_dispatcher_, mutator_task_runner_));
+ }
+
+ DCHECK(mutator_task_runner_);
+ return mutator_dispatcher_;
+}
+
+HitTestResult WebFrameWidgetImpl::CoreHitTestResultAt(
+ const gfx::PointF& point_in_viewport) {
+ LocalFrameView* view = LocalRootImpl()->GetFrameView();
+ FloatPoint point_in_root_frame(
+ view->ViewportToFrame(FloatPoint(point_in_viewport)));
+ return HitTestResultForRootFramePos(point_in_root_frame);
+}
+
+cc::AnimationHost* WebFrameWidgetImpl::AnimationHost() const {
+ return widget_base_->AnimationHost();
+}
+
+base::WeakPtr<PaintWorkletPaintDispatcher>
+WebFrameWidgetImpl::EnsureCompositorPaintDispatcher(
+ scoped_refptr<base::SingleThreadTaskRunner>* paint_task_runner) {
+ // We check paint_task_runner_ not paint_dispatcher_ because the dispatcher is
+ // a base::WeakPtr that should only be used on the compositor thread.
+ if (!paint_task_runner_) {
+ widget_base_->LayerTreeHost()->SetPaintWorkletLayerPainter(
+ PaintWorkletPaintDispatcher::CreateCompositorThreadPainter(
+ &paint_dispatcher_));
+ paint_task_runner_ = Thread::CompositorThread()->GetTaskRunner();
+ }
+ DCHECK(paint_task_runner_);
+ *paint_task_runner = paint_task_runner_;
+ return paint_dispatcher_;
+}
+
+void WebFrameWidgetImpl::SetDelegatedInkMetadata(
+ std::unique_ptr<viz::DelegatedInkMetadata> metadata) {
+ widget_base_->LayerTreeHost()->SetDelegatedInkMetadata(std::move(metadata));
+}
+
+// Enables measuring and reporting both presentation times and swap times in
+// swap promises.
+class ReportTimeSwapPromise : public cc::SwapPromise {
+ public:
+ ReportTimeSwapPromise(WebReportTimeCallback swap_time_callback,
+ WebReportTimeCallback presentation_time_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ WebFrameWidgetImpl* widget)
+ : swap_time_callback_(std::move(swap_time_callback)),
+ presentation_time_callback_(std::move(presentation_time_callback)),
+ task_runner_(std::move(task_runner)),
+ widget_(widget) {}
+ ~ReportTimeSwapPromise() override = default;
+
+ void DidActivate() override {}
+
+ void WillSwap(viz::CompositorFrameMetadata* metadata) override {
+ DCHECK_GT(metadata->frame_token, 0u);
+ // The interval between the current swap and its presentation time is
+ // reported in UMA (see corresponding code in DidSwap() below).
+ frame_token_ = metadata->frame_token;
+ }
+
+ void DidSwap() override {
+ DCHECK_GT(frame_token_, 0u);
+ PostCrossThreadTask(
+ *task_runner_, FROM_HERE,
+ CrossThreadBindOnce(
+ &RunCallbackAfterSwap, widget_, base::TimeTicks::Now(),
+ std::move(swap_time_callback_),
+ std::move(presentation_time_callback_), frame_token_));
+ }
+
+ cc::SwapPromise::DidNotSwapAction DidNotSwap(
+ DidNotSwapReason reason) override {
+ WebSwapResult result;
+ switch (reason) {
+ case cc::SwapPromise::DidNotSwapReason::SWAP_FAILS:
+ result = WebSwapResult::kDidNotSwapSwapFails;
+ break;
+ case cc::SwapPromise::DidNotSwapReason::COMMIT_FAILS:
+ result = WebSwapResult::kDidNotSwapCommitFails;
+ break;
+ case cc::SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE:
+ result = WebSwapResult::kDidNotSwapCommitNoUpdate;
+ break;
+ case cc::SwapPromise::DidNotSwapReason::ACTIVATION_FAILS:
+ result = WebSwapResult::kDidNotSwapActivationFails;
+ break;
}
- ime_accept_events_ = true;
- } else {
- LocalFrame* focused_frame = FocusedLocalFrameInWidget();
- if (focused_frame) {
- // Finish an ongoing composition to delete the composition node.
- if (focused_frame->GetInputMethodController().HasComposition()) {
- // TODO(editing-dev): The use of
- // UpdateStyleAndLayout needs to be audited.
- // See http://crbug.com/590369 for more details.
- focused_frame->GetDocument()->UpdateStyleAndLayout(
- DocumentUpdateReason::kFocus);
-
- focused_frame->GetInputMethodController().FinishComposingText(
- InputMethodController::kKeepSelection);
- }
- ime_accept_events_ = false;
+ // During a failed swap, return the current time regardless of whether we're
+ // using presentation or swap timestamps.
+ PostCrossThreadTask(
+ *task_runner_, FROM_HERE,
+ CrossThreadBindOnce(
+ [](WebSwapResult result, base::TimeTicks swap_time,
+ WebReportTimeCallback swap_time_callback,
+ WebReportTimeCallback presentation_time_callback) {
+ ReportTime(std::move(swap_time_callback), result, swap_time);
+ ReportTime(std::move(presentation_time_callback), result,
+ swap_time);
+ },
+ result, base::TimeTicks::Now(), std::move(swap_time_callback_),
+ std::move(presentation_time_callback_)));
+ return DidNotSwapAction::BREAK_PROMISE;
+ }
+
+ int64_t TraceId() const override { return 0; }
+
+ private:
+ static void RunCallbackAfterSwap(
+ WebFrameWidgetImpl* widget,
+ base::TimeTicks swap_time,
+ WebReportTimeCallback swap_time_callback,
+ WebReportTimeCallback presentation_time_callback,
+ int frame_token) {
+ // If the widget was collected or the widget wasn't collected yet, but
+ // it was closed don't schedule a presentation callback.
+ if (widget && widget->widget_base_) {
+ widget->widget_base_->AddPresentationCallback(
+ frame_token,
+ WTF::Bind(&RunCallbackAfterPresentation,
+ std::move(presentation_time_callback), swap_time));
+ ReportTime(std::move(swap_time_callback), WebSwapResult::kDidSwap,
+ swap_time);
+ } else {
+ ReportTime(std::move(swap_time_callback), WebSwapResult::kDidSwap,
+ swap_time);
+ ReportTime(std::move(presentation_time_callback), WebSwapResult::kDidSwap,
+ swap_time);
}
}
+
+ static void RunCallbackAfterPresentation(
+ WebReportTimeCallback presentation_time_callback,
+ base::TimeTicks swap_time,
+ base::TimeTicks presentation_time) {
+ DCHECK(!swap_time.is_null());
+ bool presentation_time_is_valid =
+ !presentation_time.is_null() && (presentation_time > swap_time);
+ UMA_HISTOGRAM_BOOLEAN("PageLoad.Internal.Renderer.PresentationTime.Valid",
+ presentation_time_is_valid);
+ if (presentation_time_is_valid) {
+ // This measures from 1ms to 10seconds.
+ UMA_HISTOGRAM_TIMES(
+ "PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime",
+ presentation_time - swap_time);
+ }
+ ReportTime(std::move(presentation_time_callback), WebSwapResult::kDidSwap,
+ presentation_time_is_valid ? presentation_time : swap_time);
+ }
+
+ static void ReportTime(WebReportTimeCallback callback,
+ WebSwapResult result,
+ base::TimeTicks time) {
+ if (callback)
+ std::move(callback).Run(result, time);
+ }
+
+ WebReportTimeCallback swap_time_callback_;
+ WebReportTimeCallback presentation_time_callback_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ CrossThreadWeakPersistent<WebFrameWidgetImpl> widget_;
+ uint32_t frame_token_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(ReportTimeSwapPromise);
+};
+
+void WebFrameWidgetImpl::NotifyPresentationTimeInBlink(
+ WebReportTimeCallback presentation_time_callback) {
+ NotifySwapAndPresentationTime(base::NullCallback(),
+ std::move(presentation_time_callback));
}
-void WebFrameWidgetImpl::EnableDeviceEmulation(
- const DeviceEmulationParams& parameters) {
- // This message should only be sent to the top level FrameWidget.
- NOTREACHED();
+void WebFrameWidgetImpl::NotifySwapAndPresentationTime(
+ WebReportTimeCallback swap_time_callback,
+ WebReportTimeCallback presentation_time_callback) {
+ if (!View()->does_composite())
+ return;
+ widget_base_->LayerTreeHost()->QueueSwapPromise(
+ std::make_unique<ReportTimeSwapPromise>(
+ std::move(swap_time_callback), std::move(presentation_time_callback),
+ widget_base_->LayerTreeHost()
+ ->GetTaskRunnerProvider()
+ ->MainThreadTaskRunner(),
+ this));
}
-void WebFrameWidgetImpl::DisableDeviceEmulation() {
- // This message should only be sent to the top level FrameWidget.
- NOTREACHED();
+scheduler::WebRenderWidgetSchedulingState*
+WebFrameWidgetImpl::RendererWidgetSchedulingState() {
+ return widget_base_->RendererWidgetSchedulingState();
+}
+
+void WebFrameWidgetImpl::WaitForDebuggerWhenShown() {
+ local_root_->WaitForDebuggerWhenShown();
+}
+
+void WebFrameWidgetImpl::SetTextZoomFactor(float text_zoom_factor) {
+ local_root_->GetFrame()->SetTextZoomFactor(text_zoom_factor);
+}
+
+float WebFrameWidgetImpl::TextZoomFactor() {
+ return local_root_->GetFrame()->TextZoomFactor();
+}
+
+void WebFrameWidgetImpl::SetMainFrameOverlayColor(SkColor color) {
+ DCHECK(!local_root_->Parent());
+ local_root_->GetFrame()->SetMainFrameColorOverlay(color);
+}
+
+void WebFrameWidgetImpl::AddEditCommandForNextKeyEvent(const WebString& name,
+ const WebString& value) {
+ edit_commands_.push_back(mojom::blink::EditCommand::New(name, value));
+}
+
+bool WebFrameWidgetImpl::HandleCurrentKeyboardEvent() {
+ bool did_execute_command = false;
+ WebLocalFrame* frame = FocusedWebLocalFrameInWidget();
+ if (!frame)
+ frame = local_root_;
+ for (const auto& command : edit_commands_) {
+ // In gtk and cocoa, it's possible to bind multiple edit commands to one
+ // key (but it's the exception). Once one edit command is not executed, it
+ // seems safest to not execute the rest.
+ if (!frame->ExecuteCommand(command->name, command->value))
+ break;
+ did_execute_command = true;
+ }
+
+ return did_execute_command;
+}
+
+void WebFrameWidgetImpl::ClearEditCommands() {
+ edit_commands_ = Vector<mojom::blink::EditCommandPtr>();
+}
+
+WebTextInputInfo WebFrameWidgetImpl::TextInputInfo() {
+ WebInputMethodController* controller = GetActiveWebInputMethodController();
+ if (!controller)
+ return WebTextInputInfo();
+ return controller->TextInputInfo();
+}
+
+ui::mojom::blink::VirtualKeyboardVisibilityRequest
+WebFrameWidgetImpl::GetLastVirtualKeyboardVisibilityRequest() {
+ WebInputMethodController* controller = GetActiveWebInputMethodController();
+ if (!controller)
+ return ui::mojom::blink::VirtualKeyboardVisibilityRequest::NONE;
+ return controller->GetLastVirtualKeyboardVisibilityRequest();
+}
+
+bool WebFrameWidgetImpl::ShouldSuppressKeyboardForFocusedElement() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return false;
+ return focused_frame->ShouldSuppressKeyboardForFocusedElement();
+}
+
+void WebFrameWidgetImpl::GetEditContextBoundsInWindow(
+ base::Optional<gfx::Rect>* edit_context_control_bounds,
+ base::Optional<gfx::Rect>* edit_context_selection_bounds) {
+ WebInputMethodController* controller = GetActiveWebInputMethodController();
+ if (!controller)
+ return;
+ gfx::Rect control_bounds;
+ gfx::Rect selection_bounds;
+ controller->GetLayoutBounds(&control_bounds, &selection_bounds);
+ *edit_context_control_bounds =
+ widget_base_->BlinkSpaceToEnclosedDIPs(control_bounds);
+ if (controller->IsEditContextActive()) {
+ *edit_context_selection_bounds =
+ widget_base_->BlinkSpaceToEnclosedDIPs(selection_bounds);
+ }
+}
+
+int32_t WebFrameWidgetImpl::ComputeWebTextInputNextPreviousFlags() {
+ WebInputMethodController* controller = GetActiveWebInputMethodController();
+ if (!controller)
+ return 0;
+ return controller->ComputeWebTextInputNextPreviousFlags();
+}
+
+void WebFrameWidgetImpl::ResetVirtualKeyboardVisibilityRequest() {
+ WebInputMethodController* controller = GetActiveWebInputMethodController();
+ if (!controller)
+ return;
+ controller->SetVirtualKeyboardVisibilityRequest(
+ ui::mojom::blink::VirtualKeyboardVisibilityRequest::NONE);
+ ;
+}
+
+bool WebFrameWidgetImpl::GetSelectionBoundsInWindow(
+ gfx::Rect* focus,
+ gfx::Rect* anchor,
+ base::i18n::TextDirection* focus_dir,
+ base::i18n::TextDirection* anchor_dir,
+ bool* is_anchor_first) {
+ if (ShouldDispatchImeEventsToPlugin()) {
+ // TODO(kinaba) http://crbug.com/101101
+ // Current Pepper IME API does not handle selection bounds. So we simply
+ // use the caret position as an empty range for now. It will be updated
+ // after Pepper API equips features related to surrounding text retrieval.
+ gfx::Rect pepper_caret_in_dips = widget_base_->BlinkSpaceToEnclosedDIPs(
+ GetFocusedPluginContainer()->GetPluginCaretBounds());
+ if (pepper_caret_in_dips == *focus && pepper_caret_in_dips == *anchor)
+ return false;
+ *focus = pepper_caret_in_dips;
+ *anchor = *focus;
+ return true;
+ }
+ gfx::Rect focus_root_frame;
+ gfx::Rect anchor_root_frame;
+ CalculateSelectionBounds(focus_root_frame, anchor_root_frame);
+ gfx::Rect focus_rect_in_dips =
+ widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(focus_root_frame));
+ gfx::Rect anchor_rect_in_dips =
+ widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(anchor_root_frame));
+
+ // if the bounds are the same return false.
+ if (focus_rect_in_dips == *focus && anchor_rect_in_dips == *anchor)
+ return false;
+ *focus = focus_rect_in_dips;
+ *anchor = anchor_rect_in_dips;
+
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return true;
+ focused_frame->SelectionTextDirection(*focus_dir, *anchor_dir);
+ *is_anchor_first = focused_frame->IsSelectionAnchorFirst();
+ return true;
+}
+
+void WebFrameWidgetImpl::ClearTextInputState() {
+ widget_base_->ClearTextInputState();
+}
+
+bool WebFrameWidgetImpl::IsPasting() {
+ return widget_base_->is_pasting();
+}
+
+bool WebFrameWidgetImpl::HandlingSelectRange() {
+ return widget_base_->handling_select_range();
+}
+
+void WebFrameWidgetImpl::SetFocus(bool focus) {
+ widget_base_->SetFocus(focus);
+}
+
+bool WebFrameWidgetImpl::HasFocus() {
+ return widget_base_->has_focus();
+}
+
+void WebFrameWidgetImpl::SetToolTipText(const String& tooltip_text,
+ TextDirection dir) {
+ widget_base_->SetToolTipText(tooltip_text, dir);
+}
+
+void WebFrameWidgetImpl::DidOverscroll(
+ const gfx::Vector2dF& overscroll_delta,
+ const gfx::Vector2dF& accumulated_overscroll,
+ const gfx::PointF& position,
+ const gfx::Vector2dF& velocity) {
+#if defined(OS_MAC)
+ // On OSX the user can disable the elastic overscroll effect. If that's the
+ // case, don't forward the overscroll notification.
+ if (!widget_base_->LayerTreeHost()->GetSettings().enable_elastic_overscroll)
+ return;
+#endif
+
+ cc::OverscrollBehavior overscroll_behavior =
+ widget_base_->LayerTreeHost()->overscroll_behavior();
+ if (!widget_base_->input_handler().DidOverscrollFromBlink(
+ overscroll_delta, accumulated_overscroll, position, velocity,
+ overscroll_behavior))
+ return;
+
+ // If we're currently handling an event, stash the overscroll data such that
+ // it can be bundled in the event ack.
+ if (mojom::blink::WidgetInputHandlerHost* host =
+ widget_base_->widget_input_handler_manager()
+ ->GetWidgetInputHandlerHost()) {
+ host->DidOverscroll(mojom::blink::DidOverscrollParams::New(
+ accumulated_overscroll, overscroll_delta, velocity, position,
+ overscroll_behavior));
+ }
+}
+
+void WebFrameWidgetImpl::InjectGestureScrollEvent(
+ blink::WebGestureDevice device,
+ const gfx::Vector2dF& delta,
+ ui::ScrollGranularity granularity,
+ cc::ElementId scrollable_area_element_id,
+ blink::WebInputEvent::Type injected_type) {
+ if (RuntimeEnabledFeatures::ScrollUnificationEnabled()) {
+ // create a GestureScroll Event and post it to the compositor thread
+ // TODO(crbug.com/1126098) use original input event's timestamp.
+ // TODO(crbug.com/1082590) ensure continuity in scroll metrics collection
+ base::TimeTicks now = base::TimeTicks::Now();
+ std::unique_ptr<WebGestureEvent> gesture_event =
+ WebGestureEvent::GenerateInjectedScrollGesture(
+ injected_type, now, device, gfx::PointF(0, 0), delta, granularity);
+ if (injected_type == WebInputEvent::Type::kGestureScrollBegin) {
+ gesture_event->data.scroll_begin.scrollable_area_element_id =
+ scrollable_area_element_id.GetStableId();
+ gesture_event->data.scroll_begin.main_thread_hit_tested = true;
+ }
+
+ widget_base_->widget_input_handler_manager()
+ ->DispatchScrollGestureToCompositor(std::move(gesture_event));
+ } else {
+ widget_base_->input_handler().InjectGestureScrollEvent(
+ device, delta, granularity, scrollable_area_element_id, injected_type);
+ }
+}
+
+void WebFrameWidgetImpl::DidChangeCursor(const ui::Cursor& cursor) {
+ widget_base_->SetCursor(cursor);
+}
+
+bool WebFrameWidgetImpl::SetComposition(
+ const String& text,
+ const Vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& replacement_range,
+ int selection_start,
+ int selection_end) {
+ WebInputMethodController* controller = GetActiveWebInputMethodController();
+ if (!controller)
+ return false;
+
+ return controller->SetComposition(
+ text, ime_text_spans,
+ replacement_range.IsValid()
+ ? WebRange(replacement_range.start(), replacement_range.length())
+ : WebRange(),
+ selection_start, selection_end);
+}
+
+void WebFrameWidgetImpl::CommitText(
+ const String& text,
+ const Vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& replacement_range,
+ int relative_cursor_pos) {
+ WebInputMethodController* controller = GetActiveWebInputMethodController();
+ if (!controller)
+ return;
+ controller->CommitText(
+ text, ime_text_spans,
+ replacement_range.IsValid()
+ ? WebRange(replacement_range.start(), replacement_range.length())
+ : WebRange(),
+ relative_cursor_pos);
+}
+
+void WebFrameWidgetImpl::FinishComposingText(bool keep_selection) {
+ WebInputMethodController* controller = GetActiveWebInputMethodController();
+ if (!controller)
+ return;
+ controller->FinishComposingText(
+ keep_selection ? WebInputMethodController::kKeepSelection
+ : WebInputMethodController::kDoNotKeepSelection);
+}
+
+bool WebFrameWidgetImpl::IsProvisional() {
+ return LocalRoot()->IsProvisional();
+}
+
+uint64_t WebFrameWidgetImpl::GetScrollableContainerIdAt(
+ const gfx::PointF& point_in_dips) {
+ gfx::PointF point = widget_base_->DIPsToBlinkSpace(point_in_dips);
+ return HitTestResultAt(point).GetScrollableContainerId();
+}
+
+bool WebFrameWidgetImpl::ShouldHandleImeEvents() {
+ if (ForMainFrame()) {
+ return HasFocus();
+ } else {
+ // TODO(ekaramad): main frame widget returns true only if it has focus.
+ // We track page focus in all WebViews on the page but the WebFrameWidgets
+ // corresponding to child local roots do not get the update. For now, this
+ // method returns true when the WebFrameWidget is for a child local frame,
+ // i.e., IME events will be processed regardless of page focus. We should
+ // revisit this after page focus for OOPIFs has been fully resolved
+ // (https://crbug.com/689777).
+ return LocalRootImpl();
+ }
+}
+
+void WebFrameWidgetImpl::SetEditCommandsForNextKeyEvent(
+ Vector<mojom::blink::EditCommandPtr> edit_commands) {
+ edit_commands_ = std::move(edit_commands);
+}
+
+void WebFrameWidgetImpl::FocusChangeComplete() {
+ blink::WebLocalFrame* focused = LocalRoot()->View()->FocusedFrame();
+
+ if (focused && focused->AutofillClient())
+ focused->AutofillClient()->DidCompleteFocusChangeInFrame();
+}
+
+void WebFrameWidgetImpl::ShowVirtualKeyboardOnElementFocus() {
+ widget_base_->ShowVirtualKeyboardOnElementFocus();
+}
+
+void WebFrameWidgetImpl::ProcessTouchAction(WebTouchAction touch_action) {
+ widget_base_->ProcessTouchAction(touch_action);
+}
+
+void WebFrameWidgetImpl::DidHandleGestureEvent(const WebGestureEvent& event) {
+#if defined(OS_ANDROID) || defined(USE_AURA)
+ if (event.GetType() == WebInputEvent::Type::kGestureTap) {
+ widget_base_->ShowVirtualKeyboard();
+ } else if (event.GetType() == WebInputEvent::Type::kGestureLongPress) {
+ WebInputMethodController* controller = GetActiveWebInputMethodController();
+ if (!controller || controller->TextInputInfo().value.IsEmpty())
+ widget_base_->UpdateTextInputState();
+ else
+ widget_base_->ShowVirtualKeyboard();
+ }
+#endif
+}
+
+void WebFrameWidgetImpl::SetHasPointerRawUpdateEventHandlers(
+ bool has_handlers) {
+ widget_base_->widget_input_handler_manager()
+ ->input_event_queue()
+ ->HasPointerRawUpdateEventHandlers(has_handlers);
+}
+
+void WebFrameWidgetImpl::SetNeedsLowLatencyInput(bool needs_low_latency) {
+ widget_base_->widget_input_handler_manager()
+ ->input_event_queue()
+ ->SetNeedsLowLatency(needs_low_latency);
+}
+
+void WebFrameWidgetImpl::RequestUnbufferedInputEvents() {
+ widget_base_->widget_input_handler_manager()
+ ->input_event_queue()
+ ->RequestUnbufferedInputEvents();
+}
+
+void WebFrameWidgetImpl::SetNeedsUnbufferedInputForDebugger(bool unbuffered) {
+ widget_base_->widget_input_handler_manager()
+ ->input_event_queue()
+ ->SetNeedsUnbufferedInputForDebugger(unbuffered);
+}
+
+void WebFrameWidgetImpl::DidNavigate() {
+ // The input handler wants to know about navigation so that it can
+ // suppress input until the newly navigated page has a committed frame.
+ // It also resets the state for UMA reporting of input arrival with respect
+ // to document lifecycle.
+ if (!widget_base_->widget_input_handler_manager())
+ return;
+ widget_base_->widget_input_handler_manager()->DidNavigate();
+}
+
+void WebFrameWidgetImpl::SetMouseCapture(bool capture) {
+ if (mojom::blink::WidgetInputHandlerHost* host =
+ widget_base_->widget_input_handler_manager()
+ ->GetWidgetInputHandlerHost()) {
+ host->SetMouseCapture(capture);
+ }
+}
+
+gfx::Range WebFrameWidgetImpl::CompositionRange() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame || ShouldDispatchImeEventsToPlugin())
+ return gfx::Range::InvalidRange();
+
+ blink::WebInputMethodController* controller =
+ focused_frame->GetInputMethodController();
+ WebRange web_range = controller->CompositionRange();
+ if (web_range.IsNull())
+ return gfx::Range::InvalidRange();
+ return gfx::Range(web_range.StartOffset(), web_range.EndOffset());
+}
+
+void WebFrameWidgetImpl::GetCompositionCharacterBoundsInWindow(
+ Vector<gfx::Rect>* bounds_in_dips) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame || ShouldDispatchImeEventsToPlugin())
+ return;
+ blink::WebInputMethodController* controller =
+ focused_frame->GetInputMethodController();
+ blink::WebVector<gfx::Rect> bounds_from_blink;
+ if (!controller->GetCompositionCharacterBounds(bounds_from_blink))
+ return;
+
+ for (auto& rect : bounds_from_blink) {
+ bounds_in_dips->push_back(widget_base_->BlinkSpaceToEnclosedDIPs(rect));
+ }
+}
+
+void WebFrameWidgetImpl::AddImeTextSpansToExistingText(
+ uint32_t start,
+ uint32_t end,
+ const Vector<ui::ImeTextSpan>& ime_text_spans) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->AddImeTextSpansToExistingText(ime_text_spans, start, end);
+}
+
+Vector<ui::mojom::blink::ImeTextSpanInfoPtr>
+WebFrameWidgetImpl::GetImeTextSpansInfo(
+ const WebVector<ui::ImeTextSpan>& ime_text_spans) {
+ auto* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return Vector<ui::mojom::blink::ImeTextSpanInfoPtr>();
+
+ Vector<ui::mojom::blink::ImeTextSpanInfoPtr> ime_text_spans_info;
+
+ for (const auto& ime_text_span : ime_text_spans) {
+ gfx::Rect rect;
+ unsigned length = ime_text_span.end_offset - ime_text_span.start_offset;
+ focused_frame->FirstRectForCharacterRange(ime_text_span.start_offset,
+ length, rect);
+
+ ime_text_spans_info.push_back(ui::mojom::blink::ImeTextSpanInfo::New(
+ ime_text_span, widget_base_->BlinkSpaceToEnclosedDIPs(rect)));
+ }
+ return ime_text_spans_info;
+}
+
+void WebFrameWidgetImpl::ClearImeTextSpansByType(uint32_t start,
+ uint32_t end,
+ ui::ImeTextSpan::Type type) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ClearImeTextSpansByType(type, start, end);
+}
+
+void WebFrameWidgetImpl::SetCompositionFromExistingText(
+ int32_t start,
+ int32_t end,
+ const Vector<ui::ImeTextSpan>& ime_text_spans) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->SetCompositionFromExistingText(start, end, ime_text_spans);
+}
+
+void WebFrameWidgetImpl::ExtendSelectionAndDelete(int32_t before,
+ int32_t after) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ExtendSelectionAndDelete(before, after);
+}
+
+void WebFrameWidgetImpl::DeleteSurroundingText(int32_t before, int32_t after) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->DeleteSurroundingText(before, after);
+}
+
+void WebFrameWidgetImpl::DeleteSurroundingTextInCodePoints(int32_t before,
+ int32_t after) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->DeleteSurroundingTextInCodePoints(before, after);
+}
+
+void WebFrameWidgetImpl::SetEditableSelectionOffsets(int32_t start,
+ int32_t end) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->SetEditableSelectionOffsets(start, end);
+}
+
+void WebFrameWidgetImpl::ExecuteEditCommand(const String& command,
+ const String& value) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ExecuteCommand(command, value);
+}
+
+void WebFrameWidgetImpl::Undo() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ExecuteCommand(WebString::FromLatin1("Undo"));
+}
+
+void WebFrameWidgetImpl::Redo() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ExecuteCommand(WebString::FromLatin1("Redo"));
+}
+
+void WebFrameWidgetImpl::Cut() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ExecuteCommand(WebString::FromLatin1("Cut"));
+}
+
+void WebFrameWidgetImpl::Copy() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ExecuteCommand(WebString::FromLatin1("Copy"));
+}
+
+void WebFrameWidgetImpl::CopyToFindPboard() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ To<WebLocalFrameImpl>(focused_frame)->CopyToFindPboard();
+}
+
+void WebFrameWidgetImpl::Paste() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ExecuteCommand(WebString::FromLatin1("Paste"));
+}
+
+void WebFrameWidgetImpl::PasteAndMatchStyle() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ExecuteCommand(WebString::FromLatin1("PasteAndMatchStyle"));
+}
+
+void WebFrameWidgetImpl::Delete() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ExecuteCommand(WebString::FromLatin1("Delete"));
+}
+
+void WebFrameWidgetImpl::SelectAll() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->ExecuteCommand(WebString::FromLatin1("SelectAll"));
+}
+
+void WebFrameWidgetImpl::CollapseSelection() {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ const blink::WebRange& range =
+ focused_frame->GetInputMethodController()->GetSelectionOffsets();
+ if (range.IsNull())
+ return;
+
+ focused_frame->SelectRange(blink::WebRange(range.EndOffset(), 0),
+ blink::WebLocalFrame::kHideSelectionHandle,
+ mojom::blink::SelectionMenuBehavior::kHide);
+}
+
+void WebFrameWidgetImpl::Replace(const String& word) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ if (!focused_frame->HasSelection())
+ focused_frame->SelectWordAroundCaret();
+ focused_frame->ReplaceSelection(word);
+ focused_frame->Client()->SyncSelectionIfRequired();
+}
+
+void WebFrameWidgetImpl::ReplaceMisspelling(const String& word) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ if (!focused_frame->HasSelection())
+ return;
+ focused_frame->ReplaceMisspelledRange(word);
+}
+
+void WebFrameWidgetImpl::SelectRange(const gfx::Point& base_in_dips,
+ const gfx::Point& extent_in_dips) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->SelectRange(
+ widget_base_->DIPsToRoundedBlinkSpace(base_in_dips),
+ widget_base_->DIPsToRoundedBlinkSpace(extent_in_dips));
+}
+
+void WebFrameWidgetImpl::AdjustSelectionByCharacterOffset(
+ int32_t start,
+ int32_t end,
+ mojom::blink::SelectionMenuBehavior selection_menu_behavior) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ blink::WebRange range =
+ focused_frame->GetInputMethodController()->GetSelectionOffsets();
+ if (range.IsNull())
+ return;
+
+ // Sanity checks to disallow empty and out of range selections.
+ if (start - end > range.length() || range.StartOffset() + start < 0)
+ return;
+
+ // A negative adjust amount moves the selection towards the beginning of
+ // the document, a positive amount moves the selection towards the end of
+ // the document.
+ focused_frame->SelectRange(blink::WebRange(range.StartOffset() + start,
+ range.length() + end - start),
+ blink::WebLocalFrame::kPreserveHandleVisibility,
+ selection_menu_behavior);
+}
+
+void WebFrameWidgetImpl::MoveRangeSelectionExtent(
+ const gfx::Point& extent_in_dips) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->MoveRangeSelectionExtent(
+ widget_base_->DIPsToRoundedBlinkSpace(extent_in_dips));
+}
+
+void WebFrameWidgetImpl::ScrollFocusedEditableNodeIntoRect(
+ const gfx::Rect& rect_in_dips) {
+ WebLocalFrameImpl* local_frame = FocusedWebLocalFrameInWidget();
+ if (!local_frame)
+ return;
+
+ // OnSynchronizeVisualProperties does not call DidChangeVisibleViewport
+ // on OOPIFs. Since we are starting a new scroll operation now, call
+ // DidChangeVisibleViewport to ensure that we don't assume the element
+ // is already in view and ignore the scroll.
+ local_frame->ResetHasScrolledFocusedEditableIntoView();
+ local_frame->ScrollFocusedEditableElementIntoRect(rect_in_dips);
+}
+
+void WebFrameWidgetImpl::ZoomToFindInPageRect(
+ const gfx::Rect& rect_in_root_frame) {
+ if (ForMainFrame()) {
+ View()->ZoomToFindInPageRect(rect_in_root_frame);
+ } else {
+ GetAssociatedFrameWidgetHost()->ZoomToFindInPageRectInMainFrame(
+ rect_in_root_frame);
+ }
+}
+
+void WebFrameWidgetImpl::MoveCaret(const gfx::Point& point_in_dips) {
+ WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame)
+ return;
+ focused_frame->MoveCaretSelection(
+ widget_base_->DIPsToRoundedBlinkSpace(point_in_dips));
+}
+
+#if defined(OS_ANDROID)
+void WebFrameWidgetImpl::SelectWordAroundCaret(
+ SelectWordAroundCaretCallback callback) {
+ auto* focused_frame = FocusedWebLocalFrameInWidget();
+ if (!focused_frame) {
+ std::move(callback).Run(false, 0, 0);
+ return;
+ }
+
+ bool did_select = false;
+ int start_adjust = 0;
+ int end_adjust = 0;
+ blink::WebRange initial_range = focused_frame->SelectionRange();
+ SetHandlingInputEvent(true);
+ if (!initial_range.IsNull())
+ did_select = focused_frame->SelectWordAroundCaret();
+ if (did_select) {
+ blink::WebRange adjusted_range = focused_frame->SelectionRange();
+ DCHECK(!adjusted_range.IsNull());
+ start_adjust = adjusted_range.StartOffset() - initial_range.StartOffset();
+ end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset();
+ }
+ SetHandlingInputEvent(false);
+ std::move(callback).Run(did_select, start_adjust, end_adjust);
+}
+#endif
+
+void WebFrameWidgetImpl::ForEachRemoteFrameControlledByWidget(
+ const base::RepeatingCallback<void(RemoteFrame*)>& callback) {
+ ForEachRemoteFrameChildrenControlledByWidget(local_root_->GetFrame(),
+ callback);
}
void WebFrameWidgetImpl::CalculateSelectionBounds(gfx::Rect& anchor_root_frame,
@@ -442,198 +3586,259 @@ void WebFrameWidgetImpl::CalculateSelectionBounds(gfx::Rect& anchor_root_frame,
if (!local_frame->Selection().ComputeAbsoluteBounds(anchor, focus))
return;
- // FIXME: This doesn't apply page scale. This should probably be contents to
- // viewport. crbug.com/459293.
- anchor_root_frame = local_frame->View()->ConvertToRootFrame(anchor);
- focus_root_frame = local_frame->View()->ConvertToRootFrame(focus);
+ // Apply the visual viewport for main frames this will apply the page scale.
+ // For subframes it will just be a 1:1 transformation and the browser
+ // will then apply later transformations to these rects.
+ VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
+ anchor_root_frame = visual_viewport.RootFrameToViewport(
+ local_frame->View()->ConvertToRootFrame(anchor));
+ focus_root_frame = visual_viewport.RootFrameToViewport(
+ local_frame->View()->ConvertToRootFrame(focus));
}
-void WebFrameWidgetImpl::SetRemoteViewportIntersection(
- const mojom::blink::ViewportIntersectionState& intersection_state) {
- SetViewportIntersection(intersection_state.Clone());
+void WebFrameWidgetImpl::BatterySavingsChanged(BatterySavingsFlags savings) {
+ widget_base_->LayerTreeHost()->SetEnableFrameRateThrottling(
+ savings & kAllowReducedFrameRate);
}
-void WebFrameWidgetImpl::SetViewportIntersection(
- mojom::blink::ViewportIntersectionStatePtr intersection_state) {
- // Remote viewports are only applicable to local frames with remote ancestors.
- DCHECK(LocalRootImpl()->Parent() &&
- LocalRootImpl()->Parent()->IsWebRemoteFrame() &&
- LocalRootImpl()->GetFrame());
-
- compositor_visible_rect_ =
- gfx::Rect(intersection_state->compositor_visible_rect);
- widget_base_->LayerTreeHost()->SetViewportVisibleRect(
- compositor_visible_rect_);
- LocalRootImpl()->GetFrame()->SetViewportIntersectionFromParent(
- *intersection_state);
+const viz::LocalSurfaceId& WebFrameWidgetImpl::LocalSurfaceIdFromParent() {
+ return widget_base_->local_surface_id_from_parent();
}
-void WebFrameWidgetImpl::SetIsInertForSubFrame(bool inert) {
- DCHECK(LocalRootImpl()->Parent());
- DCHECK(LocalRootImpl()->Parent()->IsWebRemoteFrame());
- LocalRootImpl()->GetFrame()->SetIsInert(inert);
+cc::LayerTreeHost* WebFrameWidgetImpl::LayerTreeHost() {
+ return widget_base_->LayerTreeHost();
}
-void WebFrameWidgetImpl::SetInheritedEffectiveTouchActionForSubFrame(
- TouchAction touch_action) {
- DCHECK(LocalRootImpl()->Parent());
- DCHECK(LocalRootImpl()->Parent()->IsWebRemoteFrame());
- LocalRootImpl()->GetFrame()->SetInheritedEffectiveTouchAction(touch_action);
+cc::LayerTreeHost* WebFrameWidgetImpl::LayerTreeHostForTesting() const {
+ return widget_base_->LayerTreeHost();
}
-void WebFrameWidgetImpl::UpdateRenderThrottlingStatusForSubFrame(
- bool is_throttled,
- bool subtree_throttled) {
- DCHECK(LocalRootImpl()->Parent());
- DCHECK(LocalRootImpl()->Parent()->IsWebRemoteFrame());
- LocalRootImpl()->GetFrameView()->UpdateRenderThrottlingStatus(
- is_throttled, subtree_throttled, true);
+ScreenMetricsEmulator* WebFrameWidgetImpl::DeviceEmulator() {
+ return device_emulator_;
}
-void WebFrameWidgetImpl::HandleMouseLeave(LocalFrame& main_frame,
- const WebMouseEvent& event) {
- // FIXME: WebWidget doesn't have the method below.
- // m_client->setMouseOverURL(WebURL());
- PageWidgetEventHandler::HandleMouseLeave(main_frame, event);
+bool WebFrameWidgetImpl::AutoResizeMode() {
+ return View()->AutoResizeMode();
}
-WebInputEventResult WebFrameWidgetImpl::HandleGestureEvent(
- const WebGestureEvent& event) {
- DCHECK(Client());
- WebInputEventResult event_result = WebInputEventResult::kNotHandled;
- bool event_cancelled = false;
- base::Optional<ContextMenuAllowedScope> maybe_context_menu_scope;
+void WebFrameWidgetImpl::SetScreenMetricsEmulationParameters(
+ bool enabled,
+ const DeviceEmulationParams& params) {
+ if (enabled)
+ View()->ActivateDevToolsTransform(params);
+ else
+ View()->DeactivateDevToolsTransform();
+}
- WebViewImpl* view_impl = View();
- switch (event.GetType()) {
- case WebInputEvent::Type::kGestureScrollBegin:
- case WebInputEvent::Type::kGestureScrollEnd:
- case WebInputEvent::Type::kGestureScrollUpdate:
- case WebInputEvent::Type::kGestureTap:
- case WebInputEvent::Type::kGestureTapUnconfirmed:
- case WebInputEvent::Type::kGestureTapDown:
- // Touch pinch zoom and scroll on the page (outside of a popup) must hide
- // the popup. In case of a touch scroll or pinch zoom, this function is
- // called with GestureTapDown rather than a GSB/GSU/GSE or GPB/GPU/GPE.
- // WebViewImpl takes additional steps to avoid the following GestureTap
- // from re-opening the popup being closed here, but since GestureTap will
- // unconditionally close the current popup here, it is not used/needed.
- // TODO(wjmaclean): We should maybe mirror what WebViewImpl does, the
- // HandleGestureEvent() needs to happen inside or before the GestureTap
- // case to do so.
- View()->CancelPagePopup();
- break;
- case WebInputEvent::Type::kGestureTapCancel:
- case WebInputEvent::Type::kGestureShowPress:
- break;
- case WebInputEvent::Type::kGestureDoubleTap:
- if (GetPage()->GetChromeClient().DoubleTapToZoomEnabled() &&
- view_impl->MinimumPageScaleFactor() !=
- view_impl->MaximumPageScaleFactor()) {
- LocalFrame* frame = LocalRootImpl()->GetFrame();
- WebGestureEvent scaled_event =
- TransformWebGestureEvent(frame->View(), event);
- IntPoint pos_in_local_frame_root =
- FlooredIntPoint(scaled_event.PositionInRootFrame());
- auto block_bounds =
- gfx::Rect(ComputeBlockBound(pos_in_local_frame_root, false));
+void WebFrameWidgetImpl::SetScreenInfoAndSize(
+ const ScreenInfo& screen_info,
+ const gfx::Size& widget_size_in_dips,
+ const gfx::Size& visible_viewport_size_in_dips) {
+ // Emulation happens on regular main frames which don't use auto-resize mode.
+ DCHECK(!AutoResizeMode());
- // This sends the tap point and bounds to the main frame renderer via
- // the browser, where their coordinates will be transformed into the
- // main frame's coordinate space.
- GetAssociatedFrameWidgetHost()->AnimateDoubleTapZoomInMainFrame(
- pos_in_local_frame_root, block_bounds);
- }
- event_result = WebInputEventResult::kHandledSystem;
- DidHandleGestureEvent(event, event_cancelled);
- return event_result;
- case WebInputEvent::Type::kGestureTwoFingerTap:
- case WebInputEvent::Type::kGestureLongPress:
- case WebInputEvent::Type::kGestureLongTap:
- GetPage()->GetContextMenuController().ClearContextMenu();
- maybe_context_menu_scope.emplace();
- break;
- default:
- NOTREACHED();
- }
- LocalFrame* frame = LocalRootImpl()->GetFrame();
- WebGestureEvent scaled_event = TransformWebGestureEvent(frame->View(), event);
- event_result = frame->GetEventHandler().HandleGestureEvent(scaled_event);
- DidHandleGestureEvent(event, event_cancelled);
- return event_result;
+ UpdateScreenInfo(screen_info);
+ widget_base_->SetVisibleViewportSizeInDIPs(visible_viewport_size_in_dips);
+ Resize(widget_base_->DIPsToCeiledBlinkSpace(widget_size_in_dips));
}
-LocalFrameView* WebFrameWidgetImpl::GetLocalFrameViewForAnimationScrolling() {
- return LocalRootImpl()->GetFrame()->View();
+float WebFrameWidgetImpl::GetCompositingScaleFactor() {
+ return compositing_scale_factor_;
}
-WebInputEventResult WebFrameWidgetImpl::HandleKeyEvent(
- const WebKeyboardEvent& event) {
- DCHECK((event.GetType() == WebInputEvent::Type::kRawKeyDown) ||
- (event.GetType() == WebInputEvent::Type::kKeyDown) ||
- (event.GetType() == WebInputEvent::Type::kKeyUp));
+const cc::LayerTreeDebugState& WebFrameWidgetImpl::GetLayerTreeDebugState() {
+ return widget_base_->LayerTreeHost()->GetDebugState();
+}
- // Please refer to the comments explaining the m_suppressNextKeypressEvent
- // member.
- // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
- // Webkit. A keyDown event is typically associated with a keyPress(char)
- // event and a keyUp event. We reset this flag here as this is a new keyDown
- // event.
- suppress_next_keypress_event_ = false;
+void WebFrameWidgetImpl::SetLayerTreeDebugState(
+ const cc::LayerTreeDebugState& state) {
+ widget_base_->LayerTreeHost()->SetDebugState(state);
+}
- // If there is a popup open, it should be the one processing the event,
- // not the page.
- scoped_refptr<WebPagePopupImpl> page_popup = View()->GetPagePopup();
- if (page_popup) {
- page_popup->HandleKeyEvent(event);
- if (event.GetType() == WebInputEvent::Type::kRawKeyDown) {
- suppress_next_keypress_event_ = true;
+void WebFrameWidgetImpl::NotifyCompositingScaleFactorChanged(
+ float compositing_scale_factor) {
+ compositing_scale_factor_ = compositing_scale_factor;
+
+ // Update the scale factor for remote frames which in turn depends on the
+ // compositing scale factor set in the widget.
+ ForEachRemoteFrameControlledByWidget(
+ WTF::BindRepeating([](RemoteFrame* remote_frame) {
+ if (remote_frame->View())
+ remote_frame->View()->UpdateCompositingScaleFactor();
+ }));
+}
+
+void WebFrameWidgetImpl::NotifyPageScaleFactorChanged(
+ float page_scale_factor,
+ bool is_pinch_gesture_active) {
+ // Store the value to give to any new RemoteFrame that will be created as a
+ // descendant of this widget.
+ page_scale_factor_in_mainframe_ = page_scale_factor;
+ is_pinch_gesture_active_in_mainframe_ = is_pinch_gesture_active;
+ // Push the page scale factor down to any child RemoteFrames.
+ // TODO(danakj): This ends up setting the page scale factor in the
+ // RenderWidgetHost of the child WebFrameWidgetImpl, so that it can bounce
+ // the value down to its WebFrameWidgetImpl. Since this is essentially a
+ // global value per-page, we could instead store it once in the browser
+ // (such as in RenderViewHost) and distribute it to each WebFrameWidgetImpl
+ // from there.
+ ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+ [](float page_scale_factor, bool is_pinch_gesture_active,
+ RemoteFrame* remote_frame) {
+ remote_frame->PageScaleFactorChanged(page_scale_factor,
+ is_pinch_gesture_active);
+ },
+ page_scale_factor, is_pinch_gesture_active));
+}
+
+void WebFrameWidgetImpl::SetPageScaleStateAndLimits(
+ float page_scale_factor,
+ bool is_pinch_gesture_active,
+ float minimum,
+ float maximum) {
+ widget_base_->LayerTreeHost()->SetPageScaleFactorAndLimits(page_scale_factor,
+ minimum, maximum);
+
+ // Only propagate page scale from the main frame.
+ if (ForMainFrame()) {
+ // If page scale hasn't changed, then just return without notifying
+ // the remote frames.
+ if (page_scale_factor == page_scale_factor_in_mainframe_ &&
+ is_pinch_gesture_active == is_pinch_gesture_active_in_mainframe_) {
+ return;
}
- return WebInputEventResult::kHandledSystem;
+
+ NotifyPageScaleFactorChanged(page_scale_factor, is_pinch_gesture_active);
}
+}
- auto* frame = DynamicTo<LocalFrame>(FocusedCoreFrame());
- if (!frame)
- return WebInputEventResult::kNotHandled;
+bool WebFrameWidgetImpl::UpdateScreenRects(
+ const gfx::Rect& widget_screen_rect,
+ const gfx::Rect& window_screen_rect) {
+ if (!device_emulator_)
+ return false;
+ device_emulator_->OnUpdateScreenRects(widget_screen_rect, window_screen_rect);
+ return true;
+}
- WebInputEventResult result = frame->GetEventHandler().KeyEvent(event);
- if (result != WebInputEventResult::kNotHandled) {
- if (WebInputEvent::Type::kRawKeyDown == event.GetType()) {
- // Suppress the next keypress event unless the focused node is a plugin
- // node. (Flash needs these keypress events to handle non-US keyboards.)
- Element* element = FocusedElement();
- if (!element || !element->GetLayoutObject() ||
- !element->GetLayoutObject()->IsEmbeddedObject())
- suppress_next_keypress_event_ = true;
- }
- return result;
+void WebFrameWidgetImpl::OrientationChanged() {
+ local_root_->SendOrientationChangeEvent();
+}
+
+void WebFrameWidgetImpl::DidUpdateSurfaceAndScreen(
+ const ScreenInfo& previous_original_screen_info) {
+ ScreenInfo screen_info = widget_base_->GetScreenInfo();
+ if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+ View()->SetZoomFactorForDeviceScaleFactor(screen_info.device_scale_factor);
+ } else {
+ View()->SetDeviceScaleFactor(screen_info.device_scale_factor);
}
-#if !defined(OS_MAC)
- const WebInputEvent::Type kContextMenuKeyTriggeringEventType =
-#if defined(OS_WIN)
- WebInputEvent::Type::kKeyUp;
-#else
- WebInputEvent::Type::kRawKeyDown;
-#endif
- const WebInputEvent::Type kShiftF10TriggeringEventType =
- WebInputEvent::Type::kRawKeyDown;
+ if (ShouldAutoDetermineCompositingToLCDTextSetting()) {
+ // This causes compositing state to be modified which dirties the
+ // document lifecycle. Android Webview relies on the document
+ // lifecycle being clean after the RenderWidget is initialized, in
+ // order to send IPCs that query and change compositing state. So
+ // WebFrameWidgetImpl::Resize() must come after this call, as it runs the
+ // entire document lifecycle.
+ View()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
+ widget_base_->ComputePreferCompositingToLCDText());
+ }
- bool is_unmodified_menu_key =
- !(event.GetModifiers() & WebInputEvent::kInputModifiers) &&
- event.windows_key_code == VKEY_APPS;
- bool is_shift_f10 = (event.GetModifiers() & WebInputEvent::kInputModifiers) ==
- WebInputEvent::kShiftKey &&
- event.windows_key_code == VKEY_F10;
- if ((is_unmodified_menu_key &&
- event.GetType() == kContextMenuKeyTriggeringEventType) ||
- (is_shift_f10 && event.GetType() == kShiftF10TriggeringEventType)) {
- View()->SendContextMenuEvent();
- return WebInputEventResult::kHandledSystem;
+ // When the device scale changes, the size and position of the popup would
+ // need to be adjusted, which we can't do. Just close the popup, which is
+ // also consistent with page zoom and resize behavior.
+ ScreenInfo original_screen_info = GetOriginalScreenInfo();
+ if (previous_original_screen_info.device_scale_factor !=
+ original_screen_info.device_scale_factor) {
+ View()->CancelPagePopup();
}
-#endif // !defined(OS_MAC)
- return WebInputEventResult::kNotHandled;
+ if (previous_original_screen_info != original_screen_info) {
+ local_root_->GetFrame()->DomWindow()->screen()->DispatchEvent(
+ *Event::Create(event_type_names::kChange));
+
+ // Propagate changes down to child local root RenderWidgets and
+ // BrowserPlugins in other frame trees/processes.
+ ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+ [](const ScreenInfo& original_screen_info, RemoteFrame* remote_frame) {
+ remote_frame->DidChangeScreenInfo(original_screen_info);
+ },
+ original_screen_info));
+ }
+}
+
+gfx::Rect WebFrameWidgetImpl::ViewportVisibleRect() {
+ if (ForMainFrame()) {
+ return widget_base_->CompositorViewportRect();
+ } else {
+ return child_data().compositor_visible_rect;
+ }
+}
+
+const ScreenInfo& WebFrameWidgetImpl::GetOriginalScreenInfo() {
+ if (device_emulator_)
+ return device_emulator_->original_screen_info();
+ return widget_base_->GetScreenInfo();
+}
+
+base::Optional<blink::mojom::ScreenOrientation>
+WebFrameWidgetImpl::ScreenOrientationOverride() {
+ return View()->ScreenOrientationOverride();
+}
+
+void WebFrameWidgetImpl::WasHidden() {
+ ForEachLocalFrameControlledByWidget(
+ local_root_->GetFrame(),
+ WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
+ local_frame->Client()->WasHidden();
+ }));
+}
+
+void WebFrameWidgetImpl::WasShown(bool was_evicted) {
+ ForEachLocalFrameControlledByWidget(
+ local_root_->GetFrame(),
+ WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
+ local_frame->Client()->WasShown();
+ }));
+ if (was_evicted) {
+ ForEachRemoteFrameControlledByWidget(
+ WTF::BindRepeating([](RemoteFrame* remote_frame) {
+ // On eviction, the last SurfaceId is invalidated. We need to
+ // allocate a new id.
+ remote_frame->ResendVisualProperties();
+ }));
+ }
+}
+
+void WebFrameWidgetImpl::RunPaintBenchmark(int repeat_count,
+ cc::PaintBenchmarkResult& result) {
+ if (!ForMainFrame())
+ return;
+ if (auto* frame_view = LocalRootImpl()->GetFrameView())
+ frame_view->RunPaintBenchmark(repeat_count, result);
+}
+
+void WebFrameWidgetImpl::NotifyInputObservers(
+ const WebCoalescedInputEvent& coalesced_event) {
+ LocalFrame* frame = FocusedLocalFrameInWidget();
+ if (!frame)
+ return;
+
+ LocalFrameView* frame_view = frame->View();
+ if (!frame_view)
+ return;
+
+ const WebInputEvent& input_event = coalesced_event.Event();
+ auto& paint_timing_detector = frame_view->GetPaintTimingDetector();
+
+ if (paint_timing_detector.NeedToNotifyInputOrScroll())
+ paint_timing_detector.NotifyInputEvent(input_event.GetType());
+}
+
+Frame* WebFrameWidgetImpl::FocusedCoreFrame() const {
+ return GetPage() ? GetPage()->GetFocusController().FocusedOrMainFrame()
+ : nullptr;
}
Element* WebFrameWidgetImpl::FocusedElement() const {
@@ -648,66 +3853,246 @@ Element* WebFrameWidgetImpl::FocusedElement() const {
return document->FocusedElement();
}
-PaintLayerCompositor* WebFrameWidgetImpl::Compositor() const {
- LocalFrame* frame = LocalRootImpl()->GetFrame();
- if (!frame || !frame->GetDocument() || !frame->GetDocument()->GetLayoutView())
- return nullptr;
+HitTestResult WebFrameWidgetImpl::HitTestResultForRootFramePos(
+ const FloatPoint& pos_in_root_frame) {
+ FloatPoint doc_point =
+ LocalRootImpl()->GetFrame()->View()->ConvertFromRootFrame(
+ pos_in_root_frame);
+ HitTestLocation location(doc_point);
+ HitTestResult result =
+ LocalRootImpl()->GetFrame()->View()->HitTestWithThrottlingAllowed(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ result.SetToShadowHostIfInRestrictedShadowRoot();
+ return result;
+}
- return frame->GetDocument()->GetLayoutView()->Compositor();
+bool WebFrameWidgetImpl::SynchronousResizeModeForTestingEnabled() {
+ return main_data().synchronous_resize_mode_for_testing;
}
-void WebFrameWidgetImpl::SetRootLayer(scoped_refptr<cc::Layer> layer) {
- if (!layer) {
- // This notifies the WebFrameWidgetImpl that its LocalFrame tree is being
- // detached.
+KURL WebFrameWidgetImpl::GetURLForDebugTrace() {
+ WebFrame* main_frame = View()->MainFrame();
+ if (main_frame->IsWebLocalFrame())
+ return main_frame->ToWebLocalFrame()->GetDocument().Url();
+ return {};
+}
+
+float WebFrameWidgetImpl::GetTestingDeviceScaleFactorOverride() {
+ return device_scale_factor_for_testing_;
+}
+
+void WebFrameWidgetImpl::ReleaseMouseLockAndPointerCaptureForTesting() {
+ GetPage()->GetPointerLockController().ExitPointerLock();
+ MouseCaptureLost();
+}
+
+const viz::FrameSinkId& WebFrameWidgetImpl::GetFrameSinkId() {
+ // It is valid to create a WebFrameWidget with an invalid frame sink id for
+ // printing and placeholders. But if we go to use it, it should be valid.
+ DCHECK(frame_sink_id_.is_valid());
+ return frame_sink_id_;
+}
+
+WebHitTestResult WebFrameWidgetImpl::HitTestResultAt(const gfx::PointF& point) {
+ return CoreHitTestResultAt(point);
+}
+
+void WebFrameWidgetImpl::SetZoomLevelForTesting(double zoom_level) {
+ DCHECK(ForMainFrame());
+ DCHECK_NE(zoom_level, -INFINITY);
+ zoom_level_for_testing_ = zoom_level;
+ SetZoomLevel(zoom_level);
+}
+
+void WebFrameWidgetImpl::ResetZoomLevelForTesting() {
+ DCHECK(ForMainFrame());
+ zoom_level_for_testing_ = -INFINITY;
+ SetZoomLevel(0);
+}
+
+void WebFrameWidgetImpl::SetDeviceScaleFactorForTesting(float factor) {
+ DCHECK(ForMainFrame());
+ DCHECK_GE(factor, 0.f);
+
+ // Stash the window size before we adjust the scale factor, as subsequent
+ // calls to convert will use the new scale factor.
+ gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(Size());
+ device_scale_factor_for_testing_ = factor;
+
+ // Receiving a 0 is used to reset between tests, it removes the override in
+ // order to listen to the browser for the next test.
+ if (!factor)
return;
+
+ // We are changing the device scale factor from the renderer, so allocate a
+ // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
+ widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
+
+ ScreenInfo info = widget_base_->GetScreenInfo();
+ info.device_scale_factor = factor;
+ gfx::Size size_with_dsf = gfx::ScaleToCeiledSize(size_in_dips, factor);
+ widget_base_->UpdateCompositorViewportAndScreenInfo(gfx::Rect(size_with_dsf),
+ info);
+ if (!AutoResizeMode()) {
+ // This picks up the new device scale factor as
+ // `UpdateCompositorViewportAndScreenInfo()` has applied a new value.
+ Resize(widget_base_->DIPsToCeiledBlinkSpace(size_in_dips));
}
+}
- // WebFrameWidgetImpl is used for child frames, which always have a
- // transparent background color.
- widget_base_->LayerTreeHost()->set_background_color(SK_ColorTRANSPARENT);
- // Pass the limits even though this is for subframes, as the limits will
- // be needed in setting the raster scale.
- SetPageScaleStateAndLimits(1.f, false /* is_pinch_gesture_active */,
- View()->MinimumPageScaleFactor(),
- View()->MaximumPageScaleFactor());
+FrameWidgetTestHelper*
+WebFrameWidgetImpl::GetFrameWidgetTestHelperForTesting() {
+ return nullptr;
+}
- widget_base_->LayerTreeHost()->SetRootLayer(layer);
+WebPlugin* WebFrameWidgetImpl::GetFocusedPluginContainer() {
+ LocalFrame* focused_frame = FocusedLocalFrameInWidget();
+ if (!focused_frame)
+ return nullptr;
+ if (auto* container = focused_frame->GetWebPluginContainer())
+ return container->Plugin();
+ return nullptr;
}
-void WebFrameWidgetImpl::ZoomToFindInPageRect(
- const WebRect& rect_in_root_frame) {
- GetAssociatedFrameWidgetHost()->ZoomToFindInPageRectInMainFrame(
- gfx::Rect(rect_in_root_frame));
+bool WebFrameWidgetImpl::HasPendingPageScaleAnimation() {
+ return LayerTreeHost()->HasPendingPageScaleAnimation();
}
-void WebFrameWidgetImpl::SetAutoResizeMode(bool auto_resize,
- const gfx::Size& min_size_before_dsf,
- const gfx::Size& max_size_before_dsf,
- float device_scale_factor) {
- // Auto resize mode only exists on the top level widget.
+void WebFrameWidgetImpl::SetSourceURLForCompositor(ukm::SourceId source_id,
+ const KURL& url) {
+ LayerTreeHost()->SetSourceURL(source_id, url);
}
-LocalFrame* WebFrameWidgetImpl::FocusedLocalFrameAvailableForIme() const {
- if (!ime_accept_events_)
- return nullptr;
- return FocusedLocalFrameInWidget();
+base::ReadOnlySharedMemoryRegion
+WebFrameWidgetImpl::CreateSharedMemoryForSmoothnessUkm() {
+ return LayerTreeHost()->CreateSharedMemoryForSmoothnessUkm();
+}
+
+bool WebFrameWidgetImpl::CanComposeInline() {
+ if (auto* plugin = GetFocusedPluginContainer())
+ return plugin->CanComposeInline();
+ return true;
+}
+
+bool WebFrameWidgetImpl::ShouldDispatchImeEventsToPlugin() {
+ if (auto* plugin = GetFocusedPluginContainer())
+ return plugin->ShouldDispatchImeEventsToPlugin();
+ return false;
+}
+
+void WebFrameWidgetImpl::ImeSetCompositionForPlugin(
+ const String& text,
+ const Vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& replacement_range,
+ int selection_start,
+ int selection_end) {
+ if (auto* plugin = GetFocusedPluginContainer()) {
+ plugin->ImeSetCompositionForPlugin(
+ text,
+ std::vector<ui::ImeTextSpan>(ime_text_spans.begin(),
+ ime_text_spans.end()),
+ replacement_range, selection_start, selection_end);
+ }
+}
+
+void WebFrameWidgetImpl::ImeCommitTextForPlugin(
+ const String& text,
+ const Vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& replacement_range,
+ int relative_cursor_pos) {
+ if (auto* plugin = GetFocusedPluginContainer()) {
+ plugin->ImeCommitTextForPlugin(
+ text,
+ std::vector<ui::ImeTextSpan>(ime_text_spans.begin(),
+ ime_text_spans.end()),
+ replacement_range, relative_cursor_pos);
+ }
+}
+
+void WebFrameWidgetImpl::ImeFinishComposingTextForPlugin(bool keep_selection) {
+ if (auto* plugin = GetFocusedPluginContainer())
+ plugin->ImeFinishComposingTextForPlugin(keep_selection);
+}
+
+void WebFrameWidgetImpl::SetWindowRect(const gfx::Rect& window_rect) {
+ DCHECK(ForMainFrame());
+ if (SynchronousResizeModeForTestingEnabled()) {
+ // This is a web-test-only path. At one point, it was planned to be
+ // removed. See https://crbug.com/309760.
+ SetWindowRectSynchronously(window_rect);
+ return;
+ }
+
+ SetPendingWindowRect(window_rect);
+ View()->SendWindowRectToMainFrameHost(
+ window_rect, WTF::Bind(&WebFrameWidgetImpl::AckPendingWindowRect,
+ WrapWeakPersistent(this)));
+}
+
+void WebFrameWidgetImpl::SetWindowRectSynchronouslyForTesting(
+ const gfx::Rect& new_window_rect) {
+ DCHECK(ForMainFrame());
+ SetWindowRectSynchronously(new_window_rect);
+}
+
+void WebFrameWidgetImpl::SetWindowRectSynchronously(
+ const gfx::Rect& new_window_rect) {
+ // This method is only call in tests, and it applies the |new_window_rect| to
+ // all three of:
+ // a) widget size (in |size_|)
+ // b) blink viewport (in |visible_viewport_size_|)
+ // c) compositor viewport (in cc::LayerTreeHost)
+ // Normally the browser controls these three things independently, but this is
+ // used in tests to control the size from the renderer.
+
+ // We are resizing the window from the renderer, so allocate a new
+ // viz::LocalSurfaceId to avoid surface invariants violations in tests.
+ widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
+
+ gfx::Rect compositor_viewport_pixel_rect(gfx::ScaleToCeiledSize(
+ new_window_rect.size(),
+ widget_base_->GetScreenInfo().device_scale_factor));
+ widget_base_->UpdateSurfaceAndScreenInfo(
+ widget_base_->local_surface_id_from_parent(),
+ compositor_viewport_pixel_rect, widget_base_->GetScreenInfo());
+
+ Resize(new_window_rect.size());
+ widget_base_->SetScreenRects(new_window_rect, new_window_rect);
}
void WebFrameWidgetImpl::DidCreateLocalRootView() {
// If this WebWidget still hasn't received its size from the embedder, block
// the parser. This is necessary, because the parser can cause layout to
// happen, which needs to be done with the correct size.
- if (!size_) {
- did_suspend_parsing_ = true;
+ if (ForSubframe() && !size_) {
+ child_data().did_suspend_parsing = true;
LocalRootImpl()->GetFrame()->Loader().GetDocumentLoader()->BlockParser();
}
}
-void WebFrameWidgetImpl::GetScrollParamsForFocusedEditableElement(
+mojom::blink::ScrollIntoViewParamsPtr
+WebFrameWidgetImpl::GetScrollParamsForFocusedEditableElement(
const Element& element,
- PhysicalRect& rect_to_scroll,
- mojom::blink::ScrollIntoViewParamsPtr& params) {
+ PhysicalRect& out_rect_to_scroll) {
+ // For main frames, scrolling takes place in two phases.
+ if (ForMainFrame()) {
+ // Since the page has been resized, the layout may have changed. The page
+ // scale animation started by ZoomAndScrollToFocusedEditableRect will scroll
+ // only the visual and layout viewports. We'll call ScrollRectToVisible with
+ // the stop_at_main_frame_layout_viewport param to ensure the element is
+ // actually visible in the page.
+ mojom::blink::ScrollIntoViewParamsPtr params =
+ ScrollAlignment::CreateScrollIntoViewParams(
+ ScrollAlignment::CenterIfNeeded(),
+ ScrollAlignment::CenterIfNeeded(),
+ mojom::blink::ScrollType::kProgrammatic, false,
+ mojom::blink::ScrollBehavior::kInstant);
+ params->stop_at_main_frame_layout_viewport = true;
+ out_rect_to_scroll =
+ PhysicalRect(element.GetLayoutObject()->AbsoluteBoundingBoxRect());
+ return params;
+ }
+
LocalFrameView& frame_view = *element.GetDocument().View();
IntRect absolute_element_bounds =
element.GetLayoutObject()->AbsoluteBoundingBoxRect();
@@ -716,7 +4101,7 @@ void WebFrameWidgetImpl::GetScrollParamsForFocusedEditableElement(
// Ideally, the chosen rectangle includes the element box and caret bounds
// plus some margin on the left. If this does not work (i.e., does not fit
// inside the frame view), then choose a subrect which includes the caret
- // bounds. It is preferrable to also include element bounds' location and left
+ // bounds. It is preferable to also include element bounds' location and left
// align the scroll. If this cant be satisfied, the scroll will be right
// aligned.
IntRect maximal_rect =
@@ -743,46 +4128,20 @@ void WebFrameWidgetImpl::GetScrollParamsForFocusedEditableElement(
}
}
+ mojom::blink::ScrollIntoViewParamsPtr params =
+ ScrollAlignment::CreateScrollIntoViewParams();
params->zoom_into_rect = View()->ShouldZoomToLegibleScale(element);
params->relative_element_bounds = NormalizeRect(
Intersection(absolute_element_bounds, maximal_rect), maximal_rect);
params->relative_caret_bounds = NormalizeRect(
Intersection(absolute_caret_bounds, maximal_rect), maximal_rect);
params->behavior = mojom::blink::ScrollBehavior::kInstant;
- rect_to_scroll = PhysicalRect(maximal_rect);
-}
-
-gfx::Rect WebFrameWidgetImpl::ViewportVisibleRect() {
- return compositor_visible_rect_;
+ out_rect_to_scroll = PhysicalRect(maximal_rect);
+ return params;
}
-void WebFrameWidgetImpl::ApplyVisualPropertiesSizing(
- const VisualProperties& visual_properties) {
- SetWindowSegments(visual_properties.root_widget_window_segments);
- widget_base_->UpdateSurfaceAndScreenInfo(
- visual_properties.local_surface_id.value_or(viz::LocalSurfaceId()),
- visual_properties.compositor_viewport_pixel_rect,
- visual_properties.screen_info);
-
- // Store this even when auto-resizing, it is the size of the full viewport
- // used for clipping, and this value is propagated down the Widget
- // hierarchy via the VisualProperties waterfall.
- widget_base_->SetVisibleViewportSizeInDIPs(
- visual_properties.visible_viewport_size);
-
- // Widgets in a WebView's frame tree without a local main frame
- // set the size of the WebView to be the |visible_viewport_size|, in order
- // to limit compositing in (out of process) child frames to what is visible.
- //
- // Note that child frames in the same process/WebView frame tree as the
- // main frame do not do this in order to not clobber the source of truth in
- // the main frame.
- if (!View()->MainFrameImpl()) {
- View()->Resize(widget_base_->DIPsToCeiledBlinkSpace(
- widget_base_->VisibleViewportSizeInDIPs()));
- }
-
- Resize(widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size));
+bool WebFrameWidgetImpl::ShouldAutoDetermineCompositingToLCDTextSetting() {
+ return true;
}
} // namespace blink