// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/renderer/chrome_render_frame_observer.h"

#include <stddef.h>
#include <string.h>

#include <limits>
#include <map>
#include <memory>
#include <set>
#include <utility>

#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_isolated_world_ids.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/open_search_description_document_handler.mojom.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/renderer/actor/journal.h"
#include "chrome/renderer/actor/page_stability_monitor.h"
#include "chrome/renderer/actor/tool_executor.h"
#include "chrome/renderer/chrome_content_settings_agent_delegate.h"
#include "chrome/renderer/media/media_feeds.h"
#include "chrome/renderer/process_state.h"
#include "components/crash/core/common/crash_key.h"
#include "components/guest_view/buildflags/buildflags.h"
#include "components/guest_view/renderer/slim_web_view/slim_web_view_bindings.h"
#include "components/lens/lens_metadata.mojom.h"
#include "components/no_state_prefetch/renderer/no_state_prefetch_helper.h"
#include "components/no_state_prefetch/renderer/no_state_prefetch_utils.h"
#include "components/offline_pages/buildflags/buildflags.h"
#include "components/optimization_guide/content/renderer/page_text_agent.h"
#include "components/translate/content/renderer/translate_agent.h"
#include "components/translate/core/common/translate_util.h"
#include "components/web_cache/renderer/web_cache_impl.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/buildflags.h"
#include "content/public/common/content_features.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_frame_visitor.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/window_features_converter.h"
#include "printing/buildflags/buildflags.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "skia/ext/image_operations.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_document_loader.h"
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_frame_content_dumper.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_node.h"
#include "third_party/blink/public/web/web_security_policy.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/libwebp/src/src/webp/decode.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/codec/webp_codec.h"
#include "ui/gfx/geometry/size_f.h"
#include "url/gurl.h"

#if !BUILDFLAG(IS_ANDROID)
#include "chrome/renderer/accessibility/read_anything/read_anything_app_controller.h"
#include "chrome/renderer/searchbox/searchbox_extension.h"
#endif  // !BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
#include "components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.h"
#include "components/safe_browsing/content/renderer/phishing_classifier/phishing_image_embedder_delegate.h"
#endif

#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
#include "chrome/common/mhtml_page_notifier.mojom.h"
#endif

#if BUILDFLAG(ENABLE_PLUGINS)
#include "chrome/renderer/plugins/chrome_plugin_placeholder.h"
#endif

using blink::WebDocumentLoader;
using blink::WebElement;
using blink::WebFrameContentDumper;
using blink::WebLocalFrame;
using blink::WebNode;
using blink::WebString;
using content::RenderFrame;

// Maximum number of characters in the document to index.
// Any text beyond this point will be clipped.
static const size_t kMaxIndexChars = 65535;


// For a page that auto-refreshes, we still show the bubble, if
// the refresh delay is less than this value (in seconds).
static constexpr base::TimeDelta kLocationChangeInterval = base::Seconds(10);

// For the context menu, we want to keep transparency as is instead of
// replacing transparent pixels with black ones
static const bool kDiscardTransparencyForContextMenu = false;

