aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/principals.rs
blob: 0594b77022c87a0c43f81d23bf46b2cec0380dbd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use std::ptr::NonNull;

use js::glue::{DestroyRustJSPrincipals, GetRustJSPrincipalsPrivate, JSPrincipalsCallbacks};
use js::jsapi::{
    JS_ReadUint32Pair, JSContext, JSPrincipals, JSStructuredCloneReader, JSStructuredCloneWriter,
};
use script_bindings::principals::{ServoJSPrincipals, ServoJSPrincipalsRef};
use servo_url::MutableOrigin;

use super::structuredclone::StructuredCloneTags;
use crate::DomTypeHolder;

#[allow(unused)]
pub(crate) unsafe extern "C" fn destroy_servo_jsprincipal(principals: *mut JSPrincipals) {
    Box::from_raw(GetRustJSPrincipalsPrivate(principals) as *mut MutableOrigin);
    DestroyRustJSPrincipals(principals);
}

pub(crate) unsafe extern "C" fn write_jsprincipal(
    principal: *mut JSPrincipals,
    _cx: *mut JSContext,
    writer: *mut JSStructuredCloneWriter,
) -> bool {
    let Some(principal) = NonNull::new(principal) else {
        return false;
    };
    let obj = ServoJSPrincipalsRef::from_raw_nonnull(principal);
    let origin = obj.origin();
    let Ok(bytes_of_origin) = bincode::serialize(&origin) else {
        return false;
    };
    let Ok(len) = bytes_of_origin.len().try_into() else {
        return false;
    };
    if !js::jsapi::JS_WriteUint32Pair(writer, StructuredCloneTags::Principals as u32, len) {
        return false;
    }
    if !js::jsapi::JS_WriteBytes(writer, bytes_of_origin.as_ptr() as _, len as usize) {
        return false;
    }
    true
}

pub(crate) unsafe extern "C" fn read_jsprincipal(
    _cx: *mut JSContext,
    reader: *mut JSStructuredCloneReader,
    principals: *mut *mut JSPrincipals,
) -> bool {
    let mut tag: u32 = 0;
    let mut len: u32 = 0;
    if !JS_ReadUint32Pair(reader, &mut tag as *mut u32, &mut len as *mut u32) {
        return false;
    }
    if tag != StructuredCloneTags::Principals as u32 {
        return false;
    }
    let mut bytes = vec![0u8; len as usize];
    if !js::jsapi::JS_ReadBytes(reader, bytes.as_mut_ptr() as _, len as usize) {
        return false;
    }
    let Ok(origin) = bincode::deserialize(&bytes[..]) else {
        return false;
    };
    let principal = ServoJSPrincipals::new::<DomTypeHolder>(&origin);
    *principals = principal.as_raw();
    // we transferred ownership of principal to the caller
    std::mem::forget(principal);
    true
}

pub(crate) const PRINCIPALS_CALLBACKS: JSPrincipalsCallbacks = JSPrincipalsCallbacks {
    write: Some(write_jsprincipal),
    isSystemOrAddonPrincipal: Some(principals_is_system_or_addon_principal),
};

unsafe extern "C" fn principals_is_system_or_addon_principal(_: *mut JSPrincipals) -> bool {
    false
}

//TODO is same_origin_domain equivalent to subsumes for our purposes
pub(crate) unsafe extern "C" fn subsumes(obj: *mut JSPrincipals, other: *mut JSPrincipals) -> bool {
    match (NonNull::new(obj), NonNull::new(other)) {
        (Some(obj), Some(other)) => {
            let obj = ServoJSPrincipalsRef::from_raw_nonnull(obj);
            let other = ServoJSPrincipalsRef::from_raw_nonnull(other);
            let obj_origin = obj.origin();
            let other_origin = other.origin();
            obj_origin.same_origin_domain(&other_origin)
        },
        (None, Some(_)) => {
            // See https://github.com/servo/servo/issues/32999#issuecomment-2542522289 for why
            // it's safe to consider the null principal here subsumes all others.
            true
        },
        _ => {
            warn!("Received null JSPrincipal argument.");
            false
        },
    }
}