mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +00:00
cdp: multiple isolated worlds
This commit is contained in:
@@ -331,7 +331,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
node_search_list: Node.Search.List,
|
node_search_list: Node.Search.List,
|
||||||
|
|
||||||
inspector: Inspector,
|
inspector: Inspector,
|
||||||
isolated_world: ?IsolatedWorld,
|
isolated_worlds: std.ArrayListUnmanaged(IsolatedWorld),
|
||||||
|
|
||||||
http_proxy_changed: bool = false,
|
http_proxy_changed: bool = false,
|
||||||
|
|
||||||
@@ -375,7 +375,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
.page_life_cycle_events = false, // TODO; Target based value
|
.page_life_cycle_events = false, // TODO; Target based value
|
||||||
.node_registry = registry,
|
.node_registry = registry,
|
||||||
.node_search_list = undefined,
|
.node_search_list = undefined,
|
||||||
.isolated_world = null,
|
.isolated_worlds = .empty,
|
||||||
.inspector = inspector,
|
.inspector = inspector,
|
||||||
.notification_arena = cdp.notification_arena.allocator(),
|
.notification_arena = cdp.notification_arena.allocator(),
|
||||||
.intercept_state = try InterceptState.init(allocator),
|
.intercept_state = try InterceptState.init(allocator),
|
||||||
@@ -404,9 +404,10 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
// so we need to shutdown the page one first.
|
// so we need to shutdown the page one first.
|
||||||
self.cdp.browser.closeSession();
|
self.cdp.browser.closeSession();
|
||||||
|
|
||||||
if (self.isolated_world) |*world| {
|
for (self.isolated_worlds.items) |*world| {
|
||||||
world.deinit();
|
world.deinit();
|
||||||
}
|
}
|
||||||
|
self.isolated_worlds.clearRetainingCapacity();
|
||||||
self.node_registry.deinit();
|
self.node_registry.deinit();
|
||||||
self.node_search_list.deinit();
|
self.node_search_list.deinit();
|
||||||
self.cdp.browser.notification.unregisterAll(self);
|
self.cdp.browser.notification.unregisterAll(self);
|
||||||
@@ -427,32 +428,19 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn createIsolatedWorld(self: *Self, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld {
|
pub fn createIsolatedWorld(self: *Self, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld {
|
||||||
if (self.isolated_world != null) {
|
|
||||||
// if the two world have different names, be safe and return an
|
|
||||||
// error.
|
|
||||||
if (std.mem.eql(u8, self.isolated_world.?.name, world_name) == false) {
|
|
||||||
return error.CurrentlyOnly1IsolatedWorldSupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the two worlds have the same name, reuse the existing one
|
|
||||||
// but send a warning.
|
|
||||||
log.warn(.cdp, "not implemented", .{
|
|
||||||
.feature = "createIsolatedWorld: Not implemented second isolated world creation",
|
|
||||||
.info = "reuse existing isolated world with the same name",
|
|
||||||
.world_name = world_name,
|
|
||||||
});
|
|
||||||
return &self.isolated_world.?;
|
|
||||||
}
|
|
||||||
|
|
||||||
var executor = try self.cdp.browser.env.newExecutionWorld();
|
var executor = try self.cdp.browser.env.newExecutionWorld();
|
||||||
errdefer executor.deinit();
|
errdefer executor.deinit();
|
||||||
|
|
||||||
self.isolated_world = .{
|
const owned_name = try self.arena.dupe(u8, world_name);
|
||||||
.name = try self.arena.dupe(u8, world_name),
|
const world = try self.isolated_worlds.addOne(self.arena);
|
||||||
|
|
||||||
|
world.* = .{
|
||||||
|
.name = owned_name,
|
||||||
.executor = executor,
|
.executor = executor,
|
||||||
.grant_universal_access = grant_universal_access,
|
.grant_universal_access = grant_universal_access,
|
||||||
};
|
};
|
||||||
return &self.isolated_world.?;
|
|
||||||
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer {
|
pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer {
|
||||||
@@ -711,6 +699,14 @@ const IsolatedWorld = struct {
|
|||||||
Env.GlobalMissingCallback.init(&self.polyfill_loader),
|
Env.GlobalMissingCallback.init(&self.polyfill_loader),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn createContextAndLoadPolyfills(self: *IsolatedWorld, arena: Allocator, page: *Page) !void {
|
||||||
|
// We need to recreate the isolated world context
|
||||||
|
try self.createContext(page);
|
||||||
|
|
||||||
|
const loader = @import("../browser/polyfill/polyfill.zig");
|
||||||
|
try loader.preload(arena, &self.executor.js_context.?);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is a generic because when we send a result we have two different
|
// This is a generic because when we send a result we have two different
|
||||||
|
|||||||
@@ -277,10 +277,15 @@ fn resolveNode(cmd: anytype) !void {
|
|||||||
var js_context = page.main_context;
|
var js_context = page.main_context;
|
||||||
if (params.executionContextId) |context_id| {
|
if (params.executionContextId) |context_id| {
|
||||||
if (js_context.v8_context.debugContextId() != context_id) {
|
if (js_context.v8_context.debugContextId() != context_id) {
|
||||||
var isolated_world = bc.isolated_world orelse return error.ContextNotFound;
|
var found = false;
|
||||||
js_context = &(isolated_world.executor.js_context orelse return error.ContextNotFound);
|
for (bc.isolated_worlds.items) |*isolated_world| {
|
||||||
|
js_context = &(isolated_world.executor.js_context orelse return error.ContextNotFound);
|
||||||
if (js_context.v8_context.debugContextId() != context_id) return error.ContextNotFound;
|
if (js_context.v8_context.debugContextId() == context_id) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) return error.ContextNotFound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ fn createIsolatedWorld(cmd: anytype) !void {
|
|||||||
|
|
||||||
const world = try bc.createIsolatedWorld(params.worldName, params.grantUniveralAccess);
|
const world = try bc.createIsolatedWorld(params.worldName, params.grantUniveralAccess);
|
||||||
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
|
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
|
||||||
try pageCreated(bc, page);
|
try world.createContextAndLoadPolyfills(bc.arena, page);
|
||||||
const js_context = &world.executor.js_context.?;
|
const js_context = &world.executor.js_context.?;
|
||||||
|
|
||||||
// Create the auxdata json for the contextCreated event
|
// Create the auxdata json for the contextCreated event
|
||||||
@@ -259,7 +259,7 @@ pub fn pageNavigate(arena: Allocator, bc: anytype, event: *const Notification.Pa
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (bc.isolated_world) |*isolated_world| {
|
for (bc.isolated_worlds.items) |*isolated_world| {
|
||||||
const aux_json = try std.fmt.allocPrint(arena, "{{\"isDefault\":false,\"type\":\"isolated\",\"frameId\":\"{s}\"}}", .{target_id});
|
const aux_json = try std.fmt.allocPrint(arena, "{{\"isDefault\":false,\"type\":\"isolated\",\"frameId\":\"{s}\"}}", .{target_id});
|
||||||
// Calling contextCreated will assign a new Id to the context and send the contextCreated event
|
// Calling contextCreated will assign a new Id to the context and send the contextCreated event
|
||||||
bc.inspector.contextCreated(
|
bc.inspector.contextCreated(
|
||||||
@@ -274,18 +274,14 @@ pub fn pageNavigate(arena: Allocator, bc: anytype, event: *const Notification.Pa
|
|||||||
|
|
||||||
pub fn pageRemove(bc: anytype) !void {
|
pub fn pageRemove(bc: anytype) !void {
|
||||||
// The main page is going to be removed, we need to remove contexts from other worlds first.
|
// The main page is going to be removed, we need to remove contexts from other worlds first.
|
||||||
if (bc.isolated_world) |*isolated_world| {
|
for (bc.isolated_worlds.items) |*isolated_world| {
|
||||||
try isolated_world.removeContext();
|
try isolated_world.removeContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageCreated(bc: anytype, page: *Page) !void {
|
pub fn pageCreated(bc: anytype, page: *Page) !void {
|
||||||
if (bc.isolated_world) |*isolated_world| {
|
for (bc.isolated_worlds.items) |*isolated_world| {
|
||||||
// We need to recreate the isolated world context
|
try isolated_world.createContextAndLoadPolyfills(bc.arena, page);
|
||||||
try isolated_world.createContext(page);
|
|
||||||
|
|
||||||
const polyfill = @import("../../browser/polyfill/polyfill.zig");
|
|
||||||
try polyfill.preload(bc.arena, &isolated_world.executor.js_context.?);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -241,10 +241,10 @@ fn closeTarget(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bc.session.removePage();
|
bc.session.removePage();
|
||||||
if (bc.isolated_world) |*world| {
|
for (bc.isolated_worlds.items) |*world| {
|
||||||
world.deinit();
|
world.deinit();
|
||||||
bc.isolated_world = null;
|
|
||||||
}
|
}
|
||||||
|
bc.isolated_worlds.clearRetainingCapacity();
|
||||||
bc.target_id = null;
|
bc.target_id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user