Class: Ronin::Web::Browser::Agent

Inherits:
Ferrum::Browser
  • Object
show all
Defined in:
lib/ronin/web/browser/agent.rb

Overview

Represents an instance of a Chrome headless or visible browser.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(visible: false, headless: !visible,, proxy: Ronin::Support::Network::HTTP.proxy, **kwargs) ⇒ Agent

Initializes the browser agent.

Parameters:

  • visible (Boolean) (defaults to: false)

    Controls whether the browser will start in visible or headless mode.

  • headless (Boolean) (defaults to: !visible,)

    Controls whether the browser will start in headless or visible mode.

  • proxy (String, URI::HTTP, Addressible::URI, Hash, nil) (defaults to: Ronin::Support::Network::HTTP.proxy)

    The proxy to send all browser requests through.

  • kwargs (Hash{Symbol => Object})

    Additional keyword arguments for Ferrum::Browser#initialize.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/ronin/web/browser/agent.rb', line 56

def initialize(visible:  false,
               headless: !visible,
               proxy:    Ronin::Support::Network::HTTP.proxy,
               **kwargs)
  proxy = case proxy
          when Hash, nil then proxy
          when URI::HTTP, Addressable::URI
            {
              host:     proxy.host,
              port:     proxy.port,
              user:     proxy.user,
              password: proxy.password
            }
          when String
            uri = URI(proxy)

            {
              host:     uri.host,
              port:     uri.port,
              user:     uri.user,
              password: uri.password
            }
          else
            raise(ArgumentError,"invalid proxy value (#{proxy.inspect}), must be either a Hash, URI::HTTP, String, or nil")
          end

  @headless = headless
  @proxy    = proxy

  super(headless: headless, proxy: proxy, **kwargs)
end

Instance Attribute Details

#proxyHash{Symbol => Object}? (readonly)

The configured proxy information.

Returns:

  • (Hash{Symbol => Object}, nil)


39
40
41
# File 'lib/ronin/web/browser/agent.rb', line 39

def proxy
  @proxy
end

Class Method Details

.open(**kwargs) {|browser| ... } ⇒ Agent

Opens a new browser.

Parameters:

  • kwargs (Hash{Symbol => Object})

    Additional keyword arguments for #initialize.

Yields:

  • (browser)

    If a block is given, it will be passed the new browser object. Once the block returns, quit will be called on the browser object.

Yield Parameters:

  • browser (Agent)

    The newly created browser object.

Returns:

  • (Agent)

    The opened browser object.



104
105
106
107
108
109
110
111
112
113
# File 'lib/ronin/web/browser/agent.rb', line 104

def self.open(**kwargs)
  browser = new(**kwargs)

  if block_given?
    yield browser
    browser.quit
  end

  return browser
end

Instance Method Details

#at(query) ⇒ Ferrum::Node?

Queries the XPath or CSS-path query and returns the first match.

Returns:

  • (Ferrum::Node, nil)

    The first matching node.



313
314
315
316
317
318
319
# File 'lib/ronin/web/browser/agent.rb', line 313

def at(query)
  if query.start_with?('/')
    at_xpath(query)
  else
    at_css(query)
  end
end

#bypass_csp=(mode) ⇒ Object

Enables or disables bypassing CSP.

Parameters:

  • mode (Boolean)

    Controls whether to enable or disable CSP bypassing.



146
147
148
149
150
# File 'lib/ronin/web/browser/agent.rb', line 146

def bypass_csp=(mode)
  if mode then bypass_csp(enabled: true)
  else         bypass_csp(enabled: false)
  end
end

Enumerates over all session cookies.

Yields:

  • (cookie)

    The given block will be passed each session cookie.

Yield Parameters:

  • cookie (Ferrum::Cookies::Cookie)

    A cookie that ends with sess or session.

Returns:

  • (Enumerator)

    If no block is given, then an Enumerator object will be returned.



358
359
360
361
362
363
364
# File 'lib/ronin/web/browser/agent.rb', line 358

def each_session_cookie
  return enum_for(__method__) unless block_given?

  cookies.each do |cookie|
    yield cookie if cookie.session?
  end
end

#every_request {|request| ... } ⇒ Object

Passes every request to the given block.

Yields:

  • (request)

    The given block will be passed each request before it's sent.

Yield Parameters:

  • request (Ferrum::Network::InterceptRequest)

    A network request object.



212
213
214
215
216
217
218
219
# File 'lib/ronin/web/browser/agent.rb', line 212

def every_request
  network.intercept

  on(:request) do |request|
    yield request
    request.continue
  end
end

#every_response {|response| ... } ⇒ Object

Passes every response to the given block.

Yields:

  • (response)

    If the given block accepts a single argument, it will be passed each response object.

  • (response, request)

    If the given block accepts two arguments, it will be passed the response and the request objects.

Yield Parameters:

  • response (Ferrum::Network::Response)

    A respone object returned for a request.

  • request (Ferrum::Network::Request)

    The request object for the response.



238
239
240
241
242
243
244
245
246
# File 'lib/ronin/web/browser/agent.rb', line 238

def every_response(&block)
  on(:response) do |exchange,index,total|
    if block.arity == 2
      yield exchange.response, exchange.request
    else
      yield exchange.response
    end
  end
end

#every_url {|url| ... } ⇒ Object

Passes every requested URL to the given block.

