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

#include "third_party/blink/renderer/core/inspector/inspector_page_agent.h"

#include <memory>

#include "build/build_config.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_timing.h"
#include "third_party/blink/renderer/core/dom/dom_implementation.h"
#include "third_party/blink/renderer/core/dom/user_gesture_indicator.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/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/report.h"
#include "third_party/blink/renderer/core/frame/reporting_context.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/test_report_body.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/html/imports/html_import_loader.h"
#include "third_party/blink/renderer/core/html/imports/html_imports_controller.h"
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
#include "third_party/blink/renderer/core/inspector/inspected_frames.h"
#include "third_party/blink/renderer/core/inspector/inspector_css_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h"
#include "third_party/blink/renderer/core/inspector/v8_inspector_string.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/loader/idleness_detector.h"
#include "third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h"
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
#include "third_party/blink/renderer/core/loader/scheduled_navigation.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "v8/include/v8-inspector.h"

namespace blink {

using protocol::Response;

namespace {

String ScheduledNavigationReasonToProtocol(ScheduledNavigation::Reason reason) {
  using ReasonEnum =
      protocol::Page::FrameScheduledNavigationNotification::ReasonEnum;
  switch (reason) {
    case ScheduledNavigation::Reason::kFormSubmissionGet:
      return ReasonEnum::FormSubmissionGet;
    case ScheduledNavigation::Reason::kFormSubmissionPost:
      return ReasonEnum::FormSubmissionPost;
    case ScheduledNavigation::Reason::kHttpHeaderRefresh:
      return ReasonEnum::HttpHeaderRefresh;
    case ScheduledNavigation::Reason::kFrameNavigation:
      return ReasonEnum::ScriptInitiated;
    case ScheduledNavigation::Reason::kMetaTagRefresh:
      return ReasonEnum::MetaTagRefresh;
    case ScheduledNavigation::Reason::kPageBlock:
      return ReasonEnum::PageBlockInterstitial;
    case ScheduledNavigation::Reason::kReload:
      return ReasonEnum::Reload;
    default:
      NOTREACHED();
  }
  return ReasonEnum::Reload;
}

Resource* CachedResource(LocalFrame* frame,
                         const KURL& url,
                         InspectorResourceContentLoader* loader) {
  Document* document = frame->GetDocument();
  if (!document)
    return nullptr;
  Resource* cached_resource = document->Fetcher()->CachedResource(url);
  if (!cached_resource) {
    HeapVector<Member<Document>> all_imports =
        InspectorPageAgent::ImportsForFrame(frame);
    for (Document* import : all_imports) {
      cached_resource = import->Fetcher()->CachedResource(url);
      if (cached_resource)
        break;
    }
  }
  if (!cached_resource) {
    cached_resource = GetMemoryCache()->ResourceForURL(
        url, document->Fetcher()->GetCacheIdentifier());
  }
  if (!cached_resource)
    cached_resource = loader->ResourceForURL(url);
  return cached_resource;
}

std::unique_ptr<protocol::Array<String>> GetEnabledWindowFeatures(
    const WebWindowFeatures& window_features) {
  std::unique_ptr<protocol::Array<String>> feature_strings =
      protocol::Array<String>::create();
  if (window_features.x_set) {
    feature_strings->addItem(
        String::Format("left=%d", static_cast<int>(window_features.x)));
  }
  if (window_features.y_set) {
    feature_strings->addItem(
        String::Format("top=%d", static_cast<int>(window_features.y)));
  }
  if (window_features.width_set) {
    feature_strings->addItem(
        String::Format("width=%d", static_cast<int>(window_features.width)));
  }
  if (window_features.height_set) {
    feature_strings->addItem(
        String::Format("height=%d", static_cast<int>(window_features.height)));
  }
  if (window_features.menu_bar_visible)
    feature_strings->addItem("menubar");
  if (window_features.tool_bar_visible)
    feature_strings->addItem("toolbar");
  if (window_features.status_bar_visible)
    feature_strings->addItem("status");
  if (window_features.scrollbars_visible)
    feature_strings->addItem("scrollbars");
  if (window_features.resizable)
    feature_strings->addItem("resizable");
  if (window_features.noopener)
    feature_strings->addItem("noopener");
  if (window_features.background)
    feature_strings->addItem("background");
  if (window_features.persistent)
    feature_strings->addItem("persistent");
  return feature_strings;
}

}  // namespace

static bool PrepareResourceBuffer(Resource* cached_resource,
                                  bool* has_zero_size) {
  if (!cached_resource)
    return false;

  if (cached_resource->GetDataBufferingPolicy() == kDoNotBufferData)
    return false;

  // Zero-sized resources don't have data at all -- so fake the empty buffer,
  // instead of indicating error by returning 0.
  if (!cached_resource->EncodedSize()) {
    *has_zero_size = true;
    return true;
  }

  *has_zero_size = false;
  return true;
}

static bool HasTextContent(Resource* cached_resource) {
  ResourceType type = cached_resource->GetType();
  return type == ResourceType::kCSSStyleSheet ||
         type == ResourceType::kXSLStyleSheet ||
         type == ResourceType::kScript || type == ResourceType::kRaw ||
         type == ResourceType::kImportResource ||
         type == ResourceType::kMainResource;
}

static std::unique_ptr<TextResourceDecoder> CreateResourceTextDecoder(
    const String& mime_type,
    const String& text_encoding_name) {
  if (!text_encoding_name.IsEmpty()) {
    return TextResourceDecoder::Create(TextResourceDecoderOptions(
        TextResourceDecoderOptions::kPlainTextContent,
        WTF::TextEncoding(text_encoding_name)));
  }
  if (DOMImplementation::IsXMLMIMEType(mime_type)) {
    TextResourceDecoderOptions options(TextResourceDecoderOptions::kXMLContent);
    options.SetUseLenientXMLDecoding();
    return TextResourceDecoder::Create(options);
  }
  if (DeprecatedEqualIgnoringCase(mime_type, "text/html")) {
    return TextResourceDecoder::Create(TextResourceDecoderOptions(
        TextResourceDecoderOptions::kHTMLContent, UTF8Encoding()));
  }
  if (MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type) ||
      DOMImplementation::IsJSONMIMEType(mime_type)) {
    return TextResourceDecoder::Create(TextResourceDecoderOptions(
        TextResourceDecoderOptions::kPlainTextContent, UTF8Encoding()));
  }
  if (DOMImplementation::IsTextMIMEType(mime_type)) {
    return TextResourceDecoder::Create(TextResourceDecoderOptions(
        TextResourceDecoderOptions::kPlainTextContent,
        WTF::TextEncoding("ISO-8859-1")));
  }
  return std::unique_ptr<TextResourceDecoder>();
}

