servo/components/devtools/actors/browsing_context.rs
bors-servo 4dcd1e71fa
Auto merge of #21943 - codehag:devtools-add-list-workers-method, r=jdm
DevTools - add ListWorkers method to BrowsingContextTargetActor

This is one of three pull requests that allows the DevTools Debugger to render.

The two related prs are #21942 and #21944

This pr introduces a `ListWorkers` method, which the debugger relies on for startup. At the moment, we are returning an empty array, but later on we can return an array populated by all workers associated with a target.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21943)
<!-- Reviewable:end -->
2018-10-14 15:07:01 -04:00

202 lines
6.3 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Liberally derived from the [Firefox JS implementation]
//! (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/webbrowser.js).
//! Connection point for remote devtools that wish to investigate a particular Browsing Context's contents.
//! Supports dynamic attaching and detaching which control notifications of navigation, etc.
use actor::{Actor, ActorMessageStatus, ActorRegistry};
use actors::console::ConsoleActor;
use devtools_traits::DevtoolScriptControlMsg::{self, WantsLiveNotifications};
use protocol::JsonPacketStream;
use serde_json::{Map, Value};
use std::net::TcpStream;
#[derive(Serialize)]
struct BrowsingContextTraits;
#[derive(Serialize)]
struct BrowsingContextAttachedReply {
from: String,
#[serde(rename = "type")]
type_: String,
threadActor: String,
cacheDisabled: bool,
javascriptEnabled: bool,
traits: BrowsingContextTraits,
}
#[derive(Serialize)]
struct BrowsingContextDetachedReply {
from: String,
#[serde(rename = "type")]
type_: String,
}
#[derive(Serialize)]
struct ReconfigureReply {
from: String,
}
#[derive(Serialize)]
struct ListFramesReply {
from: String,
frames: Vec<FrameMsg>,
}
#[derive(Serialize)]
struct FrameMsg {
id: u32,
url: String,
title: String,
parentID: u32,
}
#[derive(Serialize)]
struct ListWorkersReply {
from: String,
workers: Vec<WorkerMsg>,
}
#[derive(Serialize)]
struct WorkerMsg {
id: u32,
}
#[derive(Serialize)]
pub struct BrowsingContextActorMsg {
actor: String,
title: String,
url: String,
outerWindowID: u32,
consoleActor: String,
inspectorActor: String,
timelineActor: String,
profilerActor: String,
performanceActor: String,
styleSheetsActor: String,
}
pub struct BrowsingContextActor {
pub name: String,
pub title: String,
pub url: String,
pub console: String,
pub inspector: String,
pub timeline: String,
pub profiler: String,
pub performance: String,
pub styleSheets: String,
pub thread: String,
}
impl Actor for BrowsingContextActor {
fn name(&self) -> String {
self.name.clone()
}
fn handle_message(
&self,
registry: &ActorRegistry,
msg_type: &str,
msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type {
"reconfigure" => {
if let Some(options) = msg.get("options").and_then(|o| o.as_object()) {
if let Some(val) = options.get("performReload") {
if val.as_bool().unwrap_or(false) {
let console_actor = registry.find::<ConsoleActor>(&self.console);
let _ = console_actor
.script_chan
.send(DevtoolScriptControlMsg::Reload(console_actor.pipeline));
}
}
}
stream.write_json_packet(&ReconfigureReply { from: self.name() });
ActorMessageStatus::Processed
},
// https://docs.firefox-dev.tools/backend/protocol.html#listing-browser-tabs
// (see "To attach to a _targetActor_")
"attach" => {
let msg = BrowsingContextAttachedReply {
from: self.name(),
type_: "targetAttached".to_owned(),
threadActor: self.thread.clone(),
cacheDisabled: false,
javascriptEnabled: true,
traits: BrowsingContextTraits,
};
let console_actor = registry.find::<ConsoleActor>(&self.console);
console_actor
.streams
.borrow_mut()
.push(stream.try_clone().unwrap());
stream.write_json_packet(&msg);
console_actor
.script_chan
.send(WantsLiveNotifications(console_actor.pipeline, true))
.unwrap();
ActorMessageStatus::Processed
},
//FIXME: The current implementation won't work for multiple connections. Need to ensure 105
// that the correct stream is removed.
"detach" => {
let msg = BrowsingContextDetachedReply {
from: self.name(),
type_: "detached".to_owned(),
};
let console_actor = registry.find::<ConsoleActor>(&self.console);
console_actor.streams.borrow_mut().pop();
stream.write_json_packet(&msg);
console_actor
.script_chan
.send(WantsLiveNotifications(console_actor.pipeline, false))
.unwrap();
ActorMessageStatus::Processed
},
"listFrames" => {
let msg = ListFramesReply {
from: self.name(),
frames: vec![],
};
stream.write_json_packet(&msg);
ActorMessageStatus::Processed
},
"listWorkers" => {
let msg = ListWorkersReply {
from: self.name(),
workers: vec![],
};
stream.write_json_packet(&msg);
ActorMessageStatus::Processed
},
_ => ActorMessageStatus::Ignored,
})
}
}
impl BrowsingContextActor {
pub fn encodable(&self) -> BrowsingContextActorMsg {
BrowsingContextActorMsg {
actor: self.name(),
title: self.title.clone(),
url: self.url.clone(),
outerWindowID: 0, //FIXME: this should probably be the pipeline id
consoleActor: self.console.clone(),
inspectorActor: self.inspector.clone(),
timelineActor: self.timeline.clone(),
profilerActor: self.profiler.clone(),
performanceActor: self.performance.clone(),
styleSheetsActor: self.styleSheets.clone(),
}
}
}