namespace {

const char kImageGif[] = "image/gif";
const char kImageJpeg[] = "image/jpeg";
const char kImagePng[] = "image/png";
const char kImageWebp[] = "image/webp";

#if BUILDFLAG(IS_ANDROID)
base::Lock& GetFrameHeaderMapLock() {
  static base::NoDestructor<base::Lock> s;
  return *s;
}

using FrameHeaderMap = std::map<blink::LocalFrameToken, std::string>;

FrameHeaderMap& GetFrameHeaderMap() {
  GetFrameHeaderMapLock().AssertAcquired();
  static base::NoDestructor<FrameHeaderMap> s;
  return *s;
}
#endif

// Renderers can handle multiple pages, especially in low-memory conditions.
// Record crash keys for a few origins, in the hope of finding more culprit
// origins for OOM crashes. Keys are recorded here and not via
// ChromeContentClient::SetActiveURL() because that method is only invoked in
// response to IPC messages and most OOMs do not occur in response to an IPC.
// https://crbug.com/1310046
void UpdateLoadedOriginCrashKeys() {
  // Capture the origin for each RenderFrame.
  struct Visitor : public content::RenderFrameVisitor {
    bool Visit(RenderFrame* render_frame) override {
      if (render_frame) {
        WebLocalFrame* web_frame = render_frame->GetWebFrame();
        if (web_frame) {
          frame_count_++;
          origins_.insert(web_frame->GetSecurityOrigin().ToString().Utf8());
        }
      }
      return true;  // Keep going.
    }
    int frame_count_ = 0;
    std::set<std::string> origins_;  // Use set to collapse duplicate origins.
  } visitor;
  RenderFrame::ForEach(&visitor);

  static crash_reporter::CrashKeyString<8> frame_count("web-frame-count");
  frame_count.Set(base::NumberToString(visitor.frame_count_));

  // Record 3 recently-loaded origins in crash keys (which 3 is arbitrary).
  using ArrayItemKey = crash_reporter::CrashKeyString<64>;
  static ArrayItemKey crash_keys[] = {
      {"loaded-origin-0", ArrayItemKey::Tag::kArray},
      {"loaded-origin-1", ArrayItemKey::Tag::kArray},
      {"loaded-origin-2", ArrayItemKey::Tag::kArray},
  };
  for (auto& crash_key : crash_keys) {
    if (!visitor.origins_.empty()) {
      auto origin_it = visitor.origins_.begin();
      crash_key.Set(*origin_it);
      visitor.origins_.erase(origin_it);
    } else {
      // If there are fewer than 3 origins, clear the remaining keys.
      crash_key.Clear();
    }
  }
}

}  // namespace

ChromeRenderFrameObserver::ChromeRenderFrameObserver(
    content::RenderFrame* render_frame,
    web_cache::WebCacheImpl* web_cache_impl)
    : content::RenderFrameObserver(render_frame),
      translate_agent_(nullptr),
      page_text_agent_(new optimization_guide::PageTextAgent(render_frame)),
      actor_journal_(std::make_unique<actor::Journal>()),
      web_cache_impl_(web_cache_impl) {
  render_frame->GetAssociatedInterfaceRegistry()
      ->AddInterface<chrome::mojom::ChromeRenderFrame>(base::BindRepeating(
          &ChromeRenderFrameObserver::OnRenderFrameObserverRequest,
          base::Unretained(this)));

  // Don't do anything else for subframes.
  if (!render_frame->IsMainFrame())
    return;

#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
  SetClientSidePhishingDetection();
#endif

  translate_agent_ =
      new translate::TranslateAgent(render_frame, ISOLATED_WORLD_ID_TRANSLATE);
}

ChromeRenderFrameObserver::~ChromeRenderFrameObserver() = default;

#if BUILDFLAG(IS_ANDROID)
std::string ChromeRenderFrameObserver::GetCCTClientHeader(
    const blink::LocalFrameToken& frame_token) {
  base::AutoLock auto_lock(GetFrameHeaderMapLock());
  auto frame_map = GetFrameHeaderMap();
  auto iter = frame_map.find(frame_token);
  return iter == frame_map.end() ? std::string() : iter->second;
}
#endif

void ChromeRenderFrameObserver::OnInterfaceRequestForFrame(
    const std::string& interface_name,
    mojo::ScopedMessagePipeHandle* interface_pipe) {
  registry_.TryBindInterface(interface_name, interface_pipe);
}

bool ChromeRenderFrameObserver::OnAssociatedInterfaceRequestForFrame(
    const std::string& interface_name,
    mojo::ScopedInterfaceEndpointHandle* handle) {
  return associated_interfaces_.TryBindInterface(interface_name, handle);
}

void ChromeRenderFrameObserver::ReadyToCommitNavigation(
    WebDocumentLoader* document_loader) {
  // Execute cache clear operations that were postponed until a navigation
  // event (including tab reload).
  if (render_frame()->IsMainFrame() && web_cache_impl_)
    web_cache_impl_->ExecutePendingClearCache();

  // Let translate_agent do any preparatory work before the new document loads.
  if (translate_agent_) {
    translate_agent_->PrepareForNewDocument();
  }
}