static void MaybeEncodeTextContent(const String& text_content,
                                   const char* buffer_data,
                                   size_t buffer_size,
                                   String* result,
                                   bool* base64_encoded) {
  if (!text_content.IsNull() &&
      !text_content.Utf8(WTF::kStrictUTF8Conversion).IsNull()) {
    *result = text_content;
    *base64_encoded = false;
  } else if (buffer_data) {
    *result = Base64Encode(buffer_data, buffer_size);
    *base64_encoded = true;
  } else if (text_content.IsNull()) {
    *result = "";
    *base64_encoded = false;
  } else {
    DCHECK(!text_content.Is8Bit());
    *result = Base64Encode(text_content.Utf8(WTF::kLenientUTF8Conversion));
    *base64_encoded = true;
  }
}

static void MaybeEncodeTextContent(const String& text_content,
                                   scoped_refptr<const SharedBuffer> buffer,
                                   String* result,
                                   bool* base64_encoded) {
  if (!buffer) {
    return MaybeEncodeTextContent(text_content, nullptr, 0, result,
                                  base64_encoded);
  }

  const SharedBuffer::DeprecatedFlatData flat_buffer(std::move(buffer));
  return MaybeEncodeTextContent(text_content, flat_buffer.Data(),
                                flat_buffer.size(), result, base64_encoded);
}

// static
KURL InspectorPageAgent::UrlWithoutFragment(const KURL& url) {
  KURL result = url;
  result.RemoveFragmentIdentifier();
  return result;
}

// static
bool InspectorPageAgent::SharedBufferContent(
    scoped_refptr<const SharedBuffer> buffer,
    const String& mime_type,
    const String& text_encoding_name,
    String* result,
    bool* base64_encoded) {
  if (!buffer)
    return false;

  String text_content;
  std::unique_ptr<TextResourceDecoder> decoder =
      CreateResourceTextDecoder(mime_type, text_encoding_name);
  WTF::TextEncoding encoding(text_encoding_name);

  const SharedBuffer::DeprecatedFlatData flat_buffer(std::move(buffer));
  if (decoder) {
    text_content = decoder->Decode(flat_buffer.Data(), flat_buffer.size());
    text_content = text_content + decoder->Flush();
  } else if (encoding.IsValid()) {
    text_content = encoding.Decode(flat_buffer.Data(), flat_buffer.size());
  }

  MaybeEncodeTextContent(text_content, flat_buffer.Data(), flat_buffer.size(),
                         result, base64_encoded);
  return true;
}

// static
bool InspectorPageAgent::CachedResourceContent(Resource* cached_resource,
                                               String* result,
                                               bool* base64_encoded) {
  bool has_zero_size;
  if (!PrepareResourceBuffer(cached_resource, &has_zero_size))
    return false;

  if (!HasTextContent(cached_resource)) {
    scoped_refptr<const SharedBuffer> buffer =
        has_zero_size ? SharedBuffer::Create()
                      : cached_resource->ResourceBuffer();
    if (!buffer)
      return false;

    const SharedBuffer::DeprecatedFlatData flat_buffer(std::move(buffer));
    *result = Base64Encode(flat_buffer.Data(), flat_buffer.size());
    *base64_encoded = true;
    return true;
  }

  if (has_zero_size) {
    *result = "";
    *base64_encoded = false;
    return true;
  }

  DCHECK(cached_resource);
  switch (cached_resource->GetType()) {
    case blink::ResourceType::kCSSStyleSheet:
      MaybeEncodeTextContent(
          ToCSSStyleSheetResource(cached_resource)
              ->SheetText(nullptr, CSSStyleSheetResource::MIMETypeCheck::kLax),
          cached_resource->ResourceBuffer(), result, base64_encoded);
      return true;
    case blink::ResourceType::kScript:
      MaybeEncodeTextContent(
          cached_resource->ResourceBuffer()
              ? ToScriptResource(cached_resource)->DecodedText()
              : ToScriptResource(cached_resource)->SourceText().ToString(),
          cached_resource->ResourceBuffer(), result, base64_encoded);
      return true;
    default:
      String text_encoding_name =
          cached_resource->GetResponse().TextEncodingName();
      if (text_encoding_name.IsEmpty() &&
          cached_resource->GetType() != blink::ResourceType::kRaw)
        text_encoding_name = "WinLatin1";
      return InspectorPageAgent::SharedBufferContent(
          cached_resource->ResourceBuffer(),
          cached_resource->GetResponse().MimeType(), text_encoding_name, result,
          base64_encoded);
  }
}

InspectorPageAgent* InspectorPageAgent::Create(
    InspectedFrames* inspected_frames,
    Client* client,
    InspectorResourceContentLoader* resource_content_loader,
    v8_inspector::V8InspectorSession* v8_session) {
  return new InspectorPageAgent(inspected_frames, client,
                                resource_content_loader, v8_session);
}

String InspectorPageAgent::ResourceTypeJson(
    InspectorPageAgent::ResourceType resource_type) {
  switch (resource_type) {
    case kDocumentResource:
      return protocol::Network::ResourceTypeEnum::Document;
    case kFontResource:
      return protocol::Network::ResourceTypeEnum::Font;
    case kImageResource:
      return protocol::Network::ResourceTypeEnum::Image;
    case kMediaResource:
      return protocol::Network::ResourceTypeEnum::Media;
    case kScriptResource:
      return protocol::Network::ResourceTypeEnum::Script;
    case kStylesheetResource:
      return protocol::Network::ResourceTypeEnum::Stylesheet;
    case kTextTrackResource:
      return protocol::Network::ResourceTypeEnum::TextTrack;
    case kXHRResource:
      return protocol::Network::ResourceTypeEnum::XHR;
    case kFetchResource:
      return protocol::Network::ResourceTypeEnum::Fetch;
    case kEventSourceResource:
      return protocol::Network::ResourceTypeEnum::EventSource;
    case kWebSocketResource:
      return protocol::Network::ResourceTypeEnum::WebSocket;
    case kManifestResource:
      return protocol::Network::ResourceTypeEnum::Manifest;
    case kSignedExchangeResource:
      return protocol::Network::ResourceTypeEnum::SignedExchange;
    case kOtherResource:
      return protocol::Network::ResourceTypeEnum::Other;
  }
  return protocol::Network::ResourceTypeEnum::Other;
}

