servo_capi/lib.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5mod options;
6mod preferences;
7mod rendering_context;
8mod servo;
9mod webview;
10mod webview_delegate;
11
12extern crate servo as servo_api;
13
14use options::ServoOptions;
15use preferences::ServoPreferences;
16
17/// An opaque struct representing builder for a `Servo` instance.
18/// Refer to the documentation of the corresponding
19/// [servo::ServoBuilder] struct in Rust API for more information.
20/// [servo::ServoBuilder]: https://doc.servo.org/servo/struct.ServoBuilder.html
21///
22/// # Thread safety
23///
24/// `ServoBuilder` has no internal synchronization, so the embedder is
25/// responsible for serializing access if the handle is shared between
26/// threads. All calls to `servo_builder_set_*` should be made from the
27/// same thread on which `servo_builder_build` will eventually invoked.
28/// This is usually the embedder's main thread that will drive the event
29/// loop by calling `servo_spin_event_loop`.
30// cbindgen:opaque
31#[derive(Default)]
32pub struct ServoBuilder {
33 options: Option<Box<ServoOptions>>,
34 event_loop_waker: ServoEventLoopWaker,
35 preferences: Option<Box<ServoPreferences>>,
36}
37
38/// A callback used by Servo to wake the embedder thread when
39/// Servo has new work to process. The embedder is expected to
40/// pump Servo's event loop in response to this callback.
41///
42/// # Safety
43///
44/// The embedder must ensure that:
45///
46/// - `wake_callback` is a valid C ABI function matching the signature
47/// shown.
48/// - `wake_callback` remains valid for the lifetime of the `Servo`
49/// instance the waker is associated with.
50/// - `wake_callback` does not unwind across the FFI boundary.
51/// - `wake_callback` is safe to invoke from any thread, since Servo may
52/// call it from internal threads.
53#[repr(C)]
54#[derive(Clone, Copy)]
55pub struct ServoEventLoopWaker {
56 pub wake_callback: extern "C" fn(),
57}
58
59/// A no-op default `wake_callback` used when the embedder has not set
60/// one explicitly.
61pub extern "C" fn default_event_loop_waker_wake_callback() {}
62
63impl Default for ServoEventLoopWaker {
64 fn default() -> Self {
65 Self {
66 wake_callback: default_event_loop_waker_wake_callback,
67 }
68 }
69}
70
71impl servo_api::EventLoopWaker for ServoEventLoopWaker {
72 fn clone_box(&self) -> Box<dyn servo_api::EventLoopWaker> {
73 Box::new(*self)
74 }
75
76 fn wake(&self) {
77 (self.wake_callback)()
78 }
79}
80
81/// Creates a new `ServoBuilder` populated with default values.
82///
83/// Returns a newly allocated `ServoBuilder` handle. The ownership of
84/// the returned handle is transferred to the caller, who must free it
85/// with [`servo_builder_free`] or consume it by passing it to
86/// [`servo_builder_build`].
87#[unsafe(no_mangle)]
88pub extern "C" fn servo_builder_create() -> *mut ServoBuilder {
89 Box::into_raw(Box::new(ServoBuilder::default()))
90}
91
92/// Sets the preferences to be used by the `Servo` instance.
93///
94/// `builder` is a handle to a `ServoBuilder` object.
95/// The ownership of `builder` remains with the caller after the call.
96///
97/// `preferences` is a handle to a `ServoPreferences` object.
98/// The ownership of `preferences` is transferred to the function.
99/// The caller must not use or free `preferences` again.
100/// This function will free the previously set preferences, if any.
101///
102/// # Safety
103///
104/// The caller must ensure that:
105///
106/// - `builder` is a non-null pointer to a `ServoBuilder` previously
107/// returned by `servo_builder_create` and has not yet been freed nor
108/// passed to another API that takes ownership of it.
109/// - `preferences` is a non-null pointer to a `ServoPreferences` previously
110/// returned by `servo_preferences_create` and has not yet been freed
111/// nor passed to another API that takes ownership of it.
112#[unsafe(no_mangle)]
113pub unsafe extern "C" fn servo_builder_set_preferences(
114 builder: *mut ServoBuilder,
115 preferences: *mut ServoPreferences,
116) {
117 assert!(!builder.is_null(), "builder pointer must not be null");
118 assert!(
119 !preferences.is_null(),
120 "preferences pointer must not be null"
121 );
122
123 // SAFETY: The caller is assumed to uphold the safety requirements
124 // for `builder` and `preferences` documented above.
125 unsafe {
126 (*builder).preferences = Some(Box::from_raw(preferences));
127 }
128}
129
130/// Sets the options to be used by the `Servo` instance.
131///
132/// `builder` is a handle to a `ServoBuilder` object.
133/// The ownership of `builder` remains with the caller after the call.
134///
135/// `options` is a handle to a `ServoOptions` object.
136/// The ownership of `options` is transferred to the function. The
137/// caller must not use or free `options` again. This function will
138/// free the previously set options, if any.
139///
140/// # Safety
141///
142/// The caller must ensure that:
143///
144/// - `builder` is a non-null pointer to a `ServoBuilder` previously
145/// returned by `servo_builder_create` and has not yet been freed nor
146/// passed to another API that takes ownership of it.
147/// - `options` is a non-null pointer to a `ServoOptions` previously
148/// returned by `servo_options_create` and has not yet been freed nor
149/// passed to another API that takes ownership of it.
150#[unsafe(no_mangle)]
151pub unsafe extern "C" fn servo_builder_set_options(
152 builder: *mut ServoBuilder,
153 options: *mut ServoOptions,
154) {
155 assert!(!builder.is_null(), "builder pointer must not be null");
156 assert!(!options.is_null(), "options pointer must not be null");
157
158 // SAFETY: The caller is assumed to uphold the safety requirements
159 // for `builder` and `options` documented above.
160 unsafe {
161 (*builder).options = Some(Box::from_raw(options));
162 }
163}
164
165/// Sets the callback used to wake the embedder's event loop when Servo
166/// has new work to process (e.g, rendering updates).
167///
168/// `builder` is a handle to a `ServoBuilder` object.
169/// The ownership of `builder` remains with the caller after the call.
170///
171/// `event_loop_waker` is a `ServoEventLoopWaker` struct that is copied
172/// by value. See [`ServoEventLoopWaker`] for the safety requirements on
173/// its fields.
174///
175/// # Safety
176///
177/// The caller must ensure that:
178///
179/// - `builder` is a non-null pointer to a `ServoBuilder` previously
180/// returned by `servo_builder_create` and has not yet been freed nor
181/// passed to another API that takes ownership of it.
182/// - The safety requirements documented on [`ServoEventLoopWaker`] are
183/// uphelp by `event_loop_waker`.
184#[unsafe(no_mangle)]
185pub unsafe extern "C" fn servo_builder_set_event_loop_waker(
186 builder: *mut ServoBuilder,
187 event_loop_waker: ServoEventLoopWaker,
188) {
189 assert!(!builder.is_null(), "builder pointer must not be null");
190
191 // SAFETY: The caller is assumed to uphold the safety requirements
192 // for `builder` documented above.
193 unsafe {
194 (*builder).event_loop_waker = event_loop_waker;
195 }
196}
197
198/// Consumes the builder and creates a new `Servo` instance.
199///
200/// `builder` is a handle to a `ServoBuilder` object.
201/// The ownership of `builder` is transferred to the function. The
202/// caller must not use or free `builder` again.
203///
204/// Returns a newly allocated `Servo` handle. The ownership of the
205/// returned handle is transferred to the caller, who must free it with
206/// [`servo_free`]. The resulting `Servo` instance is tied to the thread
207/// that called this function and must only be used from that thread.
208///
209/// # Safety
210///
211/// The caller must ensure that `builder` was previously returned by
212/// `servo_builder_create` and has not yet been freed nor passed to
213/// another API that takes ownership of it.
214#[unsafe(no_mangle)]
215pub unsafe extern "C" fn servo_builder_build(builder: *mut ServoBuilder) -> *mut servo_api::Servo {
216 assert!(!builder.is_null(), "builder pointer must not be null");
217 let mut rust_builder = servo_api::ServoBuilder::default();
218
219 // SAFETY: The caller is assumed to uphold the safety requirements
220 // for `builder` documented above.
221 let builder = unsafe { &mut *builder };
222
223 if let Some(options) = builder.options.take() {
224 rust_builder = rust_builder.opts(*options);
225 }
226
227 if let Some(preferences) = builder.preferences.take() {
228 rust_builder = rust_builder.preferences(*preferences);
229 }
230
231 rust_builder = rust_builder.event_loop_waker(Box::new(builder.event_loop_waker));
232
233 let servo = rust_builder.build();
234 Box::into_raw(Box::new(servo))
235}
236
237/// Destroys `builder` and frees its memory.
238///
239/// `builder` is a handle to a `ServoBuilder` object.
240/// The ownership of `builder` is transferred to the function. The
241/// caller must not use or free `builder` again.
242///
243/// # Safety
244///
245/// The caller must ensure that `builder` was previously returned by
246/// `servo_builder_create` and has not yet been freed nor passed to
247/// another API that takes ownership of it.
248#[unsafe(no_mangle)]
249pub unsafe extern "C" fn servo_builder_free(builder: *mut ServoBuilder) {
250 assert!(!builder.is_null(), "builder pointer must not be null");
251
252 // SAFETY: The caller is assumed to uphold the safety requirements
253 // for `builder` documented above.
254 unsafe {
255 let _ = Box::from_raw(builder);
256 }
257}