void ChromeRenderFrameObserver::DidSetPageLifecycleState(
    blink::BFCacheStateChange bfcache_change) {
  if (bfcache_change == blink::BFCacheStateChange::kRestoredFromBFCache &&
      translate_agent_) {
    translate_agent_->RenewPageRegistration();
  }
  if (bfcache_change == blink::BFCacheStateChange::kStoredToBFCache) {
    // Reset actor state if entering the BFCache
    page_stability_monitor_.reset();
    tool_executor_.reset();

    // Flush any remaining log entries which may have been added in the
    // destructors above. Don't reset the actor journal since it is only created
    // from the constructor.
    actor_journal_->SendLogBuffer();
  }
}

void ChromeRenderFrameObserver::DidFinishLoad() {
  WebLocalFrame* frame = render_frame()->GetWebFrame();
  // Don't do anything for subframes.
  if (frame->Parent() || frame->IsInFencedFrameTree())
    return;

  GURL osdd_url = frame->GetDocument().OpenSearchDescriptionURL();
  if (!osdd_url.is_empty()) {
    mojo::Remote<chrome::mojom::OpenSearchDescriptionDocumentHandler>
        osdd_handler;
    render_frame()->GetBrowserInterfaceBroker().GetInterface(
        osdd_handler.BindNewPipeAndPassReceiver());
    osdd_handler->PageHasOpenSearchDescriptionDocument(
        frame->GetDocument().Url(), osdd_url);
  }
}

void ChromeRenderFrameObserver::DidCreateNewDocument() {
#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
  DCHECK(render_frame());
  if (!render_frame()->IsMainFrame())
    return;

  DCHECK(render_frame()->GetWebFrame());
  blink::WebDocumentLoader* doc_loader =
      render_frame()->GetWebFrame()->GetDocumentLoader();
  DCHECK(doc_loader);

  if (!doc_loader->HasBeenLoadedAsWebArchive())
    return;

  // Connect to Mojo service on browser to notify it of the page's archive
  // properties.
  mojo::AssociatedRemote<offline_pages::mojom::MhtmlPageNotifier>
      mhtml_notifier;
  render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
      &mhtml_notifier);
  DCHECK(mhtml_notifier);
  blink::WebArchiveInfo info = doc_loader->GetArchiveInfo();

  mhtml_notifier->NotifyMhtmlPageLoadAttempted(info.load_result, info.url,
                                               info.date);
#endif
}

void ChromeRenderFrameObserver::DidCommitProvisionalLoad(
    ui::PageTransition transition) {
  // Update crash keys on any frame transition, not just the main frame.
  UpdateLoadedOriginCrashKeys();

  WebLocalFrame* frame = render_frame()->GetWebFrame();

  // Don't do anything for subframes.
  if (frame->Parent())
    return;

  static crash_reporter::CrashKeyString<8> view_count_key("view-count");
  view_count_key.Set(base::NumberToString(blink::WebView::GetWebViewCount()));

#if !BUILDFLAG(IS_ANDROID)
  if (render_frame()->GetEnabledBindings().HasAny(
          content::kWebUIBindingsPolicySet)) {
    for (const auto& script : webui_javascript_)
      render_frame()->ExecuteJavaScript(script);
    webui_javascript_.clear();
  }
#endif
}

void ChromeRenderFrameObserver::DidClearWindowObject() {
#if !BUILDFLAG(IS_ANDROID)
  if (process_state::IsInstantProcess()) {
    SearchBoxExtension::Install(render_frame()->GetWebFrame());
  }

  // Install ReadAnythingAppController on render frames with the Read Anything
  // url, which is chrome-untrusted. ReadAnythingAppController installs v8
  // bindings in the chrome.readingMode namespace which are consumed by
  // read_anything/app.ts, the resource of the Read Anything WebUI.
  if (render_frame()->GetWebFrame()->GetDocument().Url() ==
      chrome::kChromeUIUntrustedReadAnythingSidePanelURL) {
    ReadAnythingAppController::Install(render_frame());
  }
#endif  // !BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(ENABLE_GUEST_VIEW) && !BUILDFLAG(ENABLE_EXTENSIONS_CORE)
  guest_view::SlimWebViewBindings::MaybeInstall(*render_frame());
#endif  // BUILDFLAG(ENABLE_GUEST_VIEW) && !BUILDFLAG(ENABLE_EXTENSIONS_CORE)
}

