/*
 * Copyright (c) 2014, Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/frame/local_dom_window.h"

#include "base/strings/stringprintf.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/loader/referrer_utils.h"
#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
#include "third_party/blink/renderer/core/execution_context/agent.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"

namespace blink {

using network::mojom::ContentSecurityPolicySource;
using network::mojom::ContentSecurityPolicyType;

class LocalDOMWindowTest : public PageTestBase {};

TEST_F(LocalDOMWindowTest, AttachExecutionContext) {
  auto* scheduler = GetFrame().GetFrameScheduler();
  auto* window = GetFrame().DomWindow();
  EXPECT_TRUE(
      window->GetAgent()->event_loop()->IsSchedulerAttachedForTest(scheduler));
  window->FrameDestroyed();
  EXPECT_FALSE(
      window->GetAgent()->event_loop()->IsSchedulerAttachedForTest(scheduler));
}

TEST_F(LocalDOMWindowTest, referrerPolicyParsing) {
  LocalDOMWindow* window = GetFrame().DomWindow();
  EXPECT_EQ(network::mojom::ReferrerPolicy::kDefault,
            window->GetReferrerPolicy());

  struct TestCase {
    const char* policy;
    network::mojom::ReferrerPolicy expected;
    bool uses_legacy_tokens;
  } tests[] = {
      {"", network::mojom::ReferrerPolicy::kDefault, false},
      // Test that invalid policy values are ignored.
      {"not-a-real-policy", network::mojom::ReferrerPolicy::kDefault, false},
      {"not-a-real-policy,also-not-a-real-policy",
       network::mojom::ReferrerPolicy::kDefault, false},
      {"not-a-real-policy,unsafe-url", network::mojom::ReferrerPolicy::kAlways,
       false},
      {"unsafe-url,not-a-real-policy", network::mojom::ReferrerPolicy::kAlways,
       false},
      // Test parsing each of the policy values.
      {"always", network::mojom::ReferrerPolicy::kAlways, true},
      {"default",
       ReferrerUtils::MojoReferrerPolicyResolveDefault(
           network::mojom::ReferrerPolicy::kDefault),
       true},
      {"never", network::mojom::ReferrerPolicy::kNever, true},
      {"no-referrer", network::mojom::ReferrerPolicy::kNever, false},
      {"no-referrer-when-downgrade",
       network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade, false},
      {"origin", network::mojom::ReferrerPolicy::kOrigin, false},
      {"origin-when-crossorigin",
       network::mojom::ReferrerPolicy::kOriginWhenCrossOrigin, true},
      {"origin-when-cross-origin",
       network::mojom::ReferrerPolicy::kOriginWhenCrossOrigin, false},
      {"same-origin", network::mojom::ReferrerPolicy::kSameOrigin, false},
      {"strict-origin", network::mojom::ReferrerPolicy::kStrictOrigin, false},
      {"strict-origin-when-cross-origin",
       network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin, false},
      {"unsafe-url", network::mojom::ReferrerPolicy::kAlways},
  };

  for (const auto test : tests) {
    window->SetReferrerPolicy(network::mojom::ReferrerPolicy::kDefault);
    if (test.uses_legacy_tokens) {
      // Legacy tokens are supported only for meta-specified policy.
      window->ParseAndSetReferrerPolicy(test.policy, kPolicySourceHttpHeader);
      EXPECT_EQ(network::mojom::ReferrerPolicy::kDefault,
                window->GetReferrerPolicy());
      window->ParseAndSetReferrerPolicy(test.policy, kPolicySourceMetaTag);
    } else {
      window->ParseAndSetReferrerPolicy(test.policy, kPolicySourceHttpHeader);
    }
    EXPECT_EQ(test.expected, window->GetReferrerPolicy()) << test.policy;
  }
}

TEST_F(LocalDOMWindowTest, referrerPolicyParsingWithCommas) {
  LocalDOMWindow* window = GetFrame().DomWindow();
  EXPECT_EQ(network::mojom::ReferrerPolicy::kDefault,
            window->GetReferrerPolicy());

  struct TestCase {
    const char* policy;
    network::mojom::ReferrerPolicy expected;
  } tests[] = {
      {"same-origin,strict-origin",
       network::mojom::ReferrerPolicy::kStrictOrigin},
      {"same-origin,not-a-real-policy,strict-origin",
       network::mojom::ReferrerPolicy::kStrictOrigin},
      {"strict-origin, same-origin, not-a-real-policy",
       network::mojom::ReferrerPolicy::kSameOrigin},
  };

  for (const auto test : tests) {
    window->SetReferrerPolicy(network::mojom::ReferrerPolicy::kDefault);
    // Policies containing commas are ignored when specified by a Meta element.
    window->ParseAndSetReferrerPolicy(test.policy, kPolicySourceMetaTag);
    EXPECT_EQ(network::mojom::ReferrerPolicy::kDefault,
              window->GetReferrerPolicy());

    // Header-specified policy permits commas and returns the last valid policy.
    window->ParseAndSetReferrerPolicy(test.policy, kPolicySourceHttpHeader);
    EXPECT_EQ(test.expected, window->GetReferrerPolicy()) << test.policy;
  }
}

TEST_F(LocalDOMWindowTest, OutgoingReferrer) {
  NavigateTo(KURL("https://www.example.com/hoge#fuga?piyo"));
  EXPECT_EQ("https://www.example.com/hoge",
            GetFrame().DomWindow()->OutgoingReferrer());
}

TEST_F(LocalDOMWindowTest, OutgoingReferrerWithUniqueOrigin) {
  NavigateTo(KURL("https://www.example.com/hoge#fuga?piyo"),
             {{http_names::kContentSecurityPolicy, "sandbox allow-scripts"}});
  EXPECT_TRUE(GetFrame().DomWindow()->GetSecurityOrigin()->IsOpaque());
  EXPECT_EQ(String(), GetFrame().DomWindow()->OutgoingReferrer());
}

TEST_F(LocalDOMWindowTest, EnforceSandboxFlags) {
  NavigateTo(KURL("http://example.test/"), {{http_names::kContentSecurityPolicy,
                                             "sandbox allow-same-origin"}});
  EXPECT_FALSE(GetFrame().DomWindow()->GetSecurityOrigin()->IsOpaque());
  EXPECT_FALSE(
      GetFrame().DomWindow()->GetSecurityOrigin()->IsPotentiallyTrustworthy());

  NavigateTo(KURL("http://example.test/"),
             {{http_names::kContentSecurityPolicy, "sandbox"}});
  EXPECT_TRUE(GetFrame().DomWindow()->GetSecurityOrigin()->IsOpaque());
  EXPECT_FALSE(
      GetFrame().DomWindow()->GetSecurityOrigin()->IsPotentiallyTrustworthy());

  // A unique origin does not bypass secure context checks unless it
  // is also potentially trustworthy.
  {
    url::ScopedSchemeRegistryForTests scoped_registry;
    url::AddStandardScheme("very-special-scheme", url::SCHEME_WITH_HOST);
    SchemeRegistry::RegisterURLSchemeBypassingSecureContextCheck(
        "very-special-scheme");
    NavigateTo(KURL("very-special-scheme://example.test"),
               {{http_names::kContentSecurityPolicy, "sandbox"}});
    EXPECT_TRUE(GetFrame().DomWindow()->GetSecurityOrigin()->IsOpaque());
    EXPECT_FALSE(GetFrame()
                     .DomWindow()
                     ->GetSecurityOrigin()
                     ->IsPotentiallyTrustworthy());
  }

  {
    url::ScopedSchemeRegistryForTests scoped_registry;
    url::AddStandardScheme("very-special-scheme", url::SCHEME_WITH_HOST);
    url::AddSecureScheme("very-special-scheme");
    NavigateTo(KURL("very-special-scheme://example.test"),
               {{http_names::kContentSecurityPolicy, "sandbox"}});
    EXPECT_TRUE(GetFrame().DomWindow()->GetSecurityOrigin()->IsOpaque());
    EXPECT_TRUE(GetFrame()
                    .DomWindow()
                    ->GetSecurityOrigin()
                    ->IsPotentiallyTrustworthy());

    NavigateTo(KURL("https://example.test"),
               {{http_names::kContentSecurityPolicy, "sandbox"}});
    EXPECT_TRUE(GetFrame().DomWindow()->GetSecurityOrigin()->IsOpaque());
    EXPECT_TRUE(GetFrame()
                    .DomWindow()
                    ->GetSecurityOrigin()
                    ->IsPotentiallyTrustworthy());
  }
}

// Tests ExecutionContext::GetContentSecurityPolicyForCurrentWorld().
TEST_F(PageTestBase, CSPForWorld) {
  using ::testing::ElementsAre;

  // Set a CSP for the main world.
  const char* kMainWorldCSP = "connect-src https://google.com;";
  GetFrame().DomWindow()->GetContentSecurityPolicy()->DidReceiveHeader(
      kMainWorldCSP, *(GetFrame().DomWindow()->GetSecurityOrigin()),
      ContentSecurityPolicyType::kEnforce, ContentSecurityPolicySource::kHTTP);
  const Vector<
      network::mojom::blink::ContentSecurityPolicyPtr>& parsed_main_world_csp =
      GetFrame().DomWindow()->GetContentSecurityPolicy()->GetParsedPolicies();

  LocalFrame* frame = &GetFrame();
  ScriptState* main_world_script_state = ToScriptStateForMainWorld(frame);
  v8::Isolate* isolate = main_world_script_state->GetIsolate();

  constexpr int kIsolatedWorldWithoutCSPId = 1;
  scoped_refptr<DOMWrapperWorld> world_without_csp =
      DOMWrapperWorld::EnsureIsolatedWorld(isolate, kIsolatedWorldWithoutCSPId);
  ASSERT_TRUE(world_without_csp->IsIsolatedWorld());
  ScriptState* isolated_world_without_csp_script_state =
      ToScriptState(frame, *world_without_csp);

  const char* kIsolatedWorldCSP = "script-src 'none';";
  constexpr int kIsolatedWorldWithCSPId = 2;
  scoped_refptr<DOMWrapperWorld> world_with_csp =
      DOMWrapperWorld::EnsureIsolatedWorld(isolate, kIsolatedWorldWithCSPId);
  ASSERT_TRUE(world_with_csp->IsIsolatedWorld());
  ScriptState* isolated_world_with_csp_script_state =
      ToScriptState(frame, *world_with_csp);
  IsolatedWorldCSP::Get().SetContentSecurityPolicy(
      kIsolatedWorldWithCSPId, kIsolatedWorldCSP,
      SecurityOrigin::Create(KURL("chrome-extension://123")));

  // Returns the csp headers being used for the current world.
  auto get_csp = [this]()
      -> const Vector<network::mojom::blink::ContentSecurityPolicyPtr>& {
    auto* csp =
        GetFrame().DomWindow()->GetContentSecurityPolicyForCurrentWorld();
    return csp->GetParsedPolicies();
  };

  {
    SCOPED_TRACE("In main world.");
    ScriptState::Scope scope(main_world_script_state);
    EXPECT_EQ(get_csp(), parsed_main_world_csp);
  }

  {
    SCOPED_TRACE("In isolated world without csp.");
    ScriptState::Scope scope(isolated_world_without_csp_script_state);

    // If we are in an isolated world with no CSP defined, we use the main world
    // CSP.
    EXPECT_EQ(get_csp(), parsed_main_world_csp);
  }

  {
    SCOPED_TRACE("In isolated world with csp.");
    ScriptState::Scope scope(isolated_world_with_csp_script_state);
    // We use the isolated world's CSP if it specified one.
    EXPECT_EQ(get_csp()[0]->header->header_value, kIsolatedWorldCSP);
  }
}

}  // namespace blink
