script/dom/serviceworker/
client.rs1use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::jsapi::JSObject;
8use js::rust::{CustomAutoRooterGuard, HandleValue};
9use script_bindings::error::ErrorResult;
10use script_bindings::reflector::{Reflector, reflect_dom_object};
11use script_bindings::root::DomRoot;
12use servo_base::generic_channel::GenericSender;
13use servo_base::id::ServiceWorkerId;
14use servo_constellation_traits::ServiceWorkerMsg;
15use servo_url::ServoUrl;
16
17use crate::dom::bindings::codegen::Bindings::ClientBinding::{ClientMethods, FrameType};
18use crate::dom::bindings::codegen::Bindings::MessagePortBinding::StructuredSerializeOptions;
19use crate::dom::bindings::error::Error;
20use crate::dom::bindings::reflector::DomGlobal;
21use crate::dom::bindings::str::{DOMString, USVString};
22use crate::dom::bindings::structuredclone;
23use crate::dom::globalscope::GlobalScope;
24
25#[dom_struct]
26pub(crate) struct Client {
27 reflector_: Reflector,
28
29 #[no_trace]
32 swmanager_sender: GenericSender<ServiceWorkerMsg>,
33
34 #[no_trace]
35 url: ServoUrl,
36
37 frame_type: FrameType,
39
40 #[no_trace]
41 worker_id: ServiceWorkerId,
42}
43
44impl Client {
45 fn new_inherited(
46 swmanager_sender: GenericSender<ServiceWorkerMsg>,
47 url: ServoUrl,
48 frame_type: FrameType,
49 worker_id: ServiceWorkerId,
50 ) -> Client {
51 Client {
52 reflector_: Reflector::new(),
53 swmanager_sender,
54 url,
55 frame_type,
56 worker_id,
57 }
58 }
59
60 pub(crate) fn new(
61 cx: &mut JSContext,
62 global: &GlobalScope,
63 swmanager_sender: GenericSender<ServiceWorkerMsg>,
64 url: ServoUrl,
65 frame_type: FrameType,
66 worker_id: ServiceWorkerId,
67 ) -> DomRoot<Client> {
68 reflect_dom_object(
69 cx,
70 Box::new(Client::new_inherited(
71 swmanager_sender,
72 url,
73 frame_type,
74 worker_id,
75 )),
76 global,
77 )
78 }
79
80 fn post_message_impl(
82 &self,
83 cx: &mut JSContext,
84 message: HandleValue,
85 transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
86 ) -> ErrorResult {
87 let global = self.reflector_.global();
92
93 let origin = global.origin();
96
97 let data = structuredclone::write(cx, message, Some(transfer))?;
98 self.swmanager_sender
99 .send(ServiceWorkerMsg::ForwardWorkerMessage {
100 data,
101 source: self.worker_id,
102 url: self.url.clone(),
103 origin: origin.immutable().clone(),
104 })
105 .map_err(|_| {
106 Error::Type(c"Failed to send message to service worker manager".to_owned())
107 })
108 }
109}
110
111impl ClientMethods<crate::DomTypeHolder> for Client {
112 fn PostMessage(
114 &self,
115 cx: &mut JSContext,
116 message: HandleValue,
117 transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
118 ) -> ErrorResult {
119 self.post_message_impl(cx, message, transfer)
120 }
121
122 fn PostMessage_(
124 &self,
125 cx: &mut JSContext,
126 message: HandleValue,
127 options: &StructuredSerializeOptions,
128 ) -> ErrorResult {
129 auto_root!(&in(cx) let guard =
130 options
131 .transfer
132 .iter()
133 .map(|js| js.get())
134 .collect::<Vec<_>>());
135 self.post_message_impl(cx, message, guard)
136 }
137
138 fn Url(&self) -> USVString {
140 USVString(self.url.as_str().to_owned())
141 }
142
143 fn FrameType(&self) -> FrameType {
145 self.frame_type
146 }
147
148 fn Id(&self) -> DOMString {
150 format!("{}", self.worker_id).into()
151 }
152}