context.rs (2276B)
1 // Copyright 2022 Adobe. All rights reserved. 2 // This file is licensed to you under the Apache License, 3 // Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 4 // or the MIT license (http://opensource.org/licenses/MIT), 5 // at your option. 6 7 // Unless required by applicable law or agreed to in writing, 8 // this software is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or 10 // implied. See the LICENSE-MIT and LICENSE-APACHE files for the 11 // specific language governing permissions and limitations under 12 // each license. 13 14 use wasm_bindgen::{prelude::*, JsCast, JsValue}; 15 use web_sys::{Crypto, SubtleCrypto, Window, WorkerGlobalScope}; 16 17 use crate::{Error, Result}; 18 19 // Adapted from gloo's implementation, since there doesn't seem to be a great way to do context checking using 20 // wasm-bindgen/web-sys without using something like `js_sys::eval`. References: 21 // - Issue: https://github.com/rustwasm/wasm-bindgen/issues/1046 22 // - Issue: https://github.com/rustwasm/wasm-bindgen/issues/2148#issuecomment-638606446 23 // - Code reference: https://git.io/J9crn 24 25 pub enum WindowOrWorker { 26 Window(Window), 27 Worker(WorkerGlobalScope), 28 } 29 30 impl WindowOrWorker { 31 pub fn new() -> Result<Self> { 32 #[wasm_bindgen] 33 extern "C" { 34 type Global; 35 36 #[wasm_bindgen(method, getter, js_name = Window)] 37 fn window(this: &Global) -> JsValue; 38 39 #[wasm_bindgen(method, getter, js_name = WorkerGlobalScope)] 40 fn worker(this: &Global) -> JsValue; 41 } 42 43 let global: Global = js_sys::global().unchecked_into(); 44 45 if !global.window().is_undefined() { 46 Ok(Self::Window(global.unchecked_into())) 47 } else if !global.worker().is_undefined() { 48 Ok(Self::Worker(global.unchecked_into())) 49 } else { 50 Err(Error::WasmInvalidContext) 51 } 52 } 53 54 pub fn crypto(&self) -> Result<Crypto> { 55 match self { 56 Self::Window(window) => window.crypto(), 57 Self::Worker(worker) => worker.crypto(), 58 } 59 .map_err(|_err| Error::WasmNoCrypto) 60 } 61 62 pub fn subtle_crypto(&self) -> Result<SubtleCrypto> { 63 let crypto = self.crypto()?; 64 65 Ok(crypto.subtle()) 66 } 67 }