| Index: chrome/browser/site_per_process_interactive_browsertest.cc
|
| diff --git a/chrome/browser/site_per_process_interactive_browsertest.cc b/chrome/browser/site_per_process_interactive_browsertest.cc
|
| index 4e074f8b423b79a1e42ae340666e1031ccf4d64d..79c4ca0ffa2b3f4522b4d812573ddd075019a55f 100644
|
| --- a/chrome/browser/site_per_process_interactive_browsertest.cc
|
| +++ b/chrome/browser/site_per_process_interactive_browsertest.cc
|
| @@ -4,6 +4,8 @@
|
|
|
| #include "base/command_line.h"
|
| #include "base/strings/string_number_conversions.h"
|
| +#include "base/test/scoped_feature_list.h"
|
| +#include "chrome/browser/password_manager/chrome_password_manager_client.h"
|
| #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
|
| #include "chrome/browser/ui/browser.h"
|
| #include "chrome/browser/ui/browser_window.h"
|
| @@ -12,9 +14,18 @@
|
| #include "chrome/test/base/in_process_browser_test.h"
|
| #include "chrome/test/base/interactive_test_utils.h"
|
| #include "chrome/test/base/ui_test_utils.h"
|
| +#include "components/autofill/core/browser/autofill_client.h"
|
| +#include "components/autofill/core/browser/test_autofill_client.h"
|
| #include "components/guest_view/browser/guest_view_manager_delegate.h"
|
| #include "components/guest_view/browser/test_guest_view_manager.h"
|
| +#include "components/security_state/core/security_state.h"
|
| +#include "content/public/browser/focused_node_details.h"
|
| #include "content/public/browser/navigation_handle.h"
|
| +#include "content/public/browser/notification_details.h"
|
| +#include "content/public/browser/notification_observer.h"
|
| +#include "content/public/browser/notification_registrar.h"
|
| +#include "content/public/browser/notification_service.h"
|
| +#include "content/public/browser/notification_source.h"
|
| #include "content/public/browser/render_frame_host.h"
|
| #include "content/public/browser/render_widget_host.h"
|
| #include "content/public/browser/render_widget_host_view.h"
|
| @@ -29,8 +40,16 @@
|
| #include "net/test/embedded_test_server/embedded_test_server.h"
|
| #include "ui/display/display.h"
|
| #include "ui/display/screen.h"
|
| +#include "ui/gfx/geometry/point.h"
|
| +#include "ui/gfx/geometry/rect.h"
|
| +#include "ui/gfx/geometry/vector2d.h"
|
| #include "url/gurl.h"
|
|
|
| +namespace autofill {
|
| +class AutofillPopupDelegate;
|
| +struct Suggestion;
|
| +}
|
| +
|
| class SitePerProcessInteractiveBrowserTest : public InProcessBrowserTest {
|
| public:
|
| SitePerProcessInteractiveBrowserTest() {}
|
| @@ -924,3 +943,197 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessInteractivePDFTest,
|
| EXPECT_EQ(point_in_root_window.x(), menu_waiter.params().x);
|
| EXPECT_EQ(point_in_root_window.y(), menu_waiter.params().y);
|
| }
|
| +
|
| +class SitePerProcessAutofillTest : public SitePerProcessInteractiveBrowserTest {
|
| + public:
|
| + SitePerProcessAutofillTest() : SitePerProcessInteractiveBrowserTest() {}
|
| + ~SitePerProcessAutofillTest() override{};
|
| +
|
| + void SetUpCommandLine(base::CommandLine* command_line) override {
|
| + SitePerProcessInteractiveBrowserTest::SetUpCommandLine(command_line);
|
| + // We need to set the feature state before the render process is created,
|
| + // in order for it to inherit the feature state from the browser process.
|
| + // SetUp() runs too early, and SetUpOnMainThread() runs too late.
|
| + scoped_feature_list_.InitAndEnableFeature(
|
| + security_state::kHttpFormWarningFeature);
|
| + }
|
| +
|
| + protected:
|
| + class TestAutofillClient : public autofill::TestAutofillClient {
|
| + public:
|
| + TestAutofillClient() : popup_shown_(false){};
|
| + ~TestAutofillClient() override {}
|
| +
|
| + void WaitForNextPopup() {
|
| + if (popup_shown_)
|
| + return;
|
| + loop_runner_ = new content::MessageLoopRunner();
|
| + loop_runner_->Run();
|
| + }
|
| +
|
| + void ShowAutofillPopup(
|
| + const gfx::RectF& element_bounds,
|
| + base::i18n::TextDirection text_direction,
|
| + const std::vector<autofill::Suggestion>& suggestions,
|
| + base::WeakPtr<autofill::AutofillPopupDelegate> delegate) override {
|
| + element_bounds_ = element_bounds;
|
| + popup_shown_ = true;
|
| + if (loop_runner_)
|
| + loop_runner_->Quit();
|
| + }
|
| +
|
| + const gfx::RectF& last_element_bounds() const { return element_bounds_; }
|
| +
|
| + private:
|
| + gfx::RectF element_bounds_;
|
| + bool popup_shown_;
|
| + scoped_refptr<content::MessageLoopRunner> loop_runner_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TestAutofillClient);
|
| + };
|
| +
|
| + const int kIframeTopDisplacement = 150;
|
| + const int kIframeLeftDisplacement = 200;
|
| +
|
| + void SetupMainTab() {
|
| + // Add a fresh new WebContents for which we add our own version of the
|
| + // ChromePasswordManagerClient that uses a custom TestAutofillClient.
|
| + content::WebContents* new_contents = content::WebContents::Create(
|
| + content::WebContents::CreateParams(browser()
|
| + ->tab_strip_model()
|
| + ->GetActiveWebContents()
|
| + ->GetBrowserContext()));
|
| + ASSERT_TRUE(new_contents);
|
| + ASSERT_FALSE(ChromePasswordManagerClient::FromWebContents(new_contents));
|
| +
|
| + // Create ChromePasswordManagerClient and verify it exists for the new
|
| + // WebContents.
|
| + ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
|
| + new_contents, &test_autofill_client_);
|
| + ASSERT_TRUE(ChromePasswordManagerClient::FromWebContents(new_contents));
|
| +
|
| + browser()->tab_strip_model()->AppendWebContents(new_contents, true);
|
| + }
|
| +
|
| + TestAutofillClient& autofill_client() { return test_autofill_client_; }
|
| +
|
| + private:
|
| + base::test::ScopedFeatureList scoped_feature_list_;
|
| + TestAutofillClient test_autofill_client_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SitePerProcessAutofillTest);
|
| +};
|
| +
|
| +// Observes the notifications for changes in focused node/element in the page.
|
| +class FocusedEditableNodeChangedObserver : content::NotificationObserver {
|
| + public:
|
| + FocusedEditableNodeChangedObserver() : observed_(false) {
|
| + registrar_.Add(this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
|
| + content::NotificationService::AllSources());
|
| + }
|
| + ~FocusedEditableNodeChangedObserver() override {}
|
| +
|
| + void WaitForFocusChangeInPage() {
|
| + if (observed_)
|
| + return;
|
| + loop_runner_ = new content::MessageLoopRunner();
|
| + loop_runner_->Run();
|
| + }
|
| +
|
| + // content::NotificationObserver override.
|
| + void Observe(int type,
|
| + const content::NotificationSource& source,
|
| + const content::NotificationDetails& details) override {
|
| + auto focused_node_details =
|
| + content::Details<content::FocusedNodeDetails>(details);
|
| + if (!focused_node_details->is_editable_node)
|
| + return;
|
| + focused_node_bounds_in_screen_ =
|
| + focused_node_details->node_bounds_in_screen.origin();
|
| + observed_ = true;
|
| + if (loop_runner_)
|
| + loop_runner_->Quit();
|
| + }
|
| +
|
| + const gfx::Point& focused_node_bounds_in_screen() const {
|
| + return focused_node_bounds_in_screen_;
|
| + }
|
| +
|
| + private:
|
| + content::NotificationRegistrar registrar_;
|
| + bool observed_;
|
| + gfx::Point focused_node_bounds_in_screen_;
|
| + scoped_refptr<content::MessageLoopRunner> loop_runner_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(FocusedEditableNodeChangedObserver);
|
| +};
|
| +
|
| +// This test verifies that displacements (margin, etc) in the position of an
|
| +// OOPIF is considered when showing an AutofillClient warning pop-up for
|
| +// unsecure web sites.
|
| +IN_PROC_BROWSER_TEST_F(SitePerProcessAutofillTest,
|
| + PasswordAutofillPopupPositionInsideOOPIF) {
|
| + SetupMainTab();
|
| + ASSERT_TRUE(
|
| + base::FeatureList::IsEnabled(security_state::kHttpFormWarningFeature));
|
| +
|
| + GURL main_url(embedded_test_server()->GetURL("a.com", "/iframe.html"));
|
| + ui_test_utils::NavigateToURL(browser(), main_url);
|
| + content::WebContents* active_web_contents =
|
| + browser()->tab_strip_model()->GetActiveWebContents();
|
| +
|
| + // Add some displacement for <iframe>.
|
| + ASSERT_TRUE(content::ExecuteScript(
|
| + active_web_contents,
|
| + base::StringPrintf("var iframe = document.querySelector('iframe');"
|
| + "iframe.style.marginTop = '%dpx';"
|
| + "iframe.style.marginLeft = '%dpx';",
|
| + kIframeTopDisplacement, kIframeLeftDisplacement)));
|
| +
|
| + // Navigate the <iframe> to a simple page.
|
| + GURL frame_url = embedded_test_server()->GetURL("b.com", "/title1.html");
|
| + EXPECT_TRUE(NavigateIframeToURL(active_web_contents, "test", frame_url));
|
| + content::RenderFrameHost* child_frame = content::FrameMatchingPredicate(
|
| + active_web_contents, base::Bind(&content::FrameIsChildOfMainFrame));
|
| +
|
| + // We will need to listen to focus changes to find out about the container
|
| + // bounds of any focused <input> elements on the page.
|
| + FocusedEditableNodeChangedObserver focus_observer;
|
| +
|
| + // Focus the child frame, add an <input> with type "password", and focus it.
|
| + ASSERT_TRUE(ExecuteScript(child_frame,
|
| + "window.focus();"
|
| + "var input = document.createElement('input');"
|
| + "input.type = 'password';"
|
| + "document.body.appendChild(input);"
|
| + "input.focus();"));
|
| + focus_observer.WaitForFocusChangeInPage();
|
| +
|
| + // The user gesture (input) should lead to a security warning.
|
| + content::SimulateKeyPress(active_web_contents, ui::DomKey::FromCharacter('A'),
|
| + ui::DomCode::US_A, ui::VKEY_A, false, false, false,
|
| + false);
|
| + autofill_client().WaitForNextPopup();
|
| +
|
| + gfx::Point bounds_origin(
|
| + static_cast<int>(autofill_client().last_element_bounds().origin().x()),
|
| + static_cast<int>(autofill_client().last_element_bounds().origin().y()));
|
| +
|
| + // Convert the bounds to screen coordinates (to then compare against the ones
|
| + // reported by focus change observer).
|
| + bounds_origin += active_web_contents->GetRenderWidgetHostView()
|
| + ->GetViewBounds()
|
| + .OffsetFromOrigin();
|
| +
|
| + gfx::Vector2d error =
|
| + bounds_origin - focus_observer.focused_node_bounds_in_screen();
|
| +
|
| + // Ideally, the length of the error vector should be 0.0f. But due to
|
| + // potential rounding errors, we assume a larger limit (which is slightly
|
| + // larger than square root of 2).
|
| + EXPECT_LT(error.Length(), 1.4143f)
|
| + << "Origin of bounds from focused node changed event is '"
|
| + << focus_observer.focused_node_bounds_in_screen().ToString()
|
| + << "' but AutofillClient is reporting '" << bounds_origin.ToString()
|
| + << "'";
|
| +}
|
|
|