diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2021-09-30 20:02:55 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-09-30 20:02:09 +0200 |
commit | 2c6c9b73c88bd2feea66df8766212c2e586ea9aa (patch) | |
tree | b1e0712844874577ac463a506e9164e93b93493f | |
parent | becbb0ea97bf2da194246f1dde1d2b8fba16946d (diff) | |
download | serenity-2c6c9b73c88bd2feea66df8766212c2e586ea9aa.zip |
LibWeb: Add the Web::Crypto namespace, built-in, and getRandomValues
Since we don't support IDL typedefs or unions yet, the responsibility
of verifying the type of the argument is temporarily moved from the
generated Wrapper to the implementation.
-rw-r--r-- | Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp | 22 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Bindings/WindowObject.cpp | 14 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Bindings/WindowObject.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Crypto/Crypto.cpp | 37 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Crypto/Crypto.h | 38 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Crypto/Crypto.idl | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Window.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Window.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp | 4 |
12 files changed, 129 insertions, 10 deletions
diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp index 1e86f07c1c..ce258404eb 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp @@ -726,7 +726,7 @@ int main(int argc, char** argv) auto data = file_or_error.value()->read_all(); auto interface = IDL::parse_interface(path, data); - if (namespace_.is_one_of("CSS", "DOM", "HTML", "UIEvents", "Geometry", "HighResolutionTime", "NavigationTiming", "RequestIdleCallback", "SVG", "XHR", "URL")) { + if (namespace_.is_one_of("Crypto", "CSS", "DOM", "HTML", "UIEvents", "Geometry", "HighResolutionTime", "NavigationTiming", "RequestIdleCallback", "SVG", "XHR", "URL")) { StringBuilder builder; builder.append(namespace_); builder.append("::"); @@ -1346,7 +1346,9 @@ static void generate_header(IDL::Interface const& interface) #include <LibWeb/Bindings/Wrapper.h> // FIXME: This is very strange. -#if __has_include(<LibWeb/CSS/@name@.h>) +#if __has_include(<LibWeb/Crypto/@name@.h>) +# include <LibWeb/Crypto/@name@.h> +#elif __has_include(<LibWeb/CSS/@name@.h>) # include <LibWeb/CSS/@name@.h> #elif __has_include(<LibWeb/DOM/@name@.h>) # include <LibWeb/DOM/@name@.h> @@ -2428,7 +2430,9 @@ void generate_constructor_implementation(IDL::Interface const& interface) #include <LibWeb/Bindings/@wrapper_class@.h> #include <LibWeb/Bindings/ExceptionOrUtils.h> #include <LibWeb/Bindings/WindowObject.h> -#if __has_include(<LibWeb/CSS/@name@.h>) +#if __has_include(<LibWeb/Crypto/@name@.h>) +# include <LibWeb/Crypto/@name@.h> +#elif __has_include(<LibWeb/CSS/@name@.h>) # include <LibWeb/CSS/@name@.h> #elif __has_include(<LibWeb/DOM/@name@.h>) # include <LibWeb/DOM/@name@.h> @@ -2730,7 +2734,9 @@ void generate_prototype_implementation(IDL::Interface const& interface) #if __has_include(<LibWeb/Bindings/@prototype_base_class@.h>) # include <LibWeb/Bindings/@prototype_base_class@.h> #endif -#if __has_include(<LibWeb/CSS/@name@.h>) +#if __has_include(<LibWeb/Crypto/@name@.h>) +# include <LibWeb/Crypto/@name@.h> +#elif __has_include(<LibWeb/CSS/@name@.h>) # include <LibWeb/CSS/@name@.h> #elif __has_include(<LibWeb/DOM/@name@.h>) # include <LibWeb/DOM/@name@.h> @@ -3179,7 +3185,9 @@ static void generate_iterator_header(IDL::Interface const& interface) #include <LibWeb/Bindings/Wrapper.h> // FIXME: This is very strange. -#if __has_include(<LibWeb/CSS/@name@.h>) +#if __has_include(<LibWeb/Crypto/@name@.h>) +# include <LibWeb/Crypto/@name@.h> +#elif __has_include(<LibWeb/CSS/@name@.h>) # include <LibWeb/CSS/@name@.h> #elif __has_include(<LibWeb/DOM/@name@.h>) # include <LibWeb/DOM/@name@.h> @@ -3356,7 +3364,9 @@ void generate_iterator_prototype_implementation(IDL::Interface const& interface) #include <LibWeb/Bindings/ExceptionOrUtils.h> #include <LibWeb/Bindings/WindowObject.h> -#if __has_include(<LibWeb/CSS/@name@.h>) +#if __has_include(<LibWeb/Crypto/@name@.h>) +# include <LibWeb/Crypto/@name@.h> +#elif __has_include(<LibWeb/CSS/@name@.h>) # include <LibWeb/CSS/@name@.h> #elif __has_include(<LibWeb/DOM/@name@.h>) # include <LibWeb/DOM/@name@.h> diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp index 612a2db08d..4492a47c41 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp +++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp @@ -14,6 +14,7 @@ #include <LibJS/Runtime/Shape.h> #include <LibTextCodec/Decoder.h> #include <LibWeb/Bindings/CSSStyleDeclarationWrapper.h> +#include <LibWeb/Bindings/CryptoWrapper.h> #include <LibWeb/Bindings/DocumentWrapper.h> #include <LibWeb/Bindings/ElementWrapper.h> #include <LibWeb/Bindings/EventTargetConstructor.h> @@ -30,6 +31,8 @@ #include <LibWeb/Bindings/Replaceable.h> #include <LibWeb/Bindings/ScreenWrapper.h> #include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/Bindings/WindowObjectHelper.h> +#include <LibWeb/Crypto/Crypto.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/Window.h> @@ -39,8 +42,6 @@ #include <LibWeb/Page/Page.h> #include <LibWeb/WebAssembly/WebAssemblyObject.h> -#include <LibWeb/Bindings/WindowObjectHelper.h> - namespace Web::Bindings { WindowObject::WindowObject(DOM::Window& impl) @@ -65,6 +66,7 @@ void WindowObject::initialize_global_object() define_native_accessor("document", document_getter, {}, JS::Attribute::Enumerable); define_native_accessor("history", history_getter, {}, JS::Attribute::Enumerable); define_native_accessor("performance", performance_getter, {}, JS::Attribute::Enumerable); + define_native_accessor("crypto", crypto_getter, {}, JS::Attribute::Enumerable); define_native_accessor("screen", screen_getter, {}, JS::Attribute::Enumerable); define_native_accessor("innerWidth", inner_width_getter, {}, JS::Attribute::Enumerable); define_native_accessor("innerHeight", inner_height_getter, {}, JS::Attribute::Enumerable); @@ -497,6 +499,14 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::event_setter) REPLACEABLE_PROPERTY_SETTER(WindowObject, event); } +JS_DEFINE_NATIVE_FUNCTION(WindowObject::crypto_getter) +{ + auto* impl = impl_from(vm, global_object); + if (!impl) + return {}; + return wrap(global_object, impl->crypto()); +} + JS_DEFINE_NATIVE_FUNCTION(WindowObject::inner_width_getter) { auto* impl = impl_from(vm, global_object); diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.h b/Userland/Libraries/LibWeb/Bindings/WindowObject.h index 911a93bee7..2fb2609c53 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.h @@ -111,6 +111,8 @@ private: JS_DECLARE_NATIVE_FUNCTION(queue_microtask); + JS_DECLARE_NATIVE_FUNCTION(crypto_getter); + #define __ENUMERATE(attribute, event_name) \ JS_DECLARE_NATIVE_FUNCTION(attribute##_getter); \ JS_DECLARE_NATIVE_FUNCTION(attribute##_setter); diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h index b18f0d2346..742db85dba 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h @@ -30,6 +30,8 @@ #include <LibWeb/Bindings/CloseEventPrototype.h> #include <LibWeb/Bindings/CommentConstructor.h> #include <LibWeb/Bindings/CommentPrototype.h> +#include <LibWeb/Bindings/CryptoConstructor.h> +#include <LibWeb/Bindings/CryptoPrototype.h> #include <LibWeb/Bindings/CustomEventConstructor.h> #include <LibWeb/Bindings/CustomEventPrototype.h> #include <LibWeb/Bindings/DOMExceptionConstructor.h> @@ -271,6 +273,7 @@ auto& vm = this->vm(); \ ADD_WINDOW_OBJECT_INTERFACE(AbortController) \ ADD_WINDOW_OBJECT_INTERFACE(AbortSignal) \ + ADD_WINDOW_OBJECT_INTERFACE(Crypto) \ ADD_WINDOW_OBJECT_INTERFACE(CSSRule) \ ADD_WINDOW_OBJECT_INTERFACE(CSSRuleList) \ ADD_WINDOW_OBJECT_INTERFACE(CSSStyleDeclaration) \ diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index d530f17050..a2f0517ea0 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES Bindings/ScriptExecutionContext.cpp Bindings/WindowObject.cpp Bindings/Wrappable.cpp + Crypto/Crypto.cpp CSS/CSSConditionRule.cpp CSS/CSSGroupingRule.cpp CSS/CSSImportRule.cpp @@ -341,6 +342,7 @@ function(libweb_js_wrapper class) add_dependencies(all_generated generate_${basename}Prototype.cpp) endfunction() +libweb_js_wrapper(Crypto/Crypto) libweb_js_wrapper(CSS/CSSRule) libweb_js_wrapper(CSS/CSSRuleList) libweb_js_wrapper(CSS/CSSStyleDeclaration) diff --git a/Userland/Libraries/LibWeb/Crypto/Crypto.cpp b/Userland/Libraries/LibWeb/Crypto/Crypto.cpp new file mode 100644 index 0000000000..64ba54f6ed --- /dev/null +++ b/Userland/Libraries/LibWeb/Crypto/Crypto.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/Random.h> +#include <LibJS/Runtime/TypedArray.h> +#include <LibWeb/Bindings/Wrapper.h> +#include <LibWeb/Crypto/Crypto.h> + +namespace Web::Crypto { + +DOM::ExceptionOr<JS::Value> Crypto::get_random_values(JS::Value array) const +{ + // 1. If array is not an Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, or BigUint64Array, then throw a TypeMismatchError and terminate the algorithm. + if (!array.is_object() || !(is<JS::Int8Array>(array.as_object()) || is<JS::Uint8Array>(array.as_object()) || is<JS::Uint8ClampedArray>(array.as_object()) || is<JS::Int16Array>(array.as_object()) || is<JS::Uint16Array>(array.as_object()) || is<JS::Int32Array>(array.as_object()) || is<JS::Uint32Array>(array.as_object()) || is<JS::BigInt64Array>(array.as_object()) || is<JS::BigUint64Array>(array.as_object()))) + return DOM::TypeMismatchError::create("array must be one of Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, or BigUint64Array"); + auto& typed_array = static_cast<JS::TypedArrayBase&>(array.as_object()); + + // 2. If the byteLength of array is greater than 65536, throw a QuotaExceededError and terminate the algorithm. + if (typed_array.byte_length() > 65536) + return DOM::QuotaExceededError::create("array's byteLength may not be greater than 65536"); + + // IMPLEMENTATION DEFINED: If the viewed array buffer is detached, throw a InvalidStateError and terminate the algorithm. + if (typed_array.viewed_array_buffer()->is_detached()) + return DOM::InvalidStateError::create("array is detached"); + // FIXME: Handle SharedArrayBuffers + + // 3. Overwrite all elements of array with cryptographically strong random values of the appropriate type. + fill_with_random(typed_array.viewed_array_buffer()->buffer().data(), typed_array.viewed_array_buffer()->buffer().size()); + + // 4. Return array. + return array; +} + +} diff --git a/Userland/Libraries/LibWeb/Crypto/Crypto.h b/Userland/Libraries/LibWeb/Crypto/Crypto.h new file mode 100644 index 0000000000..d469b7a48f --- /dev/null +++ b/Userland/Libraries/LibWeb/Crypto/Crypto.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibJS/Runtime/Value.h> +#include <LibWeb/Bindings/Wrappable.h> +#include <LibWeb/DOM/ExceptionOr.h> + +namespace Web::Crypto { + +class Crypto : public Bindings::Wrappable + , public RefCounted<Crypto> + , public Weakable<Crypto> { +public: + using WrapperType = Bindings::CryptoWrapper; + + static NonnullRefPtr<Crypto> create() + { + return adopt_ref(*new Crypto()); + } + + DOM::ExceptionOr<JS::Value> get_random_values(JS::Value array) const; + +private: + Crypto() = default; +}; + +} + +namespace Web::Bindings { + +CryptoWrapper* wrap(JS::GlobalObject&, Crypto::Crypto&); + +} diff --git a/Userland/Libraries/LibWeb/Crypto/Crypto.idl b/Userland/Libraries/LibWeb/Crypto/Crypto.idl new file mode 100644 index 0000000000..64941a4980 --- /dev/null +++ b/Userland/Libraries/LibWeb/Crypto/Crypto.idl @@ -0,0 +1,7 @@ +[Exposed=(Window,Worker)] +interface Crypto { + // TODO: [SecureContext] readonly attribute SubtleCrypto subtle; + + // FIXME: the argument and the return value should be of type ArrayBufferView + any getRandomValues(any array); +}; diff --git a/Userland/Libraries/LibWeb/DOM/Window.cpp b/Userland/Libraries/LibWeb/DOM/Window.cpp index 7ca96a76c9..c476b0c38f 100644 --- a/Userland/Libraries/LibWeb/DOM/Window.cpp +++ b/Userland/Libraries/LibWeb/DOM/Window.cpp @@ -7,6 +7,7 @@ #include <LibGUI/DisplayLink.h> #include <LibJS/Runtime/FunctionObject.h> #include <LibWeb/CSS/ResolvedCSSStyleDeclaration.h> +#include <LibWeb/Crypto/Crypto.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/EventDispatcher.h> @@ -94,6 +95,7 @@ Window::Window(Document& document) : EventTarget(static_cast<Bindings::ScriptExecutionContext&>(document)) , m_associated_document(document) , m_performance(make<HighResolutionTime::Performance>(*this)) + , m_crypto(Crypto::Crypto::create()) , m_screen(CSS::Screen::create(*this)) { } diff --git a/Userland/Libraries/LibWeb/DOM/Window.h b/Userland/Libraries/LibWeb/DOM/Window.h index 5199fa3bf6..871da29dec 100644 --- a/Userland/Libraries/LibWeb/DOM/Window.h +++ b/Userland/Libraries/LibWeb/DOM/Window.h @@ -74,6 +74,8 @@ public: HighResolutionTime::Performance& performance() { return *m_performance; } + Crypto::Crypto& crypto() { return *m_crypto; } + CSS::Screen& screen() { return *m_screen; } Event const* current_event() const { return m_current_event; } @@ -107,6 +109,7 @@ private: HashMap<int, NonnullRefPtr<Timer>> m_timers; NonnullOwnPtr<HighResolutionTime::Performance> m_performance; + NonnullRefPtr<Crypto::Crypto> m_crypto; NonnullRefPtr<CSS::Screen> m_screen; RefPtr<Event> m_current_event; diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 6ef1f9c6c7..66f27a3e00 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -13,6 +13,10 @@ struct ParsedCookie; enum class Source; } +namespace Web::Crypto { +class Crypto; +} + namespace Web::CSS { class CalculatedStyleValue; class CSSRule; @@ -262,6 +266,7 @@ class URLSearchParamsIterator; namespace Web::Bindings { class AbortControllerWrapper; class AbortSignalWrapper; +class CryptoWrapper; class CSSRuleListWrapper; class CSSRuleWrapper; class CSSStyleDeclarationWrapper; diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp index 8511d69aaa..e95333b82c 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp @@ -361,7 +361,7 @@ JS::Value to_js_value(Wasm::Value& wasm_value, JS::GlobalObject& global_object) { switch (wasm_value.type().kind()) { case Wasm::ValueType::I64: - return global_object.heap().allocate<JS::BigInt>(global_object, Crypto::SignedBigInteger::create_from(wasm_value.to<i64>().value())); + return global_object.heap().allocate<JS::BigInt>(global_object, ::Crypto::SignedBigInteger::create_from(wasm_value.to<i64>().value())); case Wasm::ValueType::I32: return JS::Value(wasm_value.to<i32>().value()); case Wasm::ValueType::F64: @@ -382,7 +382,7 @@ JS::Value to_js_value(Wasm::Value& wasm_value, JS::GlobalObject& global_object) Optional<Wasm::Value> to_webassembly_value(JS::Value value, const Wasm::ValueType& type, JS::GlobalObject& global_object) { - static Crypto::SignedBigInteger two_64 = "1"_sbigint.shift_left(64); + static ::Crypto::SignedBigInteger two_64 = "1"_sbigint.shift_left(64); auto& vm = global_object.vm(); switch (type.kind()) { |