зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #6505 - Implement crypto.getRandomValues() (from ttaubert:issue/4666-crypto-getRandomValues); r=Ms2ger
Didn't touch mozjs or rust-mozjs because implementing that in the code generator didn't seem too easy. I'm using the same workaround that the TextDecoder does. Using the OsRng should be the right choice here? As the OS keeps state for us we wouldn't need to have a global rng instance to keep around. Fixes #4666. Source-Repo: https://github.com/servo/servo Source-Revision: c0222628264423a67bf98775be83dcf2f85211ab
This commit is contained in:
Родитель
fac8c79199
Коммит
0cceca72b1
|
@ -78,3 +78,4 @@ string_cache = "0.1"
|
|||
string_cache_plugin = "0.1"
|
||||
euclid = "0.1"
|
||||
tendril = "0.1.1"
|
||||
rand = "0.3"
|
||||
|
|
|
@ -62,6 +62,10 @@ pub enum Error {
|
|||
DataClone,
|
||||
/// NoModificationAllowedError DOMException
|
||||
NoModificationAllowed,
|
||||
/// QuotaExceededError DOMException
|
||||
QuotaExceeded,
|
||||
/// TypeMismatchError DOMException
|
||||
TypeMismatch,
|
||||
|
||||
/// TypeError JavaScript Error
|
||||
Type(DOMString),
|
||||
|
@ -101,6 +105,8 @@ pub fn throw_dom_exception(cx: *mut JSContext, global: GlobalRef,
|
|||
Error::InvalidNodeType => DOMErrorName::InvalidNodeTypeError,
|
||||
Error::DataClone => DOMErrorName::DataCloneError,
|
||||
Error::NoModificationAllowed => DOMErrorName::NoModificationAllowedError,
|
||||
Error::QuotaExceeded => DOMErrorName::QuotaExceededError,
|
||||
Error::TypeMismatch => DOMErrorName::TypeMismatchError,
|
||||
Error::Type(message) => {
|
||||
assert!(unsafe { JS_IsExceptionPending(cx) } == 0);
|
||||
throw_type_error(cx, &message);
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::CryptoBinding;
|
||||
use dom::bindings::codegen::Bindings::CryptoBinding::CryptoMethods;
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
|
||||
use js::jsapi::{JSContext, JSObject};
|
||||
use js::jsapi::{JS_GetObjectAsArrayBufferView, JS_GetArrayBufferViewType, Type};
|
||||
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
use rand::{Rng, OsRng};
|
||||
|
||||
no_jsmanaged_fields!(OsRng);
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto
|
||||
#[dom_struct]
|
||||
pub struct Crypto {
|
||||
reflector_: Reflector,
|
||||
rng: DOMRefCell<OsRng>,
|
||||
}
|
||||
|
||||
impl Crypto {
|
||||
fn new_inherited() -> Crypto {
|
||||
Crypto {
|
||||
reflector_: Reflector::new(),
|
||||
rng: DOMRefCell::new(OsRng::new().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef) -> Root<Crypto> {
|
||||
reflect_dom_object(box Crypto::new_inherited(), global, CryptoBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CryptoMethods for &'a Crypto {
|
||||
// https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#Crypto-method-getRandomValues
|
||||
#[allow(unsafe_code)]
|
||||
fn GetRandomValues(self, _cx: *mut JSContext, input: *mut JSObject)
|
||||
-> Fallible<*mut JSObject> {
|
||||
let mut length = 0;
|
||||
let mut data = ptr::null_mut();
|
||||
if unsafe { JS_GetObjectAsArrayBufferView(input, &mut length, &mut data).is_null() } {
|
||||
return Err(Error::Type("Argument to Crypto.getRandomValues is not an ArrayBufferView".to_owned()));
|
||||
}
|
||||
if !is_integer_buffer(input) {
|
||||
return Err(Error::TypeMismatch);
|
||||
}
|
||||
if length > 65536 {
|
||||
return Err(Error::QuotaExceeded);
|
||||
}
|
||||
|
||||
let mut buffer = unsafe {
|
||||
slice::from_raw_parts_mut(data, length as usize)
|
||||
};
|
||||
|
||||
self.rng.borrow_mut().fill_bytes(&mut buffer);
|
||||
|
||||
Ok(input)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn is_integer_buffer(input: *mut JSObject) -> bool {
|
||||
match unsafe { JS_GetArrayBufferViewType(input) } {
|
||||
Type::Uint8 |
|
||||
Type::Uint8Clamped |
|
||||
Type::Int8 |
|
||||
Type::Uint16 |
|
||||
Type::Int16 |
|
||||
Type::Uint32 |
|
||||
Type::Int32 => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ pub enum DOMErrorName {
|
|||
NetworkError = DOMExceptionConstants::NETWORK_ERR,
|
||||
AbortError = DOMExceptionConstants::ABORT_ERR,
|
||||
URLMismatchError = DOMExceptionConstants::URL_MISMATCH_ERR,
|
||||
TypeMismatchError = DOMExceptionConstants::TYPE_MISMATCH_ERR,
|
||||
QuotaExceededError = DOMExceptionConstants::QUOTA_EXCEEDED_ERR,
|
||||
TimeoutError = DOMExceptionConstants::TIMEOUT_ERR,
|
||||
InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR,
|
||||
|
@ -93,6 +94,7 @@ impl<'a> DOMExceptionMethods for &'a DOMException {
|
|||
DOMErrorName::NetworkError => "A network error occurred.",
|
||||
DOMErrorName::AbortError => "The operation was aborted.",
|
||||
DOMErrorName::URLMismatchError => "The given URL does not match another URL.",
|
||||
DOMErrorName::TypeMismatchError => "The given type does not match any expected type.",
|
||||
DOMErrorName::QuotaExceededError => "The quota has been exceeded.",
|
||||
DOMErrorName::TimeoutError => "The operation timed out.",
|
||||
DOMErrorName::InvalidNodeTypeError =>
|
||||
|
|
|
@ -197,6 +197,7 @@ pub mod closeevent;
|
|||
pub mod comment;
|
||||
pub mod console;
|
||||
mod create;
|
||||
pub mod crypto;
|
||||
pub mod customevent;
|
||||
pub mod dedicatedworkerglobalscope;
|
||||
pub mod document;
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#crypto-interface
|
||||
*
|
||||
*/
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface GlobalCrypto {
|
||||
readonly attribute Crypto crypto;
|
||||
};
|
||||
|
||||
Window implements GlobalCrypto;
|
||||
WorkerGlobalScope implements GlobalCrypto;
|
||||
|
||||
//[Exposed=(Window,Worker)]
|
||||
interface Crypto {
|
||||
//readonly attribute SubtleCrypto subtle;
|
||||
//ArrayBufferView getRandomValues(ArrayBufferView array);
|
||||
[Throws]
|
||||
ArrayBufferView getRandomValues(object array);
|
||||
};
|
|
@ -19,6 +19,7 @@ use dom::bindings::num::Finite;
|
|||
use dom::bindings::utils::{GlobalStaticData, Reflectable, WindowProxyHandler};
|
||||
use dom::browsercontext::BrowserContext;
|
||||
use dom::console::Console;
|
||||
use dom::crypto::Crypto;
|
||||
use dom::document::{Document, DocumentHelpers};
|
||||
use dom::element::Element;
|
||||
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
|
||||
|
@ -100,6 +101,7 @@ pub struct Window {
|
|||
script_chan: Box<ScriptChan+Send>,
|
||||
control_chan: ScriptControlChan,
|
||||
console: MutNullableHeap<JS<Console>>,
|
||||
crypto: MutNullableHeap<JS<Crypto>>,
|
||||
navigator: MutNullableHeap<JS<Navigator>>,
|
||||
image_cache_task: ImageCacheTask,
|
||||
image_cache_chan: ImageCacheChan,
|
||||
|
@ -358,6 +360,10 @@ impl<'a> WindowMethods for &'a Window {
|
|||
self.console.or_init(|| Console::new(GlobalRef::Window(self)))
|
||||
}
|
||||
|
||||
fn Crypto(self) -> Root<Crypto> {
|
||||
self.crypto.or_init(|| Crypto::new(GlobalRef::Window(self)))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-frameelement
|
||||
fn GetFrameElement(self) -> Option<Root<Element>> {
|
||||
self.browser_context().as_ref().unwrap().frame_element()
|
||||
|
@ -973,6 +979,7 @@ impl Window {
|
|||
image_cache_chan: image_cache_chan,
|
||||
control_chan: control_chan,
|
||||
console: Default::default(),
|
||||
crypto: Default::default(),
|
||||
compositor: DOMRefCell::new(compositor),
|
||||
page: page,
|
||||
navigator: Default::default(),
|
||||
|
|
|
@ -11,6 +11,7 @@ use dom::bindings::global::GlobalRef;
|
|||
use dom::bindings::js::{JS, Root, MutNullableHeap};
|
||||
use dom::bindings::utils::Reflectable;
|
||||
use dom::console::Console;
|
||||
use dom::crypto::Crypto;
|
||||
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScopeHelpers;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::workerlocation::WorkerLocation;
|
||||
|
@ -49,6 +50,7 @@ pub struct WorkerGlobalScope {
|
|||
location: MutNullableHeap<JS<WorkerLocation>>,
|
||||
navigator: MutNullableHeap<JS<WorkerNavigator>>,
|
||||
console: MutNullableHeap<JS<Console>>,
|
||||
crypto: MutNullableHeap<JS<Crypto>>,
|
||||
timers: TimerManager,
|
||||
devtools_chan: Option<DevtoolsControlChan>,
|
||||
}
|
||||
|
@ -68,6 +70,7 @@ impl WorkerGlobalScope {
|
|||
location: Default::default(),
|
||||
navigator: Default::default(),
|
||||
console: Default::default(),
|
||||
crypto: Default::default(),
|
||||
timers: TimerManager::new(),
|
||||
devtools_chan: devtools_chan,
|
||||
}
|
||||
|
@ -157,6 +160,10 @@ impl<'a> WorkerGlobalScopeMethods for &'a WorkerGlobalScope {
|
|||
self.console.or_init(|| Console::new(GlobalRef::Worker(self)))
|
||||
}
|
||||
|
||||
fn Crypto(self) -> Root<Crypto> {
|
||||
self.crypto.or_init(|| Crypto::new(GlobalRef::Worker(self)))
|
||||
}
|
||||
|
||||
fn Btoa(self, btoa: DOMString) -> Fallible<DOMString> {
|
||||
base64_btoa(btoa)
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ extern crate rustc_serialize;
|
|||
extern crate time;
|
||||
extern crate canvas;
|
||||
extern crate canvas_traits;
|
||||
extern crate rand;
|
||||
extern crate profile_traits;
|
||||
extern crate script_traits;
|
||||
extern crate selectors;
|
||||
|
|
|
@ -1075,6 +1075,7 @@ dependencies = [
|
|||
"plugins 0.0.1",
|
||||
"png 0.1.0 (git+https://github.com/servo/rust-png)",
|
||||
"profile_traits 0.0.1",
|
||||
"rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"script_traits 0.0.1",
|
||||
"selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
|
||||
|
|
|
@ -1055,6 +1055,7 @@ dependencies = [
|
|||
"plugins 0.0.1",
|
||||
"png 0.1.0 (git+https://github.com/servo/rust-png)",
|
||||
"profile_traits 0.0.1",
|
||||
"rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"script_traits 0.0.1",
|
||||
"selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
|
||||
|
|
|
@ -963,6 +963,7 @@ dependencies = [
|
|||
"plugins 0.0.1",
|
||||
"png 0.1.0 (git+https://github.com/servo/rust-png)",
|
||||
"profile_traits 0.0.1",
|
||||
"rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"script_traits 0.0.1",
|
||||
"selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
|
||||
|
|
Загрузка…
Ссылка в новой задаче