Skip to content

Commit

Permalink
fix(runtime/) use 'URL', don't clobber config when given in 'createWi…
Browse files Browse the repository at this point in the history
…ndow'
  • Loading branch information
jwerle committed Jan 5, 2025
1 parent 863b4b2 commit 23657c7
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 104 deletions.
2 changes: 1 addition & 1 deletion api/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ export async function getScreenSize () {
}

function throwOnInvalidIndex (index) {
if (index === undefined || typeof index !== 'number' || !Number.isInteger(index) || index < 0) {
if (index === undefined || typeof index !== 'number' || !Number.isInteger(index) || index < -1) {
throw new Error(`Invalid window index: ${index} (must be a positive integer number)`)
}
}
Expand Down
6 changes: 3 additions & 3 deletions api/service-worker/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -376,14 +376,14 @@ export class ServiceWorkerContainer extends EventTarget {
return new ServiceWorkerRegistration(info, serviceWorker)
}

async getRegistrations () {
async getRegistrations (options) {
if (globalThis.top && globalThis.window && globalThis.top !== globalThis.window) {
try {
return await globalThis.top.navigator.serviceWorker.getRegistrations()
return await globalThis.top.navigator.serviceWorker.getRegistrations(options)
} catch (err) {}
}

const result = await ipc.request('serviceWorker.getRegistrations')
const result = await ipc.request('serviceWorker.getRegistrations', options)

if (result.err) {
throw result.err
Expand Down
5 changes: 5 additions & 0 deletions api/service-worker/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ export class ServiceWorkerInstance extends Worker {
options.args = JSON.parse(decodeURIComponent(decodeURIComponent(info.serializedWorkerArgs)))
}
}

if (options?.args?.index) {
options.args.index = globalThis.__args.index
}
}

super(filename, {
name: `ServiceWorker (${options?.info?.pathname ?? filename})`,
...options,
Expand Down
4 changes: 2 additions & 2 deletions bin/functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,8 @@ function determine_cxx () {
read_env_data

if [ ! "$CXX" ]; then
# TODO(@mribbons): yum support
if [ -n "$dpkg" ]; then
# TODO(@jwerle): yum support
if [[ "$(host_os)" == "Linux" ]] && [ -n "$dpkg" ]; then
tmp="$(mktemp)"
{
dpkg -S clang 2>&1| grep "clang++" | cut -d" " -f 2 | while read clang; do
Expand Down
128 changes: 77 additions & 51 deletions src/runtime/bridge/bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -597,13 +597,12 @@ export * from '{{url}}'
});

if (fetched) {
// FIXME(@jwerle): revisit timeout
//this->core->setTimeout(32000, [request] () mutable {
//if (request->isActive()) {
//auto response = SchemeHandlers::Response(request, 408);
//response.fail("ServiceWorker request timed out.");
//}
//});
this->getRuntime()->services.timers.setTimeout(32000, [request] () mutable {
if (request->isActive()) {
auto response = SchemeHandlers::Response(request, 408);
response.fail("ServiceWorker request timed out.");
}
});
return;
}
}
Expand Down Expand Up @@ -739,13 +738,12 @@ export * from '{{url}}'
});

if (fetched) {
// FIXME(@jwerle): revisit timeout
//this->core->setTimeout(32000, [request] () mutable {
//if (request->isActive()) {
//auto response = SchemeHandlers::Response(request, 408);
//response.fail("ServiceWorker request timed out.");
//}
//});
this->getRuntime()->services.timers.setTimeout(32000, [request] () mutable {
if (request->isActive()) {
auto response = SchemeHandlers::Response(request, 408);
response.fail("ServiceWorker request timed out.");
}
});
return;
}
}
Expand Down Expand Up @@ -779,23 +777,23 @@ export * from '{{url}}'
auto resource = filesystem::Resource(resourcePath, { .cache = true });

