summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/surfaces/surface_hittest_delegate.h4
-rw-r--r--cc/surfaces/surface_id.h8
-rw-r--r--content/browser/compositor/delegated_frame_host.cc3
-rw-r--r--content/browser/compositor/delegated_frame_host.h3
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.cc8
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.h2
-rw-r--r--content/browser/renderer_host/render_widget_host_input_event_router.cc41
-rw-r--r--content/browser/renderer_host/render_widget_host_input_event_router.h25
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.cc5
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.h3
-rw-r--r--content/browser/renderer_host/render_widget_host_view_base.cc1
-rw-r--r--content/browser/renderer_host/render_widget_host_view_base.h10
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.h3
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.mm5
-rw-r--r--content/browser/site_per_process_browsertest.cc75
-rw-r--r--content/common/frame_messages.h14
-rw-r--r--content/renderer/BUILD.gn1
-rw-r--r--content/renderer/child_frame_compositing_helper.cc1
-rw-r--r--content/renderer/child_frame_compositing_helper.h5
-rw-r--r--content/renderer/render_frame_proxy.cc11
-rw-r--r--content/renderer/render_frame_proxy.h4
-rw-r--r--content/renderer/render_widget.cc3
-rw-r--r--content/test/data/frame_tree/page_with_positioned_frame_pointer-events_none.html17
-rw-r--r--third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp7
-rw-r--r--third_party/WebKit/Source/web/WebRemoteFrameImpl.h2
-rw-r--r--third_party/WebKit/public/web/WebRemoteFrame.h3
26 files changed, 251 insertions, 13 deletions
diff --git a/cc/surfaces/surface_hittest_delegate.h b/cc/surfaces/surface_hittest_delegate.h
index 1f0fbf9..59095f8 100644
--- a/cc/surfaces/surface_hittest_delegate.h
+++ b/cc/surfaces/surface_hittest_delegate.h
@@ -5,6 +5,10 @@
#ifndef CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_
#define CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_
+namespace gfx {
+class Point;
+} // namespace gfx
+
namespace cc {
class SurfaceDrawQuad;
diff --git a/cc/surfaces/surface_id.h b/cc/surfaces/surface_id.h
index 0ade6ab..f43759c 100644
--- a/cc/surfaces/surface_id.h
+++ b/cc/surfaces/surface_id.h
@@ -8,6 +8,8 @@
#include <stddef.h>
#include <stdint.h>
+#include <functional>
+
#include "base/containers/hash_tables.h"
namespace cc {
@@ -33,6 +35,12 @@ inline bool operator<(const SurfaceId& a, const SurfaceId& b) {
return a.id < b.id;
}
+struct SurfaceIdHash {
+ size_t operator()(const SurfaceId& key) const {
+ return std::hash<uint64_t>()(key.id);
+ }
+};
+
} // namespace cc
namespace BASE_HASH_NAMESPACE {
diff --git a/content/browser/compositor/delegated_frame_host.cc b/content/browser/compositor/delegated_frame_host.cc
index 4a32e70..53a943f 100644
--- a/content/browser/compositor/delegated_frame_host.cc
+++ b/content/browser/compositor/delegated_frame_host.cc
@@ -207,11 +207,12 @@ uint32_t DelegatedFrameHost::GetSurfaceIdNamespace() {
}
cc::SurfaceId DelegatedFrameHost::SurfaceIdAtPoint(
+ cc::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
if (surface_id_.is_null())
return surface_id_;
- cc::SurfaceHittest hittest(nullptr, GetSurfaceManager());
+ cc::SurfaceHittest hittest(delegate, GetSurfaceManager());
gfx::Transform target_transform;
cc::SurfaceId target_surface_id =
hittest.GetTargetSurfaceAtPoint(surface_id_, point, &target_transform);
diff --git a/content/browser/compositor/delegated_frame_host.h b/content/browser/compositor/delegated_frame_host.h
index d1237af..51a89fb 100644
--- a/content/browser/compositor/delegated_frame_host.h
+++ b/content/browser/compositor/delegated_frame_host.h
@@ -159,7 +159,8 @@ class CONTENT_EXPORT DelegatedFrameHost
uint32_t GetSurfaceIdNamespace();
// Returns a null SurfaceId if this DelegatedFrameHost has not yet created
// a compositor Surface.
- cc::SurfaceId SurfaceIdAtPoint(const gfx::Point& point,
+ cc::SurfaceId SurfaceIdAtPoint(cc::SurfaceHittestDelegate* delegate,
+ const gfx::Point& point,
gfx::Point* transformed_point);
// Given the SurfaceID of a Surface that is contained within this class'
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index e121325..891d4c7 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -45,6 +45,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
+#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_owner_delegate.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_constants_internal.h"
@@ -444,6 +445,7 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostImpl, msg)
IPC_MESSAGE_HANDLER(FrameHostMsg_RenderProcessGone, OnRenderProcessGone)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_HittestData, OnHittestData)
IPC_MESSAGE_HANDLER(InputHostMsg_QueueSyntheticGesture,
OnQueueSyntheticGesture)
IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
@@ -1508,6 +1510,12 @@ void RenderWidgetHostImpl::OnRenderProcessGone(int status, int exit_code) {
}
}
+void RenderWidgetHostImpl::OnHittestData(
+ const FrameHostMsg_HittestData_Params& params) {
+ if (delegate_)
+ delegate_->GetInputEventRouter()->OnHittestData(params);
+}
+
void RenderWidgetHostImpl::OnClose() {
ShutdownAndDestroyWidget(true);
}
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index b944c20..2b3ceb7 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -46,6 +46,7 @@
#include "ui/events/latency_info.h"
#include "ui/gfx/native_widget_types.h"
+struct FrameHostMsg_HittestData_Params;
struct ViewHostMsg_SelectionBounds_Params;
struct ViewHostMsg_TextInputState_Params;
struct ViewHostMsg_UpdateRect_Params;
@@ -590,6 +591,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
void OnSelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params);
void OnForwardCompositorProto(const std::vector<uint8_t>& proto);
+ void OnHittestData(const FrameHostMsg_HittestData_Params& params);
// Called (either immediately or asynchronously) after we're done with our
// BackingStore and can send an ACK to the renderer so it can paint onto it
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index eef72ac..67bbd4e 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -4,12 +4,29 @@
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
+#include "cc/quads/surface_draw_quad.h"
+#include "cc/surfaces/surface_id_allocator.h"
#include "cc/surfaces/surface_manager.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/common/frame_messages.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
+RenderWidgetHostInputEventRouter::HittestDelegate::HittestDelegate(
+ const std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>&
+ hittest_data)
+ : hittest_data_(hittest_data) {}
+
+bool RenderWidgetHostInputEventRouter::HittestDelegate::RejectHitTarget(
+ const cc::SurfaceDrawQuad* surface_quad,
+ const gfx::Point& point_in_quad_space) {
+ auto it = hittest_data_.find(surface_quad->surface_id);
+ if (it != hittest_data_.end() && it->second.ignored_for_hittest)
+ return true;
+ return false;
+}
+
RenderWidgetHostInputEventRouter::RenderWidgetHostInputEventRouter()
: active_touches_(0) {}
@@ -28,12 +45,16 @@ RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget(
return root_view;
}
+ // The hittest delegate is used to reject hittesting quads based on extra
+ // hittesting data send by the renderer.
+ HittestDelegate delegate(hittest_data_);
+
// The conversion of point to transform_point is done over the course of the
// hit testing, and reflect transformations that would normally be applied in
// the renderer process if the event was being routed between frames within a
// single process with only one RenderWidgetHost.
uint32_t surface_id_namespace =
- root_view->SurfaceIdNamespaceAtPoint(point, transformed_point);
+ root_view->SurfaceIdNamespaceAtPoint(&delegate, point, transformed_point);
const SurfaceIdNamespaceOwnerMap::iterator iter =
owner_map_.find(surface_id_namespace);
// If the point hit a Surface whose namspace is no longer in the map, then
@@ -134,6 +155,24 @@ void RenderWidgetHostInputEventRouter::AddSurfaceIdNamespaceOwner(
void RenderWidgetHostInputEventRouter::RemoveSurfaceIdNamespaceOwner(
uint32_t id) {
owner_map_.erase(id);
+
+ for (auto it = hittest_data_.begin(); it != hittest_data_.end();) {
+ if (cc::SurfaceIdAllocator::NamespaceForId(it->first) == id)
+ it = hittest_data_.erase(it);
+ else
+ ++it;
+ }
+}
+
+void RenderWidgetHostInputEventRouter::OnHittestData(
+ const FrameHostMsg_HittestData_Params& params) {
+ if (owner_map_.find(cc::SurfaceIdAllocator::NamespaceForId(
+ params.surface_id)) == owner_map_.end()) {
+ return;
+ }
+ HittestData data;
+ data.ignored_for_hittest = params.ignored_for_hittest;
+ hittest_data_[params.surface_id] = data;
}
} // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h
index 03902f5..ec45f15 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -6,12 +6,17 @@
#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_INPUT_EVENT_ROUTER_H_
#include <stdint.h>
+#include <unordered_map>
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "cc/surfaces/surface_hittest_delegate.h"
+#include "cc/surfaces/surface_id.h"
#include "content/common/content_export.h"
+struct FrameHostMsg_HittestData_Params;
+
namespace blink {
class WebMouseEvent;
class WebMouseWheelEvent;
@@ -56,7 +61,25 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter {
return owner_map_.find(id) != owner_map_.end();
}
+ void OnHittestData(const FrameHostMsg_HittestData_Params& params);
+
private:
+ struct HittestData {
+ bool ignored_for_hittest;
+ };
+
+ class HittestDelegate : public cc::SurfaceHittestDelegate {
+ public:
+ HittestDelegate(
+ const std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>&
+ hittest_data);
+ bool RejectHitTarget(const cc::SurfaceDrawQuad* surface_quad,
+ const gfx::Point& point_in_quad_space) override;
+
+ const std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>&
+ hittest_data_;
+ };
+
using WeakTarget = base::WeakPtr<RenderWidgetHostViewBase>;
using SurfaceIdNamespaceOwnerMap =
base::hash_map<uint32_t, base::WeakPtr<RenderWidgetHostViewBase>>;
@@ -68,6 +91,8 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter {
SurfaceIdNamespaceOwnerMap owner_map_;
WeakTarget current_touch_target_;
int active_touches_;
+ std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>
+ hittest_data_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouter);
};
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 02e38ec..df5db76 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2208,6 +2208,7 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
}
uint32_t RenderWidgetHostViewAura::SurfaceIdNamespaceAtPoint(
+ cc::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
DCHECK(device_scale_factor_ != 0.0f);
@@ -2216,8 +2217,8 @@ uint32_t RenderWidgetHostViewAura::SurfaceIdNamespaceAtPoint(
// |point| from DIPs to pixels before hittesting.
gfx::Point point_in_pixels =
gfx::ConvertPointToPixel(device_scale_factor_, point);
- cc::SurfaceId id = delegated_frame_host_->SurfaceIdAtPoint(point_in_pixels,
- transformed_point);
+ cc::SurfaceId id = delegated_frame_host_->SurfaceIdAtPoint(
+ delegate, point_in_pixels, transformed_point);
*transformed_point =
gfx::ConvertPointToDIP(device_scale_factor_, *transformed_point);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 4775a6f..b3a7d24 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -195,7 +195,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void LockCompositingSurface() override;
void UnlockCompositingSurface() override;
uint32_t GetSurfaceIdNamespace() override;
- uint32_t SurfaceIdNamespaceAtPoint(const gfx::Point& point,
+ uint32_t SurfaceIdNamespaceAtPoint(cc::SurfaceHittestDelegate* delegate,
+ const gfx::Point& point,
gfx::Point* transformed_point) override;
void ProcessMouseEvent(const blink::WebMouseEvent& event) override;
void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 6adada7..780ced5 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -676,6 +676,7 @@ uint32_t RenderWidgetHostViewBase::GetSurfaceIdNamespace() {
}
uint32_t RenderWidgetHostViewBase::SurfaceIdNamespaceAtPoint(
+ cc::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
NOTREACHED();
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index fa223b8..8c6102e 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -51,6 +51,10 @@ class WebMouseEvent;
class WebMouseWheelEvent;
}
+namespace cc {
+class SurfaceHittestDelegate;
+}
+
namespace ui {
class LatencyInfo;
}
@@ -202,8 +206,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// methods are invoked on the RenderWidgetHostView that should be able to
// properly handle the event (i.e. it has focus for keyboard events, or has
// been identified by hit testing mouse, touch or gesture events).
- virtual uint32_t SurfaceIdNamespaceAtPoint(const gfx::Point& point,
- gfx::Point* transformed_point);
+ virtual uint32_t SurfaceIdNamespaceAtPoint(
+ cc::SurfaceHittestDelegate* delegate,
+ const gfx::Point& point,
+ gfx::Point* transformed_point);
virtual void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) {}
virtual void ProcessMouseEvent(const blink::WebMouseEvent& event) {}
virtual void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) {}
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index 459f16a..f4cd27b 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -349,7 +349,8 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget() override;
uint32_t GetSurfaceIdNamespace() override;
- uint32_t SurfaceIdNamespaceAtPoint(const gfx::Point& point,
+ uint32_t SurfaceIdNamespaceAtPoint(cc::SurfaceHittestDelegate* delegate,
+ const gfx::Point& point,
gfx::Point* transformed_point) override;
// Returns true when we can do SurfaceHitTesting for the event type.
bool ShouldRouteEvent(const blink::WebInputEvent& event) const;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 87b86b0..9987017 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1570,6 +1570,7 @@ uint32_t RenderWidgetHostViewMac::GetSurfaceIdNamespace() {
}
uint32_t RenderWidgetHostViewMac::SurfaceIdNamespaceAtPoint(
+ cc::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
// The surface hittest happens in device pixels, so we need to convert the
@@ -1578,8 +1579,8 @@ uint32_t RenderWidgetHostViewMac::SurfaceIdNamespaceAtPoint(
->GetDisplayNearestWindow(cocoa_view_)
.device_scale_factor();
gfx::Point point_in_pixels = gfx::ConvertPointToPixel(scale_factor, point);
- cc::SurfaceId id = delegated_frame_host_->SurfaceIdAtPoint(point_in_pixels,
- transformed_point);
+ cc::SurfaceId id = delegated_frame_host_->SurfaceIdAtPoint(
+ delegate, point_in_pixels, transformed_point);
*transformed_point = gfx::ConvertPointToDIP(scale_factor, *transformed_point);
// It is possible that the renderer has not yet produced a surface, in which
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 67318be..f7a373b 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -772,6 +772,78 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessHighDPIBrowserTest,
SurfaceHitTestTestHelper(shell(), embedded_test_server());
}
+// This test tests that browser process hittesting ignores frames with
+// pointer-events: none.
+#if defined(OS_ANDROID)
+// Browser process hit testing is not implemented on Android.
+// https://crbug.com/491334
+#define MAYBE_SurfaceHitTestPointerEventsNone \
+ DISABLED_SurfaceHitTestPointerEventsNone
+#else
+#define MAYBE_SurfaceHitTestPointerEventsNone SurfaceHitTestPointerEventsNone
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ MAYBE_SurfaceHitTestPointerEventsNone) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_frame_pointer-events_none.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* child_node = root->child_at(0);
+ GURL site_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
+ EXPECT_EQ(site_url, child_node->current_url());
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ child_node->current_frame_host()->GetSiteInstance());
+
+ // Create listeners for mouse events.
+ RenderWidgetHostMouseEventMonitor main_frame_monitor(
+ root->current_frame_host()->GetRenderWidgetHost());
+ RenderWidgetHostMouseEventMonitor child_frame_monitor(
+ child_node->current_frame_host()->GetRenderWidgetHost());
+
+ RenderWidgetHostInputEventRouter* router =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetInputEventRouter();
+
+ RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ // We need to wait for a compositor frame from the child frame, at which
+ // point its surface will be created.
+ while (rwhv_child->RendererFrameNumber() <= 0) {
+ // TODO(lazyboy): Find a better way to avoid sleeping like this. See
+ // http://crbug.com/405282 for details.
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(10));
+ run_loop.Run();
+ }
+
+ // Target input event to child frame.
+ blink::WebMouseEvent child_event;
+ child_event.type = blink::WebInputEvent::MouseDown;
+ child_event.button = blink::WebPointerProperties::ButtonLeft;
+ child_event.x = 75;
+ child_event.y = 75;
+ child_event.clickCount = 1;
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+ router->RouteMouseEvent(root_view, &child_event);
+
+ EXPECT_TRUE(main_frame_monitor.EventWasReceived());
+ EXPECT_EQ(75, main_frame_monitor.event().x);
+ EXPECT_EQ(75, main_frame_monitor.event().y);
+ EXPECT_FALSE(child_frame_monitor.EventWasReceived());
+}
+
// Tests OOPIF rendering by checking that the RWH of the iframe generates
// OnSwapCompositorFrame message.
#if defined(OS_ANDROID)
@@ -4408,7 +4480,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CreateContextMenuTest) {
// updated compositor surfaces from both renderer processes.
gfx::Point point(75, 75);
gfx::Point transformed_point;
- while (root_view->SurfaceIdNamespaceAtPoint(point, &transformed_point) !=
+ while (root_view->SurfaceIdNamespaceAtPoint(nullptr, point,
+ &transformed_point) !=
rwhv_child->GetSurfaceIdNamespace()) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 510b0fe..6e9f362 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -504,6 +504,17 @@ IPC_STRUCT_BEGIN(FrameMsg_SerializeAsMHTML_Params)
IPC_STRUCT_MEMBER(bool, is_last_frame)
IPC_STRUCT_END()
+// This message is used to send hittesting data from the renderer in order
+// to perform hittesting on the browser process.
+IPC_STRUCT_BEGIN(FrameHostMsg_HittestData_Params)
+ // |surface_id| represents the surface used by this remote frame.
+ IPC_STRUCT_MEMBER(cc::SurfaceId, surface_id)
+
+ // If |ignored_for_hittest| then this surface should be ignored during
+ // hittesting.
+ IPC_STRUCT_MEMBER(bool, ignored_for_hittest)
+IPC_STRUCT_END()
+
#if defined(OS_MACOSX) || defined(OS_ANDROID)
// This message is used for supporting popup menus on Mac OS X and Android using
// native controls. See the FrameHostMsg_ShowPopup message.
@@ -1410,6 +1421,9 @@ IPC_MESSAGE_ROUTED5(FrameHostMsg_Find_Reply,
int /* active_match_ordinal */,
bool /* final_update */)
+// Sends hittesting data needed to perform hittesting on the browser process.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_HittestData, FrameHostMsg_HittestData_Params)
+
#if defined(OS_MACOSX) || defined(OS_ANDROID)
// Message to show/hide a popup menu using native controls.
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index a8c9147..b08f9dd 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -33,6 +33,7 @@ source_set("renderer") {
"//cc/blink",
"//cc/proto",
"//cc/surfaces",
+ "//cc/surfaces:surface_id",
"//components/scheduler:scheduler",
"//components/startup_metric_utils/common",
"//components/url_formatter",
diff --git a/content/renderer/child_frame_compositing_helper.cc b/content/renderer/child_frame_compositing_helper.cc
index ef85384..0166a08 100644
--- a/content/renderer/child_frame_compositing_helper.cc
+++ b/content/renderer/child_frame_compositing_helper.cc
@@ -293,6 +293,7 @@ void ChildFrameCompositingHelper::OnSetSurface(
const gfx::Size& frame_size,
float scale_factor,
const cc::SurfaceSequence& sequence) {
+ surface_id_ = surface_id;
scoped_refptr<ThreadSafeSender> sender(
RenderThreadImpl::current()->thread_safe_sender());
cc::SurfaceLayer::SatisfyCallback satisfy_callback =
diff --git a/content/renderer/child_frame_compositing_helper.h b/content/renderer/child_frame_compositing_helper.h
index d2d4e78..707955c 100644
--- a/content/renderer/child_frame_compositing_helper.h
+++ b/content/renderer/child_frame_compositing_helper.h
@@ -15,6 +15,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "cc/layers/delegated_frame_resource_collection.h"
+#include "cc/surfaces/surface_id.h"
#include "content/common/content_export.h"
#include "ui/gfx/geometry/size.h"
@@ -23,7 +24,6 @@ class SharedMemory;
}
namespace cc {
-struct SurfaceId;
struct SurfaceSequence;
class CompositorFrame;
@@ -79,6 +79,8 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
void UpdateVisibility(bool);
void ChildFrameGone();
+ cc::SurfaceId surface_id() const { return surface_id_; }
+
// cc::DelegatedFrameProviderClient implementation.
void UnusedResourcesAreAvailable() override;
@@ -146,6 +148,7 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
scoped_ptr<blink::WebLayer> web_layer_;
+ cc::SurfaceId surface_id_;
blink::WebFrame* frame_;
DISALLOW_COPY_AND_ASSIGN(ChildFrameCompositingHelper);
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc
index d8effb5..7a52f2c 100644
--- a/content/renderer/render_frame_proxy.cc
+++ b/content/renderer/render_frame_proxy.cc
@@ -195,6 +195,17 @@ bool RenderFrameProxy::IsMainFrameDetachedFromTree() const {
render_view_->webview()->mainFrame()->isWebLocalFrame();
}
+void RenderFrameProxy::WillBeginCompositorFrame() {
+ if (compositing_helper_) {
+ FrameHostMsg_HittestData_Params params;
+ params.surface_id = compositing_helper_->surface_id();
+ params.ignored_for_hittest = web_frame_->isIgnoredForHitTest();
+ render_widget_->QueueMessage(
+ new FrameHostMsg_HittestData(render_widget_->routing_id(), params),
+ MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
+ }
+}
+
void RenderFrameProxy::DidCommitCompositorFrame() {
if (compositing_helper_.get())
compositing_helper_->DidCommitCompositorFrame();
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h
index 7581d38..f6dc700 100644
--- a/content/renderer/render_frame_proxy.h
+++ b/content/renderer/render_frame_proxy.h
@@ -104,6 +104,10 @@ class CONTENT_EXPORT RenderFrameProxy
bool Send(IPC::Message* msg) override;
// Out-of-process child frames receive a signal from RenderWidgetCompositor
+ // when a compositor frame will begin.
+ void WillBeginCompositorFrame();
+
+ // Out-of-process child frames receive a signal from RenderWidgetCompositor
// when a compositor frame has committed.
void DidCommitCompositorFrame();
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index ddd60cb..345528f 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -1223,6 +1223,9 @@ void RenderWidget::WillBeginCompositorFrame() {
// is done.
UpdateTextInputState(ShowIme::HIDE_IME, ChangeSource::FROM_NON_IME);
UpdateSelectionBounds();
+
+ FOR_EACH_OBSERVER(RenderFrameProxy, render_frame_proxies_,
+ WillBeginCompositorFrame());
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/content/test/data/frame_tree/page_with_positioned_frame_pointer-events_none.html b/content/test/data/frame_tree/page_with_positioned_frame_pointer-events_none.html
new file mode 100644
index 0000000..2e42948
--- /dev/null
+++ b/content/test/data/frame_tree/page_with_positioned_frame_pointer-events_none.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<style>
+iframe {
+ position:absolute;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 100px;
+ pointer-events: none;
+}
+</style>
+<html>
+<body>
+<iframe src="/cross-site/baz.com/title1.html"></iframe>
+This page contains a positioned cross-origin iframe.
+</body>
+</html>
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
index f4b0b21..4b3a445 100644
--- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
@@ -7,6 +7,7 @@
#include "core/frame/FrameView.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/layout/LayoutObject.h"
#include "core/page/Page.h"
#include "platform/heap/Handle.h"
#include "public/platform/WebFloatRect.h"
@@ -809,6 +810,12 @@ void WebRemoteFrameImpl::didStopLoading()
}
}
+bool WebRemoteFrameImpl::isIgnoredForHitTest() const
+{
+ HTMLFrameOwnerElement* owner = frame()->deprecatedLocalOwner();
+ return owner ? owner->layoutObject()->style()->pointerEvents() == PE_NONE : false;
+}
+
WebRemoteFrameImpl::WebRemoteFrameImpl(WebTreeScopeType scope, WebRemoteFrameClient* client)
: WebRemoteFrame(scope)
, m_frameClient(RemoteFrameClientImpl::create(this))
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
index 2d7f4db1..55a85f006 100644
--- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
+++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
@@ -192,6 +192,8 @@ public:
void didStartLoading() override;
void didStopLoading() override;
+ bool isIgnoredForHitTest() const override;
+
#if ENABLE(OILPAN)
DECLARE_TRACE();
#endif
diff --git a/third_party/WebKit/public/web/WebRemoteFrame.h b/third_party/WebKit/public/web/WebRemoteFrame.h
index f8f03e1..ba5cd0a 100644
--- a/third_party/WebKit/public/web/WebRemoteFrame.h
+++ b/third_party/WebKit/public/web/WebRemoteFrame.h
@@ -47,6 +47,9 @@ public:
virtual void didStartLoading() = 0;
virtual void didStopLoading() = 0;
+ // Returns true if this frame should be ignored during hittesting.
+ virtual bool isIgnoredForHitTest() const = 0;
+
// Temporary method to allow embedders to get the script context of a
// remote frame. This should only be used by legacy code that has not yet
// migrated over to the new OOPI infrastructure.