use devtools_traits::{BlackboxCoverage, DevtoolScriptControlMsg};
use malloc_size_of_derive::MallocSizeOf;
use serde::Deserialize;
use crate::actor::{Actor, ActorEncode, ActorError, ActorRegistry};
use crate::actors::browsing_context::BrowsingContextActor;
use crate::actors::thread::ThreadActor;
use crate::{ActorMsg, EmptyReplyMsg};
#[derive(Deserialize)]
struct BlackboxRequest {
range: Vec<BlackboxRange>,
url: String,
}
#[derive(Deserialize, Debug)]
struct BlackboxRange {
start: BlackboxSourceLocation,
end: BlackboxSourceLocation,
}
#[derive(Deserialize, Debug)]
struct BlackboxSourceLocation {
line: u32,
column: u32,
}
#[derive(MallocSizeOf)]
pub(crate) struct BlackboxingActor {
name: String,
browsing_context_name: String,
}
impl Actor for BlackboxingActor {
fn name(&self) -> String {
self.name.clone()
}
fn handle_message(
&self,
request: crate::protocol::ClientRequest,
registry: &ActorRegistry,
msg_type: &str,
msg: &serde_json::Map<String, serde_json::Value>,
_: crate::StreamId,
) -> Result<(), crate::actor::ActorError> {
if msg_type != "blackbox" && msg_type != "unblackbox" {
return Err(ActorError::UnrecognizedPacketType);
}
let blackbox_request: BlackboxRequest =
serde_json::from_value(msg.clone().into()).map_err(|_| ActorError::Internal)?;
let coverage = match &blackbox_request.range[..] {
[] => BlackboxCoverage::Full,
[range] => BlackboxCoverage::Partial(
(range.start.line, range.start.column),
(range.end.line, range.end.column),
),
_ => {
log::warn!(
"Expected 0 or 1 range elements, got {:?}",
blackbox_request.range
);
return Err(ActorError::Internal);
},
};
let browsing_context_actor =
registry.find::<BrowsingContextActor>(&self.browsing_context_name);
let thread_actor = registry.find::<ThreadActor>(&browsing_context_actor.thread_name);
let source = thread_actor
.source_manager
.find_source(registry, &blackbox_request.url)
.ok_or(ActorError::Internal)?;
let control_msg = match msg_type {
"blackbox" => DevtoolScriptControlMsg::Blackbox(source.spidermonkey_id, coverage),
"unblackbox" => DevtoolScriptControlMsg::Unblackbox(source.spidermonkey_id, coverage),
_ => unreachable!(),
};
source
.script_sender
.send(control_msg)
.map_err(|_| ActorError::Internal)?;
request.reply_final(&EmptyReplyMsg { from: self.name() })?;
Ok(())
}
}
impl BlackboxingActor {
pub fn register(registry: &ActorRegistry, browsing_context_name: String) -> String {
let name = registry.new_name::<Self>();
let actor = Self {
name: name.clone(),
browsing_context_name,
};
registry.register::<Self>(actor);
name
}
}
impl ActorEncode<ActorMsg> for BlackboxingActor {
fn encode(&self, _: &ActorRegistry) -> ActorMsg {
ActorMsg { actor: self.name() }
}
}