Skip to content

Commit

Permalink
LibWeb: Add WebSocket bindings
Browse files Browse the repository at this point in the history
The WebSocket bindings match the original specification from the
WHATWG living standard, but do not match the later update of the
standard that involves FETCH. The FETCH update will be handled later
since the changes would also affect XMLHttpRequest.
  • Loading branch information
Dexesttp authored and linusg committed Apr 25, 2021
1 parent 68bfb46 commit 22413ef
Show file tree
Hide file tree
Showing 16 changed files with 593 additions and 1 deletion.
42 changes: 42 additions & 0 deletions Base/res/html/misc/websocket.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebSocket Test</title>
</head>
<body>
<h2>WebSocket Test</h2>
<div id="output"></div>
<script type="text/javascript">
var output = document.getElementById('output');

function println(message) {
const p = document.createElement('p');
p.innerHTML = message;
output.appendChild(p);
}

// Websocket echo server, provided from https://www.websocket.org/echo.html
var targetUrl = 'wss:https://echo.websocket.org';
var messageContent = 'Hello friends :^)';
println('<span style="color: blue;">Connecting to:</span> ' + targetUrl);
websocket = new WebSocket(targetUrl);
websocket.onopen = function() {
println('<span style="color: green;">Connected to:</span> ' + targetUrl);
println('<span style="color: blue;">Sending Message:</span> ' + messageContent);
websocket.send(messageContent);
};
websocket.onmessage = function(event) {
println('<span style="color: green;">Received Response:</span> ' + event.data);
println('<span style="color: blue;">Closing connection...</span> ');
websocket.close();
};
websocket.onerror = function(evt) {
println('<span style="color: red;">ERROR:</span> ' + evt.data);
};
websocket.onclose = function() {
println('<span style="color: green;">Connection closed!</span>');
};
</script>
</body>
</html>
1 change: 1 addition & 0 deletions Base/res/html/misc/welcome.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ <h1>Welcome to the Serenity Browser!</h1>
<p>This page loaded in <b><span id="loadtime"></span></b> ms</p>
<p>Some small test pages:</p>
<ul>
<li><a href="websocket.html">WebSocket API Test</a></li>
<li><a href="cookie.html">document.cookie</a></li>
<li><a href="last-of-type.html">CSS :last-of-type selector</a></li>
<li><a href="first-of-type.html">CSS :first-of-type selector</a></li>
Expand Down
4 changes: 3 additions & 1 deletion Userland/Applications/Browser/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <LibGUI/TabWidget.h>
#include <LibGUI/Window.h>
#include <LibGfx/Bitmap.h>
#include <LibWeb/HTML/WebSocket.h>
#include <LibWeb/Loader/ContentFilter.h>
#include <LibWeb/Loader/ResourceLoader.h>
#include <stdio.h>
Expand Down Expand Up @@ -66,8 +67,9 @@ int main(int argc, char** argv)

auto app = GUI::Application::construct(argc, argv);

// Connect to the ProtocolServer immediately so we can drop the "unix" pledge.
// Connect to the ProtocolServer and the WebSocket service immediately so we can drop the "unix" pledge.
Web::ResourceLoader::the();
Web::HTML::WebSocketClientManager::the();

// Connect to LaunchServer immediately and let it know that we won't ask for anything other than opening
// the user's downloads directory.
Expand Down
6 changes: 6 additions & 0 deletions Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
* SPDX-License-Identifier: BSD-2-Clause
*/

#include <LibWeb/Bindings/CloseEventWrapper.h>
#include <LibWeb/Bindings/EventWrapper.h>
#include <LibWeb/Bindings/EventWrapperFactory.h>
#include <LibWeb/Bindings/MessageEventWrapper.h>
#include <LibWeb/Bindings/MouseEventWrapper.h>

