#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "chrome/browser/chrome_content_browser_client.h"
#include <memory>
#include <vector>
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
#include "chrome/browser/external_protocol/external_protocol_handler.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/instant_service.h"
#include "chrome/browser/search/instant_service_factory.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/search/instant_test_base.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/content_settings/core/common/features.h"
#include "components/custom_handlers/protocol_handler.h"
#include "components/custom_handlers/protocol_handler_registry.h"
#include "components/enterprise/buildflags/buildflags.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations.h"
#include "components/privacy_sandbox/privacy_sandbox_attestations/scoped_privacy_sandbox_attestations.h"
#include "components/privacy_sandbox/privacy_sandbox_features.h"
#include "components/safe_browsing/buildflags.h"
#include "components/site_isolation/site_isolation_policy.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.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/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_utils.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "services/network/public/cpp/url_loader_factory_builder.h"
#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/color/color_provider.h"
#include "ui/color/color_provider_key.h"
#include "ui/color/color_provider_manager.h"
#include "ui/color/color_provider_source.h"
#include "ui/color/color_provider_utils.h"
#include "ui/native_theme/native_theme.h"
#include "ui/native_theme/test_native_theme.h"
#include "url/gurl.h"
#include "url/origin.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/common/constants.h"
#include "extensions/common/extension_urls.h"
#include "url/url_constants.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "chrome/test/base/launchservices_utils_mac.h"
#endif
#if BUILDFLAG(ENTERPRISE_CONTENT_ANALYSIS)
#include "base/files/scoped_temp_dir.h"
#include "base/test/bind.h"
#include "base/threading/scoped_blocking_call.h"
#include "chrome/browser/enterprise/connectors/connectors_service.h"
#include "chrome/browser/enterprise/connectors/test/deep_scanning_test_utils.h"
#include "chrome/browser/enterprise/connectors/test/fake_content_analysis_delegate.h"
#include "ui/base/clipboard/clipboard_format_type.h"
#if BUILDFLAG(ENTERPRISE_LOCAL_CONTENT_ANALYSIS)
#include "chrome/browser/enterprise/connectors/test/fake_content_analysis_sdk_manager.h"
#endif
#endif
namespace {
std::vector<uint8_t> StringToVector(const std::string& str) { … }
class ChromeContentBrowserClientBrowserTest : public InProcessBrowserTest { … };
IN_PROC_BROWSER_TEST_F(ChromeContentBrowserClientBrowserTest,
SitePerProcessNavigation) { … }
class TopChromeChromeContentBrowserClientTest
: public ChromeContentBrowserClientBrowserTest { … };
#if BUILDFLAG(IS_MAC)
#define MAYBE_ShouldUseSpareRendererWhenNoTopChromePagesPresent …
#else
#define MAYBE_ShouldUseSpareRendererWhenNoTopChromePagesPresent …
#endif
IN_PROC_BROWSER_TEST_F(
TopChromeChromeContentBrowserClientTest,
MAYBE_ShouldUseSpareRendererWhenNoTopChromePagesPresent) { … }
class IsolatedOriginNTPBrowserTest : public InProcessBrowserTest,
public InstantTestBase { … };
IN_PROC_BROWSER_TEST_F(IsolatedOriginNTPBrowserTest,
IsolatedOriginDoesNotInterfereWithNTP) { … }
class OpenWindowFromNTPBrowserTest : public InProcessBrowserTest,
public InstantTestBase { … };
IN_PROC_BROWSER_TEST_F(OpenWindowFromNTPBrowserTest,
TransferFromNTPCreateNewTab) { … }
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS)
class SystemAccentColorTest : public InProcessBrowserTest {
protected:
SystemAccentColorTest() : browser_client_(&test_theme_) {}
~SystemAccentColorTest() override {
CHECK_EQ(&browser_client_, SetBrowserClientForTesting(original_client_));
}
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
"CSSSystemAccentColor");
}
void SetWebAppScope(const GURL web_app_scope) {
browser_client_.set_web_app_scope(web_app_scope);
original_client_ = content::SetBrowserClientForTesting(&browser_client_);
browser()
->tab_strip_model()
->GetActiveWebContents()
->OnWebPreferencesChanged();
}
ui::TestNativeTheme test_theme_;
private:
class BrowserClientForAccentColorTest : public ChromeContentBrowserClient {
public:
explicit BrowserClientForAccentColorTest(const ui::NativeTheme* theme)
: theme_(theme) {}
void set_web_app_scope(const GURL& web_app_scope) {
web_app_scope_ = web_app_scope;
}
void OverrideWebkitPrefs(
content::WebContents* web_contents,
blink::web_pref::WebPreferences* web_prefs) override {
ChromeContentBrowserClient::OverrideWebkitPrefs(web_contents, web_prefs);
web_prefs->web_app_scope = web_app_scope_;
}
protected:
const ui::NativeTheme* GetWebTheme() const override { return theme_; }
private:
const raw_ptr<const ui::NativeTheme> theme_;
GURL web_app_scope_;
};
BrowserClientForAccentColorTest browser_client_;
raw_ptr<content::ContentBrowserClient> original_client_ = nullptr;
};
IN_PROC_BROWSER_TEST_F(SystemAccentColorTest,
SystemAccentColorKeywordForInstalledWebApp) {
GURL web_app_scope = ui_test_utils::GetTestUrl(
base::FilePath(base::FilePath::kCurrentDirectory),
base::FilePath(FILE_PATH_LITERAL("system-accent-color.html")));
SetWebAppScope(web_app_scope);
ui::NativeTheme::GetInstanceForWeb()->set_user_color(
SkColorSetRGB(135, 115, 10));
ui::NativeTheme::GetInstanceForWeb()->NotifyOnNativeThemeUpdated();
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), web_app_scope));
EXPECT_EQ("rgb(135, 115, 10)",
EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
base::StringPrintf(
"window.getComputedStyle(document.getElementById('"
"header_element')).backgroundColor")));
}
IN_PROC_BROWSER_TEST_F(SystemAccentColorTest,
SystemAccentColorKeywordForNonWebApp) {
GURL web_app_scope = ui_test_utils::GetTestUrl(
base::FilePath(base::FilePath::kCurrentDirectory),
base::FilePath(FILE_PATH_LITERAL("system-accent-color.html")));
SetWebAppScope(GURL());
ui::NativeTheme::GetInstanceForWeb()->set_user_color(
SkColorSetRGB(135, 115, 10));
ui::NativeTheme::GetInstanceForWeb()->NotifyOnNativeThemeUpdated();
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), web_app_scope));
EXPECT_EQ("rgb(0, 117, 255)",
EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
base::StringPrintf(
"window.getComputedStyle(document.getElementById('"
"header_element')).backgroundColor")));
}
#endif
class ForcedColorsTest : public testing::WithParamInterface<bool>,
public InProcessBrowserTest { … };
IN_PROC_BROWSER_TEST_P(ForcedColorsTest, ForcedColors) { … }
IN_PROC_BROWSER_TEST_P(ForcedColorsTest, ForcedColorsWithBlockList) { … }
INSTANTIATE_TEST_SUITE_P(…);
class PageColorsBrowserClientTest : public InProcessBrowserTest { … };
IN_PROC_BROWSER_TEST_F(PageColorsBrowserClientTest,
PageColorsAffectsWebContents) { … }
IN_PROC_BROWSER_TEST_F(PageColorsBrowserClientTest,
PageColorsAffectsCssPseudoElements) { … }
class PrefersColorSchemeTest
: public testing::WithParamInterface<std::tuple<bool, bool>>,
public InProcessBrowserTest { … };
IN_PROC_BROWSER_TEST_P(PrefersColorSchemeTest, PrefersColorScheme) { … }
IN_PROC_BROWSER_TEST_P(PrefersColorSchemeTest, FeatureOverridesChromeSchemes) { … }
#if BUILDFLAG(ENABLE_EXTENSIONS)
IN_PROC_BROWSER_TEST_P(PrefersColorSchemeTest, FeatureOverridesPdfUI) { … }
#endif
INSTANTIATE_TEST_SUITE_P(…);
class PreferredRootScrollbarColorSchemeChromeClientTest
: public testing::WithParamInterface<std::tuple<bool, bool>>,
public InProcessBrowserTest { … };
IN_PROC_BROWSER_TEST_P(PreferredRootScrollbarColorSchemeChromeClientTest,
ScrollbarFollowsPreferredColorScheme) { … }
INSTANTIATE_TEST_SUITE_P(…);
class PrefersContrastTest
: public testing::WithParamInterface<ui::NativeTheme::PreferredContrast>,
public InProcessBrowserTest { … };
IN_PROC_BROWSER_TEST_P(PrefersContrastTest, PrefersContrast) { … }
INSTANTIATE_TEST_SUITE_P(…);
class ProtocolHandlerTest : public InProcessBrowserTest { … };
#if BUILDFLAG(IS_MAC)
#define MAYBE_CustomHandler …
#else
#define MAYBE_CustomHandler …
#endif
IN_PROC_BROWSER_TEST_F(ProtocolHandlerTest, MAYBE_CustomHandler) { … }
IN_PROC_BROWSER_TEST_F(ProtocolHandlerTest, HandlersIgnoredWhenDisabled) { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(ProtocolHandlerTest, ExternalProgramNotLaunched) {
ASSERT_TRUE(
ui_test_utils::NavigateToURL(browser(), GURL("mailto:[email protected]")));
EXPECT_EQ(1, browser()->tab_strip_model()->count());
std::u16string expected_title = u"mail.google.com";
content::TitleWatcher title_watcher(
browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
}
namespace {
class FakeExternalProtocolHandlerWorker
: public shell_integration::DefaultSchemeClientWorker {
public:
FakeExternalProtocolHandlerWorker(
const GURL& url,
shell_integration::DefaultWebClientState os_state,
const std::u16string& program_name)
: shell_integration::DefaultSchemeClientWorker(url),
os_state_(os_state),
program_name_(program_name) {}
private:
~FakeExternalProtocolHandlerWorker() override = default;
shell_integration::DefaultWebClientState CheckIsDefaultImpl() override {
return os_state_;
}
std::u16string GetDefaultClientNameImpl() override { return program_name_; }
void SetAsDefaultImpl(base::OnceClosure on_finished_callback) override {
std::move(on_finished_callback).Run();
}
shell_integration::DefaultWebClientState os_state_;
std::u16string program_name_;
};
class ScopedFakeExternalProtocolHandlerDelegate
: public ExternalProtocolHandler::Delegate {
public:
ScopedFakeExternalProtocolHandlerDelegate() {
ExternalProtocolHandler::SetDelegateForTesting(this);
}
~ScopedFakeExternalProtocolHandlerDelegate() override {
ExternalProtocolHandler::SetDelegateForTesting(nullptr);
}
scoped_refptr<shell_integration::DefaultSchemeClientWorker> CreateShellWorker(
const GURL& url) override {
return new FakeExternalProtocolHandlerWorker(
url, shell_integration::UNKNOWN_DEFAULT, program_name_);
}
ExternalProtocolHandler::BlockState GetBlockState(const std::string& scheme,
Profile* profile) override {
return ExternalProtocolHandler::UNKNOWN;
}
void BlockRequest() override {
FAIL() << "Unexpected BlockRequest call received";
}
void RunExternalProtocolDialog(
const GURL& url,
content::WebContents* web_contents,
ui::PageTransition page_transition,
bool has_user_gesture,
const std::optional<url::Origin>& initiating_origin,
const std::u16string& program_name) override {
EXPECT_EQ(program_name_, program_name);
external_protocol_dialog_called_ = true;
launched_url_with_security_check_ = url.spec();
}
void LaunchUrlWithoutSecurityCheck(
const GURL& url,
content::WebContents* web_contents) override {
launched_url_without_security_check_ = url.spec();
launch_url_run_loop_.Quit();
}
void FinishedProcessingCheck() override { launch_url_run_loop_.Quit(); }
void WaitExternalUrlLaunchCompleted() { launch_url_run_loop_.Run(); }
bool external_protocol_dialog_called() {
return external_protocol_dialog_called_;
}
std::string launched_url_without_security_check() {
return launched_url_without_security_check_;
}
std::string launched_url_with_security_check() {
return launched_url_with_security_check_;
}
private:
base::RunLoop launch_url_run_loop_;
const std::u16string program_name_ = u"custom";
bool launch_url_called_ = false;
bool external_protocol_dialog_called_ = false;
std::string launched_url_without_security_check_;
std::string launched_url_with_security_check_;
};
}
IN_PROC_BROWSER_TEST_F(ProtocolHandlerTest,
SecurityCheckExceptionForAllowlistedUrls) {
ProtocolHandlerRegistryFactory::GetInstance()
->GetForBrowserContext(browser()->profile())
->OnAcceptRegisterProtocolHandler(
custom_handlers::ProtocolHandler::CreateProtocolHandler(
"map", GURL("geo://%s")));
ScopedFakeExternalProtocolHandlerDelegate delegate;
base::Value::List allowlist;
allowlist.Append("geo://*");
browser()->profile()->GetPrefs()->SetList(policy::policy_prefs::kUrlAllowlist,
std::move(allowlist));
base::RunLoop().RunUntilIdle();
const char kGeoUrl[] = "geo:48.2082,16.3738";
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kGeoUrl)));
delegate.WaitExternalUrlLaunchCompleted();
EXPECT_FALSE(delegate.external_protocol_dialog_called());
EXPECT_EQ(delegate.launched_url_without_security_check(), kGeoUrl);
EXPECT_EQ(delegate.launched_url_with_security_check(), "");
}
IN_PROC_BROWSER_TEST_F(ProtocolHandlerTest,
IntentSchemeBypassSecurityExceptions) {
ProtocolHandlerRegistryFactory::GetInstance()
->GetForBrowserContext(browser()->profile())
->OnAcceptRegisterProtocolHandler(
custom_handlers::ProtocolHandler::CreateProtocolHandler(
"search", GURL("intent://%s")));
ScopedFakeExternalProtocolHandlerDelegate delegate;
base::Value::List allowlist;
allowlist.Append("intent://*");
browser()->profile()->GetPrefs()->SetList(policy::policy_prefs::kUrlAllowlist,
std::move(allowlist));
base::RunLoop().RunUntilIdle();
const char kIntentUrl[] =
"intent://www.google.com/"
"#Intent;scheme=http;package=com.android.chrome;end";
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kIntentUrl)));
delegate.WaitExternalUrlLaunchCompleted();
EXPECT_TRUE(delegate.external_protocol_dialog_called());
EXPECT_EQ(delegate.launched_url_without_security_check(), "");
EXPECT_EQ(delegate.launched_url_with_security_check(), kIntentUrl);
}
#endif
#if !BUILDFLAG(IS_ANDROID)
class KeepaliveDurationOnShutdownTest : public InProcessBrowserTest,
public InstantTestBase { … };
IN_PROC_BROWSER_TEST_F(KeepaliveDurationOnShutdownTest, DefaultValue) { … }
IN_PROC_BROWSER_TEST_F(KeepaliveDurationOnShutdownTest, PolicySettings) { … }
IN_PROC_BROWSER_TEST_F(KeepaliveDurationOnShutdownTest, DynamicUpdate) { … }
#endif
#if BUILDFLAG(ENTERPRISE_CONTENT_ANALYSIS)
class ClipboardTestContentAnalysisDelegate
: public enterprise_connectors::test::FakeContentAnalysisDelegate { … };
class IsClipboardPasteAllowedTest : public InProcessBrowserTest { … };
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, BitmapAllowed) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, BitmapBlocked) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, TextAllowed) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, TextBlocked) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, HtmlAllowed) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, HtmlBlocked) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, SvgAllowed) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, SvgBlocked) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, RtfAllowed) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, RtfBlocked) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, CustomDataAllowed) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, CustomDataBlocked) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, AllFilesAllowed) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, AllFilesBlocked) { … }
IN_PROC_BROWSER_TEST_F(IsClipboardPasteAllowedTest, SomeFilesBlocked) { … }
#endif
class AutomaticBeaconCredentialsBrowserTest : public InProcessBrowserTest,
public InstantTestBase { … };
IN_PROC_BROWSER_TEST_F(AutomaticBeaconCredentialsBrowserTest,
3PCEnabledAndDisabled) { … }
IN_PROC_BROWSER_TEST_F(TopChromeChromeContentBrowserClientTest,
UnboundRequestDoesNothing) { … }
IN_PROC_BROWSER_TEST_F(TopChromeChromeContentBrowserClientTest,
BoundRequestCreatesNetworkContext) { … }
IN_PROC_BROWSER_TEST_F(TopChromeChromeContentBrowserClientTest,
BoundRequestWithOverrideCreatesNetworkContext) { … }
}