Skip to content

Commit d6021d1

Browse files
Merge pull request #348 from lightpanda-io/dom-navigator
Dom navigator
2 parents 9fb51a1 + b391eaf commit d6021d1

File tree

8 files changed

+131
-7
lines changed

8 files changed

+131
-7
lines changed

src/browser/browser.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,15 @@ const polyfill = @import("../polyfill/polyfill.zig");
4646

4747
const log = std.log.scoped(.browser);
4848

49+
pub const user_agent = "Lightpanda/1.0";
50+
4951
// Browser is an instance of the browser.
5052
// You can create multiple browser instances.
5153
// A browser contains only one session.
5254
// TODO allow multiple sessions per browser.
5355
pub const Browser = struct {
5456
session: Session = undefined,
57+
agent: []const u8 = user_agent,
5558

5659
const uri = "about:blank";
5760

@@ -111,7 +114,7 @@ pub const Session = struct {
111114
.uri = uri,
112115
.alloc = alloc,
113116
.arena = std.heap.ArenaAllocator.init(alloc),
114-
.window = Window.create(null),
117+
.window = Window.create(null, .{ .agent = user_agent }),
115118
.loader = Loader.init(alloc),
116119
.storageShed = storage.Shed.init(alloc),
117120
.httpClient = undefined,

src/browser/loader.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
const std = @import("std");
2020
const Client = @import("../http/Client.zig");
2121

22-
const user_agent = "Lightpanda.io/1.0";
22+
const user_agent = @import("browser.zig").user_agent;
2323

2424
pub const Loader = struct {
2525
client: Client,

src/html/html.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ const generate = @import("../generate.zig");
2121
const HTMLDocument = @import("document.zig").HTMLDocument;
2222
const HTMLElem = @import("elements.zig");
2323
const Window = @import("window.zig").Window;
24+
const Navigator = @import("navigator.zig").Navigator;
2425

2526
pub const Interfaces = generate.Tuple(.{
2627
HTMLDocument,
2728
HTMLElem.HTMLElement,
2829
HTMLElem.HTMLMediaElement,
2930
HTMLElem.Interfaces,
3031
Window,
32+
Navigator,
3133
});

src/html/navigator.zig

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <[email protected]>
4+
// Pierre Tachoire <[email protected]>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
const std = @import("std");
20+
21+
const builtin = @import("builtin");
22+
const parser = @import("netsurf");
23+
const jsruntime = @import("jsruntime");
24+
const Callback = jsruntime.Callback;
25+
const CallbackArg = jsruntime.CallbackArg;
26+
const Loop = jsruntime.Loop;
27+
28+
const Case = jsruntime.test_utils.Case;
29+
const checkCases = jsruntime.test_utils.checkCases;
30+
31+
const EventTarget = @import("../dom/event_target.zig").EventTarget;
32+
33+
const storage = @import("../storage/storage.zig");
34+
35+
// https://html.spec.whatwg.org/multipage/system-state.html#navigator
36+
pub const Navigator = struct {
37+
pub const mem_guarantied = true;
38+
39+
agent: []const u8 = "Lightpanda/1.0",
40+
version: []const u8 = "1.0",
41+
vendor: []const u8 = "",
42+
platform: []const u8 = std.fmt.comptimePrint("{any} {any}", .{ builtin.os.tag, builtin.cpu.arch }),
43+
44+
language: []const u8 = "en-US",
45+
46+
pub fn get_userAgent(self: *Navigator) []const u8 {
47+
return self.agent;
48+
}
49+
pub fn get_appCodeName(_: *Navigator) []const u8 {
50+
return "Mozilla";
51+
}
52+
pub fn get_appName(_: *Navigator) []const u8 {
53+
return "Netscape";
54+
}
55+
pub fn get_appVersion(self: *Navigator) []const u8 {
56+
return self.version;
57+
}
58+
pub fn get_platform(self: *Navigator) []const u8 {
59+
return self.platform;
60+
}
61+
pub fn get_product(_: *Navigator) []const u8 {
62+
return "Gecko";
63+
}
64+
pub fn get_productSub(_: *Navigator) []const u8 {
65+
return "20030107";
66+
}
67+
pub fn get_vendor(self: *Navigator) []const u8 {
68+
return self.vendor;
69+
}
70+
pub fn get_vendorSub(_: *Navigator) []const u8 {
71+
return "";
72+
}
73+
pub fn get_language(self: *Navigator) []const u8 {
74+
return self.language;
75+
}
76+
// TODO wait for arrays.
77+
//pub fn get_languages(self: *Navigator) [][]const u8 {
78+
// return .{self.language};
79+
//}
80+
pub fn get_online(_: *Navigator) bool {
81+
return true;
82+
}
83+
pub fn _registerProtocolHandler(_: *Navigator, scheme: []const u8, url: []const u8) void {
84+
_ = scheme;
85+
_ = url;
86+
}
87+
pub fn _unregisterProtocolHandler(_: *Navigator, scheme: []const u8, url: []const u8) void {
88+
_ = scheme;
89+
_ = url;
90+
}
91+
92+
pub fn get_cookieEnabled(_: *Navigator) bool {
93+
return true;
94+
}
95+
};
96+
97+
// Tests
98+
// -----
99+
100+
pub fn testExecFn(
101+
_: std.mem.Allocator,
102+
js_env: *jsruntime.Env,
103+
) anyerror!void {
104+
var navigator = [_]Case{
105+
.{ .src = "navigator.userAgent", .ex = "Lightpanda/1.0" },
106+
.{ .src = "navigator.appVersion", .ex = "1.0" },
107+
.{ .src = "navigator.language", .ex = "en-US" },
108+
};
109+
try checkCases(js_env, &navigator);
110+
}

src/html/window.zig

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const CallbackArg = jsruntime.CallbackArg;
2525
const Loop = jsruntime.Loop;
2626

2727
const EventTarget = @import("../dom/event_target.zig").EventTarget;
28+
const Navigator = @import("navigator.zig").Navigator;
2829

2930
const storage = @import("../storage/storage.zig");
3031

@@ -48,9 +49,12 @@ pub const Window = struct {
4849
timeoutid: u32 = 0,
4950
timeoutids: [512]u64 = undefined,
5051

51-
pub fn create(target: ?[]const u8) Window {
52+
navigator: Navigator,
53+
54+
pub fn create(target: ?[]const u8, navigator: ?Navigator) Window {
5255
return Window{
5356
.target = target orelse "",
57+
.navigator = navigator orelse .{},
5458
};
5559
}
5660

@@ -66,6 +70,10 @@ pub const Window = struct {
6670
return self;
6771
}
6872

73+
pub fn get_navigator(self: *Window) *Navigator {
74+
return &self.navigator;
75+
}
76+
6977
pub fn get_self(self: *Window) *Window {
7078
return self;
7179
}

src/run_tests.zig

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ fn testExecFn(
9696
});
9797

9898
// alias global as self and window
99-
var window = Window.create(null);
99+
var window = Window.create(null, null);
100100

101101
window.replaceDocument(doc);
102102
window.setStorageShelf(&storageShelf);
@@ -137,6 +137,7 @@ fn testsAllExecFn(
137137
HTMLElementTestExecFn,
138138
MutationObserverTestExecFn,
139139
@import("polyfill/fetch.zig").testExecFn,
140+
@import("html/navigator.zig").testExecFn,
140141
};
141142

142143
inline for (testFns) |testFn| {
@@ -359,7 +360,7 @@ test "bug document html parsing #4" {
359360
}
360361

361362
test "Window is a libdom event target" {
362-
var window = Window.create(null);
363+
var window = Window.create(null, null);
363364

364365
const event = try parser.eventCreate();
365366
try parser.eventInit(event, "foo", .{});

src/wpt/run.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const
9090
}
9191

9292
// setup global env vars.
93-
var window = Window.create(null);
93+
var window = Window.create(null, null);
9494
window.replaceDocument(html_doc);
9595
window.setStorageShelf(&storageShelf);
9696
try js_env.bindGlobal(&window);

tests/wpt

Submodule wpt updated 277 files

0 commit comments

Comments
 (0)