|  | // Copyright (c) 2017 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/strings/utf_string_conversions.h" | 
|  | #include "base/test/scoped_feature_list.h" | 
|  | #include "build/build_config.h" | 
|  | #include "chrome/browser/ssl/security_state_tab_helper.h" | 
|  | #include "chrome/browser/ui/browser.h" | 
|  | #include "chrome/browser/ui/tabs/tab_strip_model.h" | 
|  | #include "chrome/common/chrome_switches.h" | 
|  | #include "chrome/test/base/in_process_browser_test.h" | 
|  | #include "chrome/test/base/ui_test_utils.h" | 
|  | #include "components/policy/core/browser/browser_policy_connector.h" | 
|  | #include "components/policy/core/common/mock_configuration_policy_provider.h" | 
|  | #include "components/policy/policy_constants.h" | 
|  | #include "components/security_state/core/features.h" | 
|  | #include "content/public/test/browser_test.h" | 
|  | #include "content/public/test/browser_test_utils.h" | 
|  | #include "net/dns/mock_host_resolver.h" | 
|  | #include "services/network/public/cpp/network_switches.h" | 
|  |  | 
|  | namespace { | 
|  | // SecureOriginAllowlistBrowsertests differ in the setup of the browser. Since | 
|  | // the setup is done before the actual test is run, we need to parameterize our | 
|  | // tests outside of the actual test bodies. We use test variants for this, | 
|  | // instead of the usual setup of mulitple tests. | 
|  | enum class TestVariant { | 
|  | kNone, | 
|  | kCommandline, | 
|  | kPolicyOld, | 
|  | kPolicy, | 
|  | kPolicy2, | 
|  | kPolicy3, | 
|  | kPolicyOldAndNew, | 
|  | }; | 
|  | }  // namespace | 
|  |  | 
|  | // End-to-end browser test that ensures the secure origin allowlist works when | 
|  | // supplied via command-line or policy. | 
|  | class SecureOriginAllowlistBrowsertest | 
|  | : public InProcessBrowserTest, | 
|  | public testing::WithParamInterface<TestVariant> { | 
|  | public: | 
|  | void SetUpOnMainThread() override { | 
|  | // We need this, so we can request the test page from 'http://foo.com'. | 
|  | // (Which, unlike 127.0.0.1, is considered an insecure origin.) | 
|  | host_resolver()->AddRule("*", "127.0.0.1"); | 
|  | } | 
|  |  | 
|  | void SetUpCommandLine(base::CommandLine* command_line) override { | 
|  | // We need to know the server port to know what to add to the command-line. | 
|  | // The port number changes with every test run. Thus, we start the server | 
|  | // here. And since all tests, not just the variant with the command-line, | 
|  | // need the embedded server, we unconditionally start it here. | 
|  | EXPECT_TRUE(embedded_test_server()->Start()); | 
|  |  | 
|  | if (GetParam() != TestVariant::kCommandline) | 
|  | return; | 
|  |  | 
|  | command_line->AppendSwitchASCII( | 
|  | network::switches::kUnsafelyTreatInsecureOriginAsSecure, BaseURL()); | 
|  | } | 
|  |  | 
|  | void SetUpInProcessBrowserTestFixture() override { | 
|  | TestVariant variant = GetParam(); | 
|  | if (variant != TestVariant::kPolicyOld && variant != TestVariant::kPolicy && | 
|  | variant != TestVariant::kPolicy2 && variant != TestVariant::kPolicy3 && | 
|  | variant != TestVariant::kPolicyOldAndNew) | 
|  | return; | 
|  |  | 
|  | // We setup the policy here, because the policy must be 'live' before | 
|  | // the renderer is created, since the value for this policy is passed | 
|  | // to the renderer via a command-line. Setting the policy in the test | 
|  | // itself or in SetUpOnMainThread works for update-able policies, but | 
|  | // is too late for this one. | 
|  | EXPECT_CALL(provider_, IsInitializationComplete(testing::_)) | 
|  | .WillRepeatedly(testing::Return(true)); | 
|  | policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); | 
|  |  | 
|  | base::Value urls(base::Value::Type::LIST); | 
|  | if (variant == TestVariant::kPolicy || variant == TestVariant::kPolicyOld || | 
|  | variant == TestVariant::kPolicyOldAndNew) { | 
|  | urls.Append(BaseURL()); | 
|  | } else if (variant == TestVariant::kPolicy2) { | 
|  | urls.Append(BaseURL()); | 
|  | urls.Append(OtherURL()); | 
|  | } else if (variant == TestVariant::kPolicy3) { | 
|  | urls.Append(OtherURL()); | 
|  | urls.Append(BaseURL()); | 
|  | } | 
|  |  | 
|  | policy::PolicyMap values; | 
|  | values.Set((variant == TestVariant::kPolicyOld || | 
|  | variant == TestVariant::kPolicyOldAndNew) | 
|  | ? policy::key::kUnsafelyTreatInsecureOriginAsSecure | 
|  | : policy::key::kOverrideSecurityRestrictionsOnInsecureOrigin, | 
|  | policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, | 
|  | policy::POLICY_SOURCE_CLOUD, std::move(urls), nullptr); | 
|  | if (variant == TestVariant::kPolicyOldAndNew) { | 
|  | base::Value other_urls(base::Value::Type::LIST); | 
|  | other_urls.Append(base::Value(OtherURL())); | 
|  | values.Set(policy::key::kOverrideSecurityRestrictionsOnInsecureOrigin, | 
|  | policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, | 
|  | policy::POLICY_SOURCE_CLOUD, std::move(other_urls), nullptr); | 
|  | } | 
|  |  | 
|  | provider_.UpdateChromePolicy(values); | 
|  | } | 
|  |  | 
|  | bool ExpectSecureContext() { return GetParam() != TestVariant::kNone; } | 
|  |  | 
|  | std::string BaseURL() { | 
|  | return embedded_test_server()->GetURL("example.com", "/").spec(); | 
|  | } | 
|  |  | 
|  | std::string OtherURL() { | 
|  | return embedded_test_server()->GetURL("otherexample.com", "/").spec(); | 
|  | } | 
|  |  | 
|  | private: | 
|  | policy::MockConfigurationPolicyProvider provider_; | 
|  | }; | 
|  |  | 
|  | INSTANTIATE_TEST_SUITE_P(SecureOriginAllowlistBrowsertest, | 
|  | SecureOriginAllowlistBrowsertest, | 
|  | testing::Values(TestVariant::kNone, | 
|  | TestVariant::kCommandline, | 
|  | // The legacy policy isn't defined on ChromeOS or Android, so skip tests that | 
|  | // use it on those platforms. | 
|  | #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) | 
|  | TestVariant::kPolicyOld, | 
|  | TestVariant::kPolicyOldAndNew, | 
|  | #endif | 
|  | TestVariant::kPolicy, | 
|  | TestVariant::kPolicy2, | 
|  | TestVariant::kPolicy3)); | 
|  |  | 
|  | IN_PROC_BROWSER_TEST_P(SecureOriginAllowlistBrowsertest, Simple) { | 
|  | GURL url = embedded_test_server()->GetURL( | 
|  | "example.com", "/secure_origin_allowlist_browsertest.html"); | 
|  | ui_test_utils::NavigateToURL(browser(), url); | 
|  |  | 
|  | std::u16string secure(u"secure context"); | 
|  | std::u16string insecure(u"insecure context"); | 
|  |  | 
|  | content::TitleWatcher title_watcher( | 
|  | browser()->tab_strip_model()->GetActiveWebContents(), secure); | 
|  | title_watcher.AlsoWaitForTitle(insecure); | 
|  |  | 
|  | if (GetParam() == TestVariant::kPolicyOldAndNew) { | 
|  | // When both policies are set, the new one should take precedence over the | 
|  | // old one. | 
|  | EXPECT_EQ(title_watcher.WaitAndGetTitle(), insecure); | 
|  | content::TitleWatcher next_title_watcher( | 
|  | browser()->tab_strip_model()->GetActiveWebContents(), secure); | 
|  | next_title_watcher.AlsoWaitForTitle(insecure); | 
|  | ui_test_utils::NavigateToURL( | 
|  | browser(), | 
|  | embedded_test_server()->GetURL( | 
|  | "otherexample.com", "/secure_origin_allowlist_browsertest.html")); | 
|  | EXPECT_EQ(next_title_watcher.WaitAndGetTitle(), secure); | 
|  | } else { | 
|  | EXPECT_EQ(title_watcher.WaitAndGetTitle(), | 
|  | ExpectSecureContext() ? secure : insecure); | 
|  | } | 
|  | } | 
|  |  | 
|  | IN_PROC_BROWSER_TEST_P(SecureOriginAllowlistBrowsertest, SecurityIndicators) { | 
|  | ui_test_utils::NavigateToURL( | 
|  | browser(), | 
|  | embedded_test_server()->GetURL( | 
|  | "example.com", "/secure_origin_allowlist_browsertest.html")); | 
|  | auto* helper = SecurityStateTabHelper::FromWebContents( | 
|  | browser()->tab_strip_model()->GetActiveWebContents()); | 
|  | ASSERT_TRUE(helper); | 
|  |  | 
|  | if (GetParam() == TestVariant::kPolicyOldAndNew) { | 
|  | // When both policies are set, the new policy overrides the old policy. | 
|  | EXPECT_EQ(security_state::WARNING, helper->GetSecurityLevel()); | 
|  | ui_test_utils::NavigateToURL( | 
|  | browser(), | 
|  | embedded_test_server()->GetURL( | 
|  | "otherexample.com", "/secure_origin_allowlist_browsertest.html")); | 
|  | EXPECT_EQ(security_state::NONE, helper->GetSecurityLevel()); | 
|  | } else { | 
|  | EXPECT_EQ( | 
|  | ExpectSecureContext() ? security_state::NONE : security_state::WARNING, | 
|  | helper->GetSecurityLevel()); | 
|  | } | 
|  | } |