@@ -13,7 +13,7 @@ def initialize(client, contexts, id)
13
13
@client = client
14
14
@contexts = contexts
15
15
@targets = Concurrent ::Map . new
16
- @pendings = Concurrent ::MVar . new
16
+ @pendings = Concurrent ::Map . new
17
17
end
18
18
19
19
def default_target
@@ -29,7 +29,7 @@ def pages
29
29
end
30
30
31
31
# When we call `page` method on target it triggers ruby to connect to given
32
- # page by WebSocket, if there are many opened windows but we need only one
32
+ # page by WebSocket, if there are many opened windows, but we need only one
33
33
# it makes more sense to get and connect to the needed one only which
34
34
# usually is the last one.
35
35
def windows ( pos = nil , size = 1 )
@@ -46,19 +46,26 @@ def create_page(**options)
46
46
end
47
47
48
48
def create_target
49
- @client . command ( "Target.createTarget" , browserContextId : @id , url : "about:blank" )
50
- target = @pendings . take ( @client . timeout )
51
- raise NoSuchTargetError unless target . is_a? ( Target )
49
+ target_id = @client . command ( "Target.createTarget" , browserContextId : @id , url : "about:blank" ) [ "targetId" ]
52
50
53
- target
51
+ new_pending = Concurrent ::IVar . new
52
+ pending = @pendings . put_if_absent ( target_id , new_pending ) || new_pending
53
+ resolved = pending . value ( @client . timeout )
54
+ raise NoSuchTargetError unless resolved
55
+
56
+ @pendings . delete ( target_id )
57
+ @targets [ target_id ]
54
58
end
55
59
56
60
def add_target ( params :, session_id : nil )
57
61
new_target = Target . new ( @client , session_id , params )
58
- target = @targets . put_if_absent ( new_target . id , new_target )
59
- target ||= new_target # `put_if_absent` returns nil if added a new value or existing if there was one already
60
- @pendings . put ( target , @client . timeout ) if @pendings . empty?
61
- target
62
+ # `put_if_absent` returns nil if added a new value or existing if there was one already
63
+ target = @targets . put_if_absent ( new_target . id , new_target ) || new_target
64
+
65
+ new_pending = Concurrent ::IVar . new
66
+ pending = @pendings . put_if_absent ( target . id , new_pending ) || new_pending
67
+ pending . try_set ( true )
68
+ true
62
69
end
63
70
64
71
def update_target ( target_id , params )
@@ -69,6 +76,21 @@ def delete_target(target_id)
69
76
@targets . delete ( target_id )
70
77
end
71
78
79
+ def attach_target ( target_id )
80
+ target = @targets [ target_id ]
81
+ raise NoSuchTargetError unless target
82
+
83
+ session = @client . command ( "Target.attachToTarget" , targetId : target_id , flatten : true )
84
+ target . session_id = session [ "sessionId" ]
85
+ true
86
+ end
87
+
88
+ def find_target
89
+ @targets . each_value { |t | return t if yield ( t ) }
90
+
91
+ nil
92
+ end
93
+
72
94
def close_targets_connection
73
95
@targets . each_value do |target |
74
96
next unless target . connected?
0 commit comments