#include <stddef.h>
#include <limits>
#include <memory>
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/run_until.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/test_launcher_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/guest_view/browser/guest_view_base.h"
#include "components/guest_view/browser/guest_view_manager.h"
#include "components/guest_view/browser/guest_view_manager_delegate.h"
#include "components/guest_view/browser/guest_view_manager_factory.h"
#include "components/guest_view/browser/test_guest_view_manager.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/text_input_test_utils.h"
#include "extensions/browser/api/extensions_api_client.h"
#include "extensions/browser/app_window/app_window.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/test/extension_test_message_listener.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/blink/public/common/switches.h"
#include "ui/base/buildflags.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/ime_text_span.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ozone_buildflags.h"
#include "ui/base/test/ui_controls.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/range/range.h"
#include "ui/touch_selection/touch_selection_menu_runner.h"
#if BUILDFLAG(IS_MAC)
#include "ui/base/test/scoped_fake_nswindow_fullscreen.h"
#endif
AppWindow;
ExtensionsAPIClient;
GuestViewBase;
GuestViewManager;
TestGuestViewManager;
TestGuestViewManagerFactory;
#if !BUILDFLAG(IS_OZONE_WAYLAND)
#define SUPPORTS_SYNC_MOUSE_UTILS
#endif
#if BUILDFLAG(IS_MAC)
class NewSubViewAddedObserver : content::RenderWidgetHostViewCocoaObserver {
public:
explicit NewSubViewAddedObserver(content::WebContents* web_contents)
: content::RenderWidgetHostViewCocoaObserver(web_contents) {}
NewSubViewAddedObserver(const NewSubViewAddedObserver&) = delete;
NewSubViewAddedObserver& operator=(const NewSubViewAddedObserver&) = delete;
~NewSubViewAddedObserver() override {}
void WaitForNextSubView() {
if (did_receive_rect_)
return;
run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
}
const gfx::Rect& view_bounds_in_screen() const { return bounds_; }
private:
void DidAddSubviewWillBeDismissed(
const gfx::Rect& bounds_in_root_view) override {
did_receive_rect_ = true;
bounds_ = bounds_in_root_view;
if (run_loop_)
run_loop_->Quit();
}
bool did_receive_rect_ = false;
gfx::Rect bounds_;
std::unique_ptr<base::RunLoop> run_loop_;
};
#endif
class WebViewInteractiveTest : public extensions::PlatformAppBrowserTest { … };
class WebViewImeInteractiveTest : public WebViewInteractiveTest { … };
class WebViewNewWindowInteractiveTest : public WebViewInteractiveTest { … };
class WebViewFocusInteractiveTest : public WebViewInteractiveTest { … };
class WebViewPointerLockInteractiveTest : public WebViewInteractiveTest { … };
class DISABLED_WebViewPopupInteractiveTest : public WebViewInteractiveTest { … };
#if defined(SUPPORTS_SYNC_MOUSE_UTILS) && !BUILDFLAG(IS_CHROMEOS) && \
!BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_WIN) && defined(NDEBUG)
#define MAYBE_PointerLock …
#else
#define MAYBE_PointerLock …
#endif
IN_PROC_BROWSER_TEST_F(WebViewPointerLockInteractiveTest, MAYBE_PointerLock) { … }
#if defined(SUPPORTS_SYNC_MOUSE_UTILS) && !BUILDFLAG(IS_CHROMEOS) && \
!BUILDFLAG(IS_MAC) && defined(NDEBUG)
#define MAYBE_PointerLockFocus …
#else
#define MAYBE_PointerLockFocus …
#endif
IN_PROC_BROWSER_TEST_F(WebViewPointerLockInteractiveTest,
MAYBE_PointerLockFocus) { … }
#if BUILDFLAG(IS_LINUX) && defined(NDEBUG)
#define MAYBE_Focus_FocusBeforeNavigation …
#else
#define MAYBE_Focus_FocusBeforeNavigation …
#endif
IN_PROC_BROWSER_TEST_F(WebViewFocusInteractiveTest,
MAYBE_Focus_FocusBeforeNavigation) { … }
IN_PROC_BROWSER_TEST_F(WebViewFocusInteractiveTest, Focus_FocusEvent) { … }
#if BUILDFLAG(IS_MAC)
#define MAYBE_Focus_FocusTakeFocus …
#else
#define MAYBE_Focus_FocusTakeFocus …
#endif
IN_PROC_BROWSER_TEST_F(WebViewFocusInteractiveTest,
MAYBE_Focus_FocusTakeFocus) { … }
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#define MAYBE_Focus_FocusTracksEmbedder …
#else
#define MAYBE_Focus_FocusTracksEmbedder …
#endif
IN_PROC_BROWSER_TEST_F(WebViewFocusInteractiveTest,
MAYBE_Focus_FocusTracksEmbedder) { … }
IN_PROC_BROWSER_TEST_F(WebViewFocusInteractiveTest, Focus_AdvanceFocus) { … }
IN_PROC_BROWSER_TEST_F(WebViewFocusInteractiveTest, Focus_BlurEvent) { … }
#if BUILDFLAG(IS_MAC) && defined(NDEBUG)
#define MAYBE_FrameInGuestWontStealFocus …
#else
#define MAYBE_FrameInGuestWontStealFocus …
#endif
IN_PROC_BROWSER_TEST_F(WebViewFocusInteractiveTest,
MAYBE_FrameInGuestWontStealFocus) { … }
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommands) { … }
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommandsNoMenu) { … }
#if BUILDFLAG(IS_MAC)
#define MAYBE_NewWindow_OpenInNewTab …
#else
#define MAYBE_NewWindow_OpenInNewTab …
#endif
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, MAYBE_NewWindow_OpenInNewTab) { … }
IN_PROC_BROWSER_TEST_F(DISABLED_WebViewPopupInteractiveTest,
PopupPositioningBasic) { … }
IN_PROC_BROWSER_TEST_F(DISABLED_WebViewPopupInteractiveTest,
PopupPositioningMoved) { … }
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Navigation) { … }
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Navigation_BackForwardKeys) { … }
IN_PROC_BROWSER_TEST_F(WebViewPointerLockInteractiveTest,
PointerLock_PointerLockLostWithFocus) { … }
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
FullscreenAllow_EmbedderHasPermission) { … }
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
FullscreenDeny_EmbedderHasPermission) { … }
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
FullscreenAllow_EmbedderHasNoPermission) { … }
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
FullscreenDeny_EmbedderHasNoPermission) { … }
IN_PROC_BROWSER_TEST_F(WebViewFocusInteractiveTest, Focus_FocusRestored) { … }
#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)
#if defined(ADDRESS_SANITIZER) || BUILDFLAG(IS_WIN)
#define MAYBE_Focus_InputMethod …
#else
#define MAYBE_Focus_InputMethod …
#endif
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, MAYBE_Focus_InputMethod) { … }
#endif
#if BUILDFLAG(IS_LINUX) || \
BUILDFLAG(IS_CHROMEOS)
#define MAYBE_LongPressSelection …
#else
#define MAYBE_LongPressSelection …
#endif
#if !BUILDFLAG(IS_MAC)
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, MAYBE_LongPressSelection) { … }
#endif
#if BUILDFLAG(IS_MAC)
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, TextSelection) {
SetupTest("web_view/text_selection",
"/extensions/platform_apps/web_view/text_selection/guest.html");
ASSERT_TRUE(GetGuestView());
ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
GetPlatformAppWindow()));
ExtensionTestMessageListener ctx_listener("MSG_CONTEXTMENU");
ContextMenuWaiter menu_observer;
SimulateRWHMouseClick(GetGuestRenderFrameHost()->GetRenderWidgetHost(),
blink::WebMouseEvent::Button::kRight, 20, 20);
menu_observer.WaitForMenuOpenAndClose();
ASSERT_TRUE(ctx_listener.WaitUntilSatisfied());
content::RenderWidgetHostView* guest_rwhv =
GetGuestRenderFrameHost()->GetView();
ASSERT_TRUE(guest_rwhv);
std::string selected_text = base::UTF16ToUTF8(guest_rwhv->GetSelectedText());
ASSERT_GE(selected_text.size(), 10u);
ASSERT_EQ("AAAAAAAAAA", selected_text.substr(0, 10));
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, WordLookup) {
SetupTest("web_view/text_selection",
"/extensions/platform_apps/web_view/text_selection/guest.html");
ASSERT_TRUE(GetGuestView());
ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow()));
content::TextInputTestLocalFrame text_input_local_frame;
text_input_local_frame.SetUp(GetGuestRenderFrameHost());
ContextMenuNotificationObserver menu_observer(IDC_CONTENT_CONTEXT_LOOK_UP);
SimulateRWHMouseClick(GetGuestRenderFrameHost()->GetRenderWidgetHost(),
blink::WebMouseEvent::Button::kRight, 20, 20);
text_input_local_frame.WaitForGetStringForRange();
ASSERT_EQ("AAAA", text_input_local_frame.GetStringFromRange().substr(0, 4));
}
#endif
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
BUILDFLAG(IS_WIN)
#define MAYBE_FocusAndVisibility …
#else
#define MAYBE_FocusAndVisibility …
#endif
IN_PROC_BROWSER_TEST_F(WebViewFocusInteractiveTest, MAYBE_FocusAndVisibility) { … }
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_KeyboardFocusSimple) { … }
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || \
BUILDFLAG(IS_WIN)
#define MAYBE_KeyboardFocusWindowCycle …
#else
#define MAYBE_KeyboardFocusWindowCycle …
#endif
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, MAYBE_KeyboardFocusWindowCycle) { … }
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
DISABLED_DestroyGuestWithPendingPointerLock) { … }
#if BUILDFLAG(IS_MAC)
IN_PROC_BROWSER_TEST_F(WebViewImeInteractiveTest,
CommitTextWithReplacementRange) {
ASSERT_TRUE(StartEmbeddedTestServer());
LoadAndLaunchPlatformApp("web_view/ime", "WebViewImeTest.Launched");
ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow()));
content::RunAllPendingInMessageLoop();
auto* guest_rfh = GetGuestViewManager()->GetLastGuestRenderFrameHostCreated();
ExtensionTestMessageListener focus_listener("WebViewImeTest.InputFocused");
WaitForHitTestData(guest_rfh);
content::SimulateMouseClickAt(
GetGuestViewManager()->GetLastGuestViewCreated()->embedder_web_contents(),
0, blink::WebMouseEvent::Button::kLeft,
guest_rfh->GetView()->TransformPointToRootCoordSpace(gfx::Point(50, 50)));
EXPECT_TRUE(focus_listener.WaitUntilSatisfied());
EXPECT_EQ("A B X D", content::EvalJs(guest_rfh,
"document.querySelector('"
"input').value"));
ExtensionTestMessageListener input_listener("WebViewImetest.InputReceived");
content::SendImeCommitTextToWidget(guest_rfh->GetRenderWidgetHost(), u"C",
std::vector<ui::ImeTextSpan>(),
gfx::Range(4, 5), 0);
EXPECT_TRUE(input_listener.WaitUntilSatisfied());
EXPECT_EQ("A B C D", content::EvalJs(guest_rfh,
"document.querySelector('"
"input').value"));
}
#endif
IN_PROC_BROWSER_TEST_F(WebViewImeInteractiveTest, CompositionRangeUpdates) { … }
#if BUILDFLAG(IS_MAC)
IN_PROC_BROWSER_TEST_F(WebViewFocusInteractiveTest,
DropDownPopupInCorrectPosition) {
TestHelper("testSelectPopupPositionInMac", "web_view/shim", NO_TEST_SERVER);
ASSERT_TRUE(GetGuestRenderFrameHost());
const float distance_from_root_view_origin = 250.0;
content::RenderWidgetHostView* guest_rwhv =
GetGuestRenderFrameHost()->GetView();
EXPECT_TRUE(base::test::RunUntil([&]() {
return guest_rwhv->TransformPointToRootCoordSpace(gfx::Point())
.OffsetFromOrigin()
.Length() >= distance_from_root_view_origin;
}));
NewSubViewAddedObserver popup_observer(embedder_web_contents_);
SimulateRWHMouseClick(guest_rwhv->GetRenderWidgetHost(),
blink::WebMouseEvent::Button::kLeft, 5, 5);
popup_observer.WaitForNextSubView();
gfx::Rect guest_bounds_in_embedder(
guest_rwhv->TransformPointToRootCoordSpace(gfx::Point()),
guest_rwhv->GetViewBounds().size());
EXPECT_TRUE(guest_bounds_in_embedder.Intersects(
popup_observer.view_bounds_in_screen()))
<< "Guest bounds:" << guest_bounds_in_embedder.ToString()
<< " do not intersect with popup bounds:"
<< popup_observer.view_bounds_in_screen().ToString();
}
#endif
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
FocusPreservedAfterCrossProcessNavigation) { … }