InspectorPageAgent::ResourceType InspectorPageAgent::ToResourceType(
    const blink::ResourceType resource_type) {
  switch (resource_type) {
    case blink::ResourceType::kImage:
      return InspectorPageAgent::kImageResource;
    case blink::ResourceType::kFont:
      return InspectorPageAgent::kFontResource;
    case blink::ResourceType::kAudio:
    case blink::ResourceType::kVideo:
      return InspectorPageAgent::kMediaResource;
    case blink::ResourceType::kManifest:
      return InspectorPageAgent::kManifestResource;
    case blink::ResourceType::kTextTrack:
      return InspectorPageAgent::kTextTrackResource;
    case blink::ResourceType::kCSSStyleSheet:
    // Fall through.
    case blink::ResourceType::kXSLStyleSheet:
      return InspectorPageAgent::kStylesheetResource;
    case blink::ResourceType::kScript:
      return InspectorPageAgent::kScriptResource;
    case blink::ResourceType::kImportResource:
    // Fall through.
    case blink::ResourceType::kMainResource:
      return InspectorPageAgent::kDocumentResource;
    default:
      break;
  }
  return InspectorPageAgent::kOtherResource;
}

String InspectorPageAgent::CachedResourceTypeJson(
    const Resource& cached_resource) {
  return ResourceTypeJson(ToResourceType(cached_resource.GetType()));
}

InspectorPageAgent::InspectorPageAgent(
    InspectedFrames* inspected_frames,
    Client* client,
    InspectorResourceContentLoader* resource_content_loader,
    v8_inspector::V8InspectorSession* v8_session)
    : inspected_frames_(inspected_frames),
      v8_session_(v8_session),
      client_(client),
      reloading_(false),
      inspector_resource_content_loader_(resource_content_loader),
      resource_content_loader_client_id_(
          resource_content_loader->CreateClientId()),
      enabled_(&agent_state_, /*default_value=*/false),
      screencast_enabled_(&agent_state_, /*default_value=*/false),
      lifecycle_events_enabled_(&agent_state_, /*default_value=*/false),
      bypass_csp_enabled_(&agent_state_, /*default_value=*/false),
      scripts_to_evaluate_on_load_(&agent_state_,
                                   /*default_value=*/WTF::String()),
      standard_font_family_(&agent_state_, /*default_value=*/WTF::String()),
      fixed_font_family_(&agent_state_, /*default_value=*/WTF::String()),
      serif_font_family_(&agent_state_, /*default_value=*/WTF::String()),
      sans_serif_font_family_(&agent_state_, /*default_value=*/WTF::String()),
      cursive_font_family_(&agent_state_, /*default_value=*/WTF::String()),
      fantasy_font_family_(&agent_state_, /*default_value=*/WTF::String()),
      pictograph_font_family_(&agent_state_, /*default_value=*/WTF::String()),
      standard_font_size_(&agent_state_, /*default_value=*/0),
      fixed_font_size_(&agent_state_, /*default_value=*/0),
      produce_compilation_cache_(&agent_state_, /*default_value=*/false) {}

void InspectorPageAgent::Restore() {
  if (enabled_.Get())
    enable();
  if (bypass_csp_enabled_.Get())
    setBypassCSP(true);
  // Re-apply generic fonts overrides.
  bool notifyGenericFontFamilyChange = false;
  LocalFrame* frame = inspected_frames_->Root();
  auto* settings = frame->GetSettings();
  if (settings) {
    auto& family_settings = settings->GetGenericFontFamilySettings();
    if (!standard_font_family_.Get().IsNull()) {
      family_settings.UpdateStandard(AtomicString(standard_font_family_.Get()));
      notifyGenericFontFamilyChange = true;
    }
    if (!fixed_font_family_.Get().IsNull()) {
      family_settings.UpdateFixed(AtomicString(fixed_font_family_.Get()));
      notifyGenericFontFamilyChange = true;
    }
    if (!serif_font_family_.Get().IsNull()) {
      family_settings.UpdateSerif(AtomicString(serif_font_family_.Get()));
      notifyGenericFontFamilyChange = true;
    }
    if (!sans_serif_font_family_.Get().IsNull()) {
      family_settings.UpdateSansSerif(
          AtomicString(sans_serif_font_family_.Get()));
      notifyGenericFontFamilyChange = true;
    }
    if (!cursive_font_family_.Get().IsNull()) {
      family_settings.UpdateCursive(AtomicString(cursive_font_family_.Get()));
      notifyGenericFontFamilyChange = true;
    }
    if (!fantasy_font_family_.Get().IsNull()) {
      family_settings.UpdateFantasy(AtomicString(fantasy_font_family_.Get()));
      notifyGenericFontFamilyChange = true;
    }
    if (!pictograph_font_family_.Get().IsNull()) {
      family_settings.UpdatePictograph(
          AtomicString(pictograph_font_family_.Get()));
      notifyGenericFontFamilyChange = true;
    }
    if (notifyGenericFontFamilyChange)
      settings->NotifyGenericFontFamilyChange();
  }

  // Re-apply default font size overrides.
  if (settings) {
    if (standard_font_size_.Get() != 0)
      settings->SetDefaultFontSize(standard_font_size_.Get());
    if (fixed_font_size_.Get() != 0)
      settings->SetDefaultFixedFontSize(fixed_font_size_.Get());
  }
}

Response InspectorPageAgent::enable() {
  enabled_.Set(true);
  instrumenting_agents_->addInspectorPageAgent(this);
  return Response::OK();
}

