Skip to content

Commit

Permalink
refactor(runtime/serviceworker): use better service worker registrati…
Browse files Browse the repository at this point in the history
…on keys, fix registrations
  • Loading branch information
jwerle committed Jan 6, 2025
1 parent 23657c7 commit 19963a3
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 254 deletions.
3 changes: 2 additions & 1 deletion api/service-worker/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export async function onActivate (event) {
export async function onFetch (event) {
const info = new ServiceWorkerInfo(event.detail)
const exists = workers.has(info.hash)
console.log(exists, event.detail)

// this may be an early fetch, just try waiting at most
// 32*16 milliseconds for the worker to be available or
Expand Down Expand Up @@ -377,7 +378,7 @@ hooks.onReady(async () => {
const result = await ipc.request('serviceWorker.getRegistrations')
if (Array.isArray(result.data)) {
for (const info of result.data) {
await navigator.serviceWorker.register(info.scriptURL, info)
//await navigator.serviceWorker.register(info.scriptURL, info)
}
}
})
1 change: 1 addition & 0 deletions api/service-worker/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ export async function onMessage (event) {
}

const url = new URL(data.fetch.request.url)
console.log('FetchEvent: %s', url.href)
const fetchEvent = new FetchEvent('fetch', {
clientId: data.fetch.client.id,
fetchId: data.fetch.request.id,
Expand Down
155 changes: 83 additions & 72 deletions src/runtime/bridge/bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,14 @@ export * from '{{url}}'
if (request->hostname.size() > 0) {
auto origin = webview::Origin(request->scheme + "://" + request->hostname);
auto serviceWorker = app->runtime.serviceWorkerManager.get(origin.name());

debug(">> %d %d %d %d",
serviceWorker != nullptr,
request->hostname != globalBundleIdentifier,
window->options.shouldPreferServiceWorker,
serviceWorker->container.registrations.size() > 0
);

if (
serviceWorker != nullptr &&
request->hostname != globalBundleIdentifier &&
Expand All @@ -463,6 +471,7 @@ export * from '{{url}}'
auto fetch = serviceworker::Request();
fetch.method = request->method;
fetch.scheme = request->scheme;
fetch.url.scheme = request->scheme;
fetch.url.hostname = request->hostname;
fetch.url.pathname = request->pathname;
fetch.url.searchParams.set(request->query);
Expand All @@ -477,6 +486,7 @@ export * from '{{url}}'

const auto app = App::sharedApplication();
const auto options = serviceworker::Fetch::Options { request->client };
debug("FETCH PLZ: %s", fetch.str().c_str());
const auto fetched = serviceWorker->fetch(fetch, options, [
this,
applicationResources,
Expand Down Expand Up @@ -541,6 +551,7 @@ export * from '{{url}}'
contentLocation = resourcePath.substr(applicationResources.size(), resourcePath.size());
}

debug("RESOURCE PATH: %s", resourcePath.c_str());
auto resource = filesystem::Resource(resourcePath);

if (!resource.exists()) {
Expand Down Expand Up @@ -607,7 +618,10 @@ export * from '{{url}}'
}
}

if (request->hostname == userConfig["meta_bundle_identifier"]) {
if (
request->hostname == userConfig["meta_bundle_identifier"] ||
request->hostname == globalConfig["meta_bundle_identifier"]
) {
const auto resolved = this->navigator.location.resolve(request->pathname, applicationResources);

if (resolved.redirect) {
Expand Down Expand Up @@ -786,7 +800,6 @@ export * from '{{url}}'
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
Expand Down Expand Up @@ -909,7 +922,6 @@ export * from '{{url}}'
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
Expand Down Expand Up @@ -994,92 +1006,92 @@ 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 (
globalUserConfig["meta_bundle_identifier"] == this->userConfig["meta_bundle_identifier"] ||
!globalProtocolHandlers.contains(scheme)
) {

if (scriptURL.size() == 0) {
continue;
}
auto scriptURL = trim(entry.second);

if (!scriptURL.starts_with(".") && !scriptURL.starts_with("/")) {
continue;
}
if (scriptURL.size() == 0) {
continue;
}

if (scriptURL.starts_with(".")) {
scriptURL = scriptURL.substr(1, scriptURL.size());
}
if (!scriptURL.starts_with(".") && !scriptURL.starts_with("/")) {
continue;
}

String scope = "/";
if (scriptURL.starts_with(".")) {
scriptURL = scriptURL.substr(1, scriptURL.size());
}

auto scopeParts = split(scriptURL, "/");
if (scopeParts.size() > 0) {
scopeParts = Vector<String>(scopeParts.begin(), scopeParts.end() - 1);
scope = join(scopeParts, "/");
}
String scope = "/";

scriptURL = (
#if SOCKET_RUNTIME_PLATFORM_ANDROID
"https://" +
#else
"socket://" +
#endif
this->userConfig["meta_bundle_identifier"] +
scriptURL
);
auto scopeParts = split(scriptURL, "/");
if (scopeParts.size() > 0) {
scopeParts = Vector<String>(scopeParts.begin(), scopeParts.end() - 1);
scope = join(scopeParts, "/");
}

debug("scriptURL: %s", scriptURL.c_str());
scriptURL = (
#if SOCKET_RUNTIME_PLATFORM_ANDROID
"https://" +
#else
"socket://" +
#endif
this->userConfig["meta_bundle_identifier"] +
scriptURL
);

auto env = JSON::Object::Entries {};
for (const auto& entry : this->userConfig) {
if (entry.first.starts_with("env_")) {
env[entry.first.substr(4)] = entry.second;
} else if (entry.first == "build_env") {
const auto keys = parseStringList(entry.second, { ',', ' ' });
for (const auto& key : keys) {
env[key] = env::get(key);
auto env = JSON::Object::Entries {};
for (const auto& entry : this->userConfig) {
if (entry.first.starts_with("env_")) {
env[entry.first.substr(4)] = entry.second;
} else if (entry.first == "build_env") {
const auto keys = parseStringList(entry.second, { ',', ' ' });
for (const auto& key : keys) {
env[key] = env::get(key);
}
}
}
}

if (scheme == "npm") {
if (globalUserConfig["meta_bundle_identifier"] == this->userConfig["meta_bundle_identifier"]) {
if (scheme == "npm") {
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 {
debug("BEFORE REGISTER: %s %s", scheme.c_str(), scope.c_str());
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,
.scriptURL = scriptURL,
.scope = scope,
.scheme = scheme,
.serializedWorkerArgs = encodeURIComponent(JSON::Object(JSON::Object::Entries {
{"index", this->client.index},
{"argv", JSON::Array {}},
{"env", env},
{"debug", isDebugEnabled()},
{"headless", this->userConfig["build_headless"] == "true"},
{"config", this->userConfig},
{"conduit", JSON::Object::Entries {
.serializedWorkerArgs = encodeURIComponent(JSON::Object(JSON::Object::Entries {
{"index", this->client.index},
{"argv", JSON::Array {}},
{"env", env},
{"debug", isDebugEnabled()},
{"headless", this->userConfig["build_headless"] == "true"},
{"config", this->userConfig},
{"conduit", JSON::Object::Entries {
{"port", this->getRuntime()->services.conduit.port},
{"hostname", this->getRuntime()->services.conduit.hostname},
{"sharedKey", this->getRuntime()->services.conduit.sharedKey}
}}
}).str()),
.id = id
});
}}
}).str()),
.id = id
});
}
}

debug("REGISTER SCHEME: %s", scheme.c_str());
this->schemeHandlers.registerSchemeHandler(scheme, [this](
auto request,
auto bridge,
Expand All @@ -1094,8 +1106,6 @@ export * from '{{url}}'
auto fetch = serviceworker::Request();
SharedPointer<serviceworker::Server> serviceWorkerServer = nullptr;

debug("request: %s", request->str().c_str());

if (window == nullptr) {
auto response = SchemeHandlers::Response(request);
response.writeHead(400);
Expand Down Expand Up @@ -1144,8 +1154,8 @@ export * from '{{url}}'
.waitForRegistrationToFinish = request->scheme != "npm"
};

debug("fetch: %s", fetch.str().c_str());
const auto origin = webview::Origin(request->str());
auto origin = webview::Origin(fetch.url.str());
origin.scheme = "socket";
debug("origin: %s", origin.name().c_str());
serviceWorkerServer = app->runtime.serviceWorkerManager.get(origin.name());
if (!serviceWorkerServer) {
Expand All @@ -1158,6 +1168,7 @@ export * from '{{url}}'
if (scope.size() > 0) {
fetch.url.pathname = scope + fetch.url.pathname;
}
debug("fetch: %s", fetch.str().c_str());

const auto fetched = serviceWorkerServer->fetch(fetch, options, [request, callback] (auto res) mutable {
if (!request->isActive()) {
Expand Down
13 changes: 7 additions & 6 deletions src/runtime/ipc/routes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2406,14 +2406,14 @@ static void mapIPCRoutes (Router *router) {
const auto scheme = message.get("scheme");

for (const auto& entry : dynamic_cast<Bridge&>(router->bridge).navigator.serviceWorkerServer->container.registrations) {
const auto& scope = entry.first;
const auto& registration = entry.second;
if (registration.options.scheme == scheme) {
auto json = JSON::Object::Entries {
{"source", message.name},
{"data", JSON::Object::Entries {
{"id", registration.id},
{"scope", scope},
{"scope", registration.options.scope},
{"origin", registration.origin.name()},
{"scheme", scheme},
{"scriptURL", registration.options.scriptURL}
}}
Expand Down Expand Up @@ -2552,15 +2552,16 @@ static void mapIPCRoutes (Router *router) {
.type = serviceworker::Registration::Options::Type::Module,
.scriptURL = message.get("scriptURL"),
.scope = message.get("scope"),
.serializedWorkerArgs = encodeURIComponent(message.get("__runtime_worker_args"))
.scheme = message.get("scheme", "socket"),
.serializedWorkerArgs = encodeURIComponent(message.get("__runtime_worker_args", message.get("serializedWorkerArgs")))
};

const auto url = URL(options.scriptURL);
const auto origin = webview::Origin(url.str());
debug("register: (%s) %s", origin.name().c_str(), url.str().c_str());

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 @@ -2611,10 +2612,10 @@ static void mapIPCRoutes (Router *router) {
}

const auto scope = message.get("scope");

const auto origin = webview::Origin(dynamic_cast<Bridge&>(router->bridge).navigator.location.str());
for (const auto& entry : dynamic_cast<Bridge&>(router->bridge).navigator.serviceWorkerServer->container.registrations) {
const auto& registration = entry.second;
if (scope.starts_with(registration.options.scope)) {
if (registration.options.scheme == "socket" && registration.origin.name() == origin.name() && scope.starts_with(registration.options.scope)) {
auto json = JSON::Object {
JSON::Object::Entries {
{"registration", registration.json()},
Expand Down
1 change: 1 addition & 0 deletions src/runtime/serviceworker.hh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ namespace ssc::runtime::serviceworker {

class Registration {
public:
static String key (const String&, const URL&, const String& = "socket");
struct Options {
enum class Type { Classic, Module };

Expand Down
Loading

0 comments on commit 19963a3

Please sign in to comment.