void ChromeRenderFrameObserver::DidMeaningfulLayout(
    blink::WebMeaningfulLayout layout_type) {
  CapturePageText(layout_type);
}

void ChromeRenderFrameObserver::OnDestruct() {
  delete this;
}

void ChromeRenderFrameObserver::WillDetach(blink::DetachReason detach_reason) {
#if BUILDFLAG(IS_ANDROID)
  base::AutoLock auto_lock(GetFrameHeaderMapLock());
  GetFrameHeaderMap().erase(
      render_frame()->GetWebFrame()->GetLocalFrameToken());
#endif
}

void ChromeRenderFrameObserver::SetWindowFeatures(
    blink::mojom::WindowFeaturesPtr window_features) {
  render_frame()->GetWebView()->SetWindowFeatures(
      content::ConvertMojoWindowFeaturesToWebWindowFeatures(*window_features));
}

void ChromeRenderFrameObserver::ExecuteWebUIJavaScript(
    const std::u16string& javascript) {
#if !BUILDFLAG(IS_ANDROID)
  webui_javascript_.push_back(javascript);
#endif
}

void ChromeRenderFrameObserver::RequestImageForContextNode(
    int32_t thumbnail_min_area_pixels,
    const gfx::Size& thumbnail_max_size_pixels,
    chrome::mojom::ImageFormat image_format,
    int32_t quality,
    RequestImageForContextNodeCallback callback) {
  WebNode context_node = render_frame()->GetWebFrame()->ContextMenuImageNode();
  std::vector<uint8_t> image_data;
  gfx::Size original_size;
  std::string mime_type;
  std::vector<lens::mojom::LatencyLogPtr> latency_logs;

  // Map for converting between multiple mojom ImageFormat structures to
  // prevent a circular dependency (go/lens-logging-in-chromium)
  // TODO(shivpatel): add default value UNKNOWN for if ImageFormat is updated
  const std::map<chrome::mojom::ImageFormat, lens::mojom::ImageFormat>
      image_format_conversion = {
          {chrome::mojom::ImageFormat::ORIGINAL,
           lens::mojom::ImageFormat::ORIGINAL},
          {chrome::mojom::ImageFormat::PNG, lens::mojom::ImageFormat::PNG},
          {chrome::mojom::ImageFormat::JPEG, lens::mojom::ImageFormat::JPEG},
          {chrome::mojom::ImageFormat::WEBP, lens::mojom::ImageFormat::WEBP},
      };

  if (context_node.IsNull() || !context_node.IsElementNode()) {
    // The downscaled size is the original size, since no downscaling was
    // required.
    std::move(callback).Run(image_data, original_size,
                            /*downscaled_size=*/original_size, mime_type,
                            std::move(latency_logs));
    return;
  }

  WebElement web_element = context_node.To<WebElement>();
  original_size = web_element.GetImageSize();
  mime_type = web_element.ImageMimeType().Utf8();
  bool needs_downscale = NeedsDownscale(
      original_size, thumbnail_min_area_pixels, thumbnail_max_size_pixels);
  bool needs_encode = NeedsEncodeImage(mime_type, image_format) ||
                      IsAnimatedWebp(web_element.CopyOfImageData());
  if (!needs_encode && !needs_downscale) {
    image_data = web_element.CopyOfImageData();
    // The downscaled size is the original size, since no downscaling was
    // required.
    std::move(callback).Run(std::move(image_data), original_size,
                            /*downscaled_size=*/original_size, mime_type,
                            std::move(latency_logs));
    return;
  }
  SkBitmap image = web_element.ImageContents();
  if (needs_downscale) {
    latency_logs.push_back(lens::mojom::LatencyLog::New(
        lens::mojom::Phase::DOWNSCALE_START, original_size, gfx::Size(),
        image_format_conversion.at(image_format), base::Time::Now(),
        /*encoded_size_bytes=*/0));
  }
  SkBitmap thumbnail =
      Downscale(image, thumbnail_min_area_pixels, thumbnail_max_size_pixels);
  gfx::Size downscaled_size = gfx::Size(thumbnail.width(), thumbnail.height());
  if (needs_downscale) {
    latency_logs.push_back(lens::mojom::LatencyLog::New(
        lens::mojom::Phase::DOWNSCALE_END, original_size, downscaled_size,
        image_format_conversion.at(image_format), base::Time::Now(),
        /*encoded_size_bytes=*/0));
  }

  SkBitmap bitmap;
  if (thumbnail.colorType() == kN32_SkColorType) {
    bitmap = thumbnail;
  } else {
    SkImageInfo info = thumbnail.info().makeColorType(kN32_SkColorType);
    if (bitmap.tryAllocPixels(info)) {
      thumbnail.readPixels(info, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
    }
  }

  if (image_format == chrome::mojom::ImageFormat::ORIGINAL) {
    // ORIGINAL will only fall back to here if the image needs to downscale.
    // Let's PNG downscale to PNG and JEPG downscale to JPEG.
    if (mime_type == kImagePng) {
      image_format = chrome::mojom::ImageFormat::PNG;
    } else if (mime_type == kImageJpeg) {
      image_format = chrome::mojom::ImageFormat::JPEG;
    }
  }

  if (needs_encode) {
    latency_logs.push_back(lens::mojom::LatencyLog::New(
        lens::mojom::Phase::ENCODE_START, original_size, downscaled_size,
        image_format_conversion.at(image_format), base::Time::Now(),
        /*encoded_size_bytes=*/0));
  }
  std::optional<std::vector<uint8_t>> data;
  switch (image_format) {
    case chrome::mojom::ImageFormat::PNG:
      data = gfx::PNGCodec::EncodeBGRASkBitmap(
          bitmap, kDiscardTransparencyForContextMenu);
      if (data) {
        image_data.swap(data.value());
        mime_type = kImagePng;
      }
      break;
    case chrome::mojom::ImageFormat::WEBP:
      data = gfx::WebpCodec::Encode(bitmap, quality);
      if (data) {
        image_data.swap(data.value());
        mime_type = kImageWebp;
      }
      break;
    case chrome::mojom::ImageFormat::ORIGINAL:
    // Any format other than PNG and JPEG fall back to here.
    case chrome::mojom::ImageFormat::JPEG:
      data = gfx::JPEGCodec::Encode(bitmap, quality);
      if (data) {
        image_data.swap(data.value());
        mime_type = kImageJpeg;
      }
      break;
  }
  if (needs_encode) {
    latency_logs.push_back(lens::mojom::LatencyLog::New(
        lens::mojom::Phase::ENCODE_END, original_size, downscaled_size,
        image_format_conversion.at(image_format), base::Time::Now(),
        sizeof(uint8_t) * image_data.size()));
  }

  std::move(callback).Run(image_data, original_size, downscaled_size, mime_type,
                          std::move(latency_logs));
}

void ChromeRenderFrameObserver::RequestBitmapForContextNode(
    RequestBitmapForContextNodeCallback callback) {
  WebNode context_node = render_frame()->GetWebFrame()->ContextMenuImageNode();
  SkBitmap image;
  if (context_node.IsNull() || !context_node.IsElementNode()) {
    std::move(callback).Run(image);
    return;
  }

  WebElement web_element = context_node.To<WebElement>();
  image = web_element.ImageContents();
  std::move(callback).Run(image);
}

void ChromeRenderFrameObserver::RequestBitmapForContextNodeWithBoundsHint(
    RequestBitmapForContextNodeWithBoundsHintCallback callback) {
  WebNode context_node = render_frame()->GetWebFrame()->ContextMenuImageNode();
  SkBitmap image;
  gfx::Rect bounds;
  if (context_node.IsNull() || !context_node.IsElementNode()) {
    std::move(callback).Run(image, bounds);
    return;
  }

  WebElement web_element = context_node.To<WebElement>();
  image = web_element.ImageContents();
  bounds = web_element.BoundsInWidget();
  std::move(callback).Run(image, bounds);
}

void ChromeRenderFrameObserver::RequestBoundsHintForAllImages(
    RequestBoundsHintForAllImagesCallback callback) {
  std::vector<blink::WebElement> image_elements;
  std::vector<gfx::Rect> all_bounds;
  const blink::WebDocument doc = render_frame()->GetWebFrame()->GetDocument();
  if (doc.IsNull() || doc.Body().IsNull()) {
    return;
  }
  FindImageElements(doc.Body(), image_elements);

  for (auto& element : image_elements) {
    all_bounds.emplace_back(
        render_frame()->ConvertViewportToWindow(element.BoundsInWidget()));
  }
  std::move(callback).Run(all_bounds);
}

// Depth-first search for recursively traversing DOM elements and pulling out
// references for images.
void ChromeRenderFrameObserver::FindImageElements(
    blink::WebElement element,
    std::vector<blink::WebElement>& images) {
  if (element.ImageContents().isNull()) {
    for (blink::WebNode child = element.FirstChild(); !child.IsNull();
         child = child.NextSibling()) {
      if (child.IsElementNode()) {
        FindImageElements(child.To<blink::WebElement>(), images);
      }
    }
  } else {
    images.emplace_back(element);
  }
}

void ChromeRenderFrameObserver::RequestReloadImageForContextNode() {
  WebLocalFrame* frame = render_frame()->GetWebFrame();
  // TODO(dglazkov): This code is clearly in the wrong place. Need
  // to investigate what it is doing and fix (http://crbug.com/41250588).
  WebNode context_node = frame->ContextMenuImageNode();
  if (!context_node.IsNull()) {
    frame->ReloadImage(context_node);
  }
}

#if BUILDFLAG(IS_ANDROID)
void ChromeRenderFrameObserver::SetCCTClientHeader(const std::string& header) {
  auto* web_frame = render_frame()->GetWebFrame();
  if (!web_frame) {
    return;
  }
  base::AutoLock auto_lock(GetFrameHeaderMapLock());
  GetFrameHeaderMap()[web_frame->GetLocalFrameToken()] = header;
}
#endif

void ChromeRenderFrameObserver::GetMediaFeedURL(
    GetMediaFeedURLCallback callback) {
  std::move(callback).Run(MediaFeeds::GetMediaFeedURL(render_frame()));
}

void ChromeRenderFrameObserver::LoadBlockedPlugins(
    const std::string& identifier) {
  // Record that this plugin is temporarily allowed and notify all placeholders.

  ChromeContentSettingsAgentDelegate::Get(render_frame())
      ->AllowPluginTemporarily(identifier);

#if BUILDFLAG(ENABLE_PLUGINS)
  ChromePluginPlaceholder::ForEach(
      render_frame(), base::BindRepeating(
                          [](const std::string& identifier,
                             ChromePluginPlaceholder* placeholder) {
                            placeholder->MaybeLoadBlockedPlugin(identifier);
                          },
                          identifier));
#endif  // BUILDFLAG(ENABLE_PLUGINS)
}

void ChromeRenderFrameObserver::SetShouldDeferMediaLoad(bool should_defer) {
  prerender::SetShouldDeferMediaLoad(render_frame(), should_defer);
}

void ChromeRenderFrameObserver::InitializeTool(
    actor::mojom::ToolInvocationPtr request,
    InitializeToolCallback callback) {
  if (!tool_executor_) {
    tool_executor_ =
        std::make_unique<actor::ToolExecutor>(render_frame(), *actor_journal_);
  }

  actor::mojom::InitializeToolResultPtr result =
      tool_executor_->InitializeTool(std::move(request));
  std::move(callback).Run(std::move(result));
}

void ChromeRenderFrameObserver::ExecuteTool(const actor::TaskId& task_id,
                                            ExecuteToolCallback callback) {
  CHECK(tool_executor_) << "ExecuteTool was called before InitializeTool";
  tool_executor_->ExecuteTool(task_id, std::move(callback));
}

void ChromeRenderFrameObserver::InvokeTool(
    actor::mojom::ToolInvocationPtr request,
    InvokeToolCallback callback) {
  if (!tool_executor_) {
    tool_executor_ =
        std::make_unique<actor::ToolExecutor>(render_frame(), *actor_journal_);
  }

  tool_executor_->InvokeTool(std::move(request), std::move(callback));
}

void ChromeRenderFrameObserver::CancelTool(const actor::TaskId& task_id) {
  if (tool_executor_) {
    tool_executor_->CancelTool(task_id);
  }
}

void ChromeRenderFrameObserver::StartActorJournal(
    mojo::PendingAssociatedRemote<actor::mojom::JournalClient> client) {
  actor_journal_->Bind(std::move(client));
}

void ChromeRenderFrameObserver::GetCrossDocumentScriptToolResult(
    GetCrossDocumentScriptToolResultCallback callback) {
  render_frame()->GetWebFrame()->GetDocument().GetCrossDocumentScriptToolResult(
      base::BindOnce(
          [](GetCrossDocumentScriptToolResultCallback cb,
             blink::WebString result) { std::move(cb).Run(result.Utf8()); },
          std::move(callback)));
}

void ChromeRenderFrameObserver::CreatePageStabilityMonitor(
    mojo::PendingReceiver<page_content_annotations::mojom::PageStabilityMonitor>
        monitor,
    const actor::TaskId& task_id,
    bool supports_paint_stability) {
  page_stability_monitor_ = std::make_unique<actor::PageStabilityMonitor>(
      *render_frame(), supports_paint_stability, task_id, *actor_journal_);
  page_stability_monitor_->Bind(std::move(monitor));
}

void ChromeRenderFrameObserver::SetClientSidePhishingDetection() {
#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
  phishing_classifier_ = safe_browsing::PhishingClassifierDelegate::Create(
      render_frame(), nullptr);
  phishing_image_embedder_ =
      safe_browsing::PhishingImageEmbedderDelegate::Create(render_frame());
#endif
}

void ChromeRenderFrameObserver::OnRenderFrameObserverRequest(
    mojo::PendingAssociatedReceiver<chrome::mojom::ChromeRenderFrame>
        receiver) {
  receivers_.Add(this, std::move(receiver));
}

bool ChromeRenderFrameObserver::ShouldCapturePageTextForTranslateOrPhishing(
    blink::WebMeaningfulLayout layout_type) const {
  WebLocalFrame* frame = render_frame()->GetWebFrame();
  if (!frame) {
    return false;
  }

  //////////////////////////////////////////////////////////////////////////////
  // Check |frame| for conditions shared by both Translate and Phishing.

  if (!render_frame()->IsMainFrame()) {
    return false;
  }

  // |kVisuallyNonEmpty| is ignored by Translate and Phishing.
  switch (layout_type) {
    case blink::WebMeaningfulLayout::kFinishedParsing:
    case blink::WebMeaningfulLayout::kFinishedLoading:
      break;
    case blink::WebMeaningfulLayout::kVisuallyNonEmpty:
    default:
      return false;
  }

  // Don't capture pages that have pending redirect or location change.
  if (frame->IsNavigationScheduledWithin(kLocationChangeInterval)) {
    return false;
  }

  // Don't capture pages that are in view source mode.
  if (frame->IsViewSourceModeEnabled()) {
    return false;
  }

  // Don't capture text of the error pages.
  WebDocumentLoader* document_loader = frame->GetDocumentLoader();
  if (document_loader && document_loader->HasUnreachableURL()) {
    return false;
  }

  // Don't capture pages that are being no-state prefetched.
  if (prerender::NoStatePrefetchHelper::IsPrefetching(render_frame())) {
    return false;
  }

  //////////////////////////////////////////////////////////////////////////////
  // Translate specific checks.
  bool should_capture_for_translate = !!translate_agent_;

  //////////////////////////////////////////////////////////////////////////////
  // Phishing specific checks.
  bool should_capture_for_phishing = false;

#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
  should_capture_for_phishing = phishing_classifier_->is_ready();
#endif

  return should_capture_for_translate || should_capture_for_phishing;
}

void ChromeRenderFrameObserver::CapturePageText(
    blink::WebMeaningfulLayout layout_type) {
  bool capture_for_translate_phishing =
      ShouldCapturePageTextForTranslateOrPhishing(layout_type);

  uint32_t capture_max_size =
      capture_for_translate_phishing ? kMaxIndexChars : 0;
  auto text_callback = page_text_agent_->MaybeRequestTextDumpOnLayoutEvent(
      layout_type, &capture_max_size);
  bool capture_for_opt_guide = !!text_callback;

  if (!capture_for_translate_phishing && !capture_for_opt_guide) {
    return;
  }
  DCHECK_GT(capture_max_size, 0U);

  scoped_refptr<const base::RefCountedString16> contents;

  {
    TRACE_EVENT0("renderer", "ChromeRenderFrameObserver::CapturePageText");
    contents = base::MakeRefCounted<const base::RefCountedString16>(
        WebFrameContentDumper::DumpFrameTreeAsText(
            render_frame()->GetWebFrame(), capture_max_size)
            .Utf16());
  }

  // Language detection should run only once. Parsing finishes before the page
  // loads, so attempt detection here first.
  if (translate_agent_ &&
      (layout_type == blink::WebMeaningfulLayout::kFinishedParsing)) {
    translate_agent_->PageCaptured(contents);
  }

  if (text_callback) {
    std::move(text_callback).Run(contents);
  }

#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
  // Will swap out the string.
  if (phishing_classifier_) {
    phishing_classifier_->PageCaptured(
        contents, layout_type == blink::WebMeaningfulLayout::kFinishedParsing);
  }
  if (phishing_image_embedder_) {
    phishing_image_embedder_->PageCaptured(
        layout_type == blink::WebMeaningfulLayout::kFinishedParsing);
  }
#endif
}

// static
bool ChromeRenderFrameObserver::NeedsDownscale(
    const gfx::Size& original_image_size,
    int32_t requested_image_min_area_pixels,
    const gfx::Size& requested_image_max_size) {
  if (original_image_size.GetArea() < requested_image_min_area_pixels)
    return false;
  if (original_image_size.width() <= requested_image_max_size.width() &&
      original_image_size.height() <= requested_image_max_size.height())
    return false;
  return true;
}

// static
SkBitmap ChromeRenderFrameObserver::Downscale(
    const SkBitmap& image,
    int requested_image_min_area_pixels,
    const gfx::Size& requested_image_max_size) {
  if (image.isNull())
    return SkBitmap();

  gfx::Size image_size(image.width(), image.height());

  if (!NeedsDownscale(image_size, requested_image_min_area_pixels,
                      requested_image_max_size))
    return image;

  gfx::SizeF scaled_size = gfx::SizeF(image_size);

  if (scaled_size.width() > requested_image_max_size.width()) {
    scaled_size.Scale(requested_image_max_size.width() / scaled_size.width());
  }

  if (scaled_size.height() > requested_image_max_size.height()) {
    scaled_size.Scale(requested_image_max_size.height() / scaled_size.height());
  }

  return skia::ImageOperations::Resize(image,
                                       skia::ImageOperations::RESIZE_GOOD,
                                       static_cast<int>(scaled_size.width()),
                                       static_cast<int>(scaled_size.height()));
}

// static
bool ChromeRenderFrameObserver::NeedsEncodeImage(
    const std::string& mime_type,
    chrome::mojom::ImageFormat image_format) {
  switch (image_format) {
    case chrome::mojom::ImageFormat::PNG:
      return mime_type != kImagePng;
    case chrome::mojom::ImageFormat::WEBP:
      return mime_type != kImageWebp;
    case chrome::mojom::ImageFormat::JPEG:
      return mime_type != kImageJpeg;
    case chrome::mojom::ImageFormat::ORIGINAL:
      return mime_type != kImageGif && mime_type != kImageJpeg &&
             mime_type != kImagePng;
  }

  // Should never hit this code since all cases were handled above.
  NOTREACHED();
}

// static
bool ChromeRenderFrameObserver::IsAnimatedWebp(
    const std::vector<uint8_t>& image_data) {
  WebPBitstreamFeatures features{};
  VP8StatusCode status =
      WebPGetFeatures(image_data.data(), image_data.size(), &features);
  return status == VP8_STATUS_OK && features.has_animation;
}