Response InspectorPageAgent::disable() {
  agent_state_.ClearAllFields();
  script_to_evaluate_on_load_once_ = String();
  pending_script_to_evaluate_on_load_once_ = String();
  instrumenting_agents_->removeInspectorPageAgent(this);
  inspector_resource_content_loader_->Cancel(
      resource_content_loader_client_id_);

  stopScreencast();

  FinishReload();
  return Response::OK();
}

Response InspectorPageAgent::addScriptToEvaluateOnLoad(const String& source,
                                                       String* identifier) {
  std::vector<WTF::String> keys = scripts_to_evaluate_on_load_.Keys();
  auto result = std::max_element(
      keys.begin(), keys.end(), [](const WTF::String& a, const WTF::String& b) {
        return Decimal::FromString(a) < Decimal::FromString(b);
      });
  if (result == keys.end()) {
    scripts_to_evaluate_on_load_.Set(String::Number(1), source);
  } else {
    scripts_to_evaluate_on_load_.Set(
        String::Number(Decimal::FromString(*result).ToDouble() + 1), source);
  }
  return Response::OK();
}

Response InspectorPageAgent::removeScriptToEvaluateOnLoad(
    const String& identifier) {
  if (scripts_to_evaluate_on_load_.Get(identifier).IsNull())
    return Response::Error("Script not found");
  scripts_to_evaluate_on_load_.Clear(identifier);
  return Response::OK();
}

Response InspectorPageAgent::addScriptToEvaluateOnNewDocument(
    const String& source,
    String* identifier) {
  return addScriptToEvaluateOnLoad(source, identifier);
}

Response InspectorPageAgent::removeScriptToEvaluateOnNewDocument(
    const String& identifier) {
  return removeScriptToEvaluateOnLoad(identifier);
}

Response InspectorPageAgent::setLifecycleEventsEnabled(bool enabled) {
  lifecycle_events_enabled_.Set(enabled);
  if (!enabled)
    return Response::OK();

  for (LocalFrame* frame : *inspected_frames_) {
    Document* document = frame->GetDocument();
    DocumentLoader* loader = frame->Loader().GetDocumentLoader();
    if (!document || !loader)
      continue;

    DocumentLoadTiming& timing = loader->GetTiming();
    TimeTicks commit_timestamp = timing.ResponseEnd();
    if (!commit_timestamp.is_null()) {
      LifecycleEvent(frame, loader, "commit",
                     TimeTicksInSeconds(commit_timestamp));
    }

    TimeTicks domcontentloaded_timestamp =
        document->GetTiming().DomContentLoadedEventEnd();
    if (!domcontentloaded_timestamp.is_null()) {
      LifecycleEvent(frame, loader, "DOMContentLoaded",
                     TimeTicksInSeconds(domcontentloaded_timestamp));
    }

    TimeTicks load_timestamp = timing.LoadEventEnd();
    if (!load_timestamp.is_null()) {
      LifecycleEvent(frame, loader, "load", TimeTicksInSeconds(load_timestamp));
    }

    IdlenessDetector* idleness_detector = frame->GetIdlenessDetector();
    TimeTicks network_almost_idle_timestamp =
        idleness_detector->GetNetworkAlmostIdleTime();
    if (!network_almost_idle_timestamp.is_null()) {
      LifecycleEvent(frame, loader, "networkAlmostIdle",
                     TimeTicksInSeconds(network_almost_idle_timestamp));
    }
    TimeTicks network_idle_timestamp = idleness_detector->GetNetworkIdleTime();
    if (!network_idle_timestamp.is_null()) {
      LifecycleEvent(frame, loader, "networkIdle",
                     TimeTicksInSeconds(network_idle_timestamp));
    }
  }

  return Response::OK();
}

Response InspectorPageAgent::setAdBlockingEnabled(bool enable) {
  return Response::OK();
}

Response InspectorPageAgent::reload(
    Maybe<bool> optional_bypass_cache,
    Maybe<String> optional_script_to_evaluate_on_load) {
  pending_script_to_evaluate_on_load_once_ =
      optional_script_to_evaluate_on_load.fromMaybe("");
  v8_session_->setSkipAllPauses(true);
  reloading_ = true;
  return Response::OK();
}

Response InspectorPageAgent::stopLoading() {
  return Response::OK();
}

static void CachedResourcesForDocument(Document* document,
                                       HeapVector<Member<Resource>>& result,
                                       bool skip_xhrs) {
  const ResourceFetcher::DocumentResourceMap& all_resources =
      document->Fetcher()->AllResources();
  for (const auto& resource : all_resources) {
    Resource* cached_resource = resource.value.Get();
    if (!cached_resource)
      continue;

    // Skip images that were not auto loaded (images disabled in the user
    // agent), fonts that were referenced in CSS but never used/downloaded, etc.
    if (cached_resource->StillNeedsLoad())
      continue;
    if (cached_resource->GetType() == ResourceType::kRaw && skip_xhrs)
      continue;
    result.push_back(cached_resource);
  }
}

// static
HeapVector<Member<Document>> InspectorPageAgent::ImportsForFrame(
    LocalFrame* frame) {
  HeapVector<Member<Document>> result;
  Document* root_document = frame->GetDocument();

  if (HTMLImportsController* controller = root_document->ImportsController()) {
    for (size_t i = 0; i < controller->LoaderCount(); ++i) {
      if (Document* document = controller->LoaderAt(i)->GetDocument())
        result.push_back(document);
    }
  }

  return result;
}

static HeapVector<Member<Resource>> CachedResourcesForFrame(LocalFrame* frame,
                                                            bool skip_xhrs) {
  HeapVector<Member<Resource>> result;
  Document* root_document = frame->GetDocument();
  HeapVector<Member<Document>> loaders =
      InspectorPageAgent::ImportsForFrame(frame);

  CachedResourcesForDocument(root_document, result, skip_xhrs);
  for (size_t i = 0; i < loaders.size(); ++i)
    CachedResourcesForDocument(loaders[i], result, skip_xhrs);

  return result;
}

Response InspectorPageAgent::getResourceTree(
    std::unique_ptr<protocol::Page::FrameResourceTree>* object) {
  *object = BuildObjectForResourceTree(inspected_frames_->Root());
  return Response::OK();
}

Response InspectorPageAgent::getFrameTree(
    std::unique_ptr<protocol::Page::FrameTree>* object) {
  *object = BuildObjectForFrameTree(inspected_frames_->Root());
  return Response::OK();
}

