host_extensions/first_party/
data.rs1use crate::HostExtension;
7
8const HOST_EXT_DATA_SCRIPT: &str = r#"
14(function(){
15 if (!window.host || !window.host.ext) return;
16 function bytesToBase64(input) {
17 var bytes;
18 if (input instanceof Uint8Array) {
19 bytes = input;
20 } else if (input instanceof ArrayBuffer) {
21 bytes = new Uint8Array(input);
22 } else if (ArrayBuffer.isView(input)) {
23 bytes = new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
24 } else {
25 throw new TypeError('sendBytes expects a Uint8Array or ArrayBuffer');
26 }
27
28 var chunkSize = 0x8000;
29 var binary = '';
30 for (var i = 0; i < bytes.length; i += chunkSize) {
31 var chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.length));
32 binary += String.fromCharCode.apply(null, chunk);
33 }
34 return btoa(binary);
35 }
36
37 window.host.ext.data = Object.freeze({
38 getPeerId: function() {
39 return window.__hostCall('hostBridge', 'dataGetPeerId', {});
40 },
41 connect: function(peerAddress) {
42 return window.__hostCall('hostBridge', 'dataConnect', { peerAddress: peerAddress });
43 },
44 send: function(connId, data) {
45 return window.__hostCall('hostBridge', 'dataSend', { connId: connId, data: data });
46 },
47 sendBytes: function(connId, data) {
48 return window.__hostCall('hostBridge', 'dataSendBytes', {
49 connId: connId,
50 dataBase64: bytesToBase64(data)
51 });
52 },
53 close: function(connId) {
54 return window.__hostCall('hostBridge', 'dataClose', { connId: connId });
55 },
56 startListening: function(address) {
57 return window.__hostCall('hostBridge', 'dataStartListening', { address: address });
58 }
59 });
60})();
61"#;
62
63pub struct DataExtension;
64
65impl Default for DataExtension {
66 fn default() -> Self {
67 Self::new()
68 }
69}
70
71impl DataExtension {
72 pub fn new() -> Self {
73 Self
74 }
75}
76
77impl HostExtension for DataExtension {
78 fn namespace(&self) -> &str {
79 "data"
80 }
81
82 fn channel(&self) -> &str {
83 "hostBridge"
85 }
86
87 fn inject_script(&self) -> &str {
88 HOST_EXT_DATA_SCRIPT
89 }
90
91 fn handle_message(&self, _method: &str, _params: &str) -> Option<String> {
92 None
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn data_extension_basics() {
104 let ext = DataExtension::new();
105 assert_eq!(ext.namespace(), "data");
106 assert!(ext.inject_script().contains("window.host.ext.data"));
107 assert!(ext.inject_script().contains("dataConnect"));
108 assert!(ext.inject_script().contains("sendBytes"));
109 }
110}