Fix focus for PDF in mainframe, add test.
This CL started out as a re-implementation of
WebPluginContainerTest.PluginDocumentPluginIsFocused to work without
BrowserPlugin, but in the process I realized that we had regressed
the behaviour that was originally fixed in
https://codereview.chromium.org/1389093002.
That regression is also fixed in this CL.
Bug: 1019360, 536637, 1022469
Change-Id: I25bbe47fb602b8a3ef5d9be931e7d5fe486c4008
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1903653
Commit-Queue: James MacLean <[email protected]>
Reviewed-by: Lei Zhang <[email protected]>
Reviewed-by: Alex Moshchuk <[email protected]>
Cr-Commit-Position: refs/heads/master@{#714635}
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 023f7bb..be3fee2a 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -469,12 +469,7 @@
auto* guest_web_contents = GetGuestViewManager()->WaitForSingleGuestCreated();
ASSERT_TRUE(guest_web_contents);
EXPECT_NE(embedder_web_contents, guest_web_contents);
- while (guest_web_contents->IsLoading()) {
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
- run_loop.Run();
- }
+ EXPECT_TRUE(content::WaitForLoadStop(guest_web_contents));
// Make sure the text area still has focus.
ASSERT_TRUE(
@@ -490,6 +485,29 @@
.ExtractBool());
}
+// This test is a re-implementation of
+// WebPluginContainerTest.PluginDocumentPluginIsFocused, which was introduced
+// for https://crbug.com/536637. The original implementation checked that the
+// BrowserPlugin hosting the pdf extension was focused; in this re-write, we
+// make sure the guest view's WebContents has focus.
+IN_PROC_BROWSER_TEST_F(PDFExtensionTestWithTestGuestViewManager,
+ PdfInMainFrameHasFocus) {
+ // Load test HTML, and verify the text area has focus.
+ GURL main_url(embedded_test_server()->GetURL("/pdf/test.pdf"));
+ ui_test_utils::NavigateToURL(browser(), main_url);
+ auto* embedder_web_contents = GetActiveWebContents();
+
+ // Verify the pdf has loaded.
+ auto* guest_web_contents = GetGuestViewManager()->WaitForSingleGuestCreated();
+ ASSERT_TRUE(guest_web_contents);
+ EXPECT_NE(embedder_web_contents, guest_web_contents);
+ EXPECT_TRUE(content::WaitForLoadStop(guest_web_contents));
+
+ // Make sure the guest WebContents has focus.
+ EXPECT_EQ(guest_web_contents,
+ content::GetFocusedWebContents(embedder_web_contents));
+}
+
class PDFExtensionLoadTest : public PDFExtensionTest,
public testing::WithParamInterface<int> {
public:
diff --git a/components/guest_view/browser/guest_view_base.cc b/components/guest_view/browser/guest_view_base.cc
index 5d58f97..806cbfa 100644
--- a/components/guest_view/browser/guest_view_base.cc
+++ b/components/guest_view/browser/guest_view_base.cc
@@ -549,7 +549,8 @@
if (content::GuestMode::IsCrossProcessFrameGuest(web_contents())) {
owner_web_contents_->AttachInnerWebContents(
- base::WrapUnique<WebContents>(web_contents()), outer_contents_frame);
+ base::WrapUnique<WebContents>(web_contents()), outer_contents_frame,
+ is_full_page_plugin);
// TODO(ekaramad): MimeHandlerViewGuest might not need this ACK
// (https://crbug.com/659750).
// We don't ACK until after AttachToOuterWebContentsFrame, so that
diff --git a/content/browser/portal/portal.cc b/content/browser/portal/portal.cc
index edd87424..1ac1f50 100644
--- a/content/browser/portal/portal.cc
+++ b/content/browser/portal/portal.cc
@@ -168,7 +168,8 @@
DCHECK_EQ(portal_contents_impl_->GetDelegate(), this);
outer_contents_impl->AttachInnerWebContents(std::move(portal_contents_),
- outer_node->current_frame_host());
+ outer_node->current_frame_host(),
+ false /* is_full_page */);
FrameTreeNode* frame_tree_node =
portal_contents_impl_->GetMainFrame()->frame_tree_node();
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 15e5b38..fdd66fa 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1768,7 +1768,8 @@
void WebContentsImpl::AttachInnerWebContents(
std::unique_ptr<WebContents> inner_web_contents,
- RenderFrameHost* render_frame_host) {
+ RenderFrameHost* render_frame_host,
+ bool is_full_page) {
WebContentsImpl* inner_web_contents_impl =
static_cast<WebContentsImpl*>(inner_web_contents.get());
DCHECK(!inner_web_contents_impl->node_.outer_web_contents());
@@ -1833,6 +1834,14 @@
render_frame_host_impl->GetSiteInstance());
}
outer_render_manager->set_attach_complete();
+
+ // If the inner WebContents is full frame, give it focus.
+ if (is_full_page) {
+ // There should only ever be one inner WebContents when |is_full_page| is
+ // true, and it is the one we just attached.
+ DCHECK_EQ(1u, node_.GetInnerWebContents().size());
+ inner_web_contents_impl->SetAsFocusedWebContentsIfNecessary();
+ }
}
std::unique_ptr<WebContents> WebContentsImpl::DetachFromOuterWebContents() {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index d33a2b55..1694eff 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -380,7 +380,8 @@
bool NeedToFireBeforeUnload() override;
void DispatchBeforeUnload(bool auto_cancel) override;
void AttachInnerWebContents(std::unique_ptr<WebContents> inner_web_contents,
- RenderFrameHost* render_frame_host) override;
+ RenderFrameHost* render_frame_host,
+ bool is_full_page) override;
RenderFrameHostImpl* GetOuterWebContentsFrame() override;
WebContentsImpl* GetOuterWebContents() override;
WebContentsImpl* GetOutermostWebContents() override;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 49f725c3..d5d0677 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -3983,8 +3983,8 @@
WebContents::Create(inner_params);
// Attach grandchild to child.
- child_contents_ptr->AttachInnerWebContents(std::move(grandchild_contents_ptr),
- child_rfh);
+ child_contents_ptr->AttachInnerWebContents(
+ std::move(grandchild_contents_ptr), child_rfh, false /* is_full_page */);
// At this point the child hasn't been attached to the root.
EXPECT_EQ(1U, root_web_contents->GetInputEventRouter()
@@ -3992,7 +3992,8 @@
// Attach child+grandchild subtree to root.
root_web_contents->AttachInnerWebContents(std::move(child_contents_ptr),
- child_to_replace_rfh);
+ child_to_replace_rfh,
+ false /* is_full_page */);
// Verify views registered for both child and grandchild.
EXPECT_EQ(3U, root_web_contents->GetInputEventRouter()
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 8a9d071..31f0ebe 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -596,9 +596,12 @@
// but ideally it should be "about:blank" to avoid problems with beforeunload.
// To ensure sane usage of this API users first should call the async API
// RenderFrameHost::PrepareForInnerWebContentsAttach first.
+ // Note: If |is_full_page| is true, focus will be given to the inner
+ // WebContents.
virtual void AttachInnerWebContents(
std::unique_ptr<WebContents> inner_web_contents,
- RenderFrameHost* render_frame_host) = 0;
+ RenderFrameHost* render_frame_host,
+ bool is_full_page) = 0;
// Returns the outer WebContents frame, the same frame that this WebContents
// was attached in AttachToOuterWebContentsFrame().
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc
index e71de39..481addfd 100644
--- a/content/public/test/test_utils.cc
+++ b/content/public/test/test_utils.cc
@@ -226,7 +226,8 @@
// Attach. |inner_contents| becomes owned by |outer_contents|.
WebContents* inner_contents = inner_contents_ptr.get();
- outer_contents->AttachInnerWebContents(std::move(inner_contents_ptr), rfh);
+ outer_contents->AttachInnerWebContents(std::move(inner_contents_ptr), rfh,
+ false /* is_full_page */);
return inner_contents;
}
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc
index 8b3692c..6dedb79 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc
@@ -196,8 +196,6 @@
fullscreen_waiter.Wait();
WaitForFullscreenAnimation();
- EXPECT_NE(guest_contents, content::GetFocusedWebContents(embedder_contents));
- EXPECT_FALSE(IsRenderWidgetHostFocused(guest_rwh));
// Send a touch to focus the guest. We can't directly test that the correct
// RenderWidgetHost got focus, but the wait seems to work.
SimulateMouseClick(guest_contents, 0, blink::WebMouseEvent::Button::kLeft);