Class: Ferrum::Page

Inherits:
Object
  • Object
show all
Includes:
DOM, Frame, Runtime, Screenshot
Defined in:
lib/ferrum/page.rb,
lib/ferrum/page/dom.rb,
lib/ferrum/page/frame.rb,
lib/ferrum/page/runtime.rb,
lib/ferrum/page/screenshot.rb

Defined Under Namespace

Modules: DOM, Frame, Runtime, Screenshot Classes: Event

Constant Summary collapse

NEW_WINDOW_WAIT =
ENV.fetch("FERRUM_NEW_WINDOW_WAIT", 0.3).to_f

Constants included from Runtime

Runtime::DEFAULT_OPTIONS, Runtime::EVALUATE_ASYNC_OPTIONS, Runtime::EXECUTE_OPTIONS, Runtime::INTERMITTENT_ATTEMPTS, Runtime::INTERMITTENT_SLEEP

Instance Attribute Summary collapse

Attributes included from Frame

#frame_id

Instance Method Summary collapse

Methods included from DOM

#at_css, #at_xpath, #body, #css, #current_url, #title, #xpath

Methods included from Runtime

#evaluate, #evaluate_async, #evaluate_on, #execute

Methods included from Frame

#execution_context_id, #frame_name, #frame_title, #frame_url, #within_frame

Methods included from Screenshot

#pdf, #screenshot

Constructor Details

#initialize(target_id, browser, new_window = false) ⇒ Page

Returns a new instance of Page.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ferrum/page.rb', line 40

def initialize(target_id, browser, new_window = false)
  @target_id, @browser = target_id, browser
  @event = Event.new.tap(&:set)

  @frames = {}
  @waiting_frames ||= Set.new
  @frame_stack = []

  # Dirty hack because new window doesn't have events at all
  sleep(NEW_WINDOW_WAIT) if new_window

  @session_id = @browser.command("Target.attachToTarget", targetId: @target_id)["sessionId"]

  host = @browser.process.host
  port = @browser.process.port
  ws_url = "ws://#{host}:#{port}/devtools/page/#{@target_id}"
  @client = Browser::Client.new(browser, ws_url, 1000)

  @mouse, @keyboard = Mouse.new(self), Keyboard.new(self)
  @headers, @cookies = Headers.new(self), Cookies.new(self)
  @network = Network.new(self)

  subscribe
  prepare_page
end

Instance Attribute Details

#browserObject (readonly)

Returns the value of attribute browser.



36
37
38
# File 'lib/ferrum/page.rb', line 36

def browser
  @browser
end

#cookiesObject (readonly)

Returns the value of attribute cookies.



36
37
38
# File 'lib/ferrum/page.rb', line 36

def cookies
  @cookies
end

#headersObject (readonly)

Returns the value of attribute headers.



36
37
38
# File 'lib/ferrum/page.rb', line 36

def headers
  @headers
end

#keyboardObject (readonly)

Returns the value of attribute keyboard.



36
37
38
# File 'lib/ferrum/page.rb', line 36

def keyboard
  @keyboard
end

#mouseObject (readonly)

Returns the value of attribute mouse.



36
37
38
# File 'lib/ferrum/page.rb', line 36

def mouse
  @mouse
end

#networkObject (readonly)

Returns the value of attribute network.



36
37
38
# File 'lib/ferrum/page.rb', line 36

def network
  @network
end

#referrerObject

Returns the value of attribute referrer.



35
36
37
# File 'lib/ferrum/page.rb', line 35

def referrer
  @referrer
end

#target_idObject (readonly)

Returns the value of attribute target_id.



36
37
38
# File 'lib/ferrum/page.rb', line 36

def target_id
  @target_id
end

Instance Method Details

#backObject



112
113
114
# File 'lib/ferrum/page.rb', line 112

def back
  history_navigate(delta: -1)
end

#closeObject



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

def close
  @headers.clear
  @browser.command("Target.detachFromTarget", sessionId: @session_id)
  @browser.command("Target.closeTarget", targetId: @target_id)
  close_connection
end

#close_connectionObject



91
92
93
# File 'lib/ferrum/page.rb', line 91

def close_connection
  @client.close
end

#command(method, wait: 0, **params) ⇒ Object



120
121
122
123
124
125
126
127
128
# File 'lib/ferrum/page.rb', line 120

def command(method, wait: 0, **params)
  iteration = @event.reset if wait > 0
  result = @client.command(method, params)
  if wait > 0
    @event.wait(wait)
    @event.wait(@browser.timeout) if iteration != @event.iteration
  end
  result
end

#forwardObject



116
117
118
# File 'lib/ferrum/page.rb', line 116

def forward
  history_navigate(delta: 1)
end

#goto(url = nil) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/ferrum/page.rb', line 70

def goto(url = nil)
  options = { url: combine_url!(url) }
  options.merge!(referrer: referrer) if referrer
  response = command("Page.navigate", wait: timeout, **options)
  # https://cs.chromium.org/chromium/src/net/base/net_error_list.h
  if %w[net::ERR_NAME_NOT_RESOLVED
        net::ERR_NAME_RESOLUTION_FAILED
        net::ERR_INTERNET_DISCONNECTED
        net::ERR_CONNECTION_TIMED_OUT].include?(response["errorText"])
    raise StatusError, options[:url]
  end
  response["frameId"]
end

#on(name, &block) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/ferrum/page.rb', line 130

def on(name, &block)
  case name
  when :dialog
    @client.on("Page.javascriptDialogOpening") do |params, index, total|
      dialog = Dialog.new(self, params)
      block.call(dialog, index, total)
    end
  when :request
    @client.on("Network.requestIntercepted") do |params, index, total|
      request = Network::InterceptedRequest.new(self, params)
      block.call(request, index, total)
    end
  else
    @client.on(name, &block)
  end
end

#refreshObject



108
109
110
# File 'lib/ferrum/page.rb', line 108

def refresh
  command("Page.reload", wait: timeout)
end

#resize(width: nil, height: nil, fullscreen: false) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/ferrum/page.rb', line 95

def resize(width: nil, height: nil, fullscreen: false)
  result = @browser.command("Browser.getWindowForTarget", targetId: @target_id)
  @window_id, @bounds = result.values_at("windowId", "bounds")

  if fullscreen
    @browser.command("Browser.setWindowBounds", windowId: @window_id, bounds: { windowState: "fullscreen" })
  else
    @browser.command("Browser.setWindowBounds", windowId: @window_id, bounds: { windowState: "normal" })
    @browser.command("Browser.setWindowBounds", windowId: @window_id, bounds: { width: width, height: height, windowState: "normal" })
    command("Emulation.setDeviceMetricsOverride", width: width, height: height, deviceScaleFactor: 1, mobile: false)
  end
end

#timeoutObject



66
67
68
# File 'lib/ferrum/page.rb', line 66

def timeout
  @browser.timeout
end