summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/blink/renderer/core
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core')
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection.h6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_test.cc127
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/radio_input_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_anchor_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/loader/form_submission.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_load_request.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_load_request.h13
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader_types.h1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/page/focus_controller.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/page/page.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation.cc156
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation.h11
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc90
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h14
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_grammar.y15
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