mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			138 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
 | 
						|
// reserved. Use of this source code is governed by a BSD-style license that
 | 
						|
// can be found in the LICENSE file.
 | 
						|
 | 
						|
#include "libcef/browser/devtools/devtools_controller.h"
 | 
						|
 | 
						|
#include "libcef/browser/devtools/devtools_util.h"
 | 
						|
#include "libcef/browser/thread_util.h"
 | 
						|
 | 
						|
#include "base/json/json_reader.h"
 | 
						|
#include "base/json/json_writer.h"
 | 
						|
#include "content/public/browser/devtools_agent_host.h"
 | 
						|
 | 
						|
CefDevToolsController::CefDevToolsController(
 | 
						|
    content::WebContents* inspected_contents)
 | 
						|
    : inspected_contents_(inspected_contents), weak_ptr_factory_(this) {
 | 
						|
  DCHECK(inspected_contents_);
 | 
						|
}
 | 
						|
 | 
						|
CefDevToolsController::~CefDevToolsController() {
 | 
						|
  if (agent_host_) {
 | 
						|
    agent_host_->DetachClient(this);
 | 
						|
    AgentHostClosed(agent_host_.get());
 | 
						|
  }
 | 
						|
 | 
						|
  for (auto& observer : observers_) {
 | 
						|
    observer.OnDevToolsControllerDestroyed();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool CefDevToolsController::SendDevToolsMessage(
 | 
						|
    const base::StringPiece& message) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
  if (!EnsureAgentHost())
 | 
						|
    return false;
 | 
						|
 | 
						|
  agent_host_->DispatchProtocolMessage(
 | 
						|
      this, base::as_bytes(base::make_span(message)));
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
int CefDevToolsController::ExecuteDevToolsMethod(
 | 
						|
    int suggested_message_id,
 | 
						|
    const std::string& method,
 | 
						|
    const base::DictionaryValue* params) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
  if (!EnsureAgentHost())
 | 
						|
    return 0;
 | 
						|
 | 
						|
  // Message IDs must always be increasing and unique.
 | 
						|
  int message_id = suggested_message_id;
 | 
						|
  if (message_id < next_message_id_)
 | 
						|
    message_id = next_message_id_++;
 | 
						|
  else
 | 
						|
    next_message_id_ = message_id + 1;
 | 
						|
 | 
						|
  base::DictionaryValue message;
 | 
						|
  message.SetIntKey("id", message_id);
 | 
						|
  message.SetStringKey("method", method);
 | 
						|
  if (params)
 | 
						|
    message.SetKey("params", params->Clone());
 | 
						|
 | 
						|
  std::string protocol_message;
 | 
						|
  if (!base::JSONWriter::Write(message, &protocol_message))
 | 
						|
    return 0;
 | 
						|
 | 
						|
  agent_host_->DispatchProtocolMessage(
 | 
						|
      this, base::as_bytes(base::make_span(protocol_message)));
 | 
						|
  return message_id;
 | 
						|
}
 | 
						|
 | 
						|
void CefDevToolsController::AgentHostClosed(
 | 
						|
    content::DevToolsAgentHost* agent_host) {
 | 
						|
  DCHECK(agent_host == agent_host_.get());
 | 
						|
  agent_host_ = nullptr;
 | 
						|
  for (auto& observer : observers_) {
 | 
						|
    observer.OnDevToolsAgentDetached();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void CefDevToolsController::AddObserver(Observer* observer) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
  observers_.AddObserver(observer);
 | 
						|
}
 | 
						|
 | 
						|
void CefDevToolsController::RemoveObserver(Observer* observer) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
  observers_.RemoveObserver(observer);
 | 
						|
}
 | 
						|
 | 
						|
void CefDevToolsController::DispatchProtocolMessage(
 | 
						|
    content::DevToolsAgentHost* agent_host,
 | 
						|
    base::span<const uint8_t> message) {
 | 
						|
  if (observers_.empty())
 | 
						|
    return;
 | 
						|
 | 
						|
  base::StringPiece str_message(reinterpret_cast<const char*>(message.data()),
 | 
						|
                                message.size());
 | 
						|
  if (!devtools_util::ProtocolParser::IsValidMessage(str_message)) {
 | 
						|
    LOG(WARNING) << "Invalid message: " << str_message.substr(0, 100);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  devtools_util::ProtocolParser parser;
 | 
						|
 | 
						|
  for (auto& observer : observers_) {
 | 
						|
    if (observer.OnDevToolsMessage(str_message)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    // Only perform parsing a single time.
 | 
						|
    if (parser.Initialize(str_message) && parser.IsFailure()) {
 | 
						|
      LOG(WARNING) << "Failed to parse message: " << str_message.substr(0, 100);
 | 
						|
    }
 | 
						|
 | 
						|
    if (parser.IsEvent()) {
 | 
						|
      observer.OnDevToolsEvent(parser.method_, parser.params_);
 | 
						|
    } else if (parser.IsResult()) {
 | 
						|
      observer.OnDevToolsMethodResult(parser.message_id_, parser.success_,
 | 
						|
                                      parser.params_);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool CefDevToolsController::EnsureAgentHost() {
 | 
						|
  if (!agent_host_) {
 | 
						|
    agent_host_ =
 | 
						|
        content::DevToolsAgentHost::GetOrCreateFor(inspected_contents_);
 | 
						|
    if (agent_host_) {
 | 
						|
      agent_host_->AttachClient(this);
 | 
						|
      for (auto& observer : observers_) {
 | 
						|
        observer.OnDevToolsAgentAttached();
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return !!agent_host_;
 | 
						|
}
 |