cast: webview: Add an API to set insets
Insets represent a "border" like area around each side of the Webview.
By setting insets the Webview's visible area will shrink.
This will be used to represent occluded area in a Webview where the
virtual keyboard will be shown.
Bug: internal b/175873498
Test: cast_shell_browsertests and on device by calling the new API
Change-Id: Ide948ab2cd955f7f7a687de7cb91ef418dd0aa70
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2596073
Reviewed-by: Ryan Daum <rdaum@chromium.org>
Commit-Queue: Daniel Nicoara <dnicoara@chromium.org>
Cr-Commit-Position: refs/heads/master@{#840352}
diff --git a/chromecast/browser/webview/proto/webview.proto b/chromecast/browser/webview/proto/webview.proto
index 6835749..582c1c0 100644
--- a/chromecast/browser/webview/proto/webview.proto
+++ b/chromecast/browser/webview/proto/webview.proto
@@ -285,6 +285,15 @@
int32 flags = 2;
}
+// Used to represent a space within a rectangle by "shrinking" the rectangle by
+// the inset amount on all four sides.
+message SetInsetsRequest {
+ int32 top = 1;
+ int32 left = 2;
+ int32 bottom = 3;
+ int32 right = 4;
+}
+
message WebviewRequest {
// Unique identifier for the request. For requests that will have a response,
// the response id will match the request id.
@@ -331,6 +340,7 @@
AssociateCastAppWindowRequest associate = 20;
ResizeRequest resize = 21;
ClearCookiesRequest clear_cookies = 22;
+ SetInsetsRequest set_insets = 23;
}
}
diff --git a/chromecast/browser/webview/web_content_controller.cc b/chromecast/browser/webview/web_content_controller.cc
index 5beda14..d5043dd 100644
--- a/chromecast/browser/webview/web_content_controller.cc
+++ b/chromecast/browser/webview/web_content_controller.cc
@@ -174,6 +174,16 @@
}
break;
+ case webview::WebviewRequest::kSetInsets:
+ if (request.has_set_insets()) {
+ HandleSetInsets(gfx::Insets(
+ request.set_insets().top(), request.set_insets().left(),
+ request.set_insets().bottom(), request.set_insets().right()));
+ } else {
+ client_->OnError("set_insets() not supplied");
+ }
+ break;
+
default:
client_->OnError("Unknown request code");
break;
@@ -506,6 +516,12 @@
}
}
+void WebContentController::HandleSetInsets(const gfx::Insets& insets) {
+ auto* contents = GetWebContents();
+ if (contents && contents->GetTopLevelRenderWidgetHostView())
+ contents->GetTopLevelRenderWidgetHostView()->SetInsets(insets);
+}
+
viz::SurfaceId WebContentController::GetSurfaceId() {
content::WebContents* web_contents = GetWebContents();
// Web contents are destroyed before controller for cast apps.
diff --git a/chromecast/browser/webview/web_content_controller.h b/chromecast/browser/webview/web_content_controller.h
index f2fbd23..e5322c1 100644
--- a/chromecast/browser/webview/web_content_controller.h
+++ b/chromecast/browser/webview/web_content_controller.h
@@ -117,6 +117,8 @@
void HandleClearCookies(int64_t id);
void HandleGetTitle(int64_t id);
void HandleResize(const gfx::Size& size);
+ void HandleSetInsets(const gfx::Insets& insets);
+
viz::SurfaceId GetSurfaceId();
void ChannelModified(content::RenderFrameHost* frame,
const std::string& channel,
diff --git a/chromecast/browser/webview/webview_browsertest.cc b/chromecast/browser/webview/webview_browsertest.cc
index 3dcaf179..c442cf0 100644
--- a/chromecast/browser/webview/webview_browsertest.cc
+++ b/chromecast/browser/webview/webview_browsertest.cc
@@ -11,6 +11,7 @@
#include "chromecast/browser/extensions/cast_extension_system_factory.h"
#include "chromecast/browser/webview/webview_controller.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_base.h"
@@ -130,4 +131,49 @@
RunMessageLoop();
}
+IN_PROC_BROWSER_TEST_F(WebviewTest, SetInsets) {
+ // Webview creation sends messages to the client (eg: accessibility ID).
+ EXPECT_CALL(client_, EnqueueSend(_)).Times(testing::AnyNumber());
+
+ WebviewController webview(context_.get(), &client_, true);
+ GURL test_url = embedded_test_server()->GetURL("foo.com", "/test");
+
+ auto check = [](const std::unique_ptr<webview::WebviewResponse>& response) {
+ return response->has_page_event() &&
+ response->page_event().current_page_state() ==
+ webview::AsyncPageEvent_State_LOADED;
+ };
+ EXPECT_CALL(client_, EnqueueSend(Truly(check)))
+ .Times(testing::AtLeast(1))
+ .WillOnce(
+ [this, &webview](std::unique_ptr<webview::WebviewResponse> response) {
+ webview::WebviewRequest request;
+ request.mutable_set_insets()->set_top(0);
+ request.mutable_set_insets()->set_left(0);
+ request.mutable_set_insets()->set_bottom(200);
+ request.mutable_set_insets()->set_right(0);
+ webview.ProcessRequest(request);
+
+ gfx::Size size_after = webview.GetWebContents()
+ ->GetRenderWidgetHostView()
+ ->GetVisibleViewportSize();
+ EXPECT_EQ(gfx::Size(800, 400), size_after);
+
+ Quit();
+ });
+
+ // Requests are executed serially. Resize first to make sure the Webview is
+ // properly sized by the time the page loads.
+ webview::WebviewRequest resize;
+ resize.mutable_resize()->set_width(800);
+ resize.mutable_resize()->set_height(600);
+ webview.ProcessRequest(resize);
+
+ webview::WebviewRequest nav;
+ nav.mutable_navigate()->set_url(test_url.spec());
+ webview.ProcessRequest(nav);
+
+ RunMessageLoop();
+}
+
} // namespace chromecast
diff --git a/chromecast/browser/webview/webview_controller.h b/chromecast/browser/webview/webview_controller.h
index 4d64453..489519d 100644
--- a/chromecast/browser/webview/webview_controller.h
+++ b/chromecast/browser/webview/webview_controller.h
@@ -28,6 +28,7 @@
namespace chromecast {
class WebviewNavigationThrottle;
+class WebviewTest;
// This owns a WebContents and CastWebContents and processes proto commands
// to allow the web contents to be controlled and embedded.
@@ -62,6 +63,8 @@
void OnNavigationThrottleDestroyed(WebviewNavigationThrottle* throttle);
protected:
+ FRIEND_TEST_ALL_PREFIXES(WebviewTest, SetInsets);
+
content::WebContents* GetWebContents() override;
private: