blob: cc0134443c52cb7b650e9e4b60b5a57e01daa08f [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/external_protocol_dialog.h"
#include <memory>
#include <string>
#include "chrome/browser/external_protocol/external_protocol_handler.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/test/test_browser_dialog.h"
#include "chrome/browser/ui/views/external_protocol_dialog_test_harness.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/metrics.h"
#include "ui/views/test/button_test_api.h"
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, TestAccept) {
ShowUi(std::string("https://example.test"));
dialog_->AcceptDialog();
EXPECT_EQ(blocked_state_, BlockState::UNKNOWN);
EXPECT_TRUE(url_did_launch_);
histogram_tester_.ExpectBucketCount(
ExternalProtocolHandler::kHandleStateMetric,
ExternalProtocolHandler::LAUNCH, 1);
}
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest,
TestAcceptWithChecked) {
ShowUi(std::string("https://example.test"));
SetChecked(true);
dialog_->AcceptDialog();
EXPECT_EQ(blocked_scheme_, "telnet");
EXPECT_EQ(blocked_origin_, url::Origin::Create(GURL("https://example.test")));
EXPECT_EQ(blocked_state_, BlockState::DONT_BLOCK);
EXPECT_TRUE(url_did_launch_);
histogram_tester_.ExpectBucketCount(
ExternalProtocolHandler::kHandleStateMetric,
ExternalProtocolHandler::CHECKED_LAUNCH, 1);
}
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest,
TestAcceptWithUntrustworthyOrigin) {
ShowUi(std::string("http://example.test"));
SetChecked(true); // This will no-opt because http:// is not trustworthy
dialog_->AcceptDialog();
EXPECT_EQ(blocked_state_, BlockState::UNKNOWN);
EXPECT_TRUE(url_did_launch_);
histogram_tester_.ExpectBucketCount(
ExternalProtocolHandler::kHandleStateMetric,
ExternalProtocolHandler::LAUNCH, 1);
}
// Regression test for http://crbug.com/835216. The OS owns the dialog, so it
// may may outlive the WebContents it is attached to.
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest,
TestAcceptAfterCloseTab) {
ShowUi(std::string("https://example.test"));
SetChecked(true); // |remember_| must be true for the segfault to occur.
browser()->tab_strip_model()->CloseAllTabs();
dialog_->AcceptDialog();
EXPECT_FALSE(url_did_launch_);
histogram_tester_.ExpectBucketCount(
ExternalProtocolHandler::kHandleStateMetric,
ExternalProtocolHandler::DONT_LAUNCH, 1);
}
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, TestCancel) {
ShowUi(std::string("https://example.test"));
dialog_->CancelDialog();
EXPECT_EQ(blocked_state_, BlockState::UNKNOWN);
EXPECT_FALSE(url_did_launch_);
histogram_tester_.ExpectBucketCount(
ExternalProtocolHandler::kHandleStateMetric,
ExternalProtocolHandler::DONT_LAUNCH, 1);
}
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest,
TestCancelWithChecked) {
ShowUi(std::string("https://example.test"));
SetChecked(true);
dialog_->CancelDialog();
// Cancel() should not enforce the remember checkbox.
EXPECT_EQ(blocked_state_, BlockState::UNKNOWN);
EXPECT_FALSE(url_did_launch_);
histogram_tester_.ExpectBucketCount(
ExternalProtocolHandler::kHandleStateMetric,
ExternalProtocolHandler::DONT_LAUNCH, 1);
}
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, TestClose) {
// Closing the dialog should be the same as canceling, except for histograms.
ShowUi(std::string("https://example.test"));
EXPECT_TRUE(dialog_->Close());
EXPECT_EQ(blocked_state_, BlockState::UNKNOWN);
EXPECT_FALSE(url_did_launch_);
histogram_tester_.ExpectBucketCount(
ExternalProtocolHandler::kHandleStateMetric,
ExternalProtocolHandler::DONT_LAUNCH, 1);
}
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest,
TestCloseWithChecked) {
// Closing the dialog should be the same as canceling, except for histograms.
ShowUi(std::string("https://example.test"));
SetChecked(true);
EXPECT_TRUE(dialog_->Close());
EXPECT_EQ(blocked_state_, BlockState::UNKNOWN);
EXPECT_FALSE(url_did_launch_);
histogram_tester_.ExpectBucketCount(
ExternalProtocolHandler::kHandleStateMetric,
ExternalProtocolHandler::DONT_LAUNCH, 1);
}
// Invokes a dialog that asks the user if an external application is allowed to
// run.
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, InvokeUi_default) {
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, OriginNameTest) {
ASSERT_TRUE(embedded_test_server()->Start());
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL("a.test", "/empty.html")));
EXPECT_TRUE(content::ExecJs(
web_contents,
content::JsReplace("location.href = $1",
embedded_test_server()->GetURL(
"b.test", "/server-redirect?ms-calc:"))));
WaitForLaunchUrl();
EXPECT_TRUE(url_did_launch_);
// The url should be the url of the last redirecting server and not of the
// request initiator
EXPECT_EQ(launch_url_, "b.test");
}
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest,
TestPictureInPictureOcclusionStateChanges) {
ShowUi(std::string("https://example.test"));
ui::MouseEvent mouse_event(ui::EventType::kMousePressed, gfx::Point(),
gfx::Point(), ui::EventTimeForNow(), 0, 0);
EXPECT_FALSE(ShouldIgnoreButtonPressedEventHandling(nullptr, mouse_event));
// Simulate Picture-in-Picture dialog occlusion.
SimulateOcclusionStateChanged(true);
EXPECT_TRUE(ShouldIgnoreButtonPressedEventHandling(nullptr, mouse_event));
// Simulate Picture-in-Picture dialog not occluded.
SimulateOcclusionStateChanged(false);
EXPECT_FALSE(ShouldIgnoreButtonPressedEventHandling(nullptr, mouse_event));
}
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest,
TestShouldIgnoreButtonEventsWhenOccluded) {
ShowUi(std::string("https://example.test"));
ui::MouseEvent mouse_event(ui::EventType::kMousePressed, gfx::Point(),
gfx::Point(), ui::EventTimeForNow(), 0, 0);
// Initially not occluded by Picture-in-Picture.
EXPECT_FALSE(ShouldIgnoreButtonPressedEventHandling(nullptr, mouse_event));
SimulateOcclusionStateChanged(true);
EXPECT_TRUE(ShouldIgnoreButtonPressedEventHandling(nullptr, mouse_event));
SimulateOcclusionStateChanged(false);
EXPECT_FALSE(ShouldIgnoreButtonPressedEventHandling(nullptr, mouse_event));
}
IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest,
TestKeyEventsAreProtected) {
ShowUi(std::string("https://example.test"));
EXPECT_FALSE(ShouldAllowKeyEventsDuringInputProtection());
ui::KeyEvent press_enter(ui::EventType::kKeyPressed, ui::VKEY_RETURN,
ui::EF_NONE, ui::EventTimeForNow());
views::test::ButtonTestApi(dialog_->GetOkButton()).NotifyClick(press_enter);
EXPECT_FALSE(url_did_launch_);
ui::KeyEvent press_enter_delayed(
ui::EventType::kKeyPressed, ui::VKEY_RETURN, ui::EF_NONE,
ui::EventTimeForNow() + views::GetDoubleClickInterval());
views::test::ButtonTestApi(dialog_->GetOkButton())
.NotifyClick(press_enter_delayed);
EXPECT_TRUE(url_did_launch_);
}