/*
 * Copyright (C) 2011 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``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 APPLE COMPUTER, INC. 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/csp/content_security_policy.h"

#include <memory>

#include "third_party/blink/public/mojom/net/ip_address_space.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_string_list.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/events/event_queue.h"
#include "third_party/blink/renderer/core/events/security_policy_violation_event.h"
#include "third_party/blink/renderer/core/frame/csp/csp_directive_list.h"
#include "third_party/blink/renderer/core/frame/csp/csp_source.h"
#include "third_party/blink/renderer/core/frame/csp/media_list_directive.h"
#include "third_party/blink/renderer/core/frame/csp/source_list_directive.h"
#include "third_party/blink/renderer/core/frame/frame_client.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/location.h"
#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/html_script_element.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/ping_loader.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worklet_global_scope.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/known_ports.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/reporting_service_proxy_ptr_holder.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/not_found.h"
#include "third_party/blink/renderer/platform/wtf/string_hasher.h"
#include "third_party/blink/renderer/platform/wtf/text/parsing_utilities.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"

namespace blink {

namespace {

// Helper function that returns true if the given |header_type| should be
// checked when the CheckHeaderType is |check_header_type|.
bool CheckHeaderTypeMatches(
    ContentSecurityPolicy::CheckHeaderType check_header_type,
    ContentSecurityPolicyHeaderType header_type) {
  switch (check_header_type) {
    case ContentSecurityPolicy::CheckHeaderType::kCheckAll:
      return true;
    case ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly:
      return header_type == kContentSecurityPolicyHeaderTypeReport;
    case ContentSecurityPolicy::CheckHeaderType::kCheckEnforce:
      return header_type == kContentSecurityPolicyHeaderTypeEnforce;
  }
  NOTREACHED();
  return false;
}

}  // namespace

bool ContentSecurityPolicy::IsNonceableElement(const Element* element) {
  if (element->nonce().IsNull())
    return false;

  bool nonceable = true;

  // To prevent an attacker from hijacking an existing nonce via a dangling
  // markup injection, we walk through the attributes of each nonced script
  // element: if their names or values contain "<script" or "<style", we won't
  // apply the nonce when loading script.
  //
  // TODO(mkwst): We'll should also skip elements for which the HTML parser
  // dropped attributes: https://crbug.com/740615 and https://crbug.com/790955.
  //
  // See http://blog.innerht.ml/csp-2015/#danglingmarkupinjection for an example
  // of the kind of attack this is aimed at mitigating.
  if (nonceable) {
    static const char kScriptString[] = "<SCRIPT";
    static const char kStyleString[] = "<STYLE";
    for (const Attribute& attr : element->Attributes()) {
      const AtomicString& name = attr.LocalName();
      const AtomicString& value = attr.Value();
      if (name.FindIgnoringASCIICase(kScriptString) != WTF::kNotFound ||
          name.FindIgnoringASCIICase(kStyleString) != WTF::kNotFound ||
          value.FindIgnoringASCIICase(kScriptString) != WTF::kNotFound ||
          value.FindIgnoringASCIICase(kStyleString) != WTF::kNotFound) {
        nonceable = false;
        break;
      }
    }
  }

  UseCounter::Count(
      element->GetDocument(),
      nonceable ? WebFeature::kCleanScriptElementWithNonce
                : WebFeature::kPotentiallyInjectedScriptElementWithNonce);

  return nonceable;
}

static WebFeature GetUseCounterType(ContentSecurityPolicyHeaderType type) {
  switch (type) {
    case kContentSecurityPolicyHeaderTypeEnforce:
      return WebFeature::kContentSecurityPolicy;
    case kContentSecurityPolicyHeaderTypeReport:
      return WebFeature::kContentSecurityPolicyReportOnly;
  }
  NOTREACHED();
  return WebFeature::kNumberOfFeatures;
}

ContentSecurityPolicy::ContentSecurityPolicy()
    : execution_context_(nullptr),
      override_inline_style_allowed_(false),
      script_hash_algorithms_used_(kContentSecurityPolicyHashAlgorithmNone),
      style_hash_algorithms_used_(kContentSecurityPolicyHashAlgorithmNone),
      sandbox_mask_(0),
      treat_as_public_address_(false),
      require_safe_types_(false),
      insecure_request_policy_(kLeaveInsecureRequestsAlone) {}

void ContentSecurityPolicy::BindToExecutionContext(
    ExecutionContext* execution_context) {
  execution_context_ = execution_context;
  ApplyPolicySideEffectsToExecutionContext();
}

void ContentSecurityPolicy::SetupSelf(const SecurityOrigin& security_origin) {
  // Ensure that 'self' processes correctly.
  self_protocol_ = security_origin.Protocol();
  self_source_ = new CSPSource(this, self_protocol_, security_origin.Host(),
                               security_origin.Port(), String(),
                               CSPSource::kNoWildcard, CSPSource::kNoWildcard);
}

void ContentSecurityPolicy::ApplyPolicySideEffectsToExecutionContext() {
  DCHECK(execution_context_ &&
         execution_context_->GetSecurityContext().GetSecurityOrigin());
  SecurityContext& security_context = execution_context_->GetSecurityContext();

  SetupSelf(*security_context.GetSecurityOrigin());

  // Set mixed content checking and sandbox flags, then dump all the parsing
  // error messages, then poke at histograms.
  Document* document = this->GetDocument();
  if (sandbox_mask_ != kSandboxNone) {
    UseCounter::Count(execution_context_, WebFeature::kSandboxViaCSP);
    if (document)
      document->EnforceSandboxFlags(sandbox_mask_);
    else
      security_context.ApplySandboxFlags(sandbox_mask_);
  }
  if (treat_as_public_address_) {
    security_context.SetAddressSpace(mojom::IPAddressSpace::kPublic);
  }
  if (require_safe_types_)
    security_context.SetRequireTrustedTypes();

  // Upgrade Insecure Requests: Update the policy.
  security_context.SetInsecureRequestPolicy(
      security_context.GetInsecureRequestPolicy() | insecure_request_policy_);
  if (document)
    document->DidEnforceInsecureRequestPolicy();

  // Upgrade Insecure Requests: Update the set of insecure URLs to upgrade.
  if (insecure_request_policy_ & kUpgradeInsecureRequests) {
    UseCounter::Count(execution_context_,
                      WebFeature::kUpgradeInsecureRequestsEnabled);
    if (!execution_context_->Url().Host().IsEmpty()) {
      uint32_t hash = execution_context_->Url().Host().Impl()->GetHash();
      security_context.AddInsecureNavigationUpgrade(hash);
      if (document)
        document->DidEnforceInsecureNavigationsSet();
    }
  }

  for (const auto& console_message : console_messages_)
    execution_context_->AddConsoleMessage(console_message);
  console_messages_.clear();

  for (const auto& policy : policies_) {
    UseCounter::Count(execution_context_,
                      GetUseCounterType(policy->HeaderType()));
    if (policy->AllowDynamic())
      UseCounter::Count(execution_context_, WebFeature::kCSPWithStrictDynamic);
    if (policy->AllowEval(nullptr,
                          SecurityViolationReportingPolicy::kSuppressReporting,
                          kWillNotThrowException, g_empty_string)) {
      UseCounter::Count(execution_context_, WebFeature::kCSPWithUnsafeEval);
    }
  }

  // We disable 'eval()' even in the case of report-only policies, and rely on
  // the check in the V8Initializer::codeGenerationCheckCallbackInMainThread
  // callback to determine whether the call should execute or not.
  if (!disable_eval_error_message_.IsNull())
    execution_context_->DisableEval(disable_eval_error_message_);
}

ContentSecurityPolicy::~ContentSecurityPolicy() = default;

void ContentSecurityPolicy::Trace(blink::Visitor* visitor) {
  visitor->Trace(execution_context_);
  visitor->Trace(policies_);
  visitor->Trace(console_messages_);
  visitor->Trace(self_source_);
}

Document* ContentSecurityPolicy::GetDocument() const {
  return (execution_context_ && execution_context_->IsDocument())
             ? ToDocument(execution_context_)
             : nullptr;
}

void ContentSecurityPolicy::CopyStateFrom(const ContentSecurityPolicy* other) {
  DCHECK(policies_.IsEmpty());
  for (const auto& policy : other->policies_)
    AddAndReportPolicyFromHeaderValue(policy->Header(), policy->HeaderType(),
                                      policy->HeaderSource());
}

void ContentSecurityPolicy::CopyPluginTypesFrom(
    const ContentSecurityPolicy* other) {
  for (const auto& policy : other->policies_) {
    if (policy->HasPluginTypes()) {
      AddAndReportPolicyFromHeaderValue(policy->PluginTypesText(),
                                        policy->HeaderType(),
                                        policy->HeaderSource());
    }
  }
}

void ContentSecurityPolicy::DidReceiveHeaders(
    const ContentSecurityPolicyResponseHeaders& headers) {
  if (headers.ShouldParseWasmEval()) {
    supports_wasm_eval_ = true;
  }
  if (!headers.ContentSecurityPolicy().IsEmpty())
    AddAndReportPolicyFromHeaderValue(headers.ContentSecurityPolicy(),
                                      kContentSecurityPolicyHeaderTypeEnforce,
                                      kContentSecurityPolicyHeaderSourceHTTP);
  if (!headers.ContentSecurityPolicyReportOnly().IsEmpty())
    AddAndReportPolicyFromHeaderValue(headers.ContentSecurityPolicyReportOnly(),
                                      kContentSecurityPolicyHeaderTypeReport,
                                      kContentSecurityPolicyHeaderSourceHTTP);
}

void ContentSecurityPolicy::DidReceiveHeader(
    const String& header,
    ContentSecurityPolicyHeaderType type,
    ContentSecurityPolicyHeaderSource source) {
  AddAndReportPolicyFromHeaderValue(header, type, source);

  // This might be called after we've been bound to an execution context. For
  // example, a <meta> element might be injected after page load.
  if (execution_context_)
    ApplyPolicySideEffectsToExecutionContext();
}

bool ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
    const ResourceResponse& response,
    const SecurityOrigin* parent_origin) {
  if (response.Url().IsEmpty() || response.Url().ProtocolIsAbout() ||
      response.Url().ProtocolIsData() || response.Url().ProtocolIs("blob") ||
      response.Url().ProtocolIs("filesystem")) {
    return true;
  }

  if (parent_origin->CanAccess(SecurityOrigin::Create(response.Url()).get()))
    return true;

  String header = response.HttpHeaderField(HTTPNames::Allow_CSP_From);
  header = header.StripWhiteSpace();
  if (header == "*")
    return true;
  if (scoped_refptr<const SecurityOrigin> child_origin =
          SecurityOrigin::CreateFromString(header)) {
    return parent_origin->CanAccess(child_origin.get());
  }

  return false;
}

void ContentSecurityPolicy::AddPolicyFromHeaderValue(
    const String& header,
    ContentSecurityPolicyHeaderType type,
    ContentSecurityPolicyHeaderSource source) {
  // If this is a report-only header inside a <meta> element, bail out.
  if (source == kContentSecurityPolicyHeaderSourceMeta &&
      type == kContentSecurityPolicyHeaderTypeReport) {
    ReportReportOnlyInMeta(header);
    return;
  }

  if (source == kContentSecurityPolicyHeaderSourceHTTP)
    header_delivered_ = true;

  Vector<UChar> characters;
  header.AppendTo(characters);

  const UChar* begin = characters.data();
  const UChar* end = begin + characters.size();

  // RFC2616, section 4.2 specifies that headers appearing multiple times can
  // be combined with a comma. Walk the header string, and parse each comma
  // separated chunk as a separate header.
  const UChar* position = begin;
  while (position < end) {
    SkipUntil<UChar>(position, end, ',');

    // header1,header2 OR header1
    //        ^                  ^
    Member<CSPDirectiveList> policy =
        CSPDirectiveList::Create(this, begin, position, type, source);

    if (!policy->AllowEval(nullptr,
                           SecurityViolationReportingPolicy::kSuppressReporting,
                           kWillNotThrowException, g_empty_string) &&
        disable_eval_error_message_.IsNull()) {
      disable_eval_error_message_ = policy->EvalDisabledErrorMessage();
    }

    policies_.push_back(policy.Release());

    // Skip the comma, and begin the next header from the current position.
    DCHECK(position == end || *position == ',');
    SkipExactly<UChar>(position, end, ',');
    begin = position;
  }
}

void ContentSecurityPolicy::ReportAccumulatedHeaders(
    LocalFrameClient* client) const {
  // Notify the embedder about headers that have accumulated before the
  // navigation got committed.  See comments in
  // addAndReportPolicyFromHeaderValue for more details and context.
  DCHECK(client);
  WebVector<WebContentSecurityPolicy> policies(policies_.size());
  for (size_t i = 0; i < policies_.size(); ++i)
    policies[i] = policies_[i]->ExposeForNavigationalChecks();
  client->DidAddContentSecurityPolicies(policies);
}

void ContentSecurityPolicy::AddAndReportPolicyFromHeaderValue(
    const String& header,
    ContentSecurityPolicyHeaderType type,
    ContentSecurityPolicyHeaderSource source) {
  size_t previous_policy_count = policies_.size();
  AddPolicyFromHeaderValue(header, type, source);
  // Notify about the new header, so that it can be reported back to the
  // browser process.  This is needed in order to:
  // 1) replicate CSP directives (i.e. frame-src) to OOPIFs (only for now /
  // short-term).
  // 2) enforce CSP in the browser process (long-term - see
  // https://crbug.com/376522).
  // TODO(arthursonzogni): policies are actually replicated (1) and some of
  // them are enforced on the browser process (2). Stop doing (1) when (2) is
  // finished.
  WebVector<WebContentSecurityPolicy> policies(policies_.size() -
                                               previous_policy_count);
  for (size_t i = previous_policy_count; i < policies_.size(); ++i) {
    policies[i - previous_policy_count] =
        policies_[i]->ExposeForNavigationalChecks();
  }
  if (GetDocument() && GetDocument()->GetFrame()) {
    GetDocument()->GetFrame()->Client()->DidAddContentSecurityPolicies(
        policies);
  }
}

void ContentSecurityPolicy::SetOverrideAllowInlineStyle(bool value) {
  override_inline_style_allowed_ = value;
}

void ContentSecurityPolicy::SetOverrideURLForSelf(const KURL& url) {
  // Create a temporary CSPSource so that 'self' expressions can be resolved
  // before we bind to an execution context (for 'frame-ancestor' resolution,
  // for example). This CSPSource will be overwritten when we bind this object
  // to an execution context.
  scoped_refptr<const SecurityOrigin> origin = SecurityOrigin::Create(url);
  self_protocol_ = origin->Protocol();
  self_source_ =
      new CSPSource(this, self_protocol_, origin->Host(), origin->Port(),
                    String(), CSPSource::kNoWildcard, CSPSource::kNoWildcard);
}

std::unique_ptr<Vector<CSPHeaderAndType>> ContentSecurityPolicy::Headers()
    const {
  std::unique_ptr<Vector<CSPHeaderAndType>> headers =
      std::make_unique<Vector<CSPHeaderAndType>>();
  for (const auto& policy : policies_) {
    CSPHeaderAndType header_and_type(policy->Header(), policy->HeaderType());
    headers->push_back(header_and_type);
  }
  return headers;
}

// static
void ContentSecurityPolicy::FillInCSPHashValues(
    const String& source,
    uint8_t hash_algorithms_used,
    Vector<CSPHashValue>& csp_hash_values) {
  // Any additions or subtractions from this struct should also modify the
  // respective entries in the kSupportedPrefixes array in
  // SourceListDirective::parseHash().
  static const struct {
    ContentSecurityPolicyHashAlgorithm csp_hash_algorithm;
    HashAlgorithm algorithm;
  } kAlgorithmMap[] = {
      {kContentSecurityPolicyHashAlgorithmSha256, kHashAlgorithmSha256},
      {kContentSecurityPolicyHashAlgorithmSha384, kHashAlgorithmSha384},
      {kContentSecurityPolicyHashAlgorithmSha512, kHashAlgorithmSha512}};

  // Only bother normalizing the source/computing digests if there are any
  // checks to be done.
  if (hash_algorithms_used == kContentSecurityPolicyHashAlgorithmNone)
    return;

  StringUTF8Adaptor utf8_source(source);

  for (const auto& algorithm_map : kAlgorithmMap) {
    DigestValue digest;
    if (algorithm_map.csp_hash_algorithm & hash_algorithms_used) {
      bool digest_success =
          ComputeDigest(algorithm_map.algorithm, utf8_source.Data(),
                        utf8_source.length(), digest);
      if (digest_success) {
        csp_hash_values.push_back(
            CSPHashValue(algorithm_map.csp_hash_algorithm, digest));
      }
    }
  }
}

// static
bool ContentSecurityPolicy::CheckScriptHashAgainstPolicy(
    Vector<CSPHashValue>& csp_hash_values,
    const Member<CSPDirectiveList>& policy,
    InlineType inline_type) {
  for (const auto& csp_hash_value : csp_hash_values) {
    if (policy->AllowScriptHash(csp_hash_value, inline_type)) {
      return true;
    }
  }
  return false;
}

// static
bool ContentSecurityPolicy::CheckStyleHashAgainstPolicy(
    Vector<CSPHashValue>& csp_hash_values,
    const Member<CSPDirectiveList>& policy,
    InlineType inline_type) {
  for (const auto& csp_hash_value : csp_hash_values) {
    if (policy->AllowStyleHash(csp_hash_value, inline_type)) {
      return true;
    }
  }
  return false;
}

bool ContentSecurityPolicy::AllowJavaScriptURLs(
    Element* element,
    const String& source,
    const String& context_url,
    const WTF::OrdinalNumber& context_line,
    SecurityViolationReportingPolicy reporting_policy) const {
  bool is_allowed = true;
  for (const auto& policy : policies_) {
    is_allowed &= policy->AllowJavaScriptURLs(element, source, context_url,
                                              context_line, reporting_policy);
  }
  return is_allowed;
}

bool ContentSecurityPolicy::AllowInlineEventHandler(
    Element* element,
    const String& source,
    const String& context_url,
    const WTF::OrdinalNumber& context_line,
    SecurityViolationReportingPolicy reporting_policy) const {
  // Inline event handlers may be whitelisted by hash, if
  // 'unsafe-hash-attributes' is present in a policy. Check against the digest
  // of the |source| and also check whether inline script is allowed.
  Vector<CSPHashValue> csp_hash_values;
  FillInCSPHashValues(source, script_hash_algorithms_used_, csp_hash_values);

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    is_allowed &=
        CheckScriptHashAgainstPolicy(csp_hash_values, policy,
                                     InlineType::kAttribute) ||
        policy->AllowInlineEventHandlers(element, source, context_url,
                                         context_line, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowInlineScript(
    Element* element,
    const String& context_url,
    const String& nonce,
    const WTF::OrdinalNumber& context_line,
    const String& script_content,
    InlineType inline_type,
    SecurityViolationReportingPolicy reporting_policy) const {
  DCHECK(element);

  Vector<CSPHashValue> csp_hash_values;
  FillInCSPHashValues(script_content, script_hash_algorithms_used_,
                      csp_hash_values);

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    is_allowed &=
        CheckScriptHashAgainstPolicy(csp_hash_values, policy, inline_type) ||
        policy->AllowInlineScript(element, context_url, nonce, context_line,
                                  reporting_policy, script_content);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowInlineStyle(
    Element* element,
    const String& context_url,
    const String& nonce,
    const WTF::OrdinalNumber& context_line,
    const String& style_content,
    InlineType inline_type,
    SecurityViolationReportingPolicy reporting_policy) const {
  DCHECK(element);

  if (override_inline_style_allowed_)
    return true;

  Vector<CSPHashValue> csp_hash_values;
  FillInCSPHashValues(style_content, style_hash_algorithms_used_,
                      csp_hash_values);

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    is_allowed &=
        CheckStyleHashAgainstPolicy(csp_hash_values, policy, inline_type) ||
        policy->AllowInlineStyle(element, context_url, nonce, context_line,
                                 reporting_policy, style_content);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowEval(
    ScriptState* script_state,
    SecurityViolationReportingPolicy reporting_policy,
    ContentSecurityPolicy::ExceptionStatus exception_status,
    const String& script_content) const {
  bool is_allowed = true;
  for (const auto& policy : policies_) {
    is_allowed &= policy->AllowEval(script_state, reporting_policy,
                                    exception_status, script_content);
  }
  return is_allowed;
}

bool ContentSecurityPolicy::AllowWasmEval(
    ScriptState* script_state,
    SecurityViolationReportingPolicy reporting_policy,
    ContentSecurityPolicy::ExceptionStatus exception_status,
    const String& script_content) const {
  bool is_allowed = true;
  for (const auto& policy : policies_) {
    is_allowed &= policy->AllowWasmEval(script_state, reporting_policy,
                                        exception_status, script_content);
  }
  return is_allowed;
}

String ContentSecurityPolicy::EvalDisabledErrorMessage() const {
  for (const auto& policy : policies_) {
    if (!policy->AllowEval(nullptr,
                           SecurityViolationReportingPolicy::kSuppressReporting,
                           kWillNotThrowException, g_empty_string)) {
      return policy->EvalDisabledErrorMessage();
    }
  }
  return String();
}

bool ContentSecurityPolicy::AllowPluginType(
    const String& type,
    const String& type_attribute,
    const KURL& url,
    SecurityViolationReportingPolicy reporting_policy) const {
  for (const auto& policy : policies_) {
    if (!policy->AllowPluginType(type, type_attribute, url, reporting_policy))
      return false;
  }
  return true;
}

bool ContentSecurityPolicy::AllowPluginTypeForDocument(
    const Document& document,
    const String& type,
    const String& type_attribute,
    const KURL& url,
    SecurityViolationReportingPolicy reporting_policy) const {
  if (document.GetContentSecurityPolicy() &&
      !document.GetContentSecurityPolicy()->AllowPluginType(
          type, type_attribute, url))
    return false;

  // CSP says that a plugin document in a nested browsing context should
  // inherit the plugin-types of its parent.
  //
  // FIXME: The plugin-types directive should be pushed down into the
  // current document instead of reaching up to the parent for it here.
  LocalFrame* frame = document.GetFrame();
  if (frame && frame->Tree().Parent() && document.IsPluginDocument()) {
    ContentSecurityPolicy* parent_csp = frame->Tree()
                                            .Parent()
                                            ->GetSecurityContext()
                                            ->GetContentSecurityPolicy();
    if (parent_csp && !parent_csp->AllowPluginType(type, type_attribute, url))
      return false;
  }

  return true;
}

bool ContentSecurityPolicy::AllowScriptFromSource(
    const KURL& url,
    const String& nonce,
    const IntegrityMetadataSet& hashes,
    ParserDisposition parser_disposition,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_)) {
    UseCounter::Count(
        GetDocument(),
        parser_disposition == kParserInserted
            ? WebFeature::kScriptWithCSPBypassingSchemeParserInserted
            : WebFeature::kScriptWithCSPBypassingSchemeNotParserInserted);

    // If we're running experimental features, bypass CSP only for
    // non-parser-inserted resources whose scheme otherwise bypasses CSP. If
    // we're not running experimental features, bypass CSP for all resources
    // regardless of parser state. Once we have more data via the
    // 'ScriptWithCSPBypassingScheme*' metrics, make a decision about what
    // behavior to ship. https://crbug.com/653521
    if ((parser_disposition == kNotParserInserted ||
         !RuntimeEnabledFeatures::
             ExperimentalContentSecurityPolicyFeaturesEnabled()) &&
        // The schemes where javascript:-URLs are blocked are usually privileged
        // pages, so do not allow the CSP to be bypassed either.
        !SchemeRegistry::ShouldTreatURLSchemeAsNotAllowingJavascriptURLs(
            execution_context_->GetSecurityOrigin()->Protocol())) {
      return true;
    }
  }

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowScriptFromSource(url, nonce, hashes, parser_disposition,
                                      redirect_status, reporting_policy);
  }
  return is_allowed;
}

bool ContentSecurityPolicy::AllowRequestWithoutIntegrity(
    WebURLRequest::RequestContext context,
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  for (const auto& policy : policies_) {
    if (CheckHeaderTypeMatches(check_header_type, policy->HeaderType()) &&
        !policy->AllowRequestWithoutIntegrity(context, url, redirect_status,
                                              reporting_policy))
      return false;
  }
  return true;
}

bool ContentSecurityPolicy::AllowRequest(
    WebURLRequest::RequestContext context,
    const KURL& url,
    const String& nonce,
    const IntegrityMetadataSet& integrity_metadata,
    ParserDisposition parser_disposition,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (integrity_metadata.IsEmpty() &&
      !AllowRequestWithoutIntegrity(context, url, redirect_status,
                                    reporting_policy, check_header_type)) {
    return false;
  }

  switch (context) {
    case WebURLRequest::kRequestContextAudio:
    case WebURLRequest::kRequestContextTrack:
    case WebURLRequest::kRequestContextVideo:
      return AllowMediaFromSource(url, redirect_status, reporting_policy,
                                  check_header_type);
    case WebURLRequest::kRequestContextBeacon:
    case WebURLRequest::kRequestContextEventSource:
    case WebURLRequest::kRequestContextFetch:
    case WebURLRequest::kRequestContextPing:
    case WebURLRequest::kRequestContextXMLHttpRequest:
    case WebURLRequest::kRequestContextSubresource:
      return AllowConnectToSource(url, redirect_status, reporting_policy,
                                  check_header_type);
    case WebURLRequest::kRequestContextEmbed:
    case WebURLRequest::kRequestContextObject:
      return AllowObjectFromSource(url, redirect_status, reporting_policy,
                                   check_header_type);
    case WebURLRequest::kRequestContextPrefetch:
      return AllowPrefetchFromSource(url, redirect_status, reporting_policy,
                                     check_header_type);
    case WebURLRequest::kRequestContextFavicon:
    case WebURLRequest::kRequestContextImage:
    case WebURLRequest::kRequestContextImageSet:
      return AllowImageFromSource(url, redirect_status, reporting_policy,
                                  check_header_type);
    case WebURLRequest::kRequestContextFont:
      return AllowFontFromSource(url, redirect_status, reporting_policy,
                                 check_header_type);
    case WebURLRequest::kRequestContextForm:
      return AllowFormAction(url, redirect_status, reporting_policy,
                             check_header_type);
    case WebURLRequest::kRequestContextFrame:
    case WebURLRequest::kRequestContextIframe:
      return AllowFrameFromSource(url, redirect_status, reporting_policy,
                                  check_header_type);
    case WebURLRequest::kRequestContextImport:
    case WebURLRequest::kRequestContextScript:
    case WebURLRequest::kRequestContextXSLT:
      return AllowScriptFromSource(url, nonce, integrity_metadata,
                                   parser_disposition, redirect_status,
                                   reporting_policy, check_header_type);
    case WebURLRequest::kRequestContextManifest:
      return AllowManifestFromSource(url, redirect_status, reporting_policy,
                                     check_header_type);
    case WebURLRequest::kRequestContextServiceWorker:
    case WebURLRequest::kRequestContextSharedWorker:
    case WebURLRequest::kRequestContextWorker:
      return AllowWorkerContextFromSource(url, redirect_status,
                                          reporting_policy, check_header_type);
    case WebURLRequest::kRequestContextStyle:
      return AllowStyleFromSource(url, nonce, redirect_status, reporting_policy,
                                  check_header_type);
    case WebURLRequest::kRequestContextCSPReport:
    case WebURLRequest::kRequestContextDownload:
    case WebURLRequest::kRequestContextHyperlink:
    case WebURLRequest::kRequestContextInternal:
    case WebURLRequest::kRequestContextLocation:
    case WebURLRequest::kRequestContextPlugin:
    case WebURLRequest::kRequestContextUnspecified:
      return true;
  }
  NOTREACHED();
  return true;
}

void ContentSecurityPolicy::UsesScriptHashAlgorithms(uint8_t algorithms) {
  script_hash_algorithms_used_ |= algorithms;
}

void ContentSecurityPolicy::UsesStyleHashAlgorithms(uint8_t algorithms) {
  style_hash_algorithms_used_ |= algorithms;
}

bool ContentSecurityPolicy::AllowObjectFromSource(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowObjectFromSource(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowPrefetchFromSource(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowPrefetchFromSource(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowFrameFromSource(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowFrameFromSource(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowImageFromSource(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_,
                                        SchemeRegistry::kPolicyAreaImage))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowImageFromSource(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowStyleFromSource(
    const KURL& url,
    const String& nonce,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_,
                                        SchemeRegistry::kPolicyAreaStyle))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &= policy->AllowStyleFromSource(url, nonce, redirect_status,
                                               reporting_policy);
  }
  return is_allowed;
}

bool ContentSecurityPolicy::AllowFontFromSource(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowFontFromSource(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowMediaFromSource(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowMediaFromSource(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowConnectToSource(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowConnectToSource(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowFormAction(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowFormAction(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowBaseURI(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy) const {
  // `base-uri` isn't affected by 'upgrade-insecure-requests', so we'll check
  // both report-only and enforce headers here.
  if (ShouldBypassContentSecurityPolicy(url, execution_context_))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(CheckHeaderType::kCheckAll,
                                policy->HeaderType()))
      continue;
    is_allowed &= policy->AllowBaseURI(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowWorkerContextFromSource(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  // CSP 1.1 moves workers from 'script-src' to the new 'child-src'. Measure the
  // impact of this backwards-incompatible change.
  // TODO(mkwst): We reverted this.
  if (Document* document = this->GetDocument()) {
    UseCounter::Count(*document, WebFeature::kWorkerSubjectToCSP);
    bool is_allowed_worker = true;
    if (!ShouldBypassContentSecurityPolicy(url, execution_context_)) {
      for (const auto& policy : policies_) {
        if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
          continue;
        is_allowed_worker &= policy->AllowWorkerFromSource(
            url, redirect_status,
            SecurityViolationReportingPolicy::kSuppressReporting);
      }
    }

    bool is_allowed_script = true;

    if (!ShouldBypassContentSecurityPolicy(url, execution_context_)) {
      for (const auto& policy : policies_) {
        if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
          continue;
        is_allowed_script &= policy->AllowScriptFromSource(
            url, AtomicString(), IntegrityMetadataSet(), kNotParserInserted,
            redirect_status,
            SecurityViolationReportingPolicy::kSuppressReporting);
      }
    }

    if (is_allowed_worker && !is_allowed_script) {
      UseCounter::Count(*document,
                        WebFeature::kWorkerAllowedByChildBlockedByScript);
    }
  }

  if (ShouldBypassContentSecurityPolicy(url, execution_context_))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowWorkerFromSource(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowManifestFromSource(
    const KURL& url,
    RedirectStatus redirect_status,
    SecurityViolationReportingPolicy reporting_policy,
    CheckHeaderType check_header_type) const {
  if (ShouldBypassContentSecurityPolicy(url, execution_context_))
    return true;

  bool is_allowed = true;
  for (const auto& policy : policies_) {
    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
      continue;
    is_allowed &=
        policy->AllowManifestFromSource(url, redirect_status, reporting_policy);
  }

  return is_allowed;
}

bool ContentSecurityPolicy::AllowAncestors(
    LocalFrame* frame,
    const KURL& url,
    SecurityViolationReportingPolicy reporting_policy) const {
  bool is_allowed = true;
  for (const auto& policy : policies_)
    is_allowed &= policy->AllowAncestors(frame, url, reporting_policy);
  return is_allowed;
}

bool ContentSecurityPolicy::IsFrameAncestorsEnforced() const {
  for (const auto& policy : policies_) {
    if (policy->IsFrameAncestorsEnforced())
      return true;
  }
  return false;
}

bool ContentSecurityPolicy::IsActive() const {
  return !policies_.IsEmpty();
}

bool ContentSecurityPolicy::IsActiveForConnections() const {
  for (const auto& policy : policies_) {
    if (policy->IsActiveForConnections())
      return true;
  }
  return false;
}

const KURL ContentSecurityPolicy::Url() const {
  return execution_context_->Url();
}

void ContentSecurityPolicy::EnforceSandboxFlags(SandboxFlags mask) {
  sandbox_mask_ |= mask;
}

void ContentSecurityPolicy::TreatAsPublicAddress() {
  if (!RuntimeEnabledFeatures::CorsRFC1918Enabled())
    return;
  treat_as_public_address_ = true;
}

void ContentSecurityPolicy::RequireTrustedTypes() {
  if (!RuntimeEnabledFeatures::TrustedDOMTypesEnabled())
    return;
  require_safe_types_ = true;
}

void ContentSecurityPolicy::EnforceStrictMixedContentChecking() {
  insecure_request_policy_ |= kBlockAllMixedContent;
}

void ContentSecurityPolicy::UpgradeInsecureRequests() {
  insecure_request_policy_ |= kUpgradeInsecureRequests;
}

static String StripURLForUseInReport(
    ExecutionContext* context,
    const KURL& url,
    RedirectStatus redirect_status,
    const ContentSecurityPolicy::DirectiveType& effective_type) {
  if (!url.IsValid())
    return String();
  if (!url.IsHierarchical() || url.ProtocolIs("file"))
    return url.Protocol();

  // Until we're more careful about the way we deal with navigations in frames
  // (and, by extension, in plugin documents), strip cross-origin 'frame-src'
  // and 'object-src' violations down to an origin. https://crbug.com/633306
  bool can_safely_expose_url =
      context->GetSecurityOrigin()->CanRequest(url) ||
      (redirect_status == RedirectStatus::kNoRedirect &&
       effective_type != ContentSecurityPolicy::DirectiveType::kFrameSrc &&
       effective_type != ContentSecurityPolicy::DirectiveType::kObjectSrc);

  if (can_safely_expose_url) {
    // 'KURL::strippedForUseAsReferrer()' dumps 'String()' for non-webby URLs.
    // It's better for developers if we return the origin of those URLs rather
    // than nothing.
    if (url.ProtocolIsInHTTPFamily())
      return url.StrippedForUseAsReferrer();
  }
  return SecurityOrigin::Create(url)->ToString();
}

static void GatherSecurityPolicyViolationEventData(
    SecurityPolicyViolationEventInit& init,
    ExecutionContext* context,
    const String& directive_text,
    const ContentSecurityPolicy::DirectiveType& effective_type,
    const KURL& blocked_url,
    const String& header,
    RedirectStatus redirect_status,
    ContentSecurityPolicyHeaderType header_type,
    ContentSecurityPolicy::ViolationType violation_type,
    std::unique_ptr<SourceLocation> source_location,
    const String& script_source) {
  if (effective_type == ContentSecurityPolicy::DirectiveType::kFrameAncestors) {
    // If this load was blocked via 'frame-ancestors', then the URL of
    // |document| has not yet been initialized. In this case, we'll set both
    // 'documentURI' and 'blockedURI' to the blocked document's URL.
    String stripped_url = StripURLForUseInReport(
        context, blocked_url, RedirectStatus::kNoRedirect,
        ContentSecurityPolicy::DirectiveType::kDefaultSrc);
    init.setDocumentURI(stripped_url);
    init.setBlockedURI(stripped_url);
  } else {
    String stripped_url = StripURLForUseInReport(
        context, context->Url(), RedirectStatus::kNoRedirect,
        ContentSecurityPolicy::DirectiveType::kDefaultSrc);
    init.setDocumentURI(stripped_url);
    switch (violation_type) {
      case ContentSecurityPolicy::kInlineViolation:
        init.setBlockedURI("inline");
        break;
      case ContentSecurityPolicy::kEvalViolation:
        init.setBlockedURI("eval");
        break;
      case ContentSecurityPolicy::kURLViolation:
        init.setBlockedURI(StripURLForUseInReport(
            context, blocked_url, redirect_status, effective_type));
        break;
    }
  }

  String effective_directive =
      ContentSecurityPolicy::GetDirectiveName(effective_type);
  init.setViolatedDirective(effective_directive);
  init.setEffectiveDirective(effective_directive);
  init.setOriginalPolicy(header);
  init.setDisposition(header_type == kContentSecurityPolicyHeaderTypeEnforce
                          ? "enforce"
                          : "report");
  init.setStatusCode(0);

  // TODO(mkwst): We only have referrer and status code information for
  // Documents. It would be nice to get them for Workers as well.
  if (context->IsDocument()) {
    Document* document = ToDocument(context);
    DCHECK(document);
    init.setReferrer(document->referrer());
    if (!SecurityOrigin::IsSecure(context->Url()) && document->Loader())
      init.setStatusCode(document->Loader()->GetResponse().HttpStatusCode());
  }

  // If no source location is provided, use the source location of the context.
  if (!source_location)
    source_location = SourceLocation::Capture(context);
  if (source_location->LineNumber()) {
    KURL source = KURL(source_location->Url());
    init.setSourceFile(StripURLForUseInReport(context, source, redirect_status,
                                              effective_type));
    init.setLineNumber(source_location->LineNumber());
    init.setColumnNumber(source_location->ColumnNumber());
  } else {
    init.setSourceFile(String());
    init.setLineNumber(0);
    init.setColumnNumber(0);
  }

  if (!script_source.IsEmpty()) {
    init.setSample(script_source.StripWhiteSpace().Left(
        ContentSecurityPolicy::kMaxSampleLength));
  }
}

void ContentSecurityPolicy::ReportViolation(
    const String& directive_text,
    const DirectiveType& effective_type,
    const String& console_message,
    const KURL& blocked_url,
    const Vector<String>& report_endpoints,
    bool use_reporting_api,
    const String& header,
    ContentSecurityPolicyHeaderType header_type,
    ViolationType violation_type,
    std::unique_ptr<SourceLocation> source_location,
    LocalFrame* context_frame,
    RedirectStatus redirect_status,
    Element* element,
    const String& source) {
  DCHECK(violation_type == kURLViolation || blocked_url.IsEmpty());

  // TODO(lukasza): Support sending reports from OOPIFs -
  // https://crbug.com/611232 (or move CSP child-src and frame-src checks to the
  // browser process - see https://crbug.com/376522).
  if (!execution_context_ && !context_frame) {
    DCHECK(effective_type == DirectiveType::kChildSrc ||
           effective_type == DirectiveType::kFrameSrc ||
           effective_type == DirectiveType::kPluginTypes);
    return;
  }

  DCHECK((execution_context_ && !context_frame) ||
         ((effective_type == DirectiveType::kFrameAncestors) && context_frame));

  SecurityPolicyViolationEventInit violation_data;

  // If we're processing 'frame-ancestors', use |contextFrame|'s execution
  // context to gather data. Otherwise, use the policy's execution context.
  ExecutionContext* relevant_context =
      context_frame ? context_frame->GetDocument() : execution_context_;
  DCHECK(relevant_context);
  GatherSecurityPolicyViolationEventData(
      violation_data, relevant_context, directive_text, effective_type,
      blocked_url, header, redirect_status, header_type, violation_type,
      std::move(source_location), source);

  // TODO(mkwst): Obviously, we shouldn't hit this check, as extension-loaded
  // resources should be allowed regardless. We apparently do, however, so
  // we should at least stop spamming reporting endpoints. See
  // https://crbug.com/524356 for detail.
  if (!violation_data.sourceFile().IsEmpty() &&
      ShouldBypassContentSecurityPolicy(KURL(violation_data.sourceFile()),
                                        execution_context_)) {
    return;
  }

  PostViolationReport(violation_data, context_frame, report_endpoints,
                      use_reporting_api);

  // Fire a violation event if we're working within an execution context (e.g.
  // we're not processing 'frame-ancestors').
  if (execution_context_) {
    execution_context_->GetTaskRunner(TaskType::kNetworking)
        ->PostTask(FROM_HERE,
                   WTF::Bind(&ContentSecurityPolicy::DispatchViolationEvents,
                             WrapPersistent(this), violation_data,
                             WrapPersistent(element)));
  }
}

void ContentSecurityPolicy::PostViolationReport(
    const SecurityPolicyViolationEventInit& violation_data,
    LocalFrame* context_frame,
    const Vector<String>& report_endpoints,
    bool use_reporting_api) {
  // We need to be careful here when deciding what information to send to the
  // report-uri. Currently, we send only the current document's URL and the
  // directive that was violated. The document's URL is safe to send because
  // it's the document itself that's requesting that it be sent. You could
  // make an argument that we shouldn't send HTTPS document URLs to HTTP
  // report-uris (for the same reasons that we supress the Referer in that
  // case), but the Referer is sent implicitly whereas this request is only
  // sent explicitly. As for which directive was violated, that's pretty
  // harmless information.
  //
  // TODO(mkwst): This justification is BS. Insecure reports are mixed content,
  // let's kill them. https://crbug.com/695363

  std::unique_ptr<JSONObject> csp_report = JSONObject::Create();
  csp_report->SetString("document-uri", violation_data.documentURI());
  csp_report->SetString("referrer", violation_data.referrer());
  csp_report->SetString("violated-directive",
                        violation_data.violatedDirective());
  csp_report->SetString("effective-directive",
                        violation_data.effectiveDirective());
  csp_report->SetString("original-policy", violation_data.originalPolicy());
  csp_report->SetString("disposition", violation_data.disposition());
  csp_report->SetString("blocked-uri", violation_data.blockedURI());
  if (violation_data.lineNumber())
    csp_report->SetInteger("line-number", violation_data.lineNumber());
  if (violation_data.columnNumber())
    csp_report->SetInteger("column-number", violation_data.columnNumber());
  if (!violation_data.sourceFile().IsEmpty())
    csp_report->SetString("source-file", violation_data.sourceFile());
  csp_report->SetInteger("status-code", violation_data.statusCode());

  csp_report->SetString("script-sample", violation_data.sample());

  std::unique_ptr<JSONObject> report_object = JSONObject::Create();
  report_object->SetObject("csp-report", std::move(csp_report));
  String stringified_report = report_object->ToJSONString();

  // Only POST unique reports to the external endpoint; repeated reports add no
  // value on the server side, as they're indistinguishable. Note that we'll
  // fire the DOM event for every violation, as the page has enough context to
  // react in some reasonable way to each violation as it occurs.
  if (ShouldSendViolationReport(stringified_report)) {
    DidSendViolationReport(stringified_report);

    // TODO(mkwst): Support POSTing violation reports from a Worker.
    Document* document =
        context_frame ? context_frame->GetDocument() : this->GetDocument();
    if (!document)
      return;

    LocalFrame* frame = document->GetFrame();
    if (!frame)
      return;

    scoped_refptr<EncodedFormData> report =
        EncodedFormData::Create(stringified_report.Utf8());

    DEFINE_STATIC_LOCAL(ReportingServiceProxyPtrHolder,
                        reporting_service_proxy_holder, ());

    for (const auto& report_endpoint : report_endpoints) {
      if (use_reporting_api) {
        reporting_service_proxy_holder.QueueCspViolationReport(
            document->Url(), report_endpoint, violation_data);
      } else {
        // If we have a context frame we're dealing with 'frame-ancestors' and
        // we don't have our own execution context. Use the frame's document to
        // complete the endpoint URL, overriding its URL with the blocked
        // document's URL.
        DCHECK(!context_frame || !execution_context_);
        DCHECK(!context_frame ||
               GetDirectiveType(violation_data.effectiveDirective()) ==
                   DirectiveType::kFrameAncestors);
        KURL url =
            context_frame
                ? frame->GetDocument()->CompleteURLWithOverride(
                      report_endpoint, KURL(violation_data.blockedURI()))
                // We use the FallbackBaseURL to ensure that we don't
                // respect base elements when determining the report
                // endpoint URL.
                : frame->GetDocument()->CompleteURLWithOverride(
                      report_endpoint, frame->GetDocument()->FallbackBaseURL());
        PingLoader::SendViolationReport(
            frame, url, report,
            PingLoader::kContentSecurityPolicyViolationReport);
      }
    }
  }
}

void ContentSecurityPolicy::DispatchViolationEvents(
    const SecurityPolicyViolationEventInit& violation_data,
    Element* element) {
  // If the context is detached or closed (thus clearing its event queue)
  // between the violation occuring and this event dispatch, exit early.
  EventQueue* queue = execution_context_->GetEventQueue();
  if (!queue)
    return;

  // Worklets don't support Events in general.
  if (execution_context_->IsWorkletGlobalScope())
    return;

  SecurityPolicyViolationEvent* event = SecurityPolicyViolationEvent::Create(
      EventTypeNames::securitypolicyviolation, violation_data);
  DCHECK(event->bubbles());

  if (execution_context_->IsDocument()) {
    Document* document = ToDocument(execution_context_);
    if (element && element->isConnected() && element->GetDocument() == document)
      event->SetTarget(element);
    else
      event->SetTarget(document);
  } else if (execution_context_->IsWorkerGlobalScope()) {
    event->SetTarget(ToWorkerGlobalScope(execution_context_));
  }
  queue->EnqueueEvent(FROM_HERE, event);
}

void ContentSecurityPolicy::ReportMixedContent(const KURL& mixed_url,
                                               RedirectStatus redirect_status) {
  for (const auto& policy : policies_)
    policy->ReportMixedContent(mixed_url, redirect_status);
}

void ContentSecurityPolicy::ReportReportOnlyInMeta(const String& header) {
  LogToConsole("The report-only Content Security Policy '" + header +
               "' was delivered via a <meta> element, which is disallowed. The "
               "policy has been ignored.");
}

void ContentSecurityPolicy::ReportMetaOutsideHead(const String& header) {
  LogToConsole("The Content Security Policy '" + header +
               "' was delivered via a <meta> element outside the document's "
               "<head>, which is disallowed. The policy has been ignored.");
}

void ContentSecurityPolicy::ReportValueForEmptyDirective(const String& name,
                                                         const String& value) {
  LogToConsole("The Content Security Policy directive '" + name +
               "' should be empty, but was delivered with a value of '" +
               value +
               "'. The directive has been applied, and the value ignored.");
}

void ContentSecurityPolicy::ReportInvalidInReportOnly(const String& name) {
  LogToConsole("The Content Security Policy directive '" + name +
               "' is ignored when delivered in a report-only policy.");
}

void ContentSecurityPolicy::ReportInvalidDirectiveInMeta(
    const String& directive) {
  LogToConsole(
      "Content Security Policies delivered via a <meta> element may not "
      "contain the " +
      directive + " directive.");
}

void ContentSecurityPolicy::ReportUnsupportedDirective(const String& name) {
  static const char kAllow[] = "allow";
  static const char kOptions[] = "options";
  static const char kPolicyURI[] = "policy-uri";
  static const char kAllowMessage[] =
      "The 'allow' directive has been replaced with 'default-src'. Please use "
      "that directive instead, as 'allow' has no effect.";
  static const char kOptionsMessage[] =
      "The 'options' directive has been replaced with 'unsafe-inline' and "
      "'unsafe-eval' source expressions for the 'script-src' and 'style-src' "
      "directives. Please use those directives instead, as 'options' has no "
      "effect.";
  static const char kPolicyURIMessage[] =
      "The 'policy-uri' directive has been removed from the "
      "specification. Please specify a complete policy via "
      "the Content-Security-Policy header.";

  String message =
      "Unrecognized Content-Security-Policy directive '" + name + "'.\n";
  MessageLevel level = kErrorMessageLevel;
  if (EqualIgnoringASCIICase(name, kAllow)) {
    message = kAllowMessage;
  } else if (EqualIgnoringASCIICase(name, kOptions)) {
    message = kOptionsMessage;
  } else if (EqualIgnoringASCIICase(name, kPolicyURI)) {
    message = kPolicyURIMessage;
  } else if (GetDirectiveType(name) != DirectiveType::kUndefined) {
    message = "The Content-Security-Policy directive '" + name +
              "' is implemented behind a flag which is currently disabled.\n";
    level = kInfoMessageLevel;
  }

  LogToConsole(message, level);
}

void ContentSecurityPolicy::ReportDirectiveAsSourceExpression(
    const String& directive_name,
    const String& source_expression) {
  String message = "The Content Security Policy directive '" + directive_name +
                   "' contains '" + source_expression +
                   "' as a source expression. Did you mean '" + directive_name +
                   " ...; " + source_expression + "...' (note the semicolon)?";
  LogToConsole(message);
}

void ContentSecurityPolicy::ReportDuplicateDirective(const String& name) {
  String message =
      "Ignoring duplicate Content-Security-Policy directive '" + name + "'.\n";
  LogToConsole(message);
}

void ContentSecurityPolicy::ReportInvalidPluginTypes(
    const String& plugin_type) {
  String message;
  if (plugin_type.IsNull())
    message =
        "'plugin-types' Content Security Policy directive is empty; all "
        "plugins will be blocked.\n";
  else if (plugin_type == "'none'")
    message =
        "Invalid plugin type in 'plugin-types' Content Security Policy "
        "directive: '" +
        plugin_type +
        "'. Did you mean to set the object-src directive to 'none'?\n";
  else
    message =
        "Invalid plugin type in 'plugin-types' Content Security Policy "
        "directive: '" +
        plugin_type + "'.\n";
  LogToConsole(message);
}

void ContentSecurityPolicy::ReportInvalidSandboxFlags(
    const String& invalid_flags) {
  LogToConsole(
      "Error while parsing the 'sandbox' Content Security Policy directive: " +
      invalid_flags);
}

void ContentSecurityPolicy::ReportInvalidRequireSRIForTokens(
    const String& invalid_tokens) {
  LogToConsole(
      "Error while parsing the 'require-sri-for' Content Security Policy "
      "directive: " +
      invalid_tokens);
}

void ContentSecurityPolicy::ReportInvalidDirectiveValueCharacter(
    const String& directive_name,
    const String& value) {
  String message = "The value for Content Security Policy directive '" +
                   directive_name + "' contains an invalid character: '" +
                   value +
                   "'. Non-whitespace characters outside ASCII 0x21-0x7E must "
                   "be percent-encoded, as described in RFC 3986, section 2.1: "
                   "http://tools.ietf.org/html/rfc3986#section-2.1.";
  LogToConsole(message);
}

void ContentSecurityPolicy::ReportInvalidPathCharacter(
    const String& directive_name,
    const String& value,
    const char invalid_char) {
  DCHECK(invalid_char == '#' || invalid_char == '?');

  String ignoring =
      "The fragment identifier, including the '#', will be ignored.";
  if (invalid_char == '?')
    ignoring = "The query component, including the '?', will be ignored.";
  String message = "The source list for Content Security Policy directive '" +
                   directive_name +
                   "' contains a source with an invalid path: '" + value +
                   "'. " + ignoring;
  LogToConsole(message);
}

void ContentSecurityPolicy::ReportInvalidSourceExpression(
    const String& directive_name,
    const String& source) {
  String message = "The source list for Content Security Policy directive '" +
                   directive_name + "' contains an invalid source: '" + source +
                   "'. It will be ignored.";
  if (EqualIgnoringASCIICase(source, "'none'"))
    message = message +
              " Note that 'none' has no effect unless it is the only "
              "expression in the source list.";
  LogToConsole(message);
}

void ContentSecurityPolicy::ReportMissingReportURI(const String& policy) {
  LogToConsole("The Content Security Policy '" + policy +
               "' was delivered in report-only mode, but does not specify a "
               "'report-uri'; the policy will have no effect. Please either "
               "add a 'report-uri' directive, or deliver the policy via the "
               "'Content-Security-Policy' header.");
}

void ContentSecurityPolicy::LogToConsole(const String& message,
                                         MessageLevel level) {
  LogToConsole(ConsoleMessage::Create(kSecurityMessageSource, level, message));
}

void ContentSecurityPolicy::LogToConsole(ConsoleMessage* console_message,
                                         LocalFrame* frame) {
  if (frame)
    frame->GetDocument()->AddConsoleMessage(console_message);
  else if (execution_context_)
    execution_context_->AddConsoleMessage(console_message);
  else
    console_messages_.push_back(console_message);
}

void ContentSecurityPolicy::ReportBlockedScriptExecutionToInspector(
    const String& directive_text) const {
  probe::scriptExecutionBlockedByCSP(execution_context_, directive_text);
}

bool ContentSecurityPolicy::ExperimentalFeaturesEnabled() const {
  return RuntimeEnabledFeatures::
      ExperimentalContentSecurityPolicyFeaturesEnabled();
}

bool ContentSecurityPolicy::ShouldSendCSPHeader(Resource::Type type) const {
  for (const auto& policy : policies_) {
    if (policy->ShouldSendCSPHeader(type))
      return true;
  }
  return false;
}

bool ContentSecurityPolicy::UrlMatchesSelf(const KURL& url) const {
  return self_source_->Matches(url, RedirectStatus::kNoRedirect);
}

bool ContentSecurityPolicy::ProtocolEqualsSelf(const String& protocol) const {
  return EqualIgnoringASCIICase(protocol, self_protocol_);
}

const String& ContentSecurityPolicy::GetSelfProtocol() const {
  return self_protocol_;
}

bool ContentSecurityPolicy::ShouldBypassMainWorld(
    const ExecutionContext* context) {
  if (context && context->IsDocument()) {
    const Document* document = ToDocument(context);
    if (document->GetFrame()) {
      return document->GetFrame()
          ->GetScriptController()
          .ShouldBypassMainWorldCSP();
    }
  }
  return false;
}

bool ContentSecurityPolicy::ShouldSendViolationReport(
    const String& report) const {
  // Collisions have no security impact, so we can save space by storing only
  // the string's hash rather than the whole report.
  return !violation_reports_sent_.Contains(report.Impl()->GetHash());
}

void ContentSecurityPolicy::DidSendViolationReport(const String& report) {
  violation_reports_sent_.insert(report.Impl()->GetHash());
}

const char* ContentSecurityPolicy::GetDirectiveName(const DirectiveType& type) {
  switch (type) {
    case DirectiveType::kBaseURI:
      return "base-uri";
    case DirectiveType::kBlockAllMixedContent:
      return "block-all-mixed-content";
    case DirectiveType::kChildSrc:
      return "child-src";
    case DirectiveType::kConnectSrc:
      return "connect-src";
    case DirectiveType::kDefaultSrc:
      return "default-src";
    case DirectiveType::kFrameAncestors:
      return "frame-ancestors";
    case DirectiveType::kFrameSrc:
      return "frame-src";
    case DirectiveType::kFontSrc:
      return "font-src";
    case DirectiveType::kFormAction:
      return "form-action";
    case DirectiveType::kImgSrc:
      return "img-src";
    case DirectiveType::kManifestSrc:
      return "manifest-src";
    case DirectiveType::kMediaSrc:
      return "media-src";
    case DirectiveType::kObjectSrc:
      return "object-src";
    case DirectiveType::kPrefetchSrc:
      return "prefetch-src";
    case DirectiveType::kPluginTypes:
      return "plugin-types";
    case DirectiveType::kReportURI:
      return "report-uri";
    case DirectiveType::kRequireSRIFor:
      return "require-sri-for";
    case DirectiveType::kRequireTrustedTypes:
      return "require-trusted-types";
    case DirectiveType::kSandbox:
      return "sandbox";
    case DirectiveType::kScriptSrc:
      return "script-src";
    case DirectiveType::kStyleSrc:
      return "style-src";
    case DirectiveType::kTreatAsPublicAddress:
      return "treat-as-public-address";
    case DirectiveType::kUpgradeInsecureRequests:
      return "upgrade-insecure-requests";
    case DirectiveType::kWorkerSrc:
      return "worker-src";
    case DirectiveType::kReportTo:
      return "report-to";
    case DirectiveType::kUndefined:
      NOTREACHED();
      return "";
  }

  NOTREACHED();
  return "";
}

ContentSecurityPolicy::DirectiveType ContentSecurityPolicy::GetDirectiveType(
    const String& name) {
  if (name == "base-uri")
    return DirectiveType::kBaseURI;
  if (name == "block-all-mixed-content")
    return DirectiveType::kBlockAllMixedContent;
  if (name == "child-src")
    return DirectiveType::kChildSrc;
  if (name == "connect-src")
    return DirectiveType::kConnectSrc;
  if (name == "default-src")
    return DirectiveType::kDefaultSrc;
  if (name == "frame-ancestors")
    return DirectiveType::kFrameAncestors;
  if (name == "frame-src")
    return DirectiveType::kFrameSrc;
  if (name == "font-src")
    return DirectiveType::kFontSrc;
  if (name == "form-action")
    return DirectiveType::kFormAction;
  if (name == "img-src")
    return DirectiveType::kImgSrc;
  if (name == "manifest-src")
    return DirectiveType::kManifestSrc;
  if (name == "media-src")
    return DirectiveType::kMediaSrc;
  if (name == "object-src")
    return DirectiveType::kObjectSrc;
  if (name == "plugin-types")
    return DirectiveType::kPluginTypes;
  if (name == "prefetch-src")
    return DirectiveType::kPrefetchSrc;
  if (name == "report-uri")
    return DirectiveType::kReportURI;
  if (name == "require-sri-for")
    return DirectiveType::kRequireSRIFor;
  if (name == "require-trusted-types")
    return DirectiveType::kRequireTrustedTypes;
  if (name == "sandbox")
    return DirectiveType::kSandbox;
  if (name == "script-src")
    return DirectiveType::kScriptSrc;
  if (name == "style-src")
    return DirectiveType::kStyleSrc;
  if (name == "treat-as-public-address")
    return DirectiveType::kTreatAsPublicAddress;
  if (name == "upgrade-insecure-requests")
    return DirectiveType::kUpgradeInsecureRequests;
  if (name == "worker-src")
    return DirectiveType::kWorkerSrc;
  if (name == "report-to")
    return DirectiveType::kReportTo;

  return DirectiveType::kUndefined;
}

bool ContentSecurityPolicy::Subsumes(const ContentSecurityPolicy& other) const {
  if (!policies_.size() || !other.policies_.size())
    return !policies_.size();
  // Required-CSP must specify only one policy.
  if (policies_.size() != 1)
    return false;

  CSPDirectiveListVector other_vector;
  for (const auto& policy : other.policies_) {
    if (!policy->IsReportOnly())
      other_vector.push_back(policy);
  }

  return policies_[0]->Subsumes(other_vector);
}

// static
bool ContentSecurityPolicy::ShouldBypassContentSecurityPolicy(
    const KURL& url,
    ExecutionContext* execution_context,
    SchemeRegistry::PolicyAreas area) {
  bool should_bypass_csp;
  if (SecurityOrigin::ShouldUseInnerURL(url)) {
    should_bypass_csp = SchemeRegistry::SchemeShouldBypassContentSecurityPolicy(
        SecurityOrigin::ExtractInnerURL(url).Protocol(), area);
    if (should_bypass_csp) {
      UseCounter::Count(execution_context, WebFeature::kInnerSchemeBypassesCSP);
    }
  } else {
    should_bypass_csp = SchemeRegistry::SchemeShouldBypassContentSecurityPolicy(
        url.Protocol(), area);
  }
  if (should_bypass_csp) {
    UseCounter::Count(execution_context, WebFeature::kSchemeBypassesCSP);
  }

  return should_bypass_csp;
}

// static
bool ContentSecurityPolicy::IsValidCSPAttr(const String& attr,
                                           const String& context_required_csp) {
  // we don't allow any newline characters in the CSP attributes
  if (attr.Contains('\n') || attr.Contains('\r'))
    return false;

  ContentSecurityPolicy* attr_policy = ContentSecurityPolicy::Create();
  attr_policy->AddPolicyFromHeaderValue(attr,
                                        kContentSecurityPolicyHeaderTypeEnforce,
                                        kContentSecurityPolicyHeaderSourceHTTP);
  if (!attr_policy->console_messages_.IsEmpty() ||
      attr_policy->policies_.size() != 1) {
    return false;
  }

  // Don't allow any report endpoints in "csp" attributes.
  for (auto& directiveList : attr_policy->policies_) {
    if (directiveList->ReportEndpoints().size() != 0)
      return false;
  }

  if (context_required_csp.IsEmpty() || context_required_csp.IsNull()) {
    return true;
  }

  ContentSecurityPolicy* context_policy = ContentSecurityPolicy::Create();
  context_policy->AddPolicyFromHeaderValue(
      context_required_csp, kContentSecurityPolicyHeaderTypeEnforce,
      kContentSecurityPolicyHeaderSourceHTTP);

  DCHECK(context_policy->console_messages_.IsEmpty() &&
         context_policy->policies_.size() == 1);

  return context_policy->Subsumes(*attr_policy);
}

}  // namespace blink