void InspectorPageAgent::FinishReload() {
  if (!reloading_)
    return;
  reloading_ = false;
  v8_session_->setSkipAllPauses(false);
}

void InspectorPageAgent::GetResourceContentAfterResourcesContentLoaded(
    const String& frame_id,
    const String& url,
    std::unique_ptr<GetResourceContentCallback> callback) {
  LocalFrame* frame =
      IdentifiersFactory::FrameById(inspected_frames_, frame_id);
  if (!frame) {
    callback->sendFailure(Response::Error("No frame for given id found"));
    return;
  }
  String content;
  bool base64_encoded;
  if (InspectorPageAgent::CachedResourceContent(
          CachedResource(frame, KURL(url), inspector_resource_content_loader_),
          &content, &base64_encoded))
    callback->sendSuccess(content, base64_encoded);
  else
    callback->sendFailure(Response::Error("No resource with given URL found"));
}

void InspectorPageAgent::getResourceContent(
    const String& frame_id,
    const String& url,
    std::unique_ptr<GetResourceContentCallback> callback) {
  if (!enabled_.Get()) {
    callback->sendFailure(Response::Error("Agent is not enabled."));
    return;
  }
  inspector_resource_content_loader_->EnsureResourcesContentLoaded(
      resource_content_loader_client_id_,
      WTF::Bind(
          &InspectorPageAgent::GetResourceContentAfterResourcesContentLoaded,
          WrapPersistent(this), frame_id, url,
          WTF::Passed(std::move(callback))));
}

void InspectorPageAgent::SearchContentAfterResourcesContentLoaded(
    const String& frame_id,
    const String& url,
    const String& query,
    bool case_sensitive,
    bool is_regex,
    std::unique_ptr<SearchInResourceCallback> callback) {
  LocalFrame* frame =
      IdentifiersFactory::FrameById(inspected_frames_, frame_id);
  if (!frame) {
    callback->sendFailure(Response::Error("No frame for given id found"));
    return;
  }
  String content;
  bool base64_encoded;
  if (!InspectorPageAgent::CachedResourceContent(
          CachedResource(frame, KURL(url), inspector_resource_content_loader_),
          &content, &base64_encoded)) {
    callback->sendFailure(Response::Error("No resource with given URL found"));
    return;
  }

  auto matches = v8_session_->searchInTextByLines(
      ToV8InspectorStringView(content), ToV8InspectorStringView(query),
      case_sensitive, is_regex);
  auto results = protocol::Array<
      v8_inspector::protocol::Debugger::API::SearchMatch>::create();
  for (size_t i = 0; i < matches.size(); ++i)
    results->addItem(std::move(matches[i]));
  callback->sendSuccess(std::move(results));
}

void InspectorPageAgent::searchInResource(
    const String& frame_id,
    const String& url,
    const String& query,
    Maybe<bool> optional_case_sensitive,
    Maybe<bool> optional_is_regex,
    std::unique_ptr<SearchInResourceCallback> callback) {
  if (!enabled_.Get()) {
    callback->sendFailure(Response::Error("Agent is not enabled."));
    return;
  }
  inspector_resource_content_loader_->EnsureResourcesContentLoaded(
      resource_content_loader_client_id_,
      WTF::Bind(&InspectorPageAgent::SearchContentAfterResourcesContentLoaded,
                WrapPersistent(this), frame_id, url, query,
                optional_case_sensitive.fromMaybe(false),
                optional_is_regex.fromMaybe(false),
                WTF::Passed(std::move(callback))));
}

Response InspectorPageAgent::setBypassCSP(bool enabled) {
  LocalFrame* frame = inspected_frames_->Root();
  frame->GetSettings()->SetBypassCSP(enabled);
  bypass_csp_enabled_.Set(enabled);
  return Response::OK();
}

Response InspectorPageAgent::setDocumentContent(const String& frame_id,
                                                const String& html) {
  LocalFrame* frame =
      IdentifiersFactory::FrameById(inspected_frames_, frame_id);
  if (!frame)
    return Response::Error("No frame for given id found");

  Document* document = frame->GetDocument();
  if (!document)
    return Response::Error("No Document instance to set HTML for");
  document->SetContent(html);
  return Response::OK();
}

void InspectorPageAgent::DidNavigateWithinDocument(LocalFrame* frame) {
  Document* document = frame->GetDocument();
  if (document) {
    return GetFrontend()->navigatedWithinDocument(
        IdentifiersFactory::FrameId(frame), document->Url());
  }
}

void InspectorPageAgent::DidClearDocumentOfWindowObject(LocalFrame* frame) {
  if (!GetFrontend())
    return;
  std::vector<WTF::String> keys = scripts_to_evaluate_on_load_.Keys();
  std::sort(keys.begin(), keys.end(),
            [](const WTF::String& a, const WTF::String& b) {
              return Decimal::FromString(a) < Decimal::FromString(b);
            });

  for (const WTF::String& key : keys) {
    const WTF::String& script = scripts_to_evaluate_on_load_.Get(key);
    frame->GetScriptController().ExecuteScriptInMainWorld(script);
  }
  if (!script_to_evaluate_on_load_once_.IsEmpty()) {
    frame->GetScriptController().ExecuteScriptInMainWorld(
        script_to_evaluate_on_load_once_);
  }
}

void InspectorPageAgent::DOMContentLoadedEventFired(LocalFrame* frame) {
  double timestamp = CurrentTimeTicksInSeconds();
  if (frame == inspected_frames_->Root())
    GetFrontend()->domContentEventFired(timestamp);
  DocumentLoader* loader = frame->Loader().GetDocumentLoader();
  LifecycleEvent(frame, loader, "DOMContentLoaded", timestamp);
}

void InspectorPageAgent::LoadEventFired(LocalFrame* frame) {
  double timestamp = CurrentTimeTicksInSeconds();
  if (frame == inspected_frames_->Root())
    GetFrontend()->loadEventFired(timestamp);
  DocumentLoader* loader = frame->Loader().GetDocumentLoader();
  LifecycleEvent(frame, loader, "load", timestamp);
}

