Skip to main content

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}