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

Returns a new instance of 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
# 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
  @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:



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

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



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

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



76
77
78
# File 'lib/ferrum/context.rb', line 76

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

#disposeObject



103
104
105
# File 'lib/ferrum/context.rb', line 103

def dispose
  @contexts.dispose(@id)
end

#find_targetObject



89
90
91
92
93
# File 'lib/ferrum/context.rb', line 89

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

  nil
end

#inspectObject



111
112
113
# File 'lib/ferrum/context.rb', line 111

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

Returns:

  • (Boolean)


107
108
109
# File 'lib/ferrum/context.rb', line 107

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

#update_target(target_id, params) ⇒ Object



72
73
74
# File 'lib/ferrum/context.rb', line 72

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