void InspectorPageAgent::WillCommitLoad(LocalFrame*, DocumentLoader* loader) {
  if (loader->GetFrame() == inspected_frames_->Root()) {
    FinishReload();
    script_to_evaluate_on_load_once_ = pending_script_to_evaluate_on_load_once_;
    pending_script_to_evaluate_on_load_once_ = String();
  }
  GetFrontend()->frameNavigated(BuildObjectForFrame(loader->GetFrame()));
}

void InspectorPageAgent::FrameAttachedToParent(LocalFrame* frame) {
  Frame* parent_frame = frame->Tree().Parent();
  std::unique_ptr<SourceLocation> location =
      SourceLocation::CaptureWithFullStackTrace();
  GetFrontend()->frameAttached(
      IdentifiersFactory::FrameId(frame),
      IdentifiersFactory::FrameId(parent_frame),
      location ? location->BuildInspectorObject() : nullptr);
  // Some network events referencing this frame will be reported from the
  // browser, so make sure to deliver FrameAttached without buffering,
  // so it gets to the front-end first.
  GetFrontend()->flush();
}

void InspectorPageAgent::FrameDetachedFromParent(LocalFrame* frame) {
  GetFrontend()->frameDetached(IdentifiersFactory::FrameId(frame));
}

bool InspectorPageAgent::ScreencastEnabled() {
  return enabled_.Get() && screencast_enabled_.Get();
}

void InspectorPageAgent::FrameStartedLoading(LocalFrame* frame) {
  GetFrontend()->frameStartedLoading(IdentifiersFactory::FrameId(frame));
}

void InspectorPageAgent::FrameStoppedLoading(LocalFrame* frame) {
  GetFrontend()->frameStoppedLoading(IdentifiersFactory::FrameId(frame));
}

void InspectorPageAgent::FrameScheduledNavigation(
    LocalFrame* frame,
    ScheduledNavigation* scheduled_navigation) {
  GetFrontend()->frameScheduledNavigation(
      IdentifiersFactory::FrameId(frame), scheduled_navigation->Delay(),
      ScheduledNavigationReasonToProtocol(scheduled_navigation->GetReason()),
      scheduled_navigation->Url().GetString());
}

void InspectorPageAgent::FrameClearedScheduledNavigation(LocalFrame* frame) {
  GetFrontend()->frameClearedScheduledNavigation(
      IdentifiersFactory::FrameId(frame));
}

void InspectorPageAgent::WillRunJavaScriptDialog() {
  GetFrontend()->flush();
}

void InspectorPageAgent::DidRunJavaScriptDialog() {
  GetFrontend()->flush();
}

void InspectorPageAgent::DidResizeMainFrame() {
  if (!inspected_frames_->Root()->IsMainFrame())
    return;
#if !defined(OS_ANDROID)
  PageLayoutInvalidated(true);
#endif
  GetFrontend()->frameResized();
}

void InspectorPageAgent::DidChangeViewport() {
  PageLayoutInvalidated(false);
}

void InspectorPageAgent::LifecycleEvent(LocalFrame* frame,
                                        DocumentLoader* loader,
                                        const char* name,
                                        double timestamp) {
  if (!loader || !lifecycle_events_enabled_.Get())
    return;
  GetFrontend()->lifecycleEvent(IdentifiersFactory::FrameId(frame),
                                IdentifiersFactory::LoaderId(loader), name,
                                timestamp);
}

void InspectorPageAgent::PaintTiming(Document* document,
                                     const char* name,
                                     double timestamp) {
  LocalFrame* frame = document->GetFrame();
  DocumentLoader* loader = frame->Loader().GetDocumentLoader();
  LifecycleEvent(frame, loader, name, timestamp);
}

void InspectorPageAgent::Will(const probe::UpdateLayout&) {}

void InspectorPageAgent::Did(const probe::UpdateLayout&) {
  PageLayoutInvalidated(false);
}

void InspectorPageAgent::Will(const probe::RecalculateStyle&) {}

void InspectorPageAgent::Did(const probe::RecalculateStyle&) {
  PageLayoutInvalidated(false);
}

void InspectorPageAgent::PageLayoutInvalidated(bool resized) {
  if (enabled_.Get() && client_)
    client_->PageLayoutInvalidated(resized);
}

void InspectorPageAgent::WindowOpen(Document* document,
                                    const String& url,
                                    const AtomicString& window_name,
                                    const WebWindowFeatures& window_features,
                                    bool user_gesture) {
  KURL completed_url = url.IsEmpty() ? BlankURL() : document->CompleteURL(url);
  GetFrontend()->windowOpen(completed_url.GetString(), window_name,
                            GetEnabledWindowFeatures(window_features),
                            user_gesture);
}

std::unique_ptr<protocol::Page::Frame> InspectorPageAgent::BuildObjectForFrame(
    LocalFrame* frame) {
  DocumentLoader* loader = frame->Loader().GetDocumentLoader();
  KURL url = loader->GetRequest().Url();
  std::unique_ptr<protocol::Page::Frame> frame_object =
      protocol::Page::Frame::create()
          .setId(IdentifiersFactory::FrameId(frame))
          .setLoaderId(IdentifiersFactory::LoaderId(loader))
          .setUrl(UrlWithoutFragment(url).GetString())
          .setMimeType(frame->Loader().GetDocumentLoader()->MimeType())
          .setSecurityOrigin(SecurityOrigin::Create(url)->ToRawString())
          .build();
  Frame* parent_frame = frame->Tree().Parent();
  if (parent_frame) {
    frame_object->setParentId(IdentifiersFactory::FrameId(parent_frame));
    AtomicString name = frame->Tree().GetName();
    if (name.IsEmpty() && frame->DeprecatedLocalOwner())
      name = frame->DeprecatedLocalOwner()->getAttribute(HTMLNames::idAttr);
    frame_object->setName(name);
  }
  if (loader && !loader->UnreachableURL().IsEmpty())
    frame_object->setUnreachableUrl(loader->UnreachableURL().GetString());
  return frame_object;
}

