void CefDevToolsFrontend::HandleMessageFromDevToolsFrontend()

in libcef/browser/devtools/devtools_frontend.cc [369:545]


void CefDevToolsFrontend::HandleMessageFromDevToolsFrontend(
    base::Value message) {
  if (!message.is_dict())
    return;
  const std::string* method = message.FindStringKey("method");
  if (!method)
    return;

  int request_id = message.FindIntKey("id").value_or(0);
  base::Value* params_value = message.FindListKey("params");

  // Since we've received message by value, we can take the list.
  base::Value::ListStorage params;
  if (params_value) {
    params = std::move(*params_value).TakeList();
  }

  if (*method == "dispatchProtocolMessage") {
    if (params.size() < 1)
      return;
    const std::string* protocol_message = params[0].GetIfString();
    if (!agent_host_ || !protocol_message)
      return;
    if (ProtocolLoggingEnabled()) {
      LogProtocolMessage(ProtocolMessageType::METHOD, *protocol_message);
    }
    agent_host_->DispatchProtocolMessage(
        this, base::as_bytes(base::make_span(*protocol_message)));
  } else if (*method == "loadCompleted") {
    web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
        u"DevToolsAPI.setUseSoftMenu(true);", base::NullCallback());
  } else if (*method == "loadNetworkResource") {
    if (params.size() < 3)
      return;

    // TODO(pfeldman): handle some of the embedder messages in content.
    const std::string* url = params[0].GetIfString();
    const std::string* headers = params[1].GetIfString();
    absl::optional<const int> stream_id = params[2].GetIfInt();
    if (!url || !headers || !stream_id.has_value()) {
      return;
    }

    GURL gurl(*url);
    if (!gurl.is_valid()) {
      base::DictionaryValue response;
      response.SetInteger("statusCode", 404);
      response.SetBoolean("urlValid", false);
      SendMessageAck(request_id, std::move(response));
      return;
    }

    net::NetworkTrafficAnnotationTag traffic_annotation =
        net::DefineNetworkTrafficAnnotation(
            "devtools_handle_front_end_messages", R"(
            semantics {
              sender: "Developer Tools"
              description:
                "When user opens Developer Tools, the browser may fetch "
                "additional resources from the network to enrich the debugging "
                "experience (e.g. source map resources)."
              trigger: "User opens Developer Tools to debug a web page."
              data: "Any resources requested by Developer Tools."
              destination: OTHER
            }
            policy {
              cookies_allowed: YES
              cookies_store: "user"
              setting:
                "It's not possible to disable this feature from settings."
              chrome_policy {
                DeveloperToolsAvailability {
                  policy_options {mode: MANDATORY}
                  DeveloperToolsAvailability: 2
                }
              }
            })");

    // Based on DevToolsUIBindings::LoadNetworkResource.
    auto resource_request = std::make_unique<network::ResourceRequest>();
    resource_request->url = gurl;
    // TODO(caseq): this preserves behavior of URLFetcher-based
    // implementation. We really need to pass proper first party origin from
    // the front-end.
    resource_request->site_for_cookies = net::SiteForCookies::FromUrl(gurl);
    resource_request->headers.AddHeadersFromString(*headers);

    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
    if (gurl.SchemeIsFile()) {
      mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote =
          content::CreateFileURLLoaderFactory(
              base::FilePath() /* profile_path */,
              nullptr /* shared_cors_origin_access_list */);
      url_loader_factory = network::SharedURLLoaderFactory::Create(
          std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
              std::move(pending_remote)));
    } else if (content::HasWebUIScheme(gurl)) {
      base::DictionaryValue response;
      response.SetInteger("statusCode", 403);
      SendMessageAck(request_id, std::move(response));
      return;
    } else {
      auto* partition =
          web_contents()->GetBrowserContext()->GetStoragePartitionForUrl(gurl);
      url_loader_factory = partition->GetURLLoaderFactoryForBrowserProcess();
    }

    auto simple_url_loader = network::SimpleURLLoader::Create(
        std::move(resource_request), traffic_annotation);
    auto resource_loader = std::make_unique<NetworkResourceLoader>(
        *stream_id, this, std::move(simple_url_loader),
        url_loader_factory.get(), request_id);
    loaders_.insert(std::move(resource_loader));
    return;
  } else if (*method == "getPreferences") {
    SendMessageAck(
        request_id,
        GetPrefs()->GetDictionary(prefs::kDevToolsPreferences)->Clone());
    return;
  } else if (*method == "setPreference") {
    if (params.size() < 2)
      return;
    const std::string* name = params[0].GetIfString();

    // We're just setting params[1] as a value anyways, so just make sure it's
    // the type we want, but don't worry about getting it.
    if (!name || !params[1].is_string())
      return;

    DictionaryPrefUpdate update(GetPrefs(), prefs::kDevToolsPreferences);
    update.Get()->SetKey(*name, std::move(params[1]));
  } else if (*method == "removePreference") {
    const std::string* name = params[0].GetIfString();
    if (!name)
      return;
    DictionaryPrefUpdate update(GetPrefs(), prefs::kDevToolsPreferences);
    update.Get()->RemoveKey(*name);
  } else if (*method == "requestFileSystems") {
    web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
        u"DevToolsAPI.fileSystemsLoaded([]);", base::NullCallback());
  } else if (*method == "reattach") {
    if (!agent_host_)
      return;
    agent_host_->DetachClient(this);
    agent_host_->AttachClient(this);
  } else if (*method == "registerExtensionsAPI") {
    if (params.size() < 2)
      return;
    const std::string* origin = params[0].GetIfString();
    const std::string* script = params[1].GetIfString();
    if (!origin || !script)
      return;
    extensions_api_[*origin + "/"] = *script;
  } else if (*method == "save") {
    if (params.size() < 3)
      return;
    const std::string* url = params[0].GetIfString();
    const std::string* content = params[1].GetIfString();
    absl::optional<bool> save_as = params[2].GetIfBool();
    if (!url || !content || !save_as.has_value())
      return;
    file_manager_.SaveToFile(*url, *content, *save_as);
  } else if (*method == "append") {
    if (params.size() < 2)
      return;
    const std::string* url = params[0].GetIfString();
    const std::string* content = params[1].GetIfString();
    if (!url || !content)
      return;
    file_manager_.AppendToFile(*url, *content);
  } else {
    return;
  }

  if (request_id)
    SendMessageAck(request_id, base::Value());
}