Serenity Operating System
1/*
2 * Copyright (c) 2020, Nicholas Hollett <niax@niax.co.uk>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include "ConnectionFromClient.h"
8#include "Launcher.h"
9#include <AK/HashMap.h>
10#include <AK/URL.h>
11#include <LaunchServer/LaunchClientEndpoint.h>
12
13namespace LaunchServer {
14
15static HashMap<int, RefPtr<ConnectionFromClient>> s_connections;
16ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> client_socket, int client_id)
17 : IPC::ConnectionFromClient<LaunchClientEndpoint, LaunchServerEndpoint>(*this, move(client_socket), client_id)
18{
19 s_connections.set(client_id, *this);
20}
21
22void ConnectionFromClient::die()
23{
24 s_connections.remove(client_id());
25}
26
27Messages::LaunchServer::OpenUrlResponse ConnectionFromClient::open_url(URL const& url, DeprecatedString const& handler_name)
28{
29 if (!m_allowlist.is_empty()) {
30 bool allowed = false;
31 auto request_url_without_fragment = url;
32 request_url_without_fragment.set_fragment({});
33 for (auto& allowed_handler : m_allowlist) {
34 if (allowed_handler.handler_name == handler_name
35 && (allowed_handler.any_url || allowed_handler.urls.contains_slow(request_url_without_fragment))) {
36 allowed = true;
37 break;
38 }
39 }
40 if (!allowed) {
41 // You are not on the list, go home!
42 did_misbehave(DeprecatedString::formatted("Client requested a combination of handler/URL that was not on the list: '{}' with '{}'", handler_name, url).characters());
43 return nullptr;
44 }
45 }
46
47 return Launcher::the().open_url(url, handler_name);
48}
49
50Messages::LaunchServer::GetHandlersForUrlResponse ConnectionFromClient::get_handlers_for_url(URL const& url)
51{
52 return Launcher::the().handlers_for_url(url);
53}
54
55Messages::LaunchServer::GetHandlersWithDetailsForUrlResponse ConnectionFromClient::get_handlers_with_details_for_url(URL const& url)
56{
57 return Launcher::the().handlers_with_details_for_url(url);
58}
59
60void ConnectionFromClient::add_allowed_url(URL const& url)
61{
62 if (m_allowlist_is_sealed) {
63 did_misbehave("Got request to add more allowed handlers after list was sealed");
64 return;
65 }
66
67 if (!url.is_valid()) {
68 did_misbehave("Got request to allow invalid URL");
69 return;
70 }
71
72 m_allowlist.empend(DeprecatedString(), false, Vector<URL> { url });
73}
74
75void ConnectionFromClient::add_allowed_handler_with_any_url(DeprecatedString const& handler_name)
76{
77 if (m_allowlist_is_sealed) {
78 did_misbehave("Got request to add more allowed handlers after list was sealed");
79 return;
80 }
81
82 if (handler_name.is_empty()) {
83 did_misbehave("Got request to allow empty handler name");
84 return;
85 }
86
87 m_allowlist.empend(handler_name, true, Vector<URL>());
88}
89
90void ConnectionFromClient::add_allowed_handler_with_only_specific_urls(DeprecatedString const& handler_name, Vector<URL> const& urls)
91{
92 if (m_allowlist_is_sealed) {
93 did_misbehave("Got request to add more allowed handlers after list was sealed");
94 return;
95 }
96
97 if (handler_name.is_empty()) {
98 did_misbehave("Got request to allow empty handler name");
99 return;
100 }
101
102 if (urls.is_empty()) {
103 did_misbehave("Got request to allow empty URL list");
104 return;
105 }
106
107 m_allowlist.empend(handler_name, false, urls);
108}
109
110void ConnectionFromClient::seal_allowlist()
111{
112 if (m_allowlist_is_sealed) {
113 did_misbehave("Got more than one request to seal the allowed handlers list");
114 return;
115 }
116
117 m_allowlist_is_sealed = true;
118}
119
120}