script/dom/serviceworker/
client.rs1use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::jsapi::{Heap, 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::bindings::trace::RootedTraceableBox;
24use crate::dom::globalscope::GlobalScope;
25
26#[dom_struct]
27pub(crate) struct Client {
28 reflector_: Reflector,
29
30 #[no_trace]
33 swmanager_sender: GenericSender<ServiceWorkerMsg>,
34
35 #[no_trace]
36 url: ServoUrl,
37
38 frame_type: FrameType,
40
41 #[no_trace]
42 worker_id: ServiceWorkerId,
43}
44
45impl Client {
46 fn new_inherited(
47 swmanager_sender: GenericSender<ServiceWorkerMsg>,
48 url: ServoUrl,
49 frame_type: FrameType,
50 worker_id: ServiceWorkerId,
51 ) -> Client {
52 Client {
53 reflector_: Reflector::new(),
54 swmanager_sender,
55 url,
56 frame_type,
57 worker_id,
58 }
59 }
60
61 pub(crate) fn new(
62 cx: &mut JSContext,
63 global: &GlobalScope,
64 swmanager_sender: GenericSender<ServiceWorkerMsg>,
65 url: ServoUrl,
66 frame_type: FrameType,
67 worker_id: ServiceWorkerId,
68 ) -> DomRoot<Client> {
69 reflect_dom_object(
70 cx,
71 Box::new(Client::new_inherited(
72 swmanager_sender,
73 url,
74 frame_type,
75 worker_id,
76 )),
77 global,
78 )
79 }
80
81 fn post_message_impl(
83 &self,
84 cx: &mut JSContext,
85 message: HandleValue,
86 transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
87 ) -> ErrorResult {
88 let global = self.reflector_.global();
93
94 let origin = global.origin();
97
98 let data = structuredclone::write(cx, message, Some(transfer))?;
99 self.swmanager_sender
100 .send(ServiceWorkerMsg::ForwardWorkerMessage {
101 data,
102 source: self.worker_id,
103 url: self.url.clone(),
104 origin: origin.immutable().clone(),
105 })
106 .map_err(|_| {
107 Error::Type(c"Failed to send message to service worker manager".to_owned())
108 })
109 }
110}
111
112impl ClientMethods<crate::DomTypeHolder> for Client {
113 fn PostMessage(
115 &self,
116 cx: &mut JSContext,
117 message: HandleValue,
118 transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
119 ) -> ErrorResult {
120 self.post_message_impl(cx, message, transfer)
121 }
122
123 fn PostMessage_(
125 &self,
126 cx: &mut JSContext,
127 message: HandleValue,
128 options: RootedTraceableBox<StructuredSerializeOptions>,
129 ) -> ErrorResult {
130 auto_root!(&in(cx) let guard =
131 options
132 .transfer
133 .iter()
134 .map(|js: &RootedTraceableBox<Heap<*mut JSObject>>| js.get())
135 .collect::<Vec<_>>());
136 self.post_message_impl(cx, message, guard)
137 }
138
139 fn Url(&self) -> USVString {
141 USVString(self.url.as_str().to_owned())
142 }
143
144 fn FrameType(&self) -> FrameType {
146 self.frame_type
147 }
148
149 fn Id(&self) -> DOMString {
151 format!("{}", self.worker_id).into()
152 }
153}