Class: Ferrum::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/ferrum/context.rb

Constant Summary collapse

POSITION =
i[first last].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, contexts, id) ⇒ Context



11
12
13
14
15
16
17
# File 'lib/ferrum/context.rb', line 11

def initialize(client, contexts, id)
  @id = id
  @client = client
  @contexts = contexts
  @targets = Concurrent::Map.new
  @pendings = Concurrent::Map.new
end

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id.



9
10
11
# File 'lib/ferrum/context.rb', line 9

def id
  @id
end

#targetsObject (readonly)

Returns the value of attribute targets.



9
10
11
# File 'lib/ferrum/context.rb', line 9

def targets
  @targets
end

Instance Method Details

#add_target(params:, session_id: nil) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/ferrum/context.rb', line 60

def add_target(params:, session_id: nil)
  new_target = Target.new(@client, session_id, params)
  # `put_if_absent` returns nil if added a new value or existing if there was one already
  target = @targets.put_if_absent(new_target.id, new_target) || new_target
  # on first iteration session_id may be nil, then if session is present here we must set it to the target
  target.session_id = session_id if session_id && target.session_id.nil?
  @default_target ||= target

  new_pending = Concurrent::IVar.new
  pending = @pendings.put_if_absent(target.id, new_pending) || new_pending
  pending.try_set(true)
  true
end

#attach_target(target_id) ⇒ Object

Raises:



82
83
84
85
86
87
88
89
# File 'lib/ferrum/context.rb', line 82

def attach_target(target_id)
  target = @targets[target_id]
  raise NoSuchTargetError unless target

  session = @client.command("Target.attachToTarget", targetId: target_id, flatten: true)
  target.session_id = session["sessionId"]
  true
end

#close_targets_connectionObject



97
98
99
100
101
102
103
# File 'lib/ferrum/context.rb', line 97

def close_targets_connection
  @targets.each_value do |target|
    next unless target.connected?

    target.page.close_connection
  end
end

#create_page(**options) ⇒ Object



43
44
45
46
# File 'lib/ferrum/context.rb', line 43

def create_page(**options)
  target = create_target
  target.page = target.build_page(**options)
end

#create_targetObject

Raises:



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/ferrum/context.rb', line 48

def create_target
  target_id = @client.command("Target.createTarget", browserContextId: @id, url: "about:blank")["targetId"]

  new_pending = Concurrent::IVar.new
  pending = @pendings.put_if_absent(target_id, new_pending) || new_pending
  resolved = pending.value(@client.timeout)
  raise NoSuchTargetError unless resolved

  @pendings.delete(target_id)
  @targets[target_id]
end

#default_targetObject



19
20
21
# File 'lib/ferrum/context.rb', line 19

def default_target
  @default_target ||= create_target
end

#delete_target(target_id) ⇒ Object



78
79
80
# File 'lib/ferrum/context.rb', line 78

def delete_target(target_id)
  @targets.delete(target_id)
end

#disposeObject



105
106
107
# File 'lib/ferrum/context.rb', line 105

def dispose
  @contexts.dispose(@id)
end

#find_targetObject



91
92
93
94
95
# File 'lib/ferrum/context.rb', line 91

def find_target
  @targets.each_value { |t| return t if yield(t) }

  nil
end

#inspectObject



113
114
115
# File 'lib/ferrum/context.rb', line 113

def inspect
  %(#<#{self.class} @id=#{@id.inspect} @targets=#{@targets.inspect} @default_target=#{@default_target.inspect}>)
end

#pageObject



23
24
25
# File 'lib/ferrum/context.rb', line 23

def page
  default_target.page
end

#pagesObject



27
28
29
# File 'lib/ferrum/context.rb', line 27

def pages
  @targets.values.reject(&:iframe?).map(&:page)
end

#target?(target_id) ⇒ Boolean



109
110
111
# File 'lib/ferrum/context.rb', line 109

def target?(target_id)
  !!@targets[target_id]
end

#update_target(target_id, params) ⇒ Object



74
75
76
# File 'lib/ferrum/context.rb', line 74

def update_target(target_id, params)
  @targets[target_id]&.update(params)
end

#windows(pos = nil, size = 1) ⇒ Object

When we call page method on target it triggers ruby to connect to given page by WebSocket, if there are many opened windows, but we need only one it makes more sense to get and connect to the needed one only which usually is the last one.

Raises:

  • (ArgumentError)


35
36
37
38
39
40
41
# File 'lib/ferrum/context.rb', line 35

def windows(pos = nil, size = 1)
  raise ArgumentError if pos && !POSITION.include?(pos)

  windows = @targets.values.select(&:window?)
  windows = windows.send(pos, size) if pos
  windows.map(&:page)
end