Yields:

  • (url)

    The given block will be passed every URL.

Yield Parameters:

  • url (String)

    A URL requested by the browser.



257
258
259
260
261
# File 'lib/ronin/web/browser/agent.rb', line 257

def every_url
  every_request do |request|
    yield request.url
  end
end

#every_url_like(pattern) {|url| ... } ⇒ Object

Passes every requested URL that matches the given pattern to the given block.

Parameters:

  • pattern (String, Regexp)

    The pattern to filter the URLs by.

Yields:

  • (url)

    The given block will be passed every URL that matches the pattern.

Yield Parameters:

  • url (String)

    A matching URL requested by the browser.



276
277
278
279
280
281
282
# File 'lib/ronin/web/browser/agent.rb', line 276

def every_url_like(pattern)
  every_url do |url|
    if pattern.match(url)
      yield url
    end
  end
end

#headless?Boolean

Determines whether the browser was opened in headless mode.

Returns:

  • (Boolean)


120
121
122
# File 'lib/ronin/web/browser/agent.rb', line 120

def headless?
  @headless
end

Queries all <a href="..."> links in the current page.

Returns:

  • (Array<String>)


326
327
328
# File 'lib/ronin/web/browser/agent.rb', line 326

def links
  xpath('//a/@href').map(&:value)
end

#load_cookies(path) ⇒ Object

Loads the cookies from the cookie file.

Parameters:

  • path (String)

    The path to the cookie file.



398
399
400
401
402
# File 'lib/ronin/web/browser/agent.rb', line 398

def load_cookies(path)
  CookieFile.new(path).each do |cookie|
    cookies.set(cookie)
  end
end

#on(event) {|request| ... } ⇒ Object

Registers a callback for the given event type.

Parameters:

Yields:

  • (request)

    If the event type is :request the given block will be passed the request object.

  • (exchange)

    If the event type is :response the given block will be passed the network exchange object containing both the request and the response objects.

  • (params, index, total)

    Other event types will be passed a params Hash, index, and total.

Yield Parameters:

  • request (Ferrum::Network::InterceptedRequest)

    A network request object.

  • exchange (Ferrum::Network::Exchange)

    A network exchange object containing both the request and respoonse objects.

  • params (Hash{String => Object})

    A params Hash containing the return value(s).

  • index (Integer)
  • total (Integer)


186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/ronin/web/browser/agent.rb', line 186

def on(event,&block)
  case event
  when :response
    super('Network.responseReceived') do |params,index,total|
      exchange = network.select(params['requestId']).last

      if exchange
        block.call(exchange,index,total)
      end
    end
  when :close
    super('Inspector.detached',&block)
  else
    super(event,&block)
  end
end

#page_uriURI::HTTP

The page's current URI.

Returns:

  • (URI::HTTP)


289
290
291
# File 'lib/ronin/web/browser/agent.rb', line 289

def page_uri
  URI.parse(url)
end

#proxy?Boolean

Determines whether the proxy was initialized with a proxy.

Returns:

  • (Boolean)


136
137
138
# File 'lib/ronin/web/browser/agent.rb', line 136

def proxy?
  !@proxy.nil?
end

#save_cookies(path) ⇒ Object

Saves the cookies to a cookie file.

Parameters:

  • path (String)

    The path to the output cookie file.



410
411
412
# File 'lib/ronin/web/browser/agent.rb', line 410

def save_cookies(path)
  CookieFile.save(path,cookies)
end

#search(query) ⇒ Array<Ferrum::Node>

Queries the XPath or CSS-path query and returns the matching nodes.

Returns:

  • (Array<Ferrum::Node>)

    The matching node.



299
300
301
302
303
304
305
# File 'lib/ronin/web/browser/agent.rb', line 299

def search(query)
  if query.start_with?('/')
    xpath(query)
  else
    css(query)
  end
end

#session_cookiesArray<Ferrum::Cookie>

Fetches all session cookies.

Returns:

  • (Array<Ferrum::Cookie>)

    The matching session cookies.



372
373
374
# File 'lib/ronin/web/browser/agent.rb', line 372

def session_cookies
  each_session_cookie.to_a
end

Sets a cookie.

Parameters:

  • name (String)

    The cookie name.

  • value (String)

    The cookie value.

  • options (Hash{Symbol => Object})

    Additional cookie attributes.



388
389
390
# File 'lib/ronin/web/browser/agent.rb', line 388

def set_cookie(name,value,**options)
  cookies.set(name: name, value: value, **options)
end

#urlsArray<URI::HTTP, URI::HTTPS>

All link URLs in the current page.

Returns:

  • (Array<URI::HTTP, URI::HTTPS>)


335
336
337
338
339
# File 'lib/ronin/web/browser/agent.rb', line 335

def urls
  page_uri = self.page_uri

  links.map { |link| page_uri.merge(link) }
end

#visible?Boolean

Determines whether the browser was opened in visible mode.

Returns:

  • (Boolean)


129
130
131
# File 'lib/ronin/web/browser/agent.rb', line 129

def visible?
  !@headless
end

#wait_until_closedObject

Waits indefinitely until the browser window is closed.



417
418
419
420
421
422
423
424
425
# File 'lib/ronin/web/browser/agent.rb', line 417

def wait_until_closed
  window_closed = false

  on('Inspector.detached') do
    window_closed = true
  end

  sleep(1) until window_closed
end