Commit 015b5b58 authored by kenrb's avatar kenrb Committed by Commit bot

Position autofill popup widgets correctly under --site-per-process

When a AutofillHostMsg_QueryFormFieldAutofill message is sent from
an out-of-process iframe, its screen coordinates are relative to the
subframe's rect and not the top-level frame's viewport.

This CL exposes a facility in the content API to perform the necessary
transformation, particularly:
- it promotes GetView() from RenderFrameHostImpl to RenderFrameHost, so the RenderWidgetHostView becomes available to the embedder, and
- it promotes TransformPointToRootCoordSpace from RenderWidgetHostViewBase to RenderWidgetHostView, so that chrome/ or components/ code that directly receives coordinates from a renderer process can ensure they properly transformed

Finally, it causes the ContentAutofillDriver to use the exposed methods to transform received autofill popup coordinates in order for them to display in the correct position.

BUG=554119
CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_site_isolation

Review URL: https://codereview.chromium.org/1526263003

Cr-Commit-Position: refs/heads/master@{#371519}
parent f1edf87b
......@@ -20,8 +20,10 @@
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/site_instance.h"
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/geometry/size_f.h"
namespace autofill {
......@@ -147,6 +149,19 @@ void ContentAutofillDriver::PopupHidden() {
RendererShouldClearPreviewedForm();
}
gfx::RectF ContentAutofillDriver::TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) {
gfx::Point orig_point(bounding_box.x(), bounding_box.y());
gfx::Point transformed_point;
transformed_point =
render_frame_host_->GetView()->TransformPointToRootCoordSpace(orig_point);
gfx::RectF new_box;
new_box.SetRect(transformed_point.x(), transformed_point.y(),
bounding_box.width(), bounding_box.height());
return new_box;
}
bool ContentAutofillDriver::HandleMessage(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ContentAutofillDriver, message)
......
......@@ -61,6 +61,8 @@ class ContentAutofillDriver : public AutofillDriver {
void RendererShouldPreviewFieldWithValue(
const base::string16& value) override;
void PopupHidden() override;
gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) override;
// Handles a message that came from the associated render frame.
bool HandleMessage(const IPC::Message& message);
......
......@@ -17,6 +17,10 @@ namespace net {
class URLRequestContextGetter;
}
namespace gfx {
class RectF;
}
namespace autofill {
class FormStructure;
......@@ -89,6 +93,12 @@ class AutofillDriver {
// Informs the renderer that the popup has been hidden.
virtual void PopupHidden() = 0;
// Transform bounding box coordinates to real viewport coordinates. In
// the case of a page spanning multiple renderer processes, subframe
// renderers cannot do this transformation themselves.
virtual gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) = 0;
};
} // namespace autofill
......
......@@ -401,7 +401,9 @@ void AutofillManager::OnQueryFormFieldAutofill(int query_id,
std::vector<Suggestion> suggestions;
external_delegate_->OnQuery(query_id, form, field, bounding_box);
gfx::RectF transformed_box =
driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
external_delegate_->OnQuery(query_id, form, field, transformed_box);
// Need to refresh models before using the form_event_loggers.
bool is_autofill_possible = RefreshDataModels();
......
......@@ -6,6 +6,7 @@
#include "base/test/sequenced_worker_pool_owner.h"
#include "base/threading/sequenced_worker_pool.h"
#include "ui/gfx/geometry/rect_f.h"
namespace autofill {
......@@ -71,4 +72,9 @@ void TestAutofillDriver::RendererShouldPreviewFieldWithValue(
void TestAutofillDriver::PopupHidden() {
}
gfx::RectF TestAutofillDriver::TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) {
return bounding_box;
}
} // namespace autofill
......@@ -44,6 +44,8 @@ class TestAutofillDriver : public AutofillDriver {
void RendererShouldPreviewFieldWithValue(
const base::string16& value) override;
void PopupHidden() override;
gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) override;
// Methods that tests can use to specialize functionality.
......
......@@ -58,6 +58,8 @@ class AutofillDriverIOS : public AutofillDriver,
void RendererShouldPreviewFieldWithValue(
const base::string16& value) override;
void PopupHidden() override;
gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) override;
private:
AutofillDriverIOS(
......
......@@ -8,6 +8,7 @@
#include "ios/web/public/browser_state.h"
#include "ios/web/public/web_state/web_state.h"
#include "ios/web/public/web_thread.h"
#include "ui/gfx/geometry/rect_f.h"
DEFINE_WEB_STATE_USER_DATA_KEY(autofill::AutofillDriverIOS);
......@@ -98,4 +99,9 @@ void AutofillDriverIOS::RendererShouldPreviewFieldWithValue(
void AutofillDriverIOS::PopupHidden() {
}
gfx::RectF AutofillDriverIOS::TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) {
return bounding_box;
}
} // namespace autofill
......@@ -172,15 +172,15 @@ void CrossProcessFrameConnector::UpdateCursor(const WebCursor& cursor) {
root_view->UpdateCursor(cursor);
}
void CrossProcessFrameConnector::TransformPointToRootCoordSpace(
gfx::Point CrossProcessFrameConnector::TransformPointToRootCoordSpace(
const gfx::Point& point,
cc::SurfaceId surface_id,
gfx::Point* transformed_point) {
cc::SurfaceId surface_id) {
gfx::Point transformed_point = point;
RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView();
*transformed_point = point;
if (root_view)
root_view->TransformPointToLocalCoordSpace(point, surface_id,
transformed_point);
&transformed_point);
return transformed_point;
}
bool CrossProcessFrameConnector::HasFocus() {
......
......@@ -101,9 +101,8 @@ class CONTENT_EXPORT CrossProcessFrameConnector {
float device_scale_factor() const { return device_scale_factor_; }
void GetScreenInfo(blink::WebScreenInfo* results);
void UpdateCursor(const WebCursor& cursor);
void TransformPointToRootCoordSpace(const gfx::Point& point,
cc::SurfaceId surface_id,
gfx::Point* transformed_point);
gfx::Point TransformPointToRootCoordSpace(const gfx::Point& point,
cc::SurfaceId surface_id);
// Determines whether the root RenderWidgetHostView (and thus the current
// page) has focus.
......
......@@ -1327,9 +1327,9 @@ void RenderFrameHostImpl::OnContextMenu(const ContextMenuParams& params) {
// It is necessary to transform the coordinates to account for nested
// RenderWidgetHosts, such as with out-of-process iframes.
gfx::Point original_point(validated_params.x, validated_params.y);
gfx::Point transformed_point = original_point;
static_cast<RenderWidgetHostViewBase*>(GetView())
->TransformPointToRootCoordSpace(original_point, &transformed_point);
gfx::Point transformed_point =
static_cast<RenderWidgetHostViewBase*>(GetView())
->TransformPointToRootCoordSpace(original_point);
validated_params.x = transformed_point.x();
validated_params.y = transformed_point.y();
......
......@@ -168,6 +168,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
void InsertVisualStateCallback(
const VisualStateCallback& callback) override;
bool IsRenderFrameLive() override;
RenderWidgetHostView* GetView() override;
#if defined(OS_ANDROID)
void ActivateNearestFindResult(int request_id, float x, float y) override;
void RequestFindMatchRects(int current_version) override;
......@@ -251,9 +252,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// pointer to the RenderViewHost (which inherits RenderWidgetHost).
RenderWidgetHostImpl* GetRenderWidgetHost();
// This returns the RenderWidgetHostView that can be used to control
// focus and visibility for this frame.
RenderWidgetHostView* GetView();
// This function is called when this is a swapped out RenderFrameHost that
// lives in the same process as the parent frame. The
......
......@@ -381,15 +381,12 @@ void RenderWidgetHostViewChildFrame::ProcessMouseWheelEvent(
host_->ForwardWheelEvent(event);
}
void RenderWidgetHostViewChildFrame::TransformPointToRootCoordSpace(
const gfx::Point& point,
gfx::Point* transformed_point) {
*transformed_point = point;
gfx::Point RenderWidgetHostViewChildFrame::TransformPointToRootCoordSpace(
const gfx::Point& point) {
if (!frame_connector_ || !use_surfaces_)
return;
return point;
frame_connector_->TransformPointToRootCoordSpace(point, surface_id_,
transformed_point);
return frame_connector_->TransformPointToRootCoordSpace(point, surface_id_);
}
#if defined(OS_MACOSX)
......
......@@ -128,8 +128,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) override;
void ProcessMouseEvent(const blink::WebMouseEvent& event) override;
void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
void TransformPointToRootCoordSpace(const gfx::Point& point,
gfx::Point* transformed_point) override;
gfx::Point TransformPointToRootCoordSpace(const gfx::Point& point) override;
#if defined(OS_MACOSX)
// RenderWidgetHostView implementation.
......
......@@ -14,6 +14,7 @@
#include "content/common/content_switches_internal.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "ui/gfx/display.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/screen.h"
......@@ -682,10 +683,15 @@ uint32_t RenderWidgetHostViewBase::SurfaceIdNamespaceAtPoint(
return 0;
}
void RenderWidgetHostViewBase::TransformPointToRootCoordSpace(
const gfx::Point& point,
gfx::Point* transformed_point) {
*transformed_point = point;
gfx::Point RenderWidgetHostViewBase::TransformPointToRootCoordSpace(
const gfx::Point& point) {
return point;
}
gfx::PointF RenderWidgetHostViewBase::TransformPointToRootCoordSpaceF(
const gfx::PointF& point) {
return gfx::PointF(TransformPointToRootCoordSpace(
gfx::ToRoundedPoint(point)));
}
void RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
......
......@@ -88,6 +88,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override;
void EndFrameSubscription() override;
// This only needs to be overridden by RenderWidgetHostViewBase subclasses
// that handle content embedded within other RenderWidgetHostViews.
gfx::Point TransformPointToRootCoordSpace(const gfx::Point& point) override;
gfx::PointF TransformPointToRootCoordSpaceF(
const gfx::PointF& point) override;
// IPC::Listener implementation:
bool OnMessageReceived(const IPC::Message& msg) override;
......@@ -204,15 +210,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
virtual void ProcessTouchEvent(const blink::WebTouchEvent& event,
const ui::LatencyInfo& latency) {}
// If a RenderWidgetHost is dealing with points that are transformed from the
// root frame for a page (i.e. because its content is contained within
// that of another RenderWidgetHost), this provides a facility to convert
// a point from its own coordinate space to that of the root frame.
// This only needs to be overriden by RenderWidgetHostView subclasses
// that handle content embedded within other RenderWidgetHostViews.
virtual void TransformPointToRootCoordSpace(const gfx::Point& point,
gfx::Point* transformed_point);
// Transform a point that is in the coordinate space of a Surface that is
// embedded within the RenderWidgetHostViewBase's Surface to the
// coordinate space of the embedding Surface. Typically this means that a
......
......@@ -26,6 +26,7 @@ class Value;
namespace content {
class RenderProcessHost;
class RenderViewHost;
class RenderWidgetHostView;
class ServiceRegistry;
class SiteInstance;
......@@ -73,6 +74,10 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
// Returns the process for this frame.
virtual RenderProcessHost* GetProcess() = 0;
// Returns the RenderWidgetHostView that can be used to control focus and
// visibility for this frame.
virtual RenderWidgetHostView* GetView() = 0;
// Returns the current RenderFrameHost of the parent frame, or nullptr if
// there is no parent. The result may be in a different process than the
// current RenderFrameHost.
......
......@@ -65,6 +65,19 @@ class CONTENT_EXPORT RenderWidgetHostView {
// Retrieves the last known scroll position.
virtual gfx::Vector2dF GetLastScrollOffset() const = 0;
// Coordinate points received from a renderer process need to be transformed
// to the top-level frame's coordinate space. For coordinates received from
// the top-level frame's renderer this is a no-op as they are already
// properly transformed; however, coordinates received from an out-of-process
// iframe renderer process require transformation.
virtual gfx::Point TransformPointToRootCoordSpace(
const gfx::Point& point) = 0;
// A floating point variant of the above. PointF values will be snapped to
// integral points before transformation.
virtual gfx::PointF TransformPointToRootCoordSpaceF(
const gfx::PointF& point) = 0;
// Retrieves the native view used to contain plugins and identify the
// renderer in IPC messages.
virtual gfx::NativeView GetNativeView() const = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment