diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core')
38 files changed, 542 insertions, 177 deletions
diff --git a/chromium/third_party/blink/renderer/core/dom/element.cc b/chromium/third_party/blink/renderer/core/dom/element.cc index d86329b115a..e5df6bbfc6a 100644 --- a/chromium/third_party/blink/renderer/core/dom/element.cc +++ b/chromium/third_party/blink/renderer/core/dom/element.cc @@ -3491,11 +3491,26 @@ bool Element::SupportsSpatialNavigationFocus() const { // events). if (!IsSpatialNavigationEnabled(GetDocument().GetFrame())) return false; + + if (!GetLayoutObject()) + return false; + if (HasEventListeners(event_type_names::kClick) || HasEventListeners(event_type_names::kKeydown) || HasEventListeners(event_type_names::kKeypress) || HasEventListeners(event_type_names::kKeyup)) return true; + + // Some web apps use click-handlers to react on clicks within rects that are + // styled with {cursor: pointer}. Such rects *look* clickable so they probably + // are. Here we make Hand-trees' tip, the first (biggest) node with {cursor: + // pointer}, navigable because users shouldn't need to navigate through every + // sub element that inherit this CSS. + if (GetComputedStyle()->Cursor() == ECursor::kPointer && + ParentComputedStyle()->Cursor() != ECursor::kPointer) { + return true; + } + if (!IsSVGElement()) return false; return (HasEventListeners(event_type_names::kFocus) || diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc index 3b6dab593bd..8f3eaf84d00 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc +++ b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc @@ -36,6 +36,7 @@ #include "third_party/blink/renderer/core/dom/events/event_path.h" #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h" #include "third_party/blink/renderer/core/dom/events/window_event_context.h" +#include "third_party/blink/renderer/core/events/keyboard_event.h" #include "third_party/blink/renderer/core/events/mouse_event.h" #include "third_party/blink/renderer/core/frame/ad_tracker.h" #include "third_party/blink/renderer/core/frame/deprecation.h" @@ -45,6 +46,8 @@ #include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/html/html_element.h" #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h" +#include "third_party/blink/renderer/core/page/page.h" +#include "third_party/blink/renderer/core/page/spatial_navigation_controller.h" #include "third_party/blink/renderer/core/timing/event_timing.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" @@ -370,6 +373,15 @@ inline void EventDispatcher::DispatchEventPostProcess( } } + if (Page* page = node_->GetDocument().GetPage()) { + if (page->GetSettings().GetSpatialNavigationEnabled() && + is_trusted_or_click && event_->IsKeyboardEvent() && + ToKeyboardEvent(*event_).key() == "Enter" && + event_->type() == event_type_names::kKeyup) { + page->GetSpatialNavigationController().ResetEnterKeyState(); + } + } + // Track the usage of sending a mousedown event to a select element to force // it to open. This measures a possible breakage of not allowing untrusted // events to open select boxes. diff --git a/chromium/third_party/blink/renderer/core/editing/frame_selection.h b/chromium/third_party/blink/renderer/core/editing/frame_selection.h index 6dc0e1cf974..1da4b7aad96 100644 --- a/chromium/third_party/blink/renderer/core/editing/frame_selection.h +++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.h @@ -201,6 +201,10 @@ class CORE_EXPORT FrameSelection final // Note: this updates styles and layout, use cautiously. bool ComputeAbsoluteBounds(IntRect& anchor, IntRect& focus) const; + // Computes the rect we should use when scrolling/zooming a selection into + // view. + IntRect ComputeRectToScroll(RevealExtentOption); + void DidChangeFocus(); SelectionInDOMTree GetSelectionInDOMTree() const; @@ -299,8 +303,6 @@ class CORE_EXPORT FrameSelection final GranularityStrategy* GetGranularityStrategy(); - IntRect ComputeRectToScroll(RevealExtentOption); - void MoveRangeSelectionInternal(const SelectionInDOMTree&, TextGranularity); // Implementation of |SynchronousMutationObserver| member functions. diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc index a6969cca501..c45adc0ced8 100644 --- a/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc @@ -122,6 +122,7 @@ #include "third_party/blink/renderer/core/fullscreen/fullscreen.h" #include "third_party/blink/renderer/core/geometry/dom_rect.h" #include "third_party/blink/renderer/core/html/forms/html_form_element.h" +#include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/html_body_element.h" #include "third_party/blink/renderer/core/html/html_iframe_element.h" #include "third_party/blink/renderer/core/html/image_document.h" @@ -3390,6 +3391,46 @@ TEST_F(WebFrameTest, CanOverrideScaleLimits) { EXPECT_EQ(2.0f, web_view_helper.GetWebView()->MaximumPageScaleFactor()); } +// Test that setting the "ignore viewport tag scale limits" override remembers +// the current defaults and restores them when the override is removed. +TEST_F(WebFrameTest, RestoreOriginalDefaultScaleLimits) { + RegisterMockedHttpURLLoad("simple_div.html"); + + FixedLayoutTestWebViewClient client; + client.screen_info_.device_scale_factor = 1; + int viewport_width = 640; + int viewport_height = 480; + + frame_test_helpers::WebViewHelper web_view_helper; + web_view_helper.InitializeAndLoad(base_url_ + "simple_div.html", nullptr, + &client, nullptr, ConfigureAndroid); + web_view_helper.Resize(WebSize(viewport_width, viewport_height)); + web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5); + + const float minimum_scale_factor = + web_view_helper.GetWebView()->MinimumPageScaleFactor(); + + web_view_helper.GetWebView()->SetInitialPageScaleOverride(2.0f); + + // Removing the override when none is set shouldn't change the initial scale. + web_view_helper.GetWebView()->SetIgnoreViewportTagScaleLimits(false); + UpdateAllLifecyclePhases(web_view_helper.GetWebView()); + EXPECT_EQ(2.0f, web_view_helper.GetWebView()->PageScaleFactor()); + + // Setting the override when will change the initial scale. + web_view_helper.GetWebView()->SetIgnoreViewportTagScaleLimits(true); + web_view_helper.GetWebView()->ResetScaleStateImmediately(); + UpdateAllLifecyclePhases(web_view_helper.GetWebView()); + EXPECT_EQ(minimum_scale_factor, + web_view_helper.GetWebView()->PageScaleFactor()); + + // Disable the override, we should now use the minimum scale factor + web_view_helper.GetWebView()->SetIgnoreViewportTagScaleLimits(false); + web_view_helper.GetWebView()->ResetScaleStateImmediately(); + UpdateAllLifecyclePhases(web_view_helper.GetWebView()); + EXPECT_EQ(2.0f, web_view_helper.GetWebView()->PageScaleFactor()); +} + // Android doesn't have scrollbars on the main LocalFrameView #if defined(OS_ANDROID) TEST_F(WebFrameTest, DISABLED_updateOverlayScrollbarLayers) @@ -11419,6 +11460,40 @@ class WebFrameSimTest : public SimTest { } }; +// This test ensures that setting the "Force Ignore Zoom" accessibility setting +// also causes us to override the initial scale set by the page so that we load +// fully zoomed out. Since we're overriding the minimum-scale, we're making the +// layout viewport larger. Since |position: fixed| elements are sized based on +// the layout viewport size, they may be cut off when the page first loads. +TEST_F(WebFrameSimTest, ForceIgnoreZoomShouldOverrideInitialScale) { + UseAndroidSettings(); + WebView().MainFrameWidget()->Resize(WebSize(500, 300)); + WebView().SetIgnoreViewportTagScaleLimits(true); + + SimRequest r("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + r.Complete(R"HTML( + <!DOCTYPE html> + <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1"> + <style> + body, html { + width: 100%; + height: 100%; + margin: 0; + } + #wide { + width: 1000px; + height: 10px; + } + </style> + <div id="wide"></div> + )HTML"); + + Compositor().BeginFrame(); + + EXPECT_EQ(0.5f, WebView().PageScaleFactor()); +} + TEST_F(WebFrameSimTest, HitTestWithIgnoreClippingAtNegativeOffset) { WebView().MainFrameWidget()->Resize(WebSize(500, 300)); WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false); @@ -11939,6 +12014,58 @@ TEST_F(WebFrameSimTest, ScrollFocusedIntoViewClipped) { EXPECT_GT(clip->scrollTop(), 0); } +// This test ensures that we scroll to the correct scale when the focused +// element has a selection rather than a carret. +TEST_F(WebFrameSimTest, ScrollFocusedSelectionIntoView) { + UseAndroidSettings(); + WebView().MainFrameWidget()->Resize(WebSize(400, 600)); + WebView().EnableFakePageScaleAnimationForTesting(true); + WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false); + + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete(R"HTML( + <!DOCTYPE html> + <style> + ::-webkit-scrollbar { + width: 0px; + height: 0px; + } + body, html { + margin: 0px; + width: 100%; + height: 100%; + } + input { + padding: 0; + width: 100px; + height: 20px; + } + </style> + <input type="text" id="target" value="test"> + )HTML"); + + Compositor().BeginFrame(); + WebView().AdvanceFocus(false); + + HTMLInputElement* input = + ToHTMLInputElement(GetDocument().getElementById("target")); + input->select(); + + // Simulate the keyboard being shown and resizing the widget. Cause a scroll + // into view after. + ASSERT_EQ(WebView().FakePageScaleAnimationPageScaleForTesting(), 0.f); + WebFrameWidget* widget = WebView().MainFrameImpl()->FrameWidgetImpl(); + widget->ScrollFocusedEditableElementIntoView(); + + // Make sure zoomed in but only up to a legible scale. The bounds are + // arbitrary and fuzzy since we don't specifically care to constrain the + // amount of zooming (that should be tested elsewhere), we just care that it + // zooms but not off to infinity. + EXPECT_GT(WebView().FakePageScaleAnimationPageScaleForTesting(), .75f); + EXPECT_LT(WebView().FakePageScaleAnimationPageScaleForTesting(), 2.f); +} + TEST_F(WebFrameSimTest, DoubleTapZoomWhileScrolled) { UseAndroidSettings(); WebView().MainFrameWidget()->Resize(WebSize(490, 500)); diff --git a/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc index fa2150289b4..41e11e56e95 100644 --- a/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc @@ -2156,7 +2156,7 @@ bool WebViewImpl::ScrollFocusedEditableElementIntoView() { element->GetDocument() .GetFrame() ->Selection() - .AbsoluteCaretBounds())), + .ComputeRectToScroll(kDoNotRevealExtent))), ShouldZoomToLegibleScale(*element)); return true; @@ -2514,16 +2514,26 @@ void WebViewImpl::SetMaximumLegibleScale(float maximum_legible_scale) { } void WebViewImpl::SetIgnoreViewportTagScaleLimits(bool ignore) { + // This method should be idempotent. + if (ignore == pre_override_default_constraints_.has_value()) + return; + PageScaleConstraints constraints = GetPageScaleConstraintsSet().UserAgentConstraints(); if (ignore) { + DCHECK(!pre_override_default_constraints_); + pre_override_default_constraints_.emplace(constraints); + constraints.minimum_scale = GetPageScaleConstraintsSet().DefaultConstraints().minimum_scale; constraints.maximum_scale = GetPageScaleConstraintsSet().DefaultConstraints().maximum_scale; + constraints.initial_scale = + GetPageScaleConstraintsSet().DefaultConstraints().minimum_scale; } else { - constraints.minimum_scale = -1; - constraints.maximum_scale = -1; + DCHECK(pre_override_default_constraints_); + constraints = pre_override_default_constraints_.value(); + pre_override_default_constraints_.reset(); } GetPage()->SetUserAgentPageScaleConstraints(constraints); } diff --git a/chromium/third_party/blink/renderer/core/exported/web_view_impl.h b/chromium/third_party/blink/renderer/core/exported/web_view_impl.h index aaa17462ee6..64a22db62db 100644 --- a/chromium/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/chromium/third_party/blink/renderer/core/exported/web_view_impl.h @@ -691,6 +691,10 @@ class CORE_EXPORT WebViewImpl final : public WebView, FloatSize elastic_overscroll_; + // When overriding the default page scale constraints, store the original so + // we can revert to them when the override is removed. + base::Optional<PageScaleConstraints> pre_override_default_constraints_; + Persistent<EventListener> popup_mouse_wheel_event_listener_; // The local root whose document has |popup_mouse_wheel_event_listener_| diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame.cc b/chromium/third_party/blink/renderer/core/frame/local_frame.cc index dd0e2f0df7b..c1f7d53655b 100644 --- a/chromium/third_party/blink/renderer/core/frame/local_frame.cc +++ b/chromium/third_party/blink/renderer/core/frame/local_frame.cc @@ -339,7 +339,7 @@ void LocalFrame::Navigate(const FrameLoadRequest& request, WebFrameLoadType frame_load_type) { if (!navigation_rate_limiter().CanProceed()) return; - if (request.ClientRedirect() == ClientRedirectPolicy::kClientRedirect) { + if (request.ClientRedirectReason() != ClientNavigationReason::kNone) { probe::FrameScheduledNavigation(this, request.GetResourceRequest().Url(), 0.0, request.ClientRedirectReason()); if (NavigationScheduler::MustReplaceCurrentItem(this)) @@ -347,7 +347,7 @@ void LocalFrame::Navigate(const FrameLoadRequest& request, } loader_.StartNavigation(request, frame_load_type); - if (request.ClientRedirect() == ClientRedirectPolicy::kClientRedirect) + if (request.ClientRedirectReason() != ClientNavigationReason::kNone) probe::FrameClearedScheduledNavigation(this); } diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame.cc b/chromium/third_party/blink/renderer/core/frame/remote_frame.cc index 9de006e1b8e..fce85b75bcd 100644 --- a/chromium/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/chromium/third_party/blink/renderer/core/frame/remote_frame.cc @@ -111,8 +111,8 @@ void RemoteFrame::Navigate(const FrameLoadRequest& passed_request, frame->GetSecurityContext() && frame->GetSecurityContext()->IsSandboxed(WebSandboxFlags::kDownloads); initiator_frame_is_ad = frame->IsAdSubframe(); - if (passed_request.ClientRedirect() == - ClientRedirectPolicy::kClientRedirect) { + if (passed_request.ClientRedirectReason() != + ClientNavigationReason::kNone) { probe::FrameRequestedNavigation(frame, this, url, passed_request.ClientRedirectReason()); } diff --git a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index 98176198d5c..334198dff21 100644 --- a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc @@ -147,8 +147,6 @@ intptr_t HTMLCanvasElement::global_gpu_memory_usage_ = 0; unsigned HTMLCanvasElement::global_accelerated_context_count_ = 0; HTMLCanvasElement::~HTMLCanvasElement() { - if (surface_layer_bridge_ && surface_layer_bridge_->GetCcLayer()) - GraphicsLayer::UnregisterContentsLayer(surface_layer_bridge_->GetCcLayer()); v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( -externally_allocated_memory_); } @@ -177,6 +175,19 @@ void HTMLCanvasElement::Dispose() { global_accelerated_context_count_--; } global_gpu_memory_usage_ -= gpu_memory_usage_; + + if (surface_layer_bridge_) { + if (surface_layer_bridge_->GetCcLayer()) { + GraphicsLayer::UnregisterContentsLayer( + surface_layer_bridge_->GetCcLayer()); + } + // Observer has to be cleared out at this point. Otherwise the + // SurfaceLayerBridge may call back into the observer which is undefined + // behavior. In the worst case, the dead canvas element re-adds itself into + // a data structure which may crash at a later point in time. See + // https://crbug.com/976577. + surface_layer_bridge_->ClearObserver(); + } } void HTMLCanvasElement::ParseAttribute( diff --git a/chromium/third_party/blink/renderer/core/html/forms/radio_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/radio_input_type.cc index 390b142468a..ac8f7326720 100644 --- a/chromium/third_party/blink/renderer/core/html/forms/radio_input_type.cc +++ b/chromium/third_party/blink/renderer/core/html/forms/radio_input_type.cc @@ -155,8 +155,6 @@ void RadioInputType::HandleKeyupEvent(KeyboardEvent& event) { event.key() == "Enter")) { DispatchSimulatedClickIfActive(event); } - - DispatchSimulatedClickIfActive(event); } bool RadioInputType::IsKeyboardFocusable() const { diff --git a/chromium/third_party/blink/renderer/core/html/html_anchor_element.cc b/chromium/third_party/blink/renderer/core/html/html_anchor_element.cc index 94733fedf25..786167ccc30 100644 --- a/chromium/third_party/blink/renderer/core/html/html_anchor_element.cc +++ b/chromium/third_party/blink/renderer/core/html/html_anchor_element.cc @@ -429,8 +429,10 @@ void HTMLAnchorElement::HandleClick(Event& event) { } request.SetRequestContext(mojom::RequestContextType::HYPERLINK); - FrameLoadRequest frame_request(&GetDocument(), request, - getAttribute(kTargetAttr)); + const AtomicString& target = getAttribute(kTargetAttr); + FrameLoadRequest frame_request( + &GetDocument(), request, + target.IsEmpty() ? GetDocument().BaseTarget() : target); frame_request.SetNavigationPolicy(NavigationPolicyFromEvent(&event)); if (HasRel(kRelationNoReferrer)) { frame_request.SetShouldSendReferrer(kNeverSendReferrer); diff --git a/chromium/third_party/blink/renderer/core/html/html_element.cc b/chromium/third_party/blink/renderer/core/html/html_element.cc index 8803bea1c77..8a830c69504 100644 --- a/chromium/third_party/blink/renderer/core/html/html_element.cc +++ b/chromium/third_party/blink/renderer/core/html/html_element.cc @@ -1332,6 +1332,8 @@ bool HTMLElement::MatchesReadWritePseudoClass() const { void HTMLElement::HandleKeypressEvent(KeyboardEvent& event) { if (!IsSpatialNavigationEnabled(GetDocument().GetFrame()) || !SupportsFocus()) return; + if (RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled()) + return; GetDocument().UpdateStyleAndLayoutTree(); // if the element is a text form control (like <input type=text> or // <textarea>) or has contentEditable attribute on, we should enter a space or diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc index bfc6b9530d1..9501d2dd946 100644 --- a/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc @@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/css/style_change_reason.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" +#include "third_party/blink/renderer/core/events/current_input_event.h" #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" @@ -403,13 +404,12 @@ bool HTMLFrameOwnerElement::LoadOrRedirectSubframe( KURL url_to_request = url.IsNull() ? BlankURL() : url; if (ContentFrame()) { // TODO(sclittle): Support lazily loading frame navigations. + FrameLoadRequest request(&GetDocument(), ResourceRequest(url_to_request)); + request.SetClientRedirectReason(ClientNavigationReason::kFrameNavigation); WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; if (replace_current_item) frame_load_type = WebFrameLoadType::kReplaceCurrentItem; - - ContentFrame()->ScheduleNavigation(GetDocument(), url_to_request, - frame_load_type, - UserGestureStatus::kNone); + ContentFrame()->Navigate(request, frame_load_type); return true; } diff --git a/chromium/third_party/blink/renderer/core/html/media/html_video_element.cc b/chromium/third_party/blink/renderer/core/html/media/html_video_element.cc index 07f6c2998fa..723c7faf25b 100644 --- a/chromium/third_party/blink/renderer/core/html/media/html_video_element.cc +++ b/chromium/third_party/blink/renderer/core/html/media/html_video_element.cc @@ -402,6 +402,8 @@ void HTMLVideoElement::OnPlay() { return; } + std::unique_ptr<UserGestureIndicator> gesture = + LocalFrame::NotifyUserActivation(GetDocument().GetFrame()); webkitEnterFullscreen(); } diff --git a/chromium/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc b/chromium/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc index c1a36918ec0..749e6a68982 100644 --- a/chromium/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc +++ b/chromium/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc @@ -157,4 +157,30 @@ TEST_F(VideoAutoFullscreen, ExitFullscreenDoesNotPauseWithPlaysInline) { EXPECT_FALSE(Video()->paused()); } +TEST_F(VideoAutoFullscreen, OnPlayTriggersFullscreenWithoutGesture) { + Video()->SetSrc("http://example.com/foo.mp4"); + { + std::unique_ptr<UserGestureIndicator> user_gesture_scope = + LocalFrame::NotifyUserActivation(GetFrame(), + UserGestureToken::kNewGesture); + Video()->Play(); + } + MakeGarbageCollected<WaitForEvent>(Video(), event_type_names::kPlay); + test::RunPendingTasks(); + + EXPECT_TRUE(Video()->IsFullscreen()); + + GetWebView()->ExitFullscreen(*GetFrame()); + test::RunPendingTasks(); + + EXPECT_TRUE(Video()->paused()); + EXPECT_FALSE(Video()->IsFullscreen()); + + Video()->Play(); + test::RunPendingTasks(); + + EXPECT_FALSE(Video()->paused()); + EXPECT_TRUE(Video()->IsFullscreen()); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/input/event_handler_test.cc b/chromium/third_party/blink/renderer/core/input/event_handler_test.cc index 0cff945a90f..33b3969cbc4 100644 --- a/chromium/third_party/blink/renderer/core/input/event_handler_test.cc +++ b/chromium/third_party/blink/renderer/core/input/event_handler_test.cc @@ -33,6 +33,8 @@ #include "third_party/blink/renderer/core/testing/sim/sim_test.h" #include "third_party/blink/renderer/platform/keyboard_codes.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" +#include "ui/events/keycodes/dom/dom_code.h" +#include "ui/events/keycodes/dom/dom_key.h" namespace blink { @@ -592,6 +594,22 @@ TEST_F(EventHandlerTest, EditableAnchorTextCanStartSelection) { Cursor::Type::kIBeam); // An I-beam signals editability. } +TEST_F(EventHandlerTest, implicitSend) { + SetHtmlInnerHTML("<button>abc</button>"); + GetDocument().GetSettings()->SetSpatialNavigationEnabled(true); + + WebKeyboardEvent e{WebInputEvent::kRawKeyDown, WebInputEvent::kNoModifiers, + WebInputEvent::GetStaticTimeStampForTests()}; + e.dom_code = static_cast<int>(ui::DomCode::ARROW_DOWN); + e.dom_key = ui::DomKey::ARROW_DOWN; + GetDocument().GetFrame()->GetEventHandler().KeyEvent(e); + + // TODO(crbug.com/949766) Should cleanup these magic numbers. + e.dom_code = 0; + e.dom_key = 0x00200310; + GetDocument().GetFrame()->GetEventHandler().KeyEvent(e); +} + // Regression test for http://crbug.com/641403 to verify we use up-to-date // layout tree for dispatching "contextmenu" event. TEST_F(EventHandlerTest, sendContextMenuEventWithHover) { diff --git a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc index aefdaab5a13..d6b65860898 100644 --- a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc +++ b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc @@ -339,6 +339,9 @@ void KeyboardEventManager::DefaultKeyboardEventHandler( DefaultEscapeEventHandler(event); } else if (event->key() == "Enter") { DefaultEnterEventHandler(event); + } else if (static_cast<int>(event->KeyEvent()->dom_key) == 0x00200310) { + // TODO(bokan): Cleanup magic numbers once https://crbug.com/949766 lands. + DefaultImeSubmitHandler(event); } else { // TODO(bokan): Seems odd to call the default _arrow_ event handler on // events that aren't necessarily arrow keys. @@ -348,16 +351,19 @@ void KeyboardEventManager::DefaultKeyboardEventHandler( frame_->GetEditor().HandleKeyboardEvent(event); if (event->DefaultHandled()) return; - if (event->charCode() == ' ') + if (event->key() == "Enter") { + DefaultEnterEventHandler(event); + } else if (event->charCode() == ' ') { DefaultSpaceEventHandler(event, possible_focused_node); + } } else if (event->type() == event_type_names::kKeyup) { + if (event->DefaultHandled()) + return; if (event->key() == "Enter") { DefaultEnterEventHandler(event); - return; - } - - if (event->keyCode() == kVKeySpatNavBack) + } else if (event->keyCode() == kVKeySpatNavBack) { DefaultSpatNavBackEventHandler(event); + } } } @@ -509,6 +515,17 @@ void KeyboardEventManager::DefaultEnterEventHandler(KeyboardEvent* event) { } } +void KeyboardEventManager::DefaultImeSubmitHandler(KeyboardEvent* event) { + Page* page = frame_->GetPage(); + if (!page) + return; + + if (IsSpatialNavigationEnabled(frame_) && + !frame_->GetDocument()->InDesignMode()) { + page->GetSpatialNavigationController().HandleImeSubmitKeyboardEvent(event); + } +} + static OverrideCapsLockState g_override_caps_lock_state; void KeyboardEventManager::SetCurrentCapsLockState( diff --git a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h index 3d9afb6f6fe..3f1b4c4de8d 100644 --- a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h +++ b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h @@ -56,6 +56,7 @@ class CORE_EXPORT KeyboardEventManager void DefaultTabEventHandler(KeyboardEvent*); void DefaultEscapeEventHandler(KeyboardEvent*); void DefaultEnterEventHandler(KeyboardEvent*); + void DefaultImeSubmitHandler(KeyboardEvent*); void DefaultArrowEventHandler(KeyboardEvent*, Node*); bool DefaultSpatNavBackEventHandler(KeyboardEvent*); diff --git a/chromium/third_party/blink/renderer/core/layout/layout_block.cc b/chromium/third_party/blink/renderer/core/layout/layout_block.cc index 481a0be7dc1..cbbd9281df3 100644 --- a/chromium/third_party/blink/renderer/core/layout/layout_block.cc +++ b/chromium/third_party/blink/renderer/core/layout/layout_block.cc @@ -1128,6 +1128,15 @@ void LayoutBlock::RemovePositionedObjects( } void LayoutBlock::AddPercentHeightDescendant(LayoutBox* descendant) { + // A replaced object is incapable of properly acting as a containing block for + // its children (this is an issue with VIDEO elements, for instance, which + // inserts some percentage height flexbox children). Assert that the + // descendant hasn't escaped from within a replaced object. Registering the + // percentage height descendant further up in the tree is only going to cause + // trouble, especially if the replaced object is out-of-flow positioned (and + // we failed to notice). + DCHECK(!descendant->Container()->IsLayoutReplaced()); + if (descendant->PercentHeightContainer()) { if (descendant->PercentHeightContainer() == this) { DCHECK(HasPercentHeightDescendant(descendant)); diff --git a/chromium/third_party/blink/renderer/core/layout/layout_box.cc b/chromium/third_party/blink/renderer/core/layout/layout_box.cc index 5313c3963a3..a28f0ae2be2 100644 --- a/chromium/third_party/blink/renderer/core/layout/layout_box.cc +++ b/chromium/third_party/blink/renderer/core/layout/layout_box.cc @@ -3743,7 +3743,13 @@ LayoutUnit LayoutBox::ComputePercentageLogicalHeight( &cb, &skipped_auto_height_containing_block); DCHECK(cb); - cb->AddPercentHeightDescendant(const_cast<LayoutBox*>(this)); + + // If the container of the descendant is a replaced element (a VIDEO, for + // instance), |cb| (which uses ContainingBlock()) may actually not be in the + // containing block chain for the descendant. + const LayoutObject* container = Container(); + if (!container->IsLayoutReplaced()) + cb->AddPercentHeightDescendant(const_cast<LayoutBox*>(this)); if (available_height == -1) return available_height; diff --git a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc index 230c3830fbc..4cfaf04e392 100644 --- a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc +++ b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc @@ -1393,7 +1393,8 @@ bool LayoutFlexibleBox::ChildHasIntrinsicMainAxisSize( const FlexLayoutAlgorithm& algorithm, const LayoutBox& child) const { bool result = false; - if (!MainAxisIsInlineAxis(child) && !child.ShouldApplySizeContainment()) { + bool main_axis_is_inline = MainAxisIsInlineAxis(child); + if (!main_axis_is_inline && !child.ShouldApplySizeContainment()) { Length child_flex_basis = FlexBasisForChild(child); const Length& child_min_size = IsHorizontalFlow() ? child.StyleRef().MinWidth() @@ -1407,6 +1408,11 @@ bool LayoutFlexibleBox::ChildHasIntrinsicMainAxisSize( } else if (algorithm.ShouldApplyMinSizeAutoForChild(child)) { result = true; } + } else if (main_axis_is_inline && + child.StyleRef().OverflowInlineDirection() == EOverflow::kAuto) { + // Because scrollbars depend on layout, we need to layout before running + // the algorithm to get an up-to-date size. + result = true; } return result; } diff --git a/chromium/third_party/blink/renderer/core/loader/form_submission.cc b/chromium/third_party/blink/renderer/core/loader/form_submission.cc index 020052ff693..1ad45a7cc58 100644 --- a/chromium/third_party/blink/renderer/core/loader/form_submission.cc +++ b/chromium/third_party/blink/renderer/core/loader/form_submission.cc @@ -288,6 +288,8 @@ FrameLoadRequest FormSubmission::CreateFrameLoadRequest( if (!target_.IsEmpty()) frame_request.SetFrameName(target_); + else + frame_request.SetFrameName(origin_document->BaseTarget()); ClientNavigationReason reason = ClientNavigationReason::kFormSubmissionGet; if (method_ == FormSubmission::kPostMethod) { diff --git a/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc b/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc index 78c15ae6085..1bfa77c670a 100644 --- a/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc +++ b/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc @@ -8,6 +8,7 @@ #include "third_party/blink/public/platform/web_url_request.h" #include "third_party/blink/renderer/core/events/current_input_event.h" #include "third_party/blink/renderer/core/fileapi/public_url_manager.h" +#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" @@ -37,7 +38,6 @@ FrameLoadRequest::FrameLoadRequest( : origin_document_(origin_document), resource_request_(resource_request), frame_name_(frame_name), - client_redirect_(ClientRedirectPolicy::kNotClientRedirect), should_send_referrer_(kMaybeSendReferrer), should_check_main_world_content_security_policy_( should_check_main_world_content_security_policy) { @@ -63,7 +63,22 @@ FrameLoadRequest::FrameLoadRequest( origin_document->GetPublicURLManager().Resolve( resource_request.Url(), MakeRequest(&blob_url_token_->data)); } + + if (ContentSecurityPolicy::ShouldBypassMainWorld(origin_document)) { + should_check_main_world_content_security_policy_ = + kDoNotCheckContentSecurityPolicy; + } } } +ClientRedirectPolicy FrameLoadRequest::ClientRedirect() const { + // Form submissions have not historically been reported to the extensions API + // as client redirects. + if (client_navigation_reason_ == ClientNavigationReason::kNone || + client_navigation_reason_ == ClientNavigationReason::kFormSubmissionGet || + client_navigation_reason_ == ClientNavigationReason::kFormSubmissionPost) + return ClientRedirectPolicy::kNotClientRedirect; + return ClientRedirectPolicy::kClientRedirect; +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/loader/frame_load_request.h b/chromium/third_party/blink/renderer/core/loader/frame_load_request.h index 3c4e77dec96..a35c92f0ca9 100644 --- a/chromium/third_party/blink/renderer/core/loader/frame_load_request.h +++ b/chromium/third_party/blink/renderer/core/loader/frame_load_request.h @@ -74,15 +74,15 @@ struct CORE_EXPORT FrameLoadRequest { frame_name_ = frame_name; } - ClientRedirectPolicy ClientRedirect() const { return client_redirect_; } + // TODO(japhet): This is only used from frame_loader.cc, and can probably be + // an implementation detail there. + ClientRedirectPolicy ClientRedirect() const; void SetClientRedirectReason(ClientNavigationReason reason) { - client_redirect_ = ClientRedirectPolicy::kClientRedirect; client_navigation_reason_ = reason; } ClientNavigationReason ClientRedirectReason() const { - DCHECK_EQ(ClientRedirectPolicy::kClientRedirect, client_redirect_); return client_navigation_reason_; } @@ -165,11 +165,8 @@ struct CORE_EXPORT FrameLoadRequest { ResourceRequest resource_request_; AtomicString frame_name_; AtomicString href_translate_; - // TODO(caseq): merge ClientRedirectPolicy and ClientNavigationReason. - // Currently, client_navigation_reason_ is set iff ClientRedirectPolicy - // is set to kClientRedirect. - ClientRedirectPolicy client_redirect_; - ClientNavigationReason client_navigation_reason_; + ClientNavigationReason client_navigation_reason_ = + ClientNavigationReason::kNone; NavigationPolicy navigation_policy_ = kNavigationPolicyCurrentTab; WebTriggeringEventInfo triggering_event_info_ = WebTriggeringEventInfo::kNotFromEvent; diff --git a/chromium/third_party/blink/renderer/core/loader/frame_loader.cc b/chromium/third_party/blink/renderer/core/loader/frame_loader.cc index ebc44803f9a..3f2dad0e9a2 100644 --- a/chromium/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/chromium/third_party/blink/renderer/core/loader/frame_loader.cc @@ -444,7 +444,7 @@ void FrameLoader::DidFinishNavigation() { // progress. DCHECK((document_loader_ && document_loader_->SentDidFinishLoad()) || !HasProvisionalNavigation()); - if (!document_loader_ || !document_loader_->SentDidFinishLoad() || + if ((document_loader_ && !document_loader_->SentDidFinishLoad()) || HasProvisionalNavigation()) { return; } @@ -730,9 +730,6 @@ bool FrameLoader::PrepareRequestForThisFrame(FrameLoadRequest& request) { "Not allowed to load local resource: " + url.ElidedString())); return false; } - - if (request.FrameName().IsEmpty()) - request.SetFrameName(frame_->GetDocument()->BaseTarget()); return true; } @@ -948,7 +945,7 @@ void FrameLoader::StartNavigation(const FrameLoadRequest& passed_request, } } - if (request.ClientRedirect() == ClientRedirectPolicy::kClientRedirect) { + if (request.ClientRedirectReason() != ClientNavigationReason::kNone) { probe::FrameRequestedNavigation(frame_, frame_, url, request.ClientRedirectReason()); } diff --git a/chromium/third_party/blink/renderer/core/loader/frame_loader_types.h b/chromium/third_party/blink/renderer/core/loader/frame_loader_types.h index 4df8bae808c..fa84bd0dfed 100644 --- a/chromium/third_party/blink/renderer/core/loader/frame_loader_types.h +++ b/chromium/third_party/blink/renderer/core/loader/frame_loader_types.h @@ -79,6 +79,7 @@ enum class ClientNavigationReason { kMetaTagRefresh, kPageBlock, kReload, + kNone }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc index e60593d480f..c9db8b3291c 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc +++ b/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc @@ -290,6 +290,7 @@ void ScriptResource::OnDataPipeReadable(MojoResult result, // This means the producer finished and streamed to completion. watcher_.reset(); response_body_loader_client_->DidFinishLoadingBody(); + response_body_loader_client_ = nullptr; return; case MOJO_RESULT_SHOULD_WAIT: @@ -300,6 +301,7 @@ void ScriptResource::OnDataPipeReadable(MojoResult result, // Some other error occurred. watcher_.reset(); response_body_loader_client_->DidFailLoadingBody(); + response_body_loader_client_ = nullptr; return; } CHECK(state.readable()); @@ -358,6 +360,7 @@ void ScriptResource::NotifyFinished() { case StreamingState::kStreamingNotAllowed: watcher_.reset(); data_pipe_.reset(); + response_body_loader_client_ = nullptr; AdvanceStreamingState(StreamingState::kFinishedNotificationSent); TextResource::NotifyFinished(); break; @@ -382,6 +385,7 @@ void ScriptResource::StreamingFinished() { // small) and b) an external error triggered the finished notification. watcher_.reset(); data_pipe_.reset(); + response_body_loader_client_ = nullptr; AdvanceStreamingState(StreamingState::kFinishedNotificationSent); TextResource::NotifyFinished(); } @@ -463,6 +467,7 @@ void ScriptResource::SetClientIsWaitingForFinished() { if (IsLoaded()) { watcher_.reset(); data_pipe_.reset(); + response_body_loader_client_ = nullptr; AdvanceStreamingState(StreamingState::kFinishedNotificationSent); TextResource::NotifyFinished(); } @@ -536,6 +541,7 @@ void ScriptResource::CheckStreamingState() const { CHECK(!streamer_ || streamer_->IsFinished()); CHECK(!watcher_ || !watcher_->IsWatching()); CHECK(!data_pipe_); + CHECK(!response_body_loader_client_); CHECK(IsLoaded()); break; } diff --git a/chromium/third_party/blink/renderer/core/page/focus_controller.cc b/chromium/third_party/blink/renderer/core/page/focus_controller.cc index 8e8348de9a5..041804d5ec7 100644 --- a/chromium/third_party/blink/renderer/core/page/focus_controller.cc +++ b/chromium/third_party/blink/renderer/core/page/focus_controller.cc @@ -1158,9 +1158,12 @@ Element* FocusController::NextFocusableElementInForm(Element* element, if (form_element->formOwner() != form_owner || form_element->IsDisabledOrReadOnly()) continue; - // Focusless spatial navigation supports all form types. + // Focusless spatial navigation supports all form types. However, submit + // buttons are explicitly excluded as moving to them isn't necessary - the + // IME should just submit instead. if (RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled() && - page_->GetSettings().GetSpatialNavigationEnabled()) { + page_->GetSettings().GetSpatialNavigationEnabled() && + !form_element->CanBeSuccessfulSubmitButton()) { return next_element; } LayoutObject* layout = next_element->GetLayoutObject(); diff --git a/chromium/third_party/blink/renderer/core/page/page.cc b/chromium/third_party/blink/renderer/core/page/page.cc index 1c2e3dbbb01..6cc6c5a6f38 100644 --- a/chromium/third_party/blink/renderer/core/page/page.cc +++ b/chromium/third_party/blink/renderer/core/page/page.cc @@ -307,8 +307,6 @@ void Page::DocumentDetached(Document* document) { if (validation_message_client_) validation_message_client_->DocumentDetached(*document); hosts_using_features_.DocumentDetached(*document); - if (spatial_navigation_controller_ && document->GetFrame()->IsMainFrame()) - spatial_navigation_controller_->ResetMojoBindings(); } bool Page::OpenedByDOM() const { diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc index b443a2d9f4a..b95b34b5118 100644 --- a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc +++ b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc @@ -827,6 +827,10 @@ bool ScrollsWithRootFrame(LayoutObject* object) { DCHECK(object); DCHECK(object->GetFrame()); + // TODO(bokan): Speculative fix for https://crbug.com/964293. + if (!object || !object->GetNode()) + return true; + const LocalFrame& frame = *object->GetFrame(); // If we're in an iframe document, we need to determine if the containing diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc b/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc index 04c10fd3910..56a992c588c 100644 --- a/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc +++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc @@ -37,6 +37,7 @@ #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" #include "third_party/blink/renderer/core/html/html_image_element.h" #include "third_party/blink/renderer/core/html_names.h" +#include "third_party/blink/renderer/core/input/event_handler.h" #include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" #include "third_party/blink/renderer/core/layout/layout_view.h" @@ -47,6 +48,14 @@ namespace blink { +// A small integer that easily fits into a double with a good margin for +// arithmetic. In particular, we don't want to use +// std::numeric_limits<double>::lowest() because, if subtracted, it becomes +// NaN which will make all following arithmetic NaN too (an unusable number). +constexpr double kMinDistance = std::numeric_limits<int>::lowest(); + +constexpr int kFudgeFactor = 2; + static void DeflateIfOverlapped(LayoutRect&, LayoutRect&); FocusCandidate::FocusCandidate(Node* node, SpatialNavigationDirection direction) @@ -185,6 +194,49 @@ ScrollableArea* ScrollableAreaFor(const Node* node) { return ToLayoutBox(object)->GetScrollableArea(); } +bool IsUnobscured(const FocusCandidate& candidate) { + DCHECK(candidate.visible_node); + + const LocalFrame* local_main_frame = DynamicTo<LocalFrame>( + candidate.visible_node->GetDocument().GetPage()->MainFrame()); + if (!local_main_frame) + return false; + + // TODO(crbug.com/955952): We cannot evaluate visibility for media element + // using hit test since attached media controls cover media element. + if (candidate.visible_node->IsMediaElement()) + return true; + + LayoutRect viewport_rect = LayoutRect( + local_main_frame->GetPage()->GetVisualViewport().VisibleContentRect()); + LayoutRect interesting_rect = + Intersection(candidate.rect_in_root_frame, viewport_rect); + + if (interesting_rect.IsEmpty()) + return false; + + HitTestLocation location(interesting_rect); + HitTestResult result = + local_main_frame->GetEventHandler().HitTestResultAtLocation( + location, HitTestRequest::kReadOnly | HitTestRequest::kListBased | + HitTestRequest::kIgnoreZeroOpacityObjects | + HitTestRequest::kAllowChildFrameContent); + + const HitTestResult::NodeSet& nodes = result.ListBasedTestResult(); + for (auto hit_node = nodes.rbegin(); hit_node != nodes.rend(); ++hit_node) { + if (candidate.visible_node->ContainsIncludingHostElements(**hit_node)) + return true; + + if (FrameOwnerElement(candidate) && + FrameOwnerElement(candidate) + ->contentDocument() + ->ContainsIncludingHostElements(**hit_node)) + return true; + } + + return false; +} + bool HasRemoteFrame(const Node* node) { auto* frame_owner_element = DynamicTo<HTMLFrameOwnerElement>(node); if (!frame_owner_element) @@ -237,7 +289,9 @@ bool ScrollInDirection(Node* container, SpatialNavigationDirection direction) { // CanScrollInDirection(). Regular arrow-key scrolling (without // --enable-spatial-navigation) already uses smooth scrolling by default. ScrollableArea* scroller = ScrollableAreaFor(container); - DCHECK(scroller); + if (!scroller) + return false; + scroller->ScrollBy(ScrollOffset(dx, dy), kUserScroll); return true; } @@ -246,7 +300,7 @@ static void DeflateIfOverlapped(LayoutRect& a, LayoutRect& b) { if (!a.Intersects(b) || a.Contains(b) || b.Contains(a)) return; - LayoutUnit deflate_factor = LayoutUnit(-FudgeFactor()); + LayoutUnit deflate_factor = LayoutUnit(-kFudgeFactor); // Avoid negative width or height values. if ((a.Width() + 2 * deflate_factor > 0) && @@ -481,55 +535,42 @@ void EntryAndExitPointsForDirection(SpatialNavigationDirection direction, } } -bool AreElementsOnSameLine(const FocusCandidate& first_candidate, - const FocusCandidate& second_candidate) { - if (first_candidate.IsNull() || second_candidate.IsNull()) - return false; - - if (!first_candidate.visible_node->GetLayoutObject() || - !second_candidate.visible_node->GetLayoutObject()) - return false; - - if (!first_candidate.rect_in_root_frame.Intersects( - second_candidate.rect_in_root_frame)) - return false; - - if (IsHTMLAreaElement(*first_candidate.focusable_node) || - IsHTMLAreaElement(*second_candidate.focusable_node)) - return false; - - if (!first_candidate.visible_node->GetLayoutObject()->IsLayoutInline() || - !second_candidate.visible_node->GetLayoutObject()->IsLayoutInline()) - return false; - - if (first_candidate.visible_node->GetLayoutObject()->ContainingBlock() != - second_candidate.visible_node->GetLayoutObject()->ContainingBlock()) - return false; - - return true; -} - double ComputeDistanceDataForNode(SpatialNavigationDirection direction, const FocusCandidate& current_interest, const FocusCandidate& candidate) { - if (!IsRectInDirection(direction, current_interest.rect_in_root_frame, - candidate.rect_in_root_frame)) - return MaxDistance(); - - if (AreElementsOnSameLine(current_interest, candidate)) { - if ((direction == SpatialNavigationDirection::kUp && - current_interest.rect_in_root_frame.Y() > - candidate.rect_in_root_frame.Y()) || - (direction == SpatialNavigationDirection::kDown && - candidate.rect_in_root_frame.Y() > - current_interest.rect_in_root_frame.Y())) { - return 0.0; - } - } - + double distance = 0.0; + double overlap = 0.0; LayoutRect node_rect = candidate.rect_in_root_frame; LayoutRect current_rect = current_interest.rect_in_root_frame; - DeflateIfOverlapped(current_rect, node_rect); + if (node_rect.Contains(current_rect)) { + // When leaving an "insider", don't focus its underlaying container box. + // Go directly to the outside world. This avoids focus from being trapped + // inside a container. + return kMaxDistance; + } + + if (current_rect.Contains(node_rect)) { + // We give priority to "insiders", candidates that are completely inside the + // current focus rect, by giving them a negative, < 0, distance number. + distance = kMinDistance; + + // For insiders we cannot meassure the distance from the outer box. Instead, + // we meassure distance _from_ the focused container's rect's "opposite + // edge" in the navigated direction, just like we do when we look for + // candidates inside a focused scroll container. + current_rect = OppositeEdge(direction, current_rect); + + // This candidate fully overlaps the current focus rect so we can omit the + // overlap term of the equation. An "insider" will always win against an + // "outsider". + } else if (!IsRectInDirection(direction, current_rect, node_rect)) { + return kMaxDistance; + } else { + DeflateIfOverlapped(current_rect, node_rect); + LayoutRect intersection_rect = Intersection(current_rect, node_rect); + overlap = + (intersection_rect.Width() * intersection_rect.Height()).ToDouble(); + } LayoutPoint exit_point; LayoutPoint entry_point; @@ -538,6 +579,9 @@ double ComputeDistanceDataForNode(SpatialNavigationDirection direction, LayoutUnit x_axis = (exit_point.X() - entry_point.X()).Abs(); LayoutUnit y_axis = (exit_point.Y() - entry_point.Y()).Abs(); + double euclidian_distance = + sqrt((x_axis * x_axis + y_axis * y_axis).ToDouble()); + distance += euclidian_distance; LayoutUnit navigation_axis_distance; LayoutUnit weighted_orthogonal_axis_distance; @@ -572,21 +616,17 @@ double ComputeDistanceDataForNode(SpatialNavigationDirection direction, break; default: NOTREACHED(); - return MaxDistance(); + return kMaxDistance; } - double euclidian_distance_pow2 = - (x_axis * x_axis + y_axis * y_axis).ToDouble(); - LayoutRect intersection_rect = Intersection(current_rect, node_rect); - double overlap = - (intersection_rect.Width() * intersection_rect.Height()).ToDouble(); - // Distance calculation is based on http://www.w3.org/TR/WICD/#focus-handling - return sqrt(euclidian_distance_pow2) + navigation_axis_distance + + return distance + navigation_axis_distance + weighted_orthogonal_axis_distance - sqrt(overlap); } -// Returns a thin rectangle that represents one of box's sides. +// Returns a thin rectangle that represents one of |box|'s edges. +// To not intersect elements that are positioned inside |box|, we add one +// LayoutUnit of margin that puts the returned slice "just outside" |box|. LayoutRect OppositeEdge(SpatialNavigationDirection side, const LayoutRect& box, LayoutUnit thickness) { @@ -595,16 +635,20 @@ LayoutRect OppositeEdge(SpatialNavigationDirection side, case SpatialNavigationDirection::kLeft: thin_rect.SetX(thin_rect.MaxX() - thickness); thin_rect.SetWidth(thickness); + thin_rect.Move(1, 0); break; case SpatialNavigationDirection::kRight: thin_rect.SetWidth(thickness); + thin_rect.Move(-1, 0); break; case SpatialNavigationDirection::kDown: thin_rect.SetHeight(thickness); + thin_rect.Move(0, -1); break; case SpatialNavigationDirection::kUp: thin_rect.SetY(thin_rect.MaxY() - thickness); thin_rect.SetHeight(thickness); + thin_rect.Move(0, 1); break; default: NOTREACHED(); @@ -623,7 +667,7 @@ LayoutRect StartEdgeForAreaElement(const HTMLAreaElement& area, direction, area.GetDocument().GetFrame()->View()->ConvertToRootFrame( area.ComputeAbsoluteRect(area.ImageElement()->GetLayoutObject())), - LayoutUnit(1) /* snav-imagemap-overlapped-areas.html */); + LayoutUnit(kFudgeFactor) /* snav-imagemap-overlapped-areas.html */); return rect; } diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation.h b/chromium/third_party/blink/renderer/core/page/spatial_navigation.h index 5a6e2725239..7112a4d3bed 100644 --- a/chromium/third_party/blink/renderer/core/page/spatial_navigation.h +++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation.h @@ -36,13 +36,7 @@ class HTMLFrameOwnerElement; enum class SpatialNavigationDirection { kNone, kUp, kRight, kDown, kLeft }; -inline double MaxDistance() { - return std::numeric_limits<double>::max(); -} - -inline int FudgeFactor() { - return 2; -} +constexpr double kMaxDistance = std::numeric_limits<double>::max(); CORE_EXPORT bool IsSpatialNavigationEnabled(const LocalFrame*); @@ -73,14 +67,13 @@ struct FocusCandidate { CORE_EXPORT bool HasRemoteFrame(const Node*); CORE_EXPORT FloatRect RectInViewport(const Node&); CORE_EXPORT bool IsOffscreen(const Node*); +CORE_EXPORT bool IsUnobscured(const FocusCandidate&); bool ScrollInDirection(Node* container, SpatialNavigationDirection); CORE_EXPORT bool IsScrollableNode(const Node* node); CORE_EXPORT bool IsScrollableAreaOrDocument(const Node*); CORE_EXPORT Node* ScrollableAreaOrDocumentOf(Node*); bool CanScrollInDirection(const Node* container, SpatialNavigationDirection); bool CanScrollInDirection(const LocalFrame*, SpatialNavigationDirection); -bool AreElementsOnSameLine(const FocusCandidate& first_candidate, - const FocusCandidate& second_candidate); double ComputeDistanceDataForNode(SpatialNavigationDirection, const FocusCandidate& current_interest, diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc index d15a56d90e2..8ba2f2a154f 100644 --- a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc +++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc @@ -17,6 +17,8 @@ #include "third_party/blink/renderer/core/frame/local_frame.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/html/forms/html_form_control_element.h" +#include "third_party/blink/renderer/core/html/forms/html_form_element.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" #include "third_party/blink/renderer/core/html/media/html_video_element.h" #include "third_party/blink/renderer/core/input/event_handler.h" @@ -90,47 +92,11 @@ static void ConsiderForBestCandidate(SpatialNavigationDirection direction, double distance = ComputeDistanceDataForNode(direction, current_interest, candidate); - if (distance == MaxDistance()) + if (distance == kMaxDistance) return; - if (best_candidate->IsNull()) { - *best_candidate = candidate; - *best_distance = distance; - return; - } - LayoutRect intersection_rect = Intersection( - candidate.rect_in_root_frame, best_candidate->rect_in_root_frame); - if (!intersection_rect.IsEmpty() && - !AreElementsOnSameLine(*best_candidate, candidate) && - intersection_rect == candidate.rect_in_root_frame) { - // If 2 nodes are intersecting, do hit test to find which node in on top. - LayoutUnit x = intersection_rect.X() + intersection_rect.Width() / 2; - LayoutUnit y = intersection_rect.Y() + intersection_rect.Height() / 2; - if (!IsA<LocalFrame>( - candidate.visible_node->GetDocument().GetPage()->MainFrame())) - return; - HitTestLocation location(IntPoint(x.ToInt(), y.ToInt())); - HitTestResult result = - candidate.visible_node->GetDocument() - .GetPage() - ->DeprecatedLocalMainFrame() - ->GetEventHandler() - .HitTestResultAtLocation( - location, HitTestRequest::kReadOnly | HitTestRequest::kActive | - HitTestRequest::kIgnoreClipping); - if (candidate.visible_node->ContainsIncludingHostElements( - *result.InnerNode())) { - *best_candidate = candidate; - *best_distance = distance; - return; - } - if (best_candidate->visible_node->ContainsIncludingHostElements( - *result.InnerNode())) - return; - } - - if (distance < *best_distance) { + if (distance < *best_distance && IsUnobscured(candidate)) { *best_candidate = candidate; *best_distance = distance; } @@ -196,10 +162,18 @@ bool SpatialNavigationController::HandleEnterKeyboardEvent( return false; if (event->type() == event_type_names::kKeydown) { + enter_key_down_seen_ = true; interest_element->SetActive(true); + } else if (event->type() == event_type_names::kKeypress) { + enter_key_press_seen_ = true; } else if (event->type() == event_type_names::kKeyup) { interest_element->SetActive(false); - if (RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled()) { + + // Ensure that the enter key has not already been handled by something else, + // or we can end up clicking elements multiple times. Some elements already + // convert the Enter key into click on down and press (and up) events. + if (RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled() && + enter_key_down_seen_ && enter_key_press_seen_) { interest_element->focus(FocusParams(SelectionBehaviorOnFocus::kReset, kWebFocusTypeSpatialNavigation, nullptr)); @@ -212,6 +186,28 @@ bool SpatialNavigationController::HandleEnterKeyboardEvent( return true; } +void SpatialNavigationController::ResetEnterKeyState() { + enter_key_down_seen_ = false; + enter_key_press_seen_ = false; +} + +bool SpatialNavigationController::HandleImeSubmitKeyboardEvent( + KeyboardEvent* event) { + DCHECK(page_->GetSettings().GetSpatialNavigationEnabled()); + + if (!IsHTMLFormControlElement(GetFocusedElement())) + return false; + + HTMLFormControlElement* element = + ToHTMLFormControlElement(GetFocusedElement()); + + if (!element->formOwner()) + return false; + + element->formOwner()->SubmitImplicitly(*event, true); + return true; +} + bool SpatialNavigationController::HandleEscapeKeyboardEvent( KeyboardEvent* event) { DCHECK(page_->GetSettings().GetSpatialNavigationEnabled()); @@ -248,6 +244,8 @@ void SpatialNavigationController::DidDetachFrameView() { // etc.) then reset navigation. if (interest_element_ && !interest_element_->GetDocument().View()) interest_element_ = nullptr; + // TODO(crbug.com/956209): should be checked via an integration test. + ResetMojoBindings(); } void SpatialNavigationController::Trace(blink::Visitor* visitor) { @@ -317,7 +315,7 @@ FocusCandidate SpatialNavigationController::FindNextCandidateInContainer( current_interest.visible_node = interest_child_in_container; FocusCandidate best_candidate; - double best_distance = MaxDistance(); + double best_distance = kMaxDistance; for (; element; element = IsScrollableAreaOrDocument(element) @@ -550,6 +548,7 @@ void SpatialNavigationController::UpdateSpatialNavigationState( bool change = false; change |= UpdateCanExitFocus(element); change |= UpdateCanSelectInterestedElement(element); + change |= UpdateIsFormFocused(element); change |= UpdateHasNextFormElement(element); change |= UpdateHasDefaultVideoControls(element); if (change) @@ -564,7 +563,7 @@ void SpatialNavigationController::OnSpatialNavigationStateChanged() { } bool SpatialNavigationController::UpdateCanExitFocus(Element* element) { - bool can_exit_focus = IsFocused(element); + bool can_exit_focus = IsFocused(element) && !IsHTMLBodyElement(element); if (can_exit_focus == spatial_navigation_state_->can_exit_focus) return false; spatial_navigation_state_->can_exit_focus = can_exit_focus; @@ -594,6 +593,15 @@ bool SpatialNavigationController::UpdateHasNextFormElement(Element* element) { return true; } +bool SpatialNavigationController::UpdateIsFormFocused(Element* element) { + bool is_form_focused = IsFocused(element) && element->IsFormControlElement(); + + if (is_form_focused == spatial_navigation_state_->is_form_focused) + return false; + spatial_navigation_state_->is_form_focused = is_form_focused; + return true; +} + bool SpatialNavigationController::UpdateHasDefaultVideoControls( Element* element) { bool has_default_video_controls = diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h index 05ee39d5615..98b709da93c 100644 --- a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h +++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h @@ -30,6 +30,11 @@ class CORE_EXPORT SpatialNavigationController bool HandleArrowKeyboardEvent(KeyboardEvent* event); bool HandleEnterKeyboardEvent(KeyboardEvent* event); bool HandleEscapeKeyboardEvent(KeyboardEvent* event); + bool HandleImeSubmitKeyboardEvent(KeyboardEvent* event); + + // Called when the enter key is released to clear local state because we don't + // get a consistent event stream when the Enter key is partially handled. + void ResetEnterKeyState(); // Returns the element that's currently interested. i.e. the Element that's // currently indicated to the user. @@ -40,8 +45,6 @@ class CORE_EXPORT SpatialNavigationController void OnSpatialNavigationSettingChanged(); void FocusedNodeChanged(Document*); - void ResetMojoBindings(); - void Trace(blink::Visitor*); private: @@ -97,15 +100,22 @@ class CORE_EXPORT SpatialNavigationController bool UpdateCanExitFocus(Element* element); bool UpdateCanSelectInterestedElement(Element* element); bool UpdateHasNextFormElement(Element* element); + bool UpdateIsFormFocused(Element* element); bool UpdateHasDefaultVideoControls(Element* element); const mojom::blink::SpatialNavigationHostPtr& GetSpatialNavigationHost(); + void ResetMojoBindings(); // The currently indicated element or nullptr if no node is indicated by // spatial navigation. WeakMember<Element> interest_element_; Member<Page> page_; + // We need to track whether the enter key has been handled in down or press to + // know whether to generate a click on the up. + bool enter_key_down_seen_ = false; + bool enter_key_press_seen_ = false; + mojom::blink::SpatialNavigationStatePtr spatial_navigation_state_; mojom::blink::SpatialNavigationHostPtr spatial_navigation_host_; }; diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc b/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc index e0716b124bf..a7416224660 100644 --- a/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc +++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc @@ -26,26 +26,28 @@ class SpatialNavigationTest : public RenderingTest { LayoutRect TopOfVisualViewport() { LayoutRect visual_viewport = RootViewport(&GetFrame()); + visual_viewport.SetY(visual_viewport.Y() - 1); visual_viewport.SetHeight(LayoutUnit(0)); return visual_viewport; } LayoutRect BottomOfVisualViewport() { LayoutRect visual_viewport = RootViewport(&GetFrame()); - visual_viewport.SetY(visual_viewport.MaxY()); + visual_viewport.SetY(visual_viewport.MaxY() + 1); visual_viewport.SetHeight(LayoutUnit(0)); return visual_viewport; } LayoutRect LeftSideOfVisualViewport() { LayoutRect visual_viewport = RootViewport(&GetFrame()); + visual_viewport.SetX(visual_viewport.X() - 1); visual_viewport.SetWidth(LayoutUnit(0)); return visual_viewport; } LayoutRect RightSideOfVisualViewport() { LayoutRect visual_viewport = RootViewport(&GetFrame()); - visual_viewport.SetX(visual_viewport.MaxX()); + visual_viewport.SetX(visual_viewport.MaxX() + 1); visual_viewport.SetWidth(LayoutUnit(0)); return visual_viewport; } @@ -245,7 +247,7 @@ TEST_F(SpatialNavigationTest, StartAtVisibleFocusedIframe) { } TEST_F(SpatialNavigationTest, StartAtTopWhenGoingDownwardsWithoutFocus) { - EXPECT_EQ(LayoutRect(0, 0, 111, 0), + EXPECT_EQ(LayoutRect(0, -1, 111, 0), SearchOrigin({0, 0, 111, 222}, nullptr, SpatialNavigationDirection::kDown)); @@ -256,7 +258,7 @@ TEST_F(SpatialNavigationTest, StartAtTopWhenGoingDownwardsWithoutFocus) { TEST_F(SpatialNavigationTest, StartAtBottomWhenGoingUpwardsWithoutFocus) { EXPECT_EQ( - LayoutRect(0, 222, 111, 0), + LayoutRect(0, 222 + 1, 111, 0), SearchOrigin({0, 0, 111, 222}, nullptr, SpatialNavigationDirection::kUp)); EXPECT_EQ(SearchOrigin(RootViewport(&GetFrame()), nullptr, @@ -265,7 +267,7 @@ TEST_F(SpatialNavigationTest, StartAtBottomWhenGoingUpwardsWithoutFocus) { } TEST_F(SpatialNavigationTest, StartAtLeftSideWhenGoingEastWithoutFocus) { - EXPECT_EQ(LayoutRect(0, 0, 0, 222), + EXPECT_EQ(LayoutRect(-1, 0, 0, 222), SearchOrigin({0, 0, 111, 222}, nullptr, SpatialNavigationDirection::kRight)); @@ -275,7 +277,7 @@ TEST_F(SpatialNavigationTest, StartAtLeftSideWhenGoingEastWithoutFocus) { } TEST_F(SpatialNavigationTest, StartAtRightSideWhenGoingWestWithoutFocus) { - EXPECT_EQ(LayoutRect(111, 0, 0, 222), + EXPECT_EQ(LayoutRect(111 + 1, 0, 0, 222), SearchOrigin({0, 0, 111, 222}, nullptr, SpatialNavigationDirection::kLeft)); @@ -330,14 +332,15 @@ TEST_F(SpatialNavigationTest, StartAtContainersEdge) { // Go down. LayoutRect container_top_edge = container_box; container_top_edge.SetHeight(LayoutUnit(0)); + container_top_edge.SetY(container_top_edge.Y() - 1); EXPECT_EQ(SearchOrigin(RootViewport(&GetFrame()), b, SpatialNavigationDirection::kDown), container_top_edge); // Go up. LayoutRect container_bottom_edge = container_box; - container_bottom_edge.SetY(container_bottom_edge.MaxX()); container_bottom_edge.SetHeight(LayoutUnit(0)); + container_bottom_edge.SetY(container_bottom_edge.MaxX() + 1); EXPECT_EQ(SearchOrigin(RootViewport(&GetFrame()), b, SpatialNavigationDirection::kUp), container_bottom_edge); @@ -345,13 +348,14 @@ TEST_F(SpatialNavigationTest, StartAtContainersEdge) { // Go right. LayoutRect container_leftmost_edge = container_box; container_leftmost_edge.SetWidth(LayoutUnit(0)); + container_leftmost_edge.SetX(container_leftmost_edge.X() - 1); EXPECT_EQ(SearchOrigin(RootViewport(&GetFrame()), b, SpatialNavigationDirection::kRight), container_leftmost_edge); // Go left. LayoutRect container_rightmost_edge = container_box; - container_rightmost_edge.SetX(container_bottom_edge.MaxX()); + container_rightmost_edge.SetX(container_bottom_edge.MaxX() + 1); container_rightmost_edge.SetWidth(LayoutUnit(0)); EXPECT_EQ(SearchOrigin(RootViewport(&GetFrame()), b, SpatialNavigationDirection::kLeft), @@ -596,7 +600,7 @@ TEST_F(SpatialNavigationTest, BottomOfPinchedViewport) { EXPECT_EQ(origin.Height(), 0); EXPECT_EQ(origin.Width(), GetFrame().View()->Width()); EXPECT_EQ(origin.X(), 0); - EXPECT_EQ(origin.Y(), GetFrame().View()->Height()); + EXPECT_EQ(origin.Y(), GetFrame().View()->Height() + 1); EXPECT_EQ(origin, BottomOfVisualViewport()); // Now, test SearchOrigin with a pinched viewport. @@ -608,7 +612,7 @@ TEST_F(SpatialNavigationTest, BottomOfPinchedViewport) { EXPECT_EQ(origin.Height(), 0); EXPECT_LT(origin.Width(), GetFrame().View()->Width()); EXPECT_GT(origin.X(), 0); - EXPECT_LT(origin.Y(), GetFrame().View()->Height()); + EXPECT_LT(origin.Y(), GetFrame().View()->Height() + 1); EXPECT_EQ(origin, BottomOfVisualViewport()); } @@ -618,7 +622,7 @@ TEST_F(SpatialNavigationTest, TopOfPinchedViewport) { EXPECT_EQ(origin.Height(), 0); EXPECT_EQ(origin.Width(), GetFrame().View()->Width()); EXPECT_EQ(origin.X(), 0); - EXPECT_EQ(origin.Y(), 0); + EXPECT_EQ(origin.Y(), -1); EXPECT_EQ(origin, TopOfVisualViewport()); // Now, test SearchOrigin with a pinched viewport. @@ -630,7 +634,7 @@ TEST_F(SpatialNavigationTest, TopOfPinchedViewport) { EXPECT_EQ(origin.Height(), 0); EXPECT_LT(origin.Width(), GetFrame().View()->Width()); EXPECT_GT(origin.X(), 0); - EXPECT_GT(origin.Y(), 0); + EXPECT_GT(origin.Y(), -1); EXPECT_EQ(origin, TopOfVisualViewport()); } diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc index aff08d420fe..50e185b0966 100644 --- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc +++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc @@ -172,8 +172,16 @@ void CompositingLayerPropertyUpdater::Update(const LayoutObject& object) { auto* main_graphics_layer = mapping->MainGraphicsLayer(); if (main_graphics_layer->ContentsLayer()) { - main_graphics_layer->SetContentsPropertyTreeState( - fragment_data.ContentsProperties()); + IntPoint offset; + // The offset should be zero when the layer has ReplacedContentTransform, + // because the offset has been baked into ReplacedContentTransform. + if (!fragment_data.PaintProperties() || + !fragment_data.PaintProperties()->ReplacedContentTransform()) { + offset = main_graphics_layer->ContentsRect().Location() + + main_graphics_layer->GetOffsetFromTransformNode(); + } + main_graphics_layer->SetContentsLayerState( + fragment_data.ContentsProperties(), offset); } if (auto* squashing_layer = mapping->SquashingLayer()) { diff --git a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc index 2e93937014a..5a6dee4b34c 100644 --- a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc +++ b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc @@ -69,6 +69,15 @@ namespace blink { static constexpr float kStartOpacity = 1; +namespace { + +float HighlightTargetOpacity() { + // For web tests we don't fade out. + return WebTestSupport::IsRunningWebTest() ? kStartOpacity : 0; +} + +} // namespace + static CompositorElementId NewElementId() { if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() || RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { @@ -103,7 +112,7 @@ LinkHighlightImpl::LinkHighlightImpl(Node* node) geometry_needs_update_ = true; EffectPaintPropertyNode::State state; - state.opacity = kStartOpacity; + state.opacity = HighlightTargetOpacity(); state.local_transform_space = &TransformPaintPropertyNode::Root(); state.compositor_element_id = element_id_; state.direct_compositing_reasons = CompositingReason::kActiveOpacityAnimation; @@ -354,10 +363,9 @@ void LinkHighlightImpl::StartHighlightAnimationIfNeeded() { curve->AddKeyframe(CompositorFloatKeyframe( extra_duration_required.InSecondsF(), kStartOpacity, timing_function)); } - // For web tests we don't fade out. curve->AddKeyframe(CompositorFloatKeyframe( (kFadeDuration + extra_duration_required).InSecondsF(), - WebTestSupport::IsRunningWebTest() ? kStartOpacity : 0, timing_function)); + HighlightTargetOpacity(), timing_function)); auto keyframe_model = std::make_unique<CompositorKeyframeModel>( *curve, compositor_target_property::OPACITY, 0, 0); diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_grammar.y b/chromium/third_party/blink/renderer/core/xml/xpath_grammar.y index 17d0b89685d..cf0208370a0 100644 --- a/chromium/third_party/blink/renderer/core/xml/xpath_grammar.y +++ b/chromium/third_party/blink/renderer/core/xml/xpath_grammar.y @@ -34,15 +34,14 @@ #include "third_party/blink/renderer/core/xml/xpath_predicate.h" #include "third_party/blink/renderer/core/xml/xpath_step.h" #include "third_party/blink/renderer/core/xml/xpath_variable_reference.h" -#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" -void* YyFastMalloc(size_t size) -{ - return WTF::Partitions::FastMalloc(size, nullptr); -} - -#define YYMALLOC YyFastMalloc -#define YYFREE WTF::Partitions::FastFree +// The union below must be located on the stack because it contains raw +// pointers to Oilpan objects. crbug.com/961413 +#define YYSTACK_USE_ALLOCA 1 +// Bison's bug? YYSTACK_ALLOC is not defined if _MSC_VER. +#if defined(_MSC_VER) +#define YYSTACK_ALLOC _alloca +#endif #define YYENABLE_NLS 0 #define YYLTYPE_IS_TRIVIAL 1 |