mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-09-18 01:34:44 -04:00
Merge pull request #3288 from lightpanda-io/WorkerNavigator
WebAPI: Add WorkerNavigator
This commit is contained in:
6 files changed
+159
-12
No files matched your search
@@ -1241,7 +1241,7 @@ pub const PageJsApis = flattenTypes(&.{
|
||||
const worker_common_apis = [_]type{
|
||||
@import("../webapi/WorkerGlobalScope.zig"),
|
||||
@import("../webapi/WorkerLocation.zig"),
|
||||
@import("../webapi/Navigator.zig"),
|
||||
@import("../webapi/WorkerNavigator.zig"),
|
||||
@import("../webapi/NavigatorUAData.zig"),
|
||||
@import("../webapi/Permissions.zig"),
|
||||
@import("../webapi/StorageManager.zig"),
|
||||
@@ -1329,6 +1329,7 @@ pub const JsApis = blk: {
|
||||
@import("../webapi/SharedWorkerGlobalScope.zig").JsApi,
|
||||
@import("../webapi/WorkerGlobalScope.zig").JsApi,
|
||||
@import("../webapi/WorkerLocation.zig").JsApi,
|
||||
@import("../webapi/WorkerNavigator.zig").JsApi,
|
||||
};
|
||||
if (lp.build_config.wpt_extensions == false) {
|
||||
break :blk base;
|
||||
|
||||
@@ -15,6 +15,10 @@ onmessage = async function(event) {
|
||||
|
||||
const results = {
|
||||
has_navigator: typeof navigator !== 'undefined',
|
||||
// The worker realm exposes WorkerNavigator, not Navigator.
|
||||
is_worker_navigator: Object.getPrototypeOf(navigator) === WorkerNavigator.prototype,
|
||||
to_string_tag: Object.prototype.toString.call(navigator),
|
||||
no_navigator_interface: typeof Navigator === 'undefined',
|
||||
// userAgent must match the value the page sees (passed in via postMessage).
|
||||
user_agent: navigator.userAgent,
|
||||
user_agent_matches_page: navigator.userAgent === event.data.pageUserAgent,
|
||||
@@ -25,6 +29,7 @@ onmessage = async function(event) {
|
||||
identity_stable: navigator === navigator,
|
||||
|
||||
// Permissions
|
||||
permissions_distinct: navigator.permissions !== navigator,
|
||||
permission_name: status.name,
|
||||
permission_state: status.state,
|
||||
|
||||
@@ -40,6 +45,8 @@ onmessage = async function(event) {
|
||||
no_plugins: navigator.plugins === undefined,
|
||||
no_register_protocol_handler: navigator.registerProtocolHandler === undefined,
|
||||
no_model_context: navigator.modelContext === undefined,
|
||||
no_send_beacon: navigator.sendBeacon === undefined,
|
||||
no_cookie_enabled: navigator.cookieEnabled === undefined,
|
||||
};
|
||||
postMessage({ ok: true, results });
|
||||
} catch (e) {
|
||||
|
||||
@@ -270,6 +270,9 @@
|
||||
const r = data.results;
|
||||
|
||||
testing.expectEqual(true, r.has_navigator);
|
||||
testing.expectEqual(true, r.is_worker_navigator);
|
||||
testing.expectEqual('[object WorkerNavigator]', r.to_string_tag);
|
||||
testing.expectEqual(true, r.no_navigator_interface);
|
||||
testing.expectEqual(true, r.user_agent_matches_page);
|
||||
testing.expectEqual('Netscape', r.app_name);
|
||||
testing.expectTrue(r.platform.length > 0);
|
||||
@@ -277,6 +280,7 @@
|
||||
testing.expectEqual(true, r.identity_stable);
|
||||
|
||||
// Permissions (transitive: Permissions -> PermissionStatus)
|
||||
testing.expectEqual(true, r.permissions_distinct);
|
||||
testing.expectEqual('geolocation', r.permission_name);
|
||||
testing.expectEqual('prompt', r.permission_state);
|
||||
|
||||
@@ -292,6 +296,8 @@
|
||||
testing.expectEqual(true, r.no_plugins);
|
||||
testing.expectEqual(true, r.no_register_protocol_handler);
|
||||
testing.expectEqual(true, r.no_model_context);
|
||||
testing.expectEqual(true, r.no_send_beacon);
|
||||
testing.expectEqual(true, r.no_cookie_enabled);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -265,17 +265,15 @@ pub const JsApi = struct {
|
||||
pub const globalPrivacyControl = bridge.accessor(Navigator.getGlobalPrivacyControl, null, .{});
|
||||
|
||||
pub const javaEnabled = bridge.function(Navigator.javaEnabled, .{});
|
||||
pub const sendBeacon = bridge.function(Navigator.sendBeacon, .{ .exposed = .window, .noop = true });
|
||||
pub const sendBeacon = bridge.function(Navigator.sendBeacon, .{ .noop = true });
|
||||
pub const permissions = bridge.accessor(Navigator.getPermissions, null, .{});
|
||||
pub const storage = bridge.accessor(Navigator.getStorage, null, .{});
|
||||
pub const userAgentData = bridge.accessor(Navigator.getUserAgentData, null, .{});
|
||||
|
||||
// window only
|
||||
pub const plugins = bridge.accessor(Navigator.getPlugins, null, .{ .exposed = .window });
|
||||
pub const geolocation = bridge.accessor(Navigator.getGeolocation, null, .{ .exposed = .window });
|
||||
pub const modelContext = bridge.accessor(Navigator.getModelContext, null, .{ .exposed = .window });
|
||||
pub const registerProtocolHandler = bridge.function(Navigator.registerProtocolHandler, .{ .exposed = .window });
|
||||
pub const unregisterProtocolHandler = bridge.function(Navigator.unregisterProtocolHandler, .{ .exposed = .window });
|
||||
pub const plugins = bridge.accessor(Navigator.getPlugins, null, .{});
|
||||
pub const geolocation = bridge.accessor(Navigator.getGeolocation, null, .{});
|
||||
pub const modelContext = bridge.accessor(Navigator.getModelContext, null, .{});
|
||||
pub const registerProtocolHandler = bridge.function(Navigator.registerProtocolHandler, .{});
|
||||
pub const unregisterProtocolHandler = bridge.function(Navigator.unregisterProtocolHandler, .{});
|
||||
};
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
|
||||
@@ -36,7 +36,7 @@ const ScriptManagerBase = @import("../ScriptManagerBase.zig");
|
||||
const Event = @import("Event.zig");
|
||||
const Crypto = @import("Crypto.zig");
|
||||
const Console = @import("Console.zig");
|
||||
const Navigator = @import("Navigator.zig");
|
||||
const WorkerNavigator = @import("WorkerNavigator.zig");
|
||||
const Timers = @import("Timers.zig");
|
||||
const Scheduler = @import("Scheduler.zig");
|
||||
const EventTarget = @import("EventTarget.zig");
|
||||
@@ -105,7 +105,7 @@ _message_ports: std.DoublyLinkedList = .{},
|
||||
_proto: *EventTarget,
|
||||
_console: Console = .init,
|
||||
_crypto: Crypto = .init,
|
||||
_navigator: Navigator = .init,
|
||||
_navigator: WorkerNavigator = .init,
|
||||
_performance: Performance,
|
||||
_idb_factory: ?*idb.IDBFactory = null,
|
||||
_on_error: ?JS.Function.Global = null,
|
||||
@@ -300,7 +300,7 @@ pub fn getCrypto(self: *WorkerGlobalScope) *Crypto {
|
||||
return &self._crypto;
|
||||
}
|
||||
|
||||
pub fn getNavigator(self: *WorkerGlobalScope) *Navigator {
|
||||
pub fn getNavigator(self: *WorkerGlobalScope) *WorkerNavigator {
|
||||
return &self._navigator;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
||||
//
|
||||
// Francis Bouvier <francis@lightpanda.io>
|
||||
// Pierre Tachoire <pierre@lightpanda.io>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const js = @import("../js/js.zig");
|
||||
const Execution = js.Execution;
|
||||
|
||||
const Navigator = @import("Navigator.zig");
|
||||
const Permissions = @import("Permissions.zig");
|
||||
const StorageManager = @import("StorageManager.zig");
|
||||
const NavigatorUAData = @import("NavigatorUAData.zig");
|
||||
|
||||
const WorkerNavigator = @This();
|
||||
|
||||
comptime {
|
||||
// protect against identity_map conflict (make sure _pad: bool does its job)
|
||||
for ([_][]const u8{ "_permissions", "_storage", "_ua_data" }) |name| {
|
||||
if (@offsetOf(WorkerNavigator, name) == 0) {
|
||||
@compileError(name ++ " aliases the WorkerNavigator");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_pad: bool = false,
|
||||
_permissions: Permissions = .{},
|
||||
_storage: StorageManager = .{},
|
||||
_ua_data: NavigatorUAData = .{},
|
||||
|
||||
pub const init: WorkerNavigator = .{};
|
||||
|
||||
pub fn getUserAgent(_: *const WorkerNavigator, exec: *const Execution) []const u8 {
|
||||
return Navigator.getUserAgent(&Navigator.init, exec);
|
||||
}
|
||||
|
||||
pub fn getLanguages(_: *const WorkerNavigator) [2][]const u8 {
|
||||
return Navigator.getLanguages(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getAppName(_: *const WorkerNavigator) []const u8 {
|
||||
return Navigator.getAppName(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getAppCodeName(_: *const WorkerNavigator) []const u8 {
|
||||
return Navigator.getAppCodeName(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getAppVersion(_: *const WorkerNavigator) []const u8 {
|
||||
return Navigator.getAppVersion(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getLanguage(_: *const WorkerNavigator) []const u8 {
|
||||
return Navigator.getLanguage(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getOnLine(_: *const WorkerNavigator) bool {
|
||||
return Navigator.getOnLine(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getHardwareConcurrency(_: *const WorkerNavigator) u32 {
|
||||
return Navigator.getHardwareConcurrency(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getDeviceMemory(_: *const WorkerNavigator) f64 {
|
||||
return Navigator.getDeviceMemory(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getVendor(_: *const WorkerNavigator) []const u8 {
|
||||
return Navigator.getVendor(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getProduct(_: *const WorkerNavigator) []const u8 {
|
||||
return Navigator.getProduct(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getGlobalPrivacyControl(_: *const WorkerNavigator) bool {
|
||||
return Navigator.getGlobalPrivacyControl(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getPlatform(_: *const WorkerNavigator) []const u8 {
|
||||
return Navigator.getPlatform(&Navigator.init);
|
||||
}
|
||||
|
||||
pub fn getPermissions(self: *WorkerNavigator) *Permissions {
|
||||
return &self._permissions;
|
||||
}
|
||||
|
||||
pub fn getStorage(self: *WorkerNavigator) *StorageManager {
|
||||
return &self._storage;
|
||||
}
|
||||
|
||||
pub fn getUserAgentData(self: *WorkerNavigator) *NavigatorUAData {
|
||||
return &self._ua_data;
|
||||
}
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(WorkerNavigator);
|
||||
|
||||
pub const Meta = struct {
|
||||
pub const name = "WorkerNavigator";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
};
|
||||
|
||||
pub const userAgent = bridge.accessor(WorkerNavigator.getUserAgent, null, .{});
|
||||
pub const appName = bridge.accessor(WorkerNavigator.getAppName, null, .{});
|
||||
pub const appCodeName = bridge.accessor(WorkerNavigator.getAppCodeName, null, .{});
|
||||
pub const appVersion = bridge.accessor(WorkerNavigator.getAppVersion, null, .{});
|
||||
pub const platform = bridge.accessor(WorkerNavigator.getPlatform, null, .{});
|
||||
pub const language = bridge.accessor(WorkerNavigator.getLanguage, null, .{});
|
||||
pub const languages = bridge.accessor(WorkerNavigator.getLanguages, null, .{});
|
||||
pub const onLine = bridge.accessor(WorkerNavigator.getOnLine, null, .{});
|
||||
pub const hardwareConcurrency = bridge.accessor(WorkerNavigator.getHardwareConcurrency, null, .{});
|
||||
pub const deviceMemory = bridge.accessor(WorkerNavigator.getDeviceMemory, null, .{});
|
||||
pub const vendor = bridge.accessor(WorkerNavigator.getVendor, null, .{});
|
||||
pub const product = bridge.accessor(WorkerNavigator.getProduct, null, .{});
|
||||
pub const globalPrivacyControl = bridge.accessor(WorkerNavigator.getGlobalPrivacyControl, null, .{});
|
||||
|
||||
pub const permissions = bridge.accessor(WorkerNavigator.getPermissions, null, .{});
|
||||
pub const storage = bridge.accessor(WorkerNavigator.getStorage, null, .{});
|
||||
pub const userAgentData = bridge.accessor(WorkerNavigator.getUserAgentData, null, .{});
|
||||
};
|
||||
Reference in new issue
Block a user