std::unique_ptr<protocol::Page::FrameTree>
InspectorPageAgent::BuildObjectForFrameTree(LocalFrame* frame) {
  std::unique_ptr<protocol::Page::FrameTree> result =
      protocol::Page::FrameTree::create()
          .setFrame(BuildObjectForFrame(frame))
          .build();

  std::unique_ptr<protocol::Array<protocol::Page::FrameTree>> children_array;
  for (Frame* child = frame->Tree().FirstChild(); child;
       child = child->Tree().NextSibling()) {
    if (!child->IsLocalFrame())
      continue;
    if (!children_array)
      children_array = protocol::Array<protocol::Page::FrameTree>::create();
    children_array->addItem(BuildObjectForFrameTree(ToLocalFrame(child)));
  }
  result->setChildFrames(std::move(children_array));
  return result;
}

std::unique_ptr<protocol::Page::FrameResourceTree>
InspectorPageAgent::BuildObjectForResourceTree(LocalFrame* frame) {
  std::unique_ptr<protocol::Page::Frame> frame_object =
      BuildObjectForFrame(frame);
  std::unique_ptr<protocol::Array<protocol::Page::FrameResource>> subresources =
      protocol::Array<protocol::Page::FrameResource>::create();

  HeapVector<Member<Resource>> all_resources =
      CachedResourcesForFrame(frame, true);
  for (Resource* cached_resource : all_resources) {
    std::unique_ptr<protocol::Page::FrameResource> resource_object =
        protocol::Page::FrameResource::create()
            .setUrl(UrlWithoutFragment(cached_resource->Url()).GetString())
            .setType(CachedResourceTypeJson(*cached_resource))
            .setMimeType(cached_resource->GetResponse().MimeType())
            .setContentSize(cached_resource->GetResponse().DecodedBodyLength())
            .build();
    double last_modified = cached_resource->GetResponse().LastModified();
    if (!std::isnan(last_modified))
      resource_object->setLastModified(last_modified);
    if (cached_resource->WasCanceled())
      resource_object->setCanceled(true);
    else if (cached_resource->GetStatus() == ResourceStatus::kLoadError)
      resource_object->setFailed(true);
    subresources->addItem(std::move(resource_object));
  }

  HeapVector<Member<Document>> all_imports =
      InspectorPageAgent::ImportsForFrame(frame);
  for (Document* import : all_imports) {
    std::unique_ptr<protocol::Page::FrameResource> resource_object =
        protocol::Page::FrameResource::create()
            .setUrl(UrlWithoutFragment(import->Url()).GetString())
            .setType(ResourceTypeJson(InspectorPageAgent::kDocumentResource))
            .setMimeType(import->SuggestedMIMEType())
            .build();
    subresources->addItem(std::move(resource_object));
  }

  std::unique_ptr<protocol::Page::FrameResourceTree> result =
      protocol::Page::FrameResourceTree::create()
          .setFrame(std::move(frame_object))
          .setResources(std::move(subresources))
          .build();

  std::unique_ptr<protocol::Array<protocol::Page::FrameResourceTree>>
      children_array;
  for (Frame* child = frame->Tree().FirstChild(); child;
       child = child->Tree().NextSibling()) {
    if (!child->IsLocalFrame())
      continue;
    if (!children_array)
      children_array =
          protocol::Array<protocol::Page::FrameResourceTree>::create();
    children_array->addItem(BuildObjectForResourceTree(ToLocalFrame(child)));
  }
  result->setChildFrames(std::move(children_array));
  return result;
}

Response InspectorPageAgent::startScreencast(Maybe<String> format,
                                             Maybe<int> quality,
                                             Maybe<int> max_width,
                                             Maybe<int> max_height,
                                             Maybe<int> every_nth_frame) {
  screencast_enabled_.Set(true);
  return Response::OK();
}

Response InspectorPageAgent::stopScreencast() {
  screencast_enabled_.Set(false);
  return Response::OK();
}

Response InspectorPageAgent::getLayoutMetrics(
    std::unique_ptr<protocol::Page::LayoutViewport>* out_layout_viewport,
    std::unique_ptr<protocol::Page::VisualViewport>* out_visual_viewport,
    std::unique_ptr<protocol::DOM::Rect>* out_content_size) {
  LocalFrame* main_frame = inspected_frames_->Root();
  VisualViewport& visual_viewport = main_frame->GetPage()->GetVisualViewport();

  main_frame->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();

  IntRect visible_contents =
      main_frame->View()->LayoutViewport()->VisibleContentRect();
  *out_layout_viewport = protocol::Page::LayoutViewport::create()
                             .setPageX(visible_contents.X())
                             .setPageY(visible_contents.Y())
                             .setClientWidth(visible_contents.Width())
                             .setClientHeight(visible_contents.Height())
                             .build();

  LocalFrameView* frame_view = main_frame->View();
  ScrollOffset page_offset = frame_view->GetScrollableArea()->GetScrollOffset();
  float page_zoom = main_frame->PageZoomFactor();
  FloatRect visible_rect = visual_viewport.VisibleRect();
  float scale = visual_viewport.Scale();

  IntSize content_size = frame_view->GetScrollableArea()->ContentsSize();
  *out_content_size = protocol::DOM::Rect::create()
                          .setX(0)
                          .setY(0)
                          .setWidth(content_size.Width())
                          .setHeight(content_size.Height())
                          .build();

  *out_visual_viewport = protocol::Page::VisualViewport::create()
                             .setOffsetX(AdjustForAbsoluteZoom::AdjustScroll(
                                 visible_rect.X(), page_zoom))
                             .setOffsetY(AdjustForAbsoluteZoom::AdjustScroll(
                                 visible_rect.Y(), page_zoom))
                             .setPageX(AdjustForAbsoluteZoom::AdjustScroll(
                                 page_offset.Width(), page_zoom))
                             .setPageY(AdjustForAbsoluteZoom::AdjustScroll(
                                 page_offset.Height(), page_zoom))
                             .setClientWidth(visible_rect.Width())
                             .setClientHeight(visible_rect.Height())
                             .setScale(scale)
                             .build();
  return Response::OK();
}