namespace Web {
namespace Bindings {

EventWrapper* wrap(JS::GlobalObject& global_object, DOM::Event& event)
{
if (is<HTML::MessageEvent>(event))
return static_cast<MessageEventWrapper*>(wrap_impl(global_object, static_cast<HTML::MessageEvent&>(event)));
if (is<HTML::CloseEvent>(event))
return static_cast<CloseEventWrapper*>(wrap_impl(global_object, static_cast<HTML::CloseEvent&>(event)));
if (is<UIEvents::MouseEvent>(event))
return static_cast<MouseEventWrapper*>(wrap_impl(global_object, static_cast<UIEvents::MouseEvent&>(event)));
return static_cast<EventWrapper*>(wrap_impl(global_object, event));
Expand Down
9 changes: 9 additions & 0 deletions Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <LibWeb/Bindings/CanvasRenderingContext2DPrototype.h>
#include <LibWeb/Bindings/CharacterDataConstructor.h>
#include <LibWeb/Bindings/CharacterDataPrototype.h>
#include <LibWeb/Bindings/CloseEventConstructor.h>
#include <LibWeb/Bindings/CloseEventPrototype.h>
#include <LibWeb/Bindings/CommentConstructor.h>
#include <LibWeb/Bindings/CommentPrototype.h>
#include <LibWeb/Bindings/DOMExceptionConstructor.h>
Expand Down Expand Up @@ -177,6 +179,8 @@
#include <LibWeb/Bindings/ImageConstructor.h>
#include <LibWeb/Bindings/ImageDataConstructor.h>
#include <LibWeb/Bindings/ImageDataPrototype.h>
#include <LibWeb/Bindings/MessageEventConstructor.h>
#include <LibWeb/Bindings/MessageEventPrototype.h>
#include <LibWeb/Bindings/MouseEventConstructor.h>
#include <LibWeb/Bindings/MouseEventPrototype.h>
#include <LibWeb/Bindings/NodeConstructor.h>
Expand Down Expand Up @@ -213,6 +217,8 @@
#include <LibWeb/Bindings/TextPrototype.h>
#include <LibWeb/Bindings/UIEventConstructor.h>
#include <LibWeb/Bindings/UIEventPrototype.h>
#include <LibWeb/Bindings/WebSocketConstructor.h>
#include <LibWeb/Bindings/WebSocketPrototype.h>
#include <LibWeb/Bindings/XMLHttpRequestConstructor.h>
#include <LibWeb/Bindings/XMLHttpRequestEventTargetConstructor.h>
#include <LibWeb/Bindings/XMLHttpRequestEventTargetPrototype.h>
Expand All @@ -233,6 +239,7 @@
auto& vm = this->vm(); \
ADD_WINDOW_OBJECT_INTERFACE(CanvasRenderingContext2D) \
ADD_WINDOW_OBJECT_INTERFACE(CharacterData) \
ADD_WINDOW_OBJECT_INTERFACE(CloseEvent) \
ADD_WINDOW_OBJECT_INTERFACE(Comment) \
ADD_WINDOW_OBJECT_INTERFACE(CSSStyleSheet) \
ADD_WINDOW_OBJECT_INTERFACE(DocumentFragment) \
Expand Down Expand Up @@ -315,6 +322,7 @@
ADD_WINDOW_OBJECT_INTERFACE(HTMLUnknownElement) \
ADD_WINDOW_OBJECT_INTERFACE(HTMLVideoElement) \
ADD_WINDOW_OBJECT_INTERFACE(ImageData) \
ADD_WINDOW_OBJECT_INTERFACE(MessageEvent) \
ADD_WINDOW_OBJECT_INTERFACE(MouseEvent) \
ADD_WINDOW_OBJECT_INTERFACE(Node) \
ADD_WINDOW_OBJECT_INTERFACE(Performance) \
Expand All @@ -333,6 +341,7 @@
ADD_WINDOW_OBJECT_INTERFACE(SVGSVGElement) \
ADD_WINDOW_OBJECT_INTERFACE(Text) \
ADD_WINDOW_OBJECT_INTERFACE(UIEvent) \
ADD_WINDOW_OBJECT_INTERFACE(WebSocket) \
ADD_WINDOW_OBJECT_INTERFACE(XMLHttpRequest) \
ADD_WINDOW_OBJECT_INTERFACE(XMLHttpRequestEventTarget) \
ADD_WINDOW_OBJECT_CONSTRUCTOR_AND_PROTOTYPE(Image, ImageConstructor, HTMLImageElementPrototype)
4 changes: 4 additions & 0 deletions Userland/Libraries/LibWeb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ set(SOURCES
HTML/Parser/StackOfOpenElements.cpp
HTML/SubmitEvent.cpp
HTML/TagNames.cpp
HTML/WebSocket.cpp
HighResolutionTime/Performance.cpp
InProcessWebView.cpp
Layout/BlockBox.cpp
Expand Down Expand Up @@ -318,6 +319,7 @@ libweb_js_wrapper(DOM/Node)
libweb_js_wrapper(DOM/Range)
libweb_js_wrapper(DOM/Text)
libweb_js_wrapper(HTML/CanvasRenderingContext2D)
libweb_js_wrapper(HTML/CloseEvent)
libweb_js_wrapper(HTML/HTMLAnchorElement)
libweb_js_wrapper(HTML/HTMLAreaElement)
libweb_js_wrapper(HTML/HTMLAudioElement)
Expand Down Expand Up @@ -390,7 +392,9 @@ libweb_js_wrapper(HTML/HTMLUListElement)
libweb_js_wrapper(HTML/HTMLUnknownElement)
libweb_js_wrapper(HTML/HTMLVideoElement)
libweb_js_wrapper(HTML/ImageData)
libweb_js_wrapper(HTML/MessageEvent)
libweb_js_wrapper(HTML/SubmitEvent)
libweb_js_wrapper(HTML/WebSocket)
libweb_js_wrapper(HighResolutionTime/Performance)
libweb_js_wrapper(NavigationTiming/PerformanceTiming)
libweb_js_wrapper(SVG/SVGElement)
Expand Down
6 changes: 6 additions & 0 deletions Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,12 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
auto @cpp_name@ = @js_name@@[email protected]_u32(global_object);
if (vm.exception())
@return_statement@
)~~~");
} else if (parameter.type.name == "unsigned short") {
scoped_generator.append(R"~~~(
auto @cpp_name@ = (u16)@js_name@@[email protected]_u32(global_object);
if (vm.exception())
@return_statement@
)~~~");
} else if (parameter.type.name == "EventHandler") {
// x.onfoo = function() { ... }
Expand Down
6 changes: 6 additions & 0 deletions Userland/Libraries/LibWeb/Forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ enum class QuirksMode;

namespace Web::HTML {
class CanvasRenderingContext2D;
class CloseEvent;
class EventHandler;
class HTMLAnchorElement;
class HTMLAreaElement;
Expand Down Expand Up @@ -133,6 +134,8 @@ class HTMLUListElement;
class HTMLUnknownElement;
class HTMLVideoElement;
class ImageData;
class MessageEvent;
class WebSocket;
}

namespace Web::HighResolutionTime {
Expand Down Expand Up @@ -201,6 +204,7 @@ class CSSStyleDeclarationWrapper;
class CSSStyleSheetWrapper;
class CanvasRenderingContext2DWrapper;
class CharacterDataWrapper;
class CloseEventWrapper;
class CommentWrapper;
class DocumentFragmentWrapper;
class DocumentTypeWrapper;
Expand Down Expand Up @@ -285,6 +289,7 @@ class HTMLUnknownElementWrapper;
class HTMLVideoElementWrapper;
class ImageDataWrapper;
class LocationObject;
class MessageEventWrapper;
class MouseEventWrapper;
class NodeWrapper;
class PerformanceTimingWrapper;
Expand All @@ -303,6 +308,7 @@ class StyleSheetWrapper;
class StyleSheetListWrapper;
class TextWrapper;
class UIEventWrapper;
class WebSocketWrapper;
class WindowObject;
class Wrappable;
class Wrapper;
Expand Down
42 changes: 42 additions & 0 deletions Userland/Libraries/LibWeb/HTML/CloseEvent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2021, Dex♪ <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <LibWeb/DOM/Event.h>

namespace Web::HTML {

class CloseEvent : public DOM::Event {
public:
using WrapperType = Bindings::CloseEventWrapper;

static NonnullRefPtr<CloseEvent> create(const FlyString& event_name, bool was_clean, u16 code, const String& reason)
{
return adopt_ref(*new CloseEvent(event_name, was_clean, code, reason));
}

virtual ~CloseEvent() override = default;

bool was_clean() { return m_was_clean; }
u16 code() const { return m_code; }
String reason() const { return m_reason; }

protected:
CloseEvent(const FlyString& event_name, bool was_clean, u16 code, const String& reason)
: Event(event_name)
, m_was_clean(was_clean)
, m_code(code)
, m_reason(reason)
{
}

bool m_was_clean { false };
u16 m_code { 0 };
String m_reason;
};

}
7 changes: 7 additions & 0 deletions Userland/Libraries/LibWeb/HTML/CloseEvent.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
interface CloseEvent : Event {

readonly attribute boolean wasClean;
readonly attribute unsigned short code;
readonly attribute USVString reason;

};
39 changes: 39 additions & 0 deletions Userland/Libraries/LibWeb/HTML/MessageEvent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2021, Dex♪ <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <LibWeb/DOM/Event.h>

namespace Web::HTML {

class MessageEvent : public DOM::Event {
public:
using WrapperType = Bindings::MessageEventWrapper;

static NonnullRefPtr<MessageEvent> create(const FlyString& event_name, const String& data, const String& origin)
{
return adopt_ref(*new MessageEvent(event_name, data, origin));
}

virtual ~MessageEvent() override = default;

const String& data() const { return m_data; }
const String& origin() const { return m_origin; }

protected:
MessageEvent(const FlyString& event_name, const String& data, const String& origin)
: DOM::Event(event_name)
, m_data(data)
, m_origin(origin)
{
}

String m_data;
String m_origin;
};

}
7 changes: 7 additions & 0 deletions Userland/Libraries/LibWeb/HTML/MessageEvent.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
interface MessageEvent : Event {

// FIXME: This should be of type "any" instead of "USVString"
readonly attribute USVString data;
readonly attribute USVString origin;

};
Loading

0 comments on commit 22413ef

Please sign in to comment.