class Ferrum::Page
Constants
- GOTO_WAIT
Attributes
browser[R]
document_id[R]
event[R]
headers[R]
keyboard[R]
mouse[R]
network[R]
referrer[RW]
target_id[R]
Public Class Methods
new(target_id, browser)
click to toggle source
# File lib/ferrum/page.rb, line 46 def initialize(target_id, browser) @frames = {} @main_frame = Frame.new(nil, self) @target_id, @browser = target_id, browser @event = Event.new.tap(&:set) host = @browser.process.host port = @browser.process.port ws_url = "ws://#{host}:#{port}/devtools/page/#{@target_id}" @client = Browser::Client.new(browser, ws_url, id_starts_with: 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
Public Instance Methods
back()
click to toggle source
# File lib/ferrum/page.rb, line 129 def back history_navigate(delta: -1) end
bypass_csp(value = true)
click to toggle source
# File lib/ferrum/page.rb, line 143 def bypass_csp(value = true) enabled = !!value command("Page.setBypassCSP", enabled: enabled) enabled end
close()
click to toggle source
# File lib/ferrum/page.rb, line 89 def close @headers.clear @browser.command("Target.closeTarget", targetId: @target_id) @client.close end
command(method, wait: 0, slowmoable: false, **params)
click to toggle source
# File lib/ferrum/page.rb, line 157 def command(method, wait: 0, slowmoable: false, **params) iteration = @event.reset if wait > 0 sleep(@browser.slowmo) if slowmoable && @browser.slowmo > 0 result = @client.command(method, params) if wait > 0 @event.wait(wait) # Wait a bit after command and check if iteration has # changed which means there was some network event for # the main frame and it started to load new content. if iteration != @event.iteration set = @event.wait(@browser.timeout) raise TimeoutError unless set end end result end
forward()
click to toggle source
# File lib/ferrum/page.rb, line 133 def forward history_navigate(delta: 1) end
go_to(url = nil)
click to toggle source
# File lib/ferrum/page.rb, line 69 def go_to(url = nil) options = { url: combine_url!(url) } options.merge!(referrer: referrer) if referrer response = command("Page.navigate", wait: GOTO_WAIT, **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"] rescue TimeoutError if @browser.pending_connection_errors pendings = network.traffic.select(&:pending?).map { |e| e.request.url } raise PendingConnectionsError.new(options[:url], pendings) unless pendings.empty? end end
Also aliased as: goto
on(name, &block)
click to toggle source
# File lib/ferrum/page.rb, line 174 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("Fetch.requestPaused") do |params, index, total| request = Network::InterceptedRequest.new(self, params) exchange = network.select(request.network_id).last exchange ||= network.build_exchange(request.network_id) exchange.intercepted_request = request block.call(request, index, total) end when :auth @client.on("Fetch.authRequired") do |params, index, total| request = Network::AuthRequest.new(self, params) block.call(request, index, total) end else @client.on(name, &block) end end
position()
click to toggle source
# File lib/ferrum/page.rb, line 112 def position @browser.command("Browser.getWindowBounds", windowId: window_id).fetch("bounds").values_at("left", "top") end
position=(left:, top:)
click to toggle source
# File lib/ferrum/page.rb, line 116 def position=(left:, top:) @browser.command("Browser.setWindowBounds", windowId: window_id, bounds: { left: left, top: top }) end
refresh()
click to toggle source
# File lib/ferrum/page.rb, line 120 def refresh command("Page.reload", wait: timeout, slowmoable: true) end
Also aliased as: reload
resize(width: nil, height: nil, fullscreen: false)
click to toggle source
# File lib/ferrum/page.rb, line 95 def resize(width: nil, height: nil, fullscreen: false) if fullscreen width, height = document_size set_window_bounds(windowState: "fullscreen") else set_window_bounds(windowState: "normal") set_window_bounds(width: width, height: height) end command("Emulation.setDeviceMetricsOverride", slowmoable: true, width: width, height: height, deviceScaleFactor: 1, mobile: false, fitWindow: false) end
set_window_bounds(bounds = {})
click to toggle source
# File lib/ferrum/page.rb, line 153 def set_window_bounds(bounds = {}) @browser.command("Browser.setWindowBounds", windowId: window_id, bounds: bounds) end
stop()
click to toggle source
# File lib/ferrum/page.rb, line 125 def stop command("Page.stopLoading", slowmoable: true) end
subscribed?(event)
click to toggle source
# File lib/ferrum/page.rb, line 199 def subscribed?(event) @client.subscribed?(event) end
timeout()
click to toggle source
# File lib/ferrum/page.rb, line 65 def timeout @browser.timeout end
wait_for_reload(sec = 1)
click to toggle source
# File lib/ferrum/page.rb, line 137 def wait_for_reload(sec = 1) @event.reset if @event.set? @event.wait(sec) @event.set end
window_id()
click to toggle source
# File lib/ferrum/page.rb, line 149 def window_id @browser.command("Browser.getWindowForTarget", targetId: @target_id)["windowId"] end
Private Instance Methods
combine_url!(url_or_path)
click to toggle source
# File lib/ferrum/page.rb, line 280 def combine_url!(url_or_path) url = Addressable::URI.parse(url_or_path) nil_or_relative = url.nil? || url.relative? if nil_or_relative && !@browser.base_url raise "Set :base_url browser's option or use absolute url in `go_to`, you passed: #{url_or_path}" end (nil_or_relative ? @browser.base_url.join(url.to_s) : url).to_s end
get_document_id()
click to toggle source
# File lib/ferrum/page.rb, line 291 def get_document_id @document_id = command("DOM.getDocument", depth: 0).dig("root", "nodeId") end
inject_extensions()
click to toggle source
# File lib/ferrum/page.rb, line 255 def inject_extensions @browser.extensions.each do |extension| # https://github.com/GoogleChrome/puppeteer/issues/1443 # https://github.com/ChromeDevTools/devtools-protocol/issues/77 # https://github.com/cyrus-and/chrome-remote-interface/issues/319 # We also evaluate script just in case because # `Page.addScriptToEvaluateOnNewDocument` doesn't work in popups. command("Runtime.evaluate", expression: extension, contextId: execution_id, returnByValue: true) end end
prepare_page()
click to toggle source
# File lib/ferrum/page.rb, line 223 def prepare_page command("Page.enable") command("Runtime.enable") command("DOM.enable") command("CSS.enable") command("Log.enable") command("Network.enable") if @browser.options[:save_path] command("Page.setDownloadBehavior", behavior: "allow", downloadPath: @browser.options[:save_path]) end @browser.extensions.each do |extension| command("Page.addScriptToEvaluateOnNewDocument", source: extension) end inject_extensions width, height = @browser.window_size resize(width: width, height: height) response = command("Page.getNavigationHistory") if response.dig("entries", 0, "transitionType") != "typed" # If we create page by clicking links, submiting forms and so on it # opens a new window for which `frameStoppedLoading` event never # occurs and thus search for nodes cannot be completed. Here we check # the history and if the transitionType for example `link` then # content is already loaded and we can try to get the document. get_document_id end end
subscribe()
click to toggle source
# File lib/ferrum/page.rb, line 205 def subscribe frames_subscribe network.subscribe if @browser.logger on("Runtime.consoleAPICalled") do |params| params["args"].each { |r| @browser.logger.puts(r["value"]) } end end if @browser.js_errors on("Runtime.exceptionThrown") do |params| # FIXME https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/ Thread.main.raise JavaScriptError.new(params.dig("exceptionDetails", "exception")) end end end