1use devtools_traits::DevtoolScriptControlMsg;
13use serde::Serialize;
14use serde_json::{Map, Value};
15
16use crate::actor::{Actor, ActorError, ActorRegistry};
17use crate::actors::browsing_context::{BrowsingContextActor, BrowsingContextActorMsg};
18use crate::actors::root::{DescriptorTraits, RootActor};
19use crate::actors::watcher::{WatcherActor, WatcherActorMsg};
20use crate::protocol::ClientRequest;
21use crate::{EmptyReplyMsg, StreamId};
22
23#[derive(Serialize)]
24#[serde(rename_all = "camelCase")]
25pub struct TabDescriptorActorMsg {
26 actor: String,
27 #[serde(rename = "browserId")]
29 browser_id: u32,
30 #[serde(rename = "browsingContextID")]
31 browsing_context_id: u32,
32 is_zombie_tab: bool,
33 #[serde(rename = "outerWindowID")]
34 outer_window_id: u32,
35 selected: bool,
36 title: String,
37 traits: DescriptorTraits,
38 url: String,
39}
40
41impl TabDescriptorActorMsg {
42 pub fn browser_id(&self) -> u32 {
43 self.browser_id
44 }
45
46 pub fn actor(&self) -> String {
47 self.actor.clone()
48 }
49}
50
51#[derive(Serialize)]
52struct GetTargetReply {
53 from: String,
54 frame: BrowsingContextActorMsg,
55}
56
57#[derive(Serialize)]
58struct GetFaviconReply {
59 from: String,
60 favicon: String,
61}
62
63#[derive(Serialize)]
64struct GetWatcherReply {
65 from: String,
66 #[serde(flatten)]
67 watcher: WatcherActorMsg,
68}
69
70pub struct TabDescriptorActor {
71 name: String,
72 browsing_context_actor: String,
73 is_top_level_global: bool,
74}
75
76impl Actor for TabDescriptorActor {
77 fn name(&self) -> String {
78 self.name.clone()
79 }
80
81 fn handle_message(
92 &self,
93 request: ClientRequest,
94 registry: &ActorRegistry,
95 msg_type: &str,
96 _msg: &Map<String, Value>,
97 _id: StreamId,
98 ) -> Result<(), ActorError> {
99 match msg_type {
100 "getTarget" => {
101 let frame = registry
102 .find::<BrowsingContextActor>(&self.browsing_context_actor)
103 .encodable();
104 request.reply_final(&GetTargetReply {
105 from: self.name(),
106 frame,
107 })?
108 },
109 "getFavicon" => {
110 request.reply_final(&GetFaviconReply {
112 from: self.name(),
113 favicon: String::new(),
114 })?
115 },
116 "getWatcher" => {
117 let ctx_actor = registry.find::<BrowsingContextActor>(&self.browsing_context_actor);
118 let watcher = registry.find::<WatcherActor>(&ctx_actor.watcher);
119 request.reply_final(&GetWatcherReply {
120 from: self.name(),
121 watcher: watcher.encodable(),
122 })?
123 },
124 "reloadDescriptor" => {
125 let ctx_actor = registry.find::<BrowsingContextActor>(&self.browsing_context_actor);
127 let pipeline = ctx_actor.active_pipeline_id.get();
128 ctx_actor
129 .script_chan
130 .send(DevtoolScriptControlMsg::Reload(pipeline))
131 .map_err(|_| ActorError::Internal)?;
132
133 request.reply_final(&EmptyReplyMsg { from: self.name() })?
134 },
135 _ => return Err(ActorError::UnrecognizedPacketType),
136 };
137 Ok(())
138 }
139}
140
141impl TabDescriptorActor {
142 pub(crate) fn new(
143 actors: &mut ActorRegistry,
144 browsing_context_actor: String,
145 is_top_level_global: bool,
146 ) -> TabDescriptorActor {
147 let name = actors.new_name("tab-description");
148 let root = actors.find_mut::<RootActor>("root");
149 root.tabs.push(name.clone());
150 TabDescriptorActor {
151 name,
152 browsing_context_actor,
153 is_top_level_global,
154 }
155 }
156
157 pub fn encodable(&self, registry: &ActorRegistry, selected: bool) -> TabDescriptorActorMsg {
158 let ctx_actor = registry.find::<BrowsingContextActor>(&self.browsing_context_actor);
159 let title = ctx_actor.title.borrow().clone();
160 let url = ctx_actor.url.borrow().clone();
161
162 TabDescriptorActorMsg {
163 actor: self.name(),
164 browser_id: ctx_actor.browser_id.value(),
165 browsing_context_id: ctx_actor.browsing_context_id.value(),
166 is_zombie_tab: false,
167 outer_window_id: ctx_actor.active_outer_window_id.get().value(),
168 selected,
169 title,
170 traits: DescriptorTraits {
171 watcher: true,
172 supports_reload_descriptor: true,
173 },
174 url,
175 }
176 }
177
178 pub(crate) fn is_top_level_global(&self) -> bool {
179 self.is_top_level_global
180 }
181
182 pub fn browsing_context(&self) -> String {
183 self.browsing_context_actor.clone()
184 }
185}