/*
 * Copyright (C) 2012 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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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/loader/mixed_content_checker.h"

#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/net/ip_address_space.mojom-blink.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
#include "third_party/blink/public/platform/web_mixed_content.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame.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/settings.h"
#include "third_party/blink/renderer/core/frame/use_counter.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/frame_fetch_context.h"
#include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
#include "third_party/blink/renderer/core/workers/worker_content_settings_client.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_settings.h"
#include "third_party/blink/renderer/platform/network/network_utils.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"

namespace blink {

namespace {

// When a frame is local, use its full URL to represent the main resource. When
// the frame is remote, the full URL isn't accessible, so use the origin. This
// function is used, for example, to determine the URL to show in console
// messages about mixed content.
KURL MainResourceUrlForFrame(Frame* frame) {
  if (frame->IsRemoteFrame()) {
    return KURL(NullURL(),
                frame->GetSecurityContext()->GetSecurityOrigin()->ToString());
  }
  return ToLocalFrame(frame)->GetDocument()->Url();
}

const char* RequestContextName(mojom::RequestContextType context) {
  switch (context) {
    case mojom::RequestContextType::AUDIO:
      return "audio file";
    case mojom::RequestContextType::BEACON:
      return "Beacon endpoint";
    case mojom::RequestContextType::CSP_REPORT:
      return "Content Security Policy reporting endpoint";
    case mojom::RequestContextType::DOWNLOAD:
      return "download";
    case mojom::RequestContextType::EMBED:
      return "plugin resource";
    case mojom::RequestContextType::EVENT_SOURCE:
      return "EventSource endpoint";
    case mojom::RequestContextType::FAVICON:
      return "favicon";
    case mojom::RequestContextType::FETCH:
      return "resource";
    case mojom::RequestContextType::FONT:
      return "font";
    case mojom::RequestContextType::FORM:
      return "form action";
    case mojom::RequestContextType::FRAME:
      return "frame";
    case mojom::RequestContextType::HYPERLINK:
      return "resource";
    case mojom::RequestContextType::IFRAME:
      return "frame";
    case mojom::RequestContextType::IMAGE:
      return "image";
    case mojom::RequestContextType::IMAGE_SET:
      return "image";
    case mojom::RequestContextType::IMPORT:
      return "HTML Import";
    case mojom::RequestContextType::INTERNAL:
      return "resource";
    case mojom::RequestContextType::LOCATION:
      return "resource";
    case mojom::RequestContextType::MANIFEST:
      return "manifest";
    case mojom::RequestContextType::OBJECT:
      return "plugin resource";
    case mojom::RequestContextType::PING:
      return "hyperlink auditing endpoint";
    case mojom::RequestContextType::PLUGIN:
      return "plugin data";
    case mojom::RequestContextType::PREFETCH:
      return "prefetch resource";
    case mojom::RequestContextType::SCRIPT:
      return "script";
    case mojom::RequestContextType::SERVICE_WORKER:
      return "Service Worker script";
    case mojom::RequestContextType::SHARED_WORKER:
      return "Shared Worker script";
    case mojom::RequestContextType::STYLE:
      return "stylesheet";
    case mojom::RequestContextType::SUBRESOURCE:
      return "resource";
    case mojom::RequestContextType::TRACK:
      return "Text Track";
    case mojom::RequestContextType::UNSPECIFIED:
      return "resource";
    case mojom::RequestContextType::VIDEO:
      return "video";
    case mojom::RequestContextType::WORKER:
      return "Worker script";
    case mojom::RequestContextType::XML_HTTP_REQUEST:
      return "XMLHttpRequest endpoint";
    case mojom::RequestContextType::XSLT:
      return "XSLT";
  }
  NOTREACHED();
  return "resource";
}

// TODO(nhiroki): Consider adding interfaces for Settings/WorkerSettings
// to avoid using C++ template.
template <typename SettingsType>
bool IsWebSocketAllowedImpl(const BaseFetchContext& fetch_context,
                            SecurityContext* security_context,
                            SettingsType* settings,
                            const KURL& url) {
  fetch_context.CountUsage(WebFeature::kMixedContentPresent);
  fetch_context.CountUsage(WebFeature::kMixedContentWebSocket);
  if (ContentSecurityPolicy* policy =
          security_context->GetContentSecurityPolicy()) {
    policy->ReportMixedContent(url,
                               ResourceRequest::RedirectStatus::kNoRedirect);
  }

  // If we're in strict mode, we'll automagically fail everything, and
  // intentionally skip the client checks in order to prevent degrading the
  // site's security UI.
  bool strict_mode =
      security_context->GetInsecureRequestPolicy() & kBlockAllMixedContent ||
      settings->GetStrictMixedContentChecking();
  if (strict_mode)
    return false;
  return settings && settings->GetAllowRunningOfInsecureContent();
}

}  // namespace

static void MeasureStricterVersionOfIsMixedContent(Frame& frame,
                                                   const KURL& url,
                                                   const LocalFrame* source) {
  // We're currently only checking for mixed content in `https://*` contexts.
  // What about other "secure" contexts the SchemeRegistry knows about? We'll
  // use this method to measure the occurrence of non-webby mixed content to
  // make sure we're not breaking the world without realizing it.
  const SecurityOrigin* origin =
      frame.GetSecurityContext()->GetSecurityOrigin();
  if (MixedContentChecker::IsMixedContent(origin, url)) {
    if (origin->Protocol() != "https") {
      UseCounter::Count(
          source,
          WebFeature::kMixedContentInNonHTTPSFrameThatRestrictsMixedContent);
    }
  } else if (!SecurityOrigin::IsSecure(url) &&
             SchemeRegistry::ShouldTreatURLSchemeAsSecure(origin->Protocol())) {
    UseCounter::Count(
        source,
        WebFeature::kMixedContentInSecureFrameThatDoesNotRestrictMixedContent);
  }
}

bool RequestIsSubframeSubresource(
    Frame* frame,
    network::mojom::RequestContextFrameType frame_type) {
  return (frame && frame != frame->Tree().Top() &&
          frame_type != network::mojom::RequestContextFrameType::kNested);
}

static bool IsInsecureUrl(const KURL& url) {
  // |url| is mixed content if its origin is not potentially trustworthy nor
  // secure. We do a quick check against `SecurityOrigin::IsSecure` to catch
  // things like `about:blank`, which cannot be sanely passed into
  // `SecurityOrigin::Create` (as their origin depends on their context).
  // blob: and filesystem: URLs never hit the network, and access is restricted
  // to same-origin contexts, so they are not blocked either.
  bool is_allowed = url.ProtocolIs("blob") || url.ProtocolIs("filesystem") ||
                    SecurityOrigin::IsSecure(url) ||
                    SecurityOrigin::Create(url)->IsPotentiallyTrustworthy();
  return !is_allowed;
}

// static
bool MixedContentChecker::IsMixedContent(const SecurityOrigin* security_origin,
                                         const KURL& url) {
  if (!SchemeRegistry::ShouldTreatURLSchemeAsRestrictingMixedContent(
          security_origin->Protocol()))
    return false;

  return IsInsecureUrl(url);
}

// static
bool MixedContentChecker::IsMixedContent(
    const FetchClientSettingsObject& settings,
    const KURL& url) {
  switch (settings.GetHttpsState()) {
    case HttpsState::kNone:
      return false;

    case HttpsState::kModern:
      return IsInsecureUrl(url);
  }
}

// static
Frame* MixedContentChecker::InWhichFrameIsContentMixed(
    Frame* frame,
    network::mojom::RequestContextFrameType frame_type,
    const KURL& url,
    const LocalFrame* source) {
  // We only care about subresource loads; top-level navigations cannot be mixed
  // content. Neither can frameless requests.
  if (frame_type == network::mojom::RequestContextFrameType::kTopLevel ||
      !frame)
    return nullptr;

  // Check the top frame first.
  Frame& top = frame->Tree().Top();
  MeasureStricterVersionOfIsMixedContent(top, url, source);
  if (IsMixedContent(top.GetSecurityContext()->GetSecurityOrigin(), url))
    return &top;

  MeasureStricterVersionOfIsMixedContent(*frame, url, source);
  if (IsMixedContent(frame->GetSecurityContext()->GetSecurityOrigin(), url))
    return frame;

  // No mixed content, no problem.
  return nullptr;
}

// static
ConsoleMessage* MixedContentChecker::CreateConsoleMessageAboutFetch(
    const KURL& main_resource_url,
    const KURL& url,
    mojom::RequestContextType request_context,
    bool allowed,
    std::unique_ptr<SourceLocation> source_location) {
  String message = String::Format(
      "Mixed Content: The page at '%s' was loaded over HTTPS, but requested an "
      "insecure %s '%s'. %s",
      main_resource_url.ElidedString().Utf8().data(),
      RequestContextName(request_context), url.ElidedString().Utf8().data(),
      allowed ? "This content should also be served over HTTPS."
              : "This request has been blocked; the content must be served "
                "over HTTPS.");
  MessageLevel message_level =
      allowed ? kWarningMessageLevel : kErrorMessageLevel;
  if (source_location) {
    return ConsoleMessage::Create(kSecurityMessageSource, message_level,
                                  message, std::move(source_location));
  }
  return ConsoleMessage::Create(kSecurityMessageSource, message_level, message);
}

// static
void MixedContentChecker::Count(Frame* frame,
                                mojom::RequestContextType request_context,
                                const LocalFrame* source) {
  UseCounter::Count(source, WebFeature::kMixedContentPresent);

  // Roll blockable content up into a single counter, count unblocked types
  // individually so we can determine when they can be safely moved to the
  // blockable category:
  WebMixedContentContextType context_type =
      WebMixedContent::ContextTypeFromRequestContext(
          request_context,
          frame->GetSettings()->GetStrictMixedContentCheckingForPlugin());
  if (context_type == WebMixedContentContextType::kBlockable) {
    UseCounter::Count(source, WebFeature::kMixedContentBlockable);
    return;
  }

  WebFeature feature;
  switch (request_context) {
    case mojom::RequestContextType::AUDIO:
      feature = WebFeature::kMixedContentAudio;
      break;
    case mojom::RequestContextType::DOWNLOAD:
      feature = WebFeature::kMixedContentDownload;
      break;
    case mojom::RequestContextType::FAVICON:
      feature = WebFeature::kMixedContentFavicon;
      break;
    case mojom::RequestContextType::IMAGE:
      feature = WebFeature::kMixedContentImage;
      break;
    case mojom::RequestContextType::INTERNAL:
      feature = WebFeature::kMixedContentInternal;
      break;
    case mojom::RequestContextType::PLUGIN:
      feature = WebFeature::kMixedContentPlugin;
      break;
    case mojom::RequestContextType::PREFETCH:
      feature = WebFeature::kMixedContentPrefetch;
      break;
    case mojom::RequestContextType::VIDEO:
      feature = WebFeature::kMixedContentVideo;
      break;

    default:
      NOTREACHED();
      return;
  }
  UseCounter::Count(source, feature);
}

// static
bool MixedContentChecker::ShouldBlockFetch(
    LocalFrame* frame,
    mojom::RequestContextType request_context,
    network::mojom::RequestContextFrameType frame_type,
    ResourceRequest::RedirectStatus redirect_status,
    const KURL& url,
    SecurityViolationReportingPolicy reporting_policy) {
  // Frame-level loads are checked by the browser. No need to check them again
  // here.
  if (frame_type != network::mojom::RequestContextFrameType::kNone)
    return false;

  Frame* effective_frame = EffectiveFrameForFrameType(frame, frame_type);
  Frame* mixed_frame =
      InWhichFrameIsContentMixed(effective_frame, frame_type, url, frame);
  if (!mixed_frame)
    return false;

  MixedContentChecker::Count(mixed_frame, request_context, frame);
  if (ContentSecurityPolicy* policy =
          frame->GetSecurityContext()->GetContentSecurityPolicy())
    policy->ReportMixedContent(url, redirect_status);

  Settings* settings = mixed_frame->GetSettings();
  // Use the current local frame's client; the embedder doesn't distinguish
  // mixed content signals from different frames on the same page.
  LocalFrameClient* client = frame->Client();
  WebContentSettingsClient* content_settings_client =
      frame->GetContentSettingsClient();
  const SecurityOrigin* security_origin =
      mixed_frame->GetSecurityContext()->GetSecurityOrigin();
  bool allowed = false;

  // If we're in strict mode, we'll automagically fail everything, and
  // intentionally skip the client checks in order to prevent degrading the
  // site's security UI.
  bool strict_mode =
      mixed_frame->GetSecurityContext()->GetInsecureRequestPolicy() &
          kBlockAllMixedContent ||
      settings->GetStrictMixedContentChecking();

  WebMixedContentContextType context_type =
      WebMixedContent::ContextTypeFromRequestContext(
          request_context, settings->GetStrictMixedContentCheckingForPlugin());

  // If we're loading the main resource of a subframe, we need to take a close
  // look at the loaded URL. If we're dealing with a CORS-enabled scheme, then
  // block mixed frames as active content. Otherwise, treat frames as passive
  // content.
  //
  // FIXME: Remove this temporary hack once we have a reasonable API for
  // launching external applications via URLs. http://crbug.com/318788 and
  // https://crbug.com/393481
  if (frame_type == network::mojom::RequestContextFrameType::kNested &&
      !SchemeRegistry::ShouldTreatURLSchemeAsCorsEnabled(url.Protocol()))
    context_type = WebMixedContentContextType::kOptionallyBlockable;

  switch (context_type) {
    case WebMixedContentContextType::kOptionallyBlockable:
      allowed = !strict_mode;
      if (allowed) {
        if (content_settings_client)
          content_settings_client->PassiveInsecureContentFound(url);
        client->DidDisplayInsecureContent();
      }
      break;

    case WebMixedContentContextType::kBlockable: {
      // Strictly block subresources that are mixed with respect to their
      // subframes, unless all insecure content is allowed. This is to avoid the
      // following situation: https://a.com embeds https://b.com, which loads a
      // script over insecure HTTP. The user opts to allow the insecure content,
      // thinking that they are allowing an insecure script to run on
      // https://a.com and not realizing that they are in fact allowing an
      // insecure script on https://b.com.
      if (!settings->GetAllowRunningOfInsecureContent() &&
          RequestIsSubframeSubresource(effective_frame, frame_type) &&
          IsMixedContent(frame->GetSecurityContext()->GetSecurityOrigin(),
                         url)) {
        UseCounter::Count(frame,
                          WebFeature::kBlockableMixedContentInSubframeBlocked);
        allowed = false;
        break;
      }

      bool should_ask_embedder =
          !strict_mode && settings &&
          (!settings->GetStrictlyBlockBlockableMixedContent() ||
           settings->GetAllowRunningOfInsecureContent());
      if (should_ask_embedder) {
        allowed = settings && settings->GetAllowRunningOfInsecureContent();
        if (content_settings_client) {
          allowed = content_settings_client->AllowRunningInsecureContent(
              allowed, WebSecurityOrigin(security_origin), url);
        }
      }
      if (allowed) {
        client->DidRunInsecureContent(security_origin, url);
        UseCounter::Count(frame, WebFeature::kMixedContentBlockableAllowed);
      }
      break;
    }

    case WebMixedContentContextType::kShouldBeBlockable:
      allowed = !strict_mode;
      if (allowed)
        client->DidDisplayInsecureContent();
      break;
    case WebMixedContentContextType::kNotMixedContent:
      NOTREACHED();
      break;
  };

  if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
    frame->GetDocument()->AddConsoleMessage(
        CreateConsoleMessageAboutFetch(MainResourceUrlForFrame(mixed_frame),
                                       url, request_context, allowed, nullptr));
  }
  return !allowed;
}

// static
bool MixedContentChecker::ShouldBlockFetchOnWorker(
    const WorkerFetchContext& worker_fetch_context,
    mojom::RequestContextType request_context,
    ResourceRequest::RedirectStatus redirect_status,
    const KURL& url,
    SecurityViolationReportingPolicy reporting_policy,
    bool is_worklet_global_scope) {
  if (!MixedContentChecker::IsMixedContent(
          *worker_fetch_context.GetFetchClientSettingsObject(), url)) {
    return false;
  }

  worker_fetch_context.CountUsage(WebFeature::kMixedContentPresent);
  worker_fetch_context.CountUsage(WebFeature::kMixedContentBlockable);
  if (auto* policy = worker_fetch_context.GetContentSecurityPolicy())
    policy->ReportMixedContent(url, redirect_status);

  // Blocks all mixed content request from worklets.
  // TODO(horo): Revise this when the spec is updated.
  // Worklets spec: https://www.w3.org/TR/worklets-1/#security-considerations
  // Spec issue: https://github.com/w3c/css-houdini-drafts/issues/92
  if (is_worklet_global_scope)
    return true;

  WorkerSettings* settings = worker_fetch_context.GetWorkerSettings();
  DCHECK(settings);
  bool allowed = false;
  if (!settings->GetAllowRunningOfInsecureContent() &&
      worker_fetch_context.GetWebWorkerFetchContext()->IsOnSubframe()) {
    worker_fetch_context.CountUsage(
        WebFeature::kBlockableMixedContentInSubframeBlocked);
    allowed = false;
  } else {
    bool strict_mode =
        worker_fetch_context.GetSecurityContext().GetInsecureRequestPolicy() &
            kBlockAllMixedContent ||
        settings->GetStrictMixedContentChecking();
    bool should_ask_embedder =
        !strict_mode && (!settings->GetStrictlyBlockBlockableMixedContent() ||
                         settings->GetAllowRunningOfInsecureContent());
    allowed = should_ask_embedder &&
              worker_fetch_context.GetWorkerContentSettingsClient()
                  ->AllowRunningInsecureContent(
                      settings->GetAllowRunningOfInsecureContent(),
                      worker_fetch_context.GetSecurityOrigin(), url);
    if (allowed) {
      worker_fetch_context.GetWebWorkerFetchContext()->DidRunInsecureContent(
          WebSecurityOrigin(worker_fetch_context.GetSecurityOrigin()), url);
      worker_fetch_context.CountUsage(
          WebFeature::kMixedContentBlockableAllowed);
    }
  }

  if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
    worker_fetch_context.AddConsoleMessage(CreateConsoleMessageAboutFetch(
        worker_fetch_context.Url(), url, request_context, allowed, nullptr));
  }
  return !allowed;
}

// static
ConsoleMessage* MixedContentChecker::CreateConsoleMessageAboutWebSocket(
    const KURL& main_resource_url,
    const KURL& url,
    bool allowed) {
  String message = String::Format(
      "Mixed Content: The page at '%s' was loaded over HTTPS, but attempted to "
      "connect to the insecure WebSocket endpoint '%s'. %s",
      main_resource_url.ElidedString().Utf8().data(),
      url.ElidedString().Utf8().data(),
      allowed ? "This endpoint should be available via WSS. Insecure access is "
                "deprecated."
              : "This request has been blocked; this endpoint must be "
                "available over WSS.");
  MessageLevel message_level =
      allowed ? kWarningMessageLevel : kErrorMessageLevel;
  return ConsoleMessage::Create(kSecurityMessageSource, message_level, message);
}

// static
bool MixedContentChecker::IsWebSocketAllowed(
    const FrameFetchContext& frame_fetch_context,
    LocalFrame* frame,
    const KURL& url) {
  Frame* mixed_frame = InWhichFrameIsContentMixed(
      frame, network::mojom::RequestContextFrameType::kNone, url, frame);
  if (!mixed_frame)
    return true;

  Settings* settings = mixed_frame->GetSettings();
  // Use the current local frame's client; the embedder doesn't distinguish
  // mixed content signals from different frames on the same page.
  WebContentSettingsClient* content_settings_client =
      frame->GetContentSettingsClient();
  SecurityContext* security_context = mixed_frame->GetSecurityContext();
  const SecurityOrigin* security_origin = security_context->GetSecurityOrigin();

  bool allowed = IsWebSocketAllowedImpl(frame_fetch_context, security_context,
                                        settings, url);
  if (content_settings_client) {
    allowed = content_settings_client->AllowRunningInsecureContent(
        allowed, WebSecurityOrigin(security_origin), url);
  }

  if (allowed)
    frame->Client()->DidRunInsecureContent(security_origin, url);

  frame->GetDocument()->AddConsoleMessage(CreateConsoleMessageAboutWebSocket(
      MainResourceUrlForFrame(mixed_frame), url, allowed));

  return allowed;
}

// static
bool MixedContentChecker::IsWebSocketAllowed(
    const WorkerFetchContext& worker_fetch_context,
    const KURL& url) {
  if (!MixedContentChecker::IsMixedContent(
          *worker_fetch_context.GetFetchClientSettingsObject(), url)) {
    return true;
  }

  WorkerSettings* settings = worker_fetch_context.GetWorkerSettings();
  WorkerContentSettingsClient* content_settings_client =
      worker_fetch_context.GetWorkerContentSettingsClient();
  SecurityContext* security_context =
      &worker_fetch_context.GetSecurityContext();
  const SecurityOrigin* security_origin =
      worker_fetch_context.GetSecurityOrigin();

  bool allowed = IsWebSocketAllowedImpl(worker_fetch_context, security_context,
                                        settings, url);
  if (content_settings_client) {
    allowed = content_settings_client->AllowRunningInsecureContent(
        allowed, security_origin, url);
  }

  if (allowed) {
    worker_fetch_context.GetWebWorkerFetchContext()->DidRunInsecureContent(
        WebSecurityOrigin(security_origin), url);
  }

  worker_fetch_context.AddConsoleMessage(CreateConsoleMessageAboutWebSocket(
      worker_fetch_context.Url(), url, allowed));

  return allowed;
}

bool MixedContentChecker::IsMixedFormAction(
    LocalFrame* frame,
    const KURL& url,
    SecurityViolationReportingPolicy reporting_policy) {
  // For whatever reason, some folks handle forms via JavaScript, and submit to
  // `javascript:void(0)` rather than calling `preventDefault()`. We
  // special-case `javascript:` URLs here, as they don't introduce MixedContent
  // for form submissions.
  if (url.ProtocolIs("javascript"))
    return false;

  Frame* mixed_frame = InWhichFrameIsContentMixed(
      frame, network::mojom::RequestContextFrameType::kNone, url, frame);
  if (!mixed_frame)
    return false;

  UseCounter::Count(frame, WebFeature::kMixedContentPresent);

  // Use the current local frame's client; the embedder doesn't distinguish
  // mixed content signals from different frames on the same page.
  frame->Client()->DidContainInsecureFormAction();

  if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
    String message = String::Format(
        "Mixed Content: The page at '%s' was loaded over a secure connection, "
        "but contains a form that targets an insecure endpoint '%s'. This "
        "endpoint should be made available over a secure connection.",
        MainResourceUrlForFrame(mixed_frame).ElidedString().Utf8().data(),
        url.ElidedString().Utf8().data());
    frame->GetDocument()->AddConsoleMessage(ConsoleMessage::Create(
        kSecurityMessageSource, kWarningMessageLevel, message));
  }

  return true;
}

bool MixedContentChecker::ShouldAutoupgrade(KURL frame_url,
                                            WebMixedContentContextType type) {
  if (!base::FeatureList::IsEnabled(
          blink::features::kMixedContentAutoupgrade) ||
      !frame_url.ProtocolIs("https") ||
      type == WebMixedContentContextType::kNotMixedContent) {
    return false;
  }

  std::string autoupgrade_mode = base::GetFieldTrialParamValueByFeature(
      blink::features::kMixedContentAutoupgrade,
      blink::features::kMixedContentAutoupgradeModeParamName);

  if (autoupgrade_mode ==
      blink::features::kMixedContentAutoupgradeModeBlockable) {
    return type == WebMixedContentContextType::kBlockable ||
           type == WebMixedContentContextType::kShouldBeBlockable;
  }
  if (autoupgrade_mode ==
      blink::features::kMixedContentAutoupgradeModeOptionallyBlockable) {
    return type == WebMixedContentContextType::kOptionallyBlockable;
  }

  // Otherwise we default to autoupgrading all mixed content.
  return true;
}

void MixedContentChecker::CheckMixedPrivatePublic(
    LocalFrame* frame,
    const AtomicString& resource_ip_address) {
  if (!frame || !frame->GetDocument() || !frame->GetDocument()->Loader())
    return;

  // Just count these for the moment, don't block them.
  if (network_utils::IsReservedIPAddress(resource_ip_address) &&
      frame->GetDocument()->AddressSpace() == mojom::IPAddressSpace::kPublic) {
    UseCounter::Count(frame->GetDocument(),
                      WebFeature::kMixedContentPrivateHostnameInPublicHostname);
    // We can simplify the IP checks here, as we've already verified that
    // |resourceIPAddress| is a reserved IP address, which means it's also a
    // valid IP address in a normalized form.
    if (resource_ip_address.StartsWith("127.0.0.") ||
        resource_ip_address == "[::1]") {
      UseCounter::Count(frame->GetDocument(),
                        frame->GetDocument()->IsSecureContext()
                            ? WebFeature::kLoopbackEmbeddedInSecureContext
                            : WebFeature::kLoopbackEmbeddedInNonSecureContext);
    }
  }
}

Frame* MixedContentChecker::EffectiveFrameForFrameType(
    LocalFrame* frame,
    network::mojom::RequestContextFrameType frame_type) {
  // If we're loading the main resource of a subframe, ensure that we check
  // against the parent of the active frame, rather than the frame itself.
  if (frame_type != network::mojom::RequestContextFrameType::kNested)
    return frame;

  Frame* parent_frame = frame->Tree().Parent();
  DCHECK(parent_frame);
  return parent_frame;
}

void MixedContentChecker::HandleCertificateError(
    LocalFrame* frame,
    const ResourceResponse& response,
    network::mojom::RequestContextFrameType frame_type,
    mojom::RequestContextType request_context) {
  Frame* effective_frame = EffectiveFrameForFrameType(frame, frame_type);
  if (frame_type == network::mojom::RequestContextFrameType::kTopLevel ||
      !effective_frame)
    return;

  // Use the current local frame's client; the embedder doesn't distinguish
  // mixed content signals from different frames on the same page.
  LocalFrameClient* client = frame->Client();
  bool strict_mixed_content_checking_for_plugin =
      effective_frame->GetSettings() &&
      effective_frame->GetSettings()->GetStrictMixedContentCheckingForPlugin();
  WebMixedContentContextType context_type =
      WebMixedContent::ContextTypeFromRequestContext(
          request_context, strict_mixed_content_checking_for_plugin);
  if (context_type == WebMixedContentContextType::kBlockable) {
    client->DidRunContentWithCertificateErrors();
  } else {
    // contextTypeFromRequestContext() never returns NotMixedContent (it
    // computes the type of mixed content, given that the content is mixed).
    DCHECK_NE(context_type, WebMixedContentContextType::kNotMixedContent);
    client->DidDisplayContentWithCertificateErrors();
  }
}

// static
void MixedContentChecker::MixedContentFound(
    LocalFrame* frame,
    const KURL& main_resource_url,
    const KURL& mixed_content_url,
    mojom::RequestContextType request_context,
    bool was_allowed,
    bool had_redirect,
    std::unique_ptr<SourceLocation> source_location) {
  // Logs to the frame console.
  frame->GetDocument()->AddConsoleMessage(CreateConsoleMessageAboutFetch(
      main_resource_url, mixed_content_url, request_context, was_allowed,
      std::move(source_location)));
  // Reports to the CSP policy.
  ContentSecurityPolicy* policy =
      frame->GetSecurityContext()->GetContentSecurityPolicy();
  if (policy) {
    policy->ReportMixedContent(
        mixed_content_url,
        had_redirect ? ResourceRequest::RedirectStatus::kFollowedRedirect
                     : ResourceRequest::RedirectStatus::kNoRedirect);
  }
}

// static
ConsoleMessage* MixedContentChecker::CreateConsoleMessageAboutFetchAutoupgrade(
    const KURL& main_resource_url,
    const KURL& mixed_content_url) {
  String message = String::Format(
      "Mixed Content: The page at '%s' was loaded over HTTPS, but requested an "
      "insecure element '%s'. As part of an experiment this request was "
      "automatically upgraded to HTTPS, For more information see "
      "https://chromium.googlesource.com/chromium/src/+/master/docs/security/"
      "autougprade-mixed.md",
      main_resource_url.ElidedString().Utf8().data(),
      mixed_content_url.ElidedString().Utf8().data());
  return ConsoleMessage::Create(kSecurityMessageSource, kWarningMessageLevel,
                                message);
}

// static
ConsoleMessage*
MixedContentChecker::CreateConsoleMessageAboutWebSocketAutoupgrade(
    const KURL& main_resource_url,
    const KURL& mixed_content_url) {
  String message = String::Format(
      "Mixed Content: The page at '%s' was loaded over HTTPS, but attempted "
      "to connect to the insecure WebSocket endpoint '%s'. As part of an "
      "experiment this request was automatically upgraded to HTTPS, For more "
      "information see "
      "https://chromium.googlesource.com/chromium/src/+/master/docs/security/"
      "autougprade-mixed.md",
      main_resource_url.ElidedString().Utf8().data(),
      mixed_content_url.ElidedString().Utf8().data());
  return ConsoleMessage::Create(kSecurityMessageSource, kWarningMessageLevel,
                                message);
}

WebMixedContentContextType MixedContentChecker::ContextTypeForInspector(
    LocalFrame* frame,
    const ResourceRequest& request) {
  Frame* effective_frame =
      EffectiveFrameForFrameType(frame, request.GetFrameType());

  Frame* mixed_frame = InWhichFrameIsContentMixed(
      effective_frame, request.GetFrameType(), request.Url(), frame);
  if (!mixed_frame)
    return WebMixedContentContextType::kNotMixedContent;

  // See comment in ShouldBlockFetch() about loading the main resource of a
  // subframe.
  if (request.GetFrameType() ==
          network::mojom::RequestContextFrameType::kNested &&
      !SchemeRegistry::ShouldTreatURLSchemeAsCorsEnabled(
          request.Url().Protocol())) {
    return WebMixedContentContextType::kOptionallyBlockable;
  }

  bool strict_mixed_content_checking_for_plugin =
      mixed_frame->GetSettings() &&
      mixed_frame->GetSettings()->GetStrictMixedContentCheckingForPlugin();
  return WebMixedContent::ContextTypeFromRequestContext(
      request.GetRequestContext(), strict_mixed_content_checking_for_plugin);
}

}  // namespace blink