if (resource.exists()) {
const auto url = (
#if SOCKET_RUNTIME_PLATFORM_ANDROID
"https://" +
#else
"socket://" +
#endif
toLowerCase(bundleIdentifier) +
contentLocation +
(request->query.size() > 0 ? "?" + request->query : "")
);
auto url = URL();
#if SOCKET_RUNTIME_PLATFORM_ANDROID
url.scheme = "https";
#else
url.scheme = "socket";
#endif
url.hostname = toLowerCase(bundleIdentifier);
url.pathname = contentLocation;
url.search = request->query;
debug("URL1: %s", url.str().c_str());

const auto moduleImportProxy = tmpl(
String(reinterpret_cast<const char*>(resource.read())).find("export default") != String::npos
? ESM_IMPORT_PROXY_TEMPLATE_WITH_DEFAULT_EXPORT
: ESM_IMPORT_PROXY_TEMPLATE_WITHOUT_DEFAULT_EXPORT,
Map<String, String> {
{"url", url},
{"url", url.str()},
{"commit", version::VERSION_HASH_STRING},
{"protocol", "socket"},
{"pathname", pathname},
Expand Down Expand Up @@ -902,22 +900,22 @@ export * from '{{url}}'
}

if (resource.exists()) {
const auto url = (
#if SOCKET_RUNTIME_PLATFORM_ANDROID
"https://" +
#else
"socket://" +
#endif
toLowerCase(bundleIdentifier) +
"/socket" +
pathname
);
auto url = URL();
#if SOCKET_RUNTIME_PLATFORM_ANDROID
url.scheme = "https";
#else
url.scheme = "socket";
#endif
url.hostname = toLowerCase(bundleIdentifier);
url.pathname = "/socket" + pathname;
url.search = request->query;
debug("URL2: %s", url.str().c_str());
const auto moduleImportProxy = tmpl(
String(reinterpret_cast<const char*>(resource.read())).find("export default") != String::npos
? ESM_IMPORT_PROXY_TEMPLATE_WITH_DEFAULT_EXPORT
: ESM_IMPORT_PROXY_TEMPLATE_WITHOUT_DEFAULT_EXPORT,
Map<String, String> {
{"url", url},
{"url", url.str()},
{"commit", version::VERSION_HASH_STRING},
{"protocol", "node"},
{"pathname", pathname},
Expand Down Expand Up @@ -949,10 +947,29 @@ export * from '{{url}}'
callback(response);
});

Set<String> globalProtocolHandlers = { "npm" };
Map<String, String> protocolHandlers = {};
auto globalUserConfig = getUserConfig();
if (globalUserConfig["meta_bundle_identifier"] == this->userConfig["meta_bundle_identifier"]) {
protocolHandlers.insert({"npm", "/socket/npm/service-worker.js"});
protocolHandlers.insert({"npm", "/socket/npm/service-worker.js"});

for (const auto& entry : split(globalUserConfig["webview_protocol-handlers"], " ")) {
const auto scheme = replace(trim(entry), ":", "");
if (this->navigator.serviceWorkerServer->container.protocols.registerHandler(scheme)) {
protocolHandlers.insert_or_assign(scheme, "");
globalProtocolHandlers.insert(scheme);
}
}

for (const auto& entry : globalUserConfig) {
const auto& key = entry.first;
if (key.starts_with("webview_protocol-handlers_")) {
const auto scheme = replace(replace(trim(key), "webview_protocol-handlers_", ""), ":", "");;
const auto data = entry.second;
if (this->navigator.serviceWorkerServer->container.protocols.registerHandler(scheme, { data })) {
protocolHandlers.insert_or_assign(scheme, data);
globalProtocolHandlers.insert(scheme);
}
}
}

for (const auto& entry : split(this->userConfig["webview_protocol-handlers"], " ")) {
Expand All @@ -968,7 +985,6 @@ export * from '{{url}}'
const auto scheme = replace(replace(trim(key), "webview_protocol-handlers_", ""), ":", "");;
const auto data = entry.second;
if (this->navigator.serviceWorkerServer->container.protocols.registerHandler(scheme, { data })) {
debug("protocol: %s %s", scheme.c_str(), data.c_str());
protocolHandlers.insert_or_assign(scheme, data);
}
}
Expand All @@ -978,6 +994,12 @@ export * from '{{url}}'
const auto& scheme = entry.first;
const auto id = rand64();

if (globalUserConfig["meta_bundle_identifier"] != this->userConfig["meta_bundle_identifier"]) {
if (globalProtocolHandlers.contains(scheme)) {
continue;
}
}

auto scriptURL = trim(entry.second);

if (scriptURL.size() == 0) {
Expand Down Expand Up @@ -1010,6 +1032,8 @@ export * from '{{url}}'
scriptURL
);

debug("scriptURL: %s", scriptURL.c_str());

auto env = JSON::Object::Entries {};
for (const auto& entry : this->userConfig) {
if (entry.first.starts_with("env_")) {
Expand All @@ -1023,14 +1047,16 @@ export * from '{{url}}'
}

if (scheme == "npm") {
this->navigator.serviceWorkerServer->container.registerServiceWorker({
.type = serviceworker::Registration::Options::Type::Module,
.scriptURL = scriptURL,
.scope = scope,
.scheme = scheme,
.serializedWorkerArgs = "",
.id = id
});
if (globalUserConfig["meta_bundle_identifier"] == this->userConfig["meta_bundle_identifier"]) {
this->navigator.serviceWorkerServer->container.registerServiceWorker({
.type = serviceworker::Registration::Options::Type::Module,
.scriptURL = scriptURL,
.scope = scope,
.scheme = scheme,
.serializedWorkerArgs = "",
.id = id
});
}
} else {
this->navigator.serviceWorkerServer->container.registerServiceWorker({
.type = serviceworker::Registration::Options::Type::Module,
Expand All @@ -1045,9 +1071,9 @@ export * from '{{url}}'
{"headless", this->userConfig["build_headless"] == "true"},
{"config", this->userConfig},
{"conduit", JSON::Object::Entries {
{"port", this->context.getRuntime()->services.conduit.port},
{"hostname", this->context.getRuntime()->services.conduit.hostname},
{"sharedKey", this->context.getRuntime()->services.conduit.sharedKey}
{"port", this->getRuntime()->services.conduit.port},
{"hostname", this->getRuntime()->services.conduit.hostname},
{"sharedKey", this->getRuntime()->services.conduit.sharedKey}
}}
}).str()),
.id = id
Expand Down Expand Up @@ -1248,7 +1274,7 @@ extern "C" {
return false;
}

const auto window = app->windowManager.getWindow(index);
const auto window = app->runtime.windowManager.getWindow(index);

if (!window) {
ANDROID_THROW(env, "Invalid window requested");
Expand Down
10 changes: 9 additions & 1 deletion src/runtime/ipc/routes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2560,6 +2560,7 @@ static void mapIPCRoutes (Router *router) {

auto serviceWorkerServer = app->runtime.serviceWorkerManager.get(origin.name());
if (!serviceWorkerServer) {
debug("no server for: %s", origin.name().c_str());
serviceWorkerServer = dynamic_cast<Bridge&>(router->bridge).navigator.serviceWorkerServer;
}

Expand Down Expand Up @@ -2634,8 +2635,15 @@ static void mapIPCRoutes (Router *router) {
* Gets all service worker scope registrations.
*/
router->map("serviceWorker.getRegistrations", [=](auto message, auto router, auto reply) {
const auto origin = webview::Origin(message.get("origin"));
auto serviceWorkerServer = dynamic_cast<Bridge&>(router->bridge).getRuntime()->serviceWorkerManager.get(origin.name());

if (!serviceWorkerServer) {
serviceWorkerServer = dynamic_cast<Bridge&>(router->bridge).navigator.serviceWorkerServer;
}

auto json = JSON::Array::Entries {};
for (const auto& entry : dynamic_cast<Bridge&>(router->bridge).navigator.serviceWorkerServer->container.registrations) {
for (const auto& entry : serviceWorkerServer->container.registrations) {
const auto& registration = entry.second;
json.push_back(registration.json());
}
Expand Down
46 changes: 22 additions & 24 deletions src/runtime/serviceworker/container.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,22 @@ namespace ssc::runtime::serviceworker {
if (bridge->userConfig["webview_service-workers"].size() > 0) {
const auto scripts = split(bridge->userConfig["webview_service-workers"], " ");
for (const auto& value : scripts) {
auto parts = split(value, "/");
parts = Vector<String>(parts.begin(), parts.end() - 1);
auto url = URL(
value,
"socket://" + bridge->userConfig["meta_bundle_identifier"]
);

#if SOCKET_RUNTIME_PLATFORM_ANDROID
auto scriptURL = String("https://");
url.scheme = "https";
#else
auto scriptURL = String("socket://");
url.scheme = "socket";
#endif
scriptURL += bridge->userConfig["meta_bundle_identifier"];

if (!value.starts_with("/")) {
scriptURL += "/";
}

scriptURL += value;

const auto scope = normalizeScope(join(parts, "/"));
const auto scriptURL = url.str();
const auto parts = split(url.pathname, "/");
const auto scope = parts.size() > 2
? join(Vector<String>(parts.begin(), parts.end() - 1), "/")
: "/";
const auto id = rand64();
this->registrations.insert_or_assign(scope, Registration(
id,
Expand Down Expand Up @@ -425,24 +424,23 @@ namespace ssc::runtime::serviceworker {
: getUserConfig();

if (scope.size() == 0) {
auto tmp = trim(options.scriptURL);
tmp = replace(tmp, "https://", "");
tmp = replace(tmp, "socket://", "");
tmp = replace(tmp, userConfig["meta_bundle_identifier"], "");

auto parts = split(tmp, "/");
parts = Vector<String>(parts.begin(), parts.end() - 1);
auto url = URL(
scriptURL,
"socket://" + userConfig["meta_bundle_identifier"]
);

#if SOCKET_RUNTIME_PLATFORM_ANDROID
scriptURL = String("https://");
url.scheme = "https";
#else
scriptURL = String("socket://");
url.scheme = "socket";
#endif

scriptURL += userConfig["meta_bundle_identifier"];
scriptURL += tmp;
scriptURL = url.str();

scope = join(parts, "/");
const auto parts = split(url.pathname, "/");
scope = parts.size() > 2
? join(Vector<String>(parts.begin(), parts.end() - 1), "/")
: "/";
}

scope = normalizeScope(scope);
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/serviceworker/fetch.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,11 @@ namespace ssc::runtime::serviceworker {
auto json = registration.json();
json.set("fetch", fetch);

debug("dispatch fetch: %s", json.str().c_str());
return this->container.bridge->emit("serviceWorker.fetch", json);
}

debug("failed to dispatch fetch: %s %s", pathname.c_str(), this->request.str().c_str());
return false;
}

Expand Down
1 change: 1 addition & 0 deletions src/runtime/url.hh
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ namespace ssc::runtime::url {
const char* c_str () const;
const JSON::Object json () const;
const size_t size () const;
bool empty () const;
};

size_t url_encode_uri_component (
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/url/url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -422,4 +422,8 @@ namespace ssc::runtime::url {
const size_t URL::size () const {
return this->str().size();
}

bool URL::empty () const {
return this->str().empty();
}
}
Loading

0 comments on commit 23657c7

Please sign in to comment.