protocol::Response InspectorPageAgent::createIsolatedWorld(
    const String& frame_id,
    Maybe<String> world_name,
    Maybe<bool> grant_universal_access,
    int* execution_context_id) {
  LocalFrame* frame =
      IdentifiersFactory::FrameById(inspected_frames_, frame_id);
  if (!frame)
    return Response::Error("No frame for given id found");

  scoped_refptr<DOMWrapperWorld> world =
      frame->GetScriptController().CreateNewInspectorIsolatedWorld(
          world_name.fromMaybe(""));
  if (!world)
    return Response::Error("Could not create isolated world");

  if (grant_universal_access.fromMaybe(false)) {
    scoped_refptr<SecurityOrigin> security_origin =
        frame->GetSecurityContext()->GetSecurityOrigin()->IsolatedCopy();
    security_origin->GrantUniversalAccess();
    DOMWrapperWorld::SetIsolatedWorldSecurityOrigin(world->GetWorldId(),
                                                    security_origin);
  }

  LocalWindowProxy* isolated_world_window_proxy =
      frame->GetScriptController().WindowProxy(*world);
  v8::HandleScope handle_scope(V8PerIsolateData::MainThreadIsolate());
  *execution_context_id = v8_inspector::V8ContextInfo::executionContextId(
      isolated_world_window_proxy->ContextIfInitialized());
  return Response::OK();
}

Response InspectorPageAgent::setFontFamilies(
    std::unique_ptr<protocol::Page::FontFamilies> font_families) {
  LocalFrame* frame = inspected_frames_->Root();
  auto* settings = frame->GetSettings();
  if (settings) {
    auto& family_settings = settings->GetGenericFontFamilySettings();
    if (font_families->hasStandard()) {
      standard_font_family_.Set(font_families->getStandard(String()));
      family_settings.UpdateStandard(AtomicString(standard_font_family_.Get()));
    }
    if (font_families->hasFixed()) {
      fixed_font_family_.Set(font_families->getFixed(String()));
      family_settings.UpdateFixed(AtomicString(fixed_font_family_.Get()));
    }
    if (font_families->hasSerif()) {
      serif_font_family_.Set(font_families->getSerif(String()));
      family_settings.UpdateSerif(AtomicString(serif_font_family_.Get()));
    }
    if (font_families->hasSansSerif()) {
      sans_serif_font_family_.Set(font_families->getSansSerif(String()));
      family_settings.UpdateSansSerif(
          AtomicString(sans_serif_font_family_.Get()));
    }
    if (font_families->hasCursive()) {
      cursive_font_family_.Set(font_families->getCursive(String()));
      family_settings.UpdateCursive(AtomicString(cursive_font_family_.Get()));
    }
    if (font_families->hasFantasy()) {
      fantasy_font_family_.Set(font_families->getFantasy(String()));
      family_settings.UpdateFantasy(AtomicString(fantasy_font_family_.Get()));
    }
    if (font_families->hasPictograph()) {
      pictograph_font_family_.Set(font_families->getPictograph(String()));
      family_settings.UpdatePictograph(
          AtomicString(pictograph_font_family_.Get()));
    }
    settings->NotifyGenericFontFamilyChange();
  }

  return Response::OK();
}

Response InspectorPageAgent::setFontSizes(
    std::unique_ptr<protocol::Page::FontSizes> font_sizes) {
  LocalFrame* frame = inspected_frames_->Root();
  auto* settings = frame->GetSettings();
  if (settings) {
    if (font_sizes->hasStandard()) {
      standard_font_size_.Set(font_sizes->getStandard(0));
      settings->SetDefaultFontSize(standard_font_size_.Get());
    }
    if (font_sizes->hasFixed()) {
      fixed_font_size_.Set(font_sizes->getFixed(0));
      settings->SetDefaultFixedFontSize(fixed_font_size_.Get());
    }
  }

  return Response::OK();
}

void InspectorPageAgent::ConsumeCompilationCache(
    const ScriptSourceCode& source,
    v8::ScriptCompiler::CachedData** cached_data) {
  if (source.SourceLocationType() != ScriptSourceLocationType::kExternalFile)
    return;
  if (source.Url().IsEmpty())
    return;
  auto it = compilation_cache_.find(source.Url().GetString());
  if (it == compilation_cache_.end())
    return;
  const Vector<char>& data = it->value;
  *cached_data = new v8::ScriptCompiler::CachedData(
      reinterpret_cast<const uint8_t*>(data.data()), data.size(),
      v8::ScriptCompiler::CachedData::BufferNotOwned);
}

void InspectorPageAgent::ProduceCompilationCache(const ScriptSourceCode& source,
                                                 v8::Local<v8::Script> script) {
  if (!produce_compilation_cache_.Get())
    return;
  KURL url = source.Url();
  if (source.Streamer())
    return;
  if (source.SourceLocationType() != ScriptSourceLocationType::kExternalFile)
    return;
  if (url.IsEmpty())
    return;
  String url_string = url.GetString();
  auto it = compilation_cache_.find(url_string);
  if (it != compilation_cache_.end())
    return;
  static const int kMinimalCodeLength = 1024;
  if (source.Source().length() < kMinimalCodeLength)
    return;
  std::unique_ptr<v8::ScriptCompiler::CachedData> cached_data(
      v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript()));
  if (cached_data) {
    String base64data = Base64Encode(
        reinterpret_cast<const char*>(cached_data->data), cached_data->length);
    GetFrontend()->compilationCacheProduced(url_string, base64data);
  }
}

Response InspectorPageAgent::setProduceCompilationCache(bool enabled) {
  produce_compilation_cache_.Set(enabled);
  return Response::OK();
}

Response InspectorPageAgent::addCompilationCache(const String& url,
                                                 const String& base64data) {
  Vector<char> data;
  if (!Base64Decode(base64data, data))
    return Response::Error("data should be base64-encoded");
  compilation_cache_.Set(url, std::move(data));
  return Response::OK();
}

Response InspectorPageAgent::clearCompilationCache() {
  compilation_cache_.clear();
  return Response::OK();
}

protocol::Response InspectorPageAgent::generateTestReport(const String& message,
                                                          Maybe<String> group) {
  Document* document = inspected_frames_->Root()->GetDocument();

  // Construct the test report.
  TestReportBody* body = new TestReportBody(message);
  Report* report = new Report("test", document->Url().GetString(), body);

  // Send the test report to any ReportingObservers.
  ReportingContext::From(document)->QueueReport(report);

  return Response::OK();
}

void InspectorPageAgent::Trace(blink::Visitor* visitor) {
  visitor->Trace(inspected_frames_);
  visitor->Trace(inspector_resource_content_loader_);
  InspectorBaseAgent::Trace(visitor);
}

}  // namespace blink
