blob: a3a6447e10530cb6559b4a9f96346c3d93496244 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/shell/test_runner/web_view_test_proxy.h"
#include <stddef.h>
#include <stdint.h>
#include "content/renderer/compositor/layer_tree_view.h"
#include "content/shell/test_runner/accessibility_controller.h"
#include "content/shell/test_runner/test_interfaces.h"
#include "content/shell/test_runner/test_runner.h"
#include "content/shell/test_runner/test_runner_for_specific_view.h"
#include "content/shell/test_runner/text_input_controller.h"
#include "content/shell/test_runner/web_test_delegate.h"
#include "content/shell/test_runner/web_test_interfaces.h"
#include "content/shell/test_runner/web_widget_test_proxy.h"
#include "third_party/blink/public/web/web_frame.h"
#include "third_party/blink/public/web/web_view.h"
namespace test_runner {
ProxyWebWidgetClient::ProxyWebWidgetClient(
blink::WebWidgetClient* base_class_widget_client,
blink::WebWidgetClient* widget_test_client,
content::RenderWidget* render_widget)
: base_class_widget_client_(base_class_widget_client),
widget_test_client_(widget_test_client),
render_widget_(render_widget) {}
void ProxyWebWidgetClient::DidInvalidateRect(const blink::WebRect& r) {
base_class_widget_client_->DidInvalidateRect(r);
}
void ProxyWebWidgetClient::ScheduleAnimation() {
// When using threaded compositing, have the RenderWidget schedule a request
// for a frame, as we use the compositor's scheduler. Otherwise the testing
// WebWidgetClient schedules it.
// Note that for WebViewTestProxy the RenderWidget is not subclassed to
// override the WebWidgetClient, instead it is injected into RenderViewImpl,
// so if we call RenderWidget here we jump out of the test harness as
// intended.
if (!render_widget_->layer_tree_view()->CompositeIsSynchronousForTesting())
render_widget_->ScheduleAnimation();
else
widget_test_client_->ScheduleAnimation();
}
void ProxyWebWidgetClient::IntrinsicSizingInfoChanged(
const blink::WebIntrinsicSizingInfo& info) {
base_class_widget_client_->IntrinsicSizingInfoChanged(info);
}
void ProxyWebWidgetClient::DidMeaningfulLayout(
blink::WebMeaningfulLayout layout) {
base_class_widget_client_->DidMeaningfulLayout(layout);
}
void ProxyWebWidgetClient::DidFirstLayoutAfterFinishedParsing() {
base_class_widget_client_->DidFirstLayoutAfterFinishedParsing();
}
void ProxyWebWidgetClient::DidChangeCursor(const blink::WebCursorInfo& info) {
base_class_widget_client_->DidChangeCursor(info);
}
void ProxyWebWidgetClient::AutoscrollStart(const blink::WebFloatPoint& p) {
base_class_widget_client_->AutoscrollStart(p);
}
void ProxyWebWidgetClient::AutoscrollFling(
const blink::WebFloatSize& velocity) {
base_class_widget_client_->AutoscrollFling(velocity);
}
void ProxyWebWidgetClient::AutoscrollEnd() {
base_class_widget_client_->AutoscrollEnd();
}
void ProxyWebWidgetClient::CloseWidgetSoon() {
base_class_widget_client_->CloseWidgetSoon();
}
void ProxyWebWidgetClient::Show(blink::WebNavigationPolicy policy) {
base_class_widget_client_->Show(policy);
}
blink::WebRect ProxyWebWidgetClient::WindowRect() {
return base_class_widget_client_->WindowRect();
}
void ProxyWebWidgetClient::SetWindowRect(const blink::WebRect& r) {
base_class_widget_client_->SetWindowRect(r);
}
blink::WebRect ProxyWebWidgetClient::ViewRect() {
return base_class_widget_client_->ViewRect();
}
void ProxyWebWidgetClient::SetToolTipText(const blink::WebString& text,
blink::WebTextDirection hint) {
widget_test_client_->SetToolTipText(text, hint);
base_class_widget_client_->SetToolTipText(text, hint);
}
bool ProxyWebWidgetClient::RequestPointerLock() {
return widget_test_client_->RequestPointerLock();
}
void ProxyWebWidgetClient::RequestPointerUnlock() {
widget_test_client_->RequestPointerUnlock();
}
bool ProxyWebWidgetClient::IsPointerLocked() {
return widget_test_client_->IsPointerLocked();
}
void ProxyWebWidgetClient::DidHandleGestureEvent(
const blink::WebGestureEvent& event,
bool event_cancelled) {
base_class_widget_client_->DidHandleGestureEvent(event, event_cancelled);
}
void ProxyWebWidgetClient::DidOverscroll(
const blink::WebFloatSize& overscroll_delta,
const blink::WebFloatSize& accumulated_overscroll,
const blink::WebFloatPoint& position_in_viewport,
const blink::WebFloatSize& velocity_in_viewport,
const cc::OverscrollBehavior& behavior) {
base_class_widget_client_->DidOverscroll(
overscroll_delta, accumulated_overscroll, position_in_viewport,
velocity_in_viewport, behavior);
}
void ProxyWebWidgetClient::HasTouchEventHandlers(bool has) {
base_class_widget_client_->HasTouchEventHandlers(has);
}
void ProxyWebWidgetClient::SetNeedsLowLatencyInput(bool needs) {
base_class_widget_client_->SetNeedsLowLatencyInput(needs);
}
void ProxyWebWidgetClient::RequestUnbufferedInputEvents() {
base_class_widget_client_->RequestUnbufferedInputEvents();
}
void ProxyWebWidgetClient::SetTouchAction(blink::WebTouchAction touch_action) {
base_class_widget_client_->SetTouchAction(touch_action);
}
void ProxyWebWidgetClient::ShowVirtualKeyboardOnElementFocus() {
base_class_widget_client_->ShowVirtualKeyboardOnElementFocus();
}
void ProxyWebWidgetClient::ConvertViewportToWindow(blink::WebRect* rect) {
base_class_widget_client_->ConvertViewportToWindow(rect);
}
void ProxyWebWidgetClient::ConvertWindowToViewport(blink::WebFloatRect* rect) {
base_class_widget_client_->ConvertWindowToViewport(rect);
}
void ProxyWebWidgetClient::StartDragging(network::mojom::ReferrerPolicy policy,
const blink::WebDragData& data,
blink::WebDragOperationsMask mask,
const SkBitmap& drag_image,
const gfx::Point& image_offset) {
widget_test_client_->StartDragging(policy, data, mask, drag_image,
image_offset);
// Don't forward this call to |base_class_widget_client_| because we don't
// want to do a real drag-and-drop.
}
WebViewTestProxyBase::WebViewTestProxyBase()
: accessibility_controller_(new AccessibilityController(this)),
text_input_controller_(new TextInputController(this)),
// TODO(danakj): We should collapse WebViewTestProxy and
// WebViewTestProxyBase into one class really. They are both
// concrete types now.
view_test_runner_(
new TestRunnerForSpecificView(static_cast<WebViewTestProxy*>(this))) {
WebWidgetTestProxyBase::set_web_view_test_proxy_base(this);
}
WebViewTestProxyBase::~WebViewTestProxyBase() {
test_interfaces_->WindowClosed(this);
if (test_interfaces_->GetDelegate() == delegate_)
test_interfaces_->SetDelegate(nullptr);
}
void WebViewTestProxyBase::Reset() {
accessibility_controller_->Reset();
// text_input_controller_ doesn't have any state to reset.
view_test_runner_->Reset();
WebWidgetTestProxyBase::Reset();
for (blink::WebFrame* frame = web_view_->MainFrame(); frame;
frame = frame->TraverseNext()) {
if (frame->IsWebLocalFrame())
delegate_->GetWebWidgetTestProxyBase(frame->ToWebLocalFrame())->Reset();
}
}
void WebViewTestProxyBase::BindTo(blink::WebLocalFrame* frame) {
accessibility_controller_->Install(frame);
text_input_controller_->Install(frame);
view_test_runner_->Install(frame);
}
void WebViewTestProxy::Initialize(WebTestInterfaces* interfaces,
WebTestDelegate* delegate) {
// On WebViewTestProxyBase.
set_delegate(delegate);
auto test_widget_client = std::make_unique<WebWidgetTestClient>(
/*main_frame_widget=*/true, web_widget_test_proxy_base());
// This passes calls through to the the |test_widget_client| as well as the
// production client pulled from RenderViewImpl as needed.
auto proxy_widget_client = std::make_unique<ProxyWebWidgetClient>(
RenderViewImpl::WidgetClient(), test_widget_client.get(),
RenderViewImpl::GetWidget());
// This returns the |proxy_widget_client| as the WebWidgetClient.
view_test_client_ =
std::make_unique<WebViewTestClient>(this, std::move(proxy_widget_client));
// On WebWidgetTestProxyBase.
// It's weird that the WebView has the proxy client, but the
// WebWidgetProxyBase has the test one only, but that's because the
// WebWidgetTestProxyBase does not itself use the WebWidgetClient, only its
// subclasses do.
web_widget_test_proxy_base()->set_widget_test_client(
std::move(test_widget_client));
// On WebViewTestProxyBase.
set_test_interfaces(interfaces->GetTestInterfaces());
test_interfaces()->WindowOpened(this);
}
blink::WebView* WebViewTestProxy::CreateView(
blink::WebLocalFrame* creator,
const blink::WebURLRequest& request,
const blink::WebWindowFeatures& features,
const blink::WebString& frame_name,
blink::WebNavigationPolicy policy,
bool suppress_opener,
blink::WebSandboxFlags sandbox_flags,
const blink::SessionStorageNamespaceId& session_storage_namespace_id) {
if (!view_test_client_->CreateView(creator, request, features, frame_name,
policy, suppress_opener, sandbox_flags,
session_storage_namespace_id))
return nullptr;
return RenderViewImpl::CreateView(creator, request, features, frame_name,
policy, suppress_opener, sandbox_flags,
session_storage_namespace_id);
}
void WebViewTestProxy::PrintPage(blink::WebLocalFrame* frame) {
view_test_client_->PrintPage(frame);
}
blink::WebString WebViewTestProxy::AcceptLanguages() {
return view_test_client_->AcceptLanguages();
}
void WebViewTestProxy::DidFocus(blink::WebLocalFrame* calling_frame) {
view_test_client_->DidFocus(calling_frame);
RenderViewImpl::DidFocus(calling_frame);
}
blink::WebScreenInfo WebViewTestProxy::GetScreenInfo() {
blink::WebScreenInfo info = RenderViewImpl::GetScreenInfo();
blink::WebScreenInfo test_info = view_test_client_->GetScreenInfo();
if (test_info.orientation_type != blink::kWebScreenOrientationUndefined) {
info.orientation_type = test_info.orientation_type;
info.orientation_angle = test_info.orientation_angle;
}
return info;
}
blink::WebWidgetClient* WebViewTestProxy::WidgetClient() {
return view_test_client_->WidgetClient();
}
WebViewTestProxy::~WebViewTestProxy() = default;
} // namespace test_runner