Class: Puppeteer::Bidi::BrowserContext

Inherits:
Object
  • Object
show all
Defined in:
lib/puppeteer/bidi/browser_context.rb,
sig/puppeteer/bidi/browser_context.rbs

Overview

BrowserContext represents an isolated browsing session This is a high-level wrapper around Core::UserContext

Constant Summary collapse

WEB_PERMISSION_TO_PROTOCOL_PERMISSION =

Maps web permission names to protocol permission names Based on Puppeteer's WEB_PERMISSION_TO_PROTOCOL_PERMISSION

Returns:

  • (Object)
{
  'accelerometer' => 'sensors',
  'ambient-light-sensor' => 'sensors',
  'background-sync' => 'backgroundSync',
  'camera' => 'videoCapture',
  'clipboard-read' => 'clipboardReadWrite',
  'clipboard-sanitized-write' => 'clipboardSanitizedWrite',
  'clipboard-write' => 'clipboardReadWrite',
  'geolocation' => 'geolocation',
  'gyroscope' => 'sensors',
  'idle-detection' => 'idleDetection',
  'keyboard-lock' => 'keyboardLock',
  'magnetometer' => 'sensors',
  'microphone' => 'audioCapture',
  'midi' => 'midi',
  'midi-sysex' => 'midiSysex',
  'notifications' => 'notifications',
  'payment-handler' => 'paymentHandler',
  'persistent-storage' => 'durableStorage',
  'pointer-lock' => 'pointerLock'
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(browser, user_context) ⇒ BrowserContext

Returns a new instance of BrowserContext.

Parameters:



41
42
43
44
45
46
47
# File 'lib/puppeteer/bidi/browser_context.rb', line 41

def initialize(browser, user_context)
  @browser = browser
  @user_context = user_context
  @pages = {}
  @frame_targets = {}
  @overrides = []
end

Instance Attribute Details

#browserBrowser (readonly)

: Browser

Returns:



36
37
38
# File 'lib/puppeteer/bidi/browser_context.rb', line 36

def browser
  @browser
end

#user_contextCore::UserContext (readonly)

: Core::UserContext

Returns:



35
36
37
# File 'lib/puppeteer/bidi/browser_context.rb', line 35

def user_context
  @user_context
end

Instance Method Details

#clear_permission_overridesvoid

This method returns an undefined value.

Clear permissions set through #override_permissions.



269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/puppeteer/bidi/browser_context.rb', line 269

def clear_permission_overrides
  tasks = @overrides.map do |override|
    lambda do
      begin
        @user_context.set_permissions(override[:origin], { name: override[:permission] }, 'prompt').wait
      rescue StandardError => error
        debug_error(error)
      end
    end
  end

  @overrides = []
  AsyncUtils.await_promise_all(*tasks) unless tasks.empty?
end

#closevoid

This method returns an undefined value.

Close the browser context



286
287
288
289
290
# File 'lib/puppeteer/bidi/browser_context.rb', line 286

def close
  return if closed?

  @user_context.remove.wait
end

#closed?Boolean

Check if context is closed

Returns:

  • (Boolean)


294
295
296
# File 'lib/puppeteer/bidi/browser_context.rb', line 294

def closed?
  @user_context.disposed?
end

Parameters:

  • cookie (Object)
  • raw_filter (Object)

Returns:

  • (Boolean)


313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/puppeteer/bidi/browser_context.rb', line 313

def cookie_matches_filter?(cookie, raw_filter)
  filter = CookieUtils.normalize_cookie_input(raw_filter)
  return false unless filter["name"] == cookie["name"]

  return true if filter.key?("domain") && filter["domain"] == cookie["domain"]
  return true if filter.key?("path") && filter["path"] == cookie["path"]

  if filter.key?("partitionKey") && cookie.key?("partitionKey")
    cookie_partition = cookie["partitionKey"]
    unless cookie_partition.is_a?(Hash)
      raise Error, "Unexpected string partition key"
    end

    filter_partition = filter["partitionKey"]
    if filter_partition.is_a?(String)
      return true if filter_partition == cookie_partition["sourceOrigin"]
    elsif filter_partition.is_a?(Hash)
      normalized_partition = CookieUtils.normalize_cookie_input(filter_partition)
      return true if normalized_partition["sourceOrigin"] == cookie_partition["sourceOrigin"]
    end
  end

  if filter.key?("url")
    url = URI.parse(filter["url"])
    url_path = url.path
    url_path = "/" if url_path.nil? || url_path.empty?
    return true if url.host == cookie["domain"] && url_path == cookie["path"]
  end

  true
end

#cookiesArray[Hash[String, untyped]]

Get all cookies in this context.

Returns:

  • (Array[Hash[String, untyped]])


108
109
110
111
112
113
114
# File 'lib/puppeteer/bidi/browser_context.rb', line 108

def cookies
  return [] if closed?

  @user_context.get_cookies.wait.map do |cookie|
    CookieUtils.bidi_to_puppeteer_cookie(cookie, return_composite_partition_key: true)
  end
end

#debug_error(error) ⇒ Object

Parameters:

  • error (Object)

Returns:

  • (Object)


345
346
347
348
349
# File 'lib/puppeteer/bidi/browser_context.rb', line 345

def debug_error(error)
  return unless ENV['DEBUG_BIDI_COMMAND']

  warn(error.full_message)
end

This method returns an undefined value.

Delete cookies in this context.

Parameters:

  • cookies (Array[Hash[String, untyped]])
  • cookie (Object)


166
167
168
169
170
171
172
173
174
175
176
# File 'lib/puppeteer/bidi/browser_context.rb', line 166

def delete_cookie(*cookies, **cookie)
  cookies = cookies.dup
  cookies << cookie unless cookie.empty?

  delete_candidates = cookies.map do |raw_cookie|
    normalized_cookie = CookieUtils.normalize_cookie_input(raw_cookie)
    normalized_cookie.merge("expires" => 1)
  end

  set_cookie(*delete_candidates)
end

#delete_matching_cookies(*filters, **filter) ⇒ void

This method returns an undefined value.

Delete cookies matching the provided filters.

Parameters:

  • filters (Array[Hash[String, untyped]])
  • filter (Object)


182
183
184
185
186
187
188
189
190
191
# File 'lib/puppeteer/bidi/browser_context.rb', line 182

def delete_matching_cookies(*filters, **filter)
  filters = filters.dup
  filters << filter unless filter.empty?

  cookies_to_delete = cookies.select do |cookie|
    filters.any? { |filter_entry| cookie_matches_filter?(cookie, filter_entry) }
  end

  delete_cookie(*cookies_to_delete)
end

#new_page(background: nil, type: nil, window_bounds: nil) ⇒ Page

Create a new page (tab/window)

Parameters:

  • background: (Boolean, nil) (defaults to: nil)
  • type: (String, nil) (defaults to: nil)
  • window_bounds: (Hash[Symbol | String, untyped], nil) (defaults to: nil)

Returns:



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/puppeteer/bidi/browser_context.rb', line 54

def new_page(background: nil, type: nil, window_bounds: nil)
  create_type = type.to_s == 'window' ? 'window' : 'tab'
  browsing_context = @user_context.create_browsing_context(create_type, background: background)
  page = page_for(browsing_context)

  if create_type == 'window' && window_bounds
    begin
      @browser.set_window_bounds(browsing_context.window_id, window_bounds)
    rescue StandardError => error
      debug_error(error)
    end
  end

  page
end

#override_permissions(origin, permissions) ⇒ void

This method returns an undefined value.

Override permissions for an origin

Parameters:

  • origin (String)
  • permissions (Array[String])


212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/puppeteer/bidi/browser_context.rb', line 212

def override_permissions(origin, permissions)
  # Validate all permissions are known
  permissions_set = permissions.map do |permission|
    protocol_permission = WEB_PERMISSION_TO_PROTOCOL_PERMISSION[permission.to_s]
    raise ArgumentError, "Unknown permission: #{permission}" unless protocol_permission

    permission.to_s
  end.to_set

  # Set each permission
  WEB_PERMISSION_TO_PROTOCOL_PERMISSION.each_key do |permission|
    state = permissions_set.include?(permission) ? 'granted' : 'denied'
    begin
      @user_context.set_permissions(origin, { name: permission }, state).wait
      @overrides << { origin: origin, permission: permission }
    rescue StandardError
      # Ignore errors for denied permissions (some may not be supported)
      raise if permissions_set.include?(permission)
    end
  end
end

#page_for(browsing_context) ⇒ Page

Get or create a Page for the given browsing context

Parameters:

Returns:



196
197
198
199
200
201
202
203
204
205
206
# File 'lib/puppeteer/bidi/browser_context.rb', line 196

def page_for(browsing_context)
  @pages[browsing_context.id] ||= begin
    page = Page.new(self, browsing_context)

    browsing_context.once(:closed) do
      @pages.delete(browsing_context.id)
    end

    page
  end
end

#pagesArray[Page]

Get all pages in this context

Returns:



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/puppeteer/bidi/browser_context.rb', line 72

def pages
  return [] if closed?

  # Return pages for all currently-known top-level browsing contexts.
  # Browsing contexts are synchronized from `browsingContext.getTree` during browser/session
  # initialization, so this allows `Puppeteer::Bidi.connect` to expose existing pages without
  # requiring an explicit enumeration via `wait_for_target`.
  @user_context.browsing_contexts
               .reject(&:disposed?)
               .map { |browsing_context| page_for(browsing_context) }
end

This method returns an undefined value.

Set cookies in this context.

Parameters:

  • cookies (Array[Hash[String, untyped]])
  • cookie (Object)


120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/puppeteer/bidi/browser_context.rb', line 120

def set_cookie(*cookies, **cookie)
  cookies = cookies.dup
  cookies << cookie unless cookie.empty?

  tasks = cookies.map do |raw_cookie|
    normalized_cookie = CookieUtils.normalize_cookie_input(raw_cookie)
    domain = normalized_cookie["domain"]
    if domain.nil?
      raise ArgumentError, "At least one of the url and domain needs to be specified"
    end

    bidi_cookie = {
      "domain" => domain,
      "name" => normalized_cookie["name"],
      "value" => { "type" => "string", "value" => normalized_cookie["value"] },
    }
    bidi_cookie["path"] = normalized_cookie["path"] if normalized_cookie.key?("path")
    bidi_cookie["httpOnly"] = normalized_cookie["httpOnly"] if normalized_cookie.key?("httpOnly")
    bidi_cookie["secure"] = normalized_cookie["secure"] if normalized_cookie.key?("secure")
    if normalized_cookie.key?("sameSite") && !normalized_cookie["sameSite"].nil?
      bidi_cookie["sameSite"] = CookieUtils.convert_cookies_same_site_cdp_to_bidi(
        normalized_cookie["sameSite"]
      )
    end
    expiry = CookieUtils.convert_cookies_expiry_cdp_to_bidi(normalized_cookie["expires"])
    bidi_cookie["expiry"] = expiry unless expiry.nil?
    bidi_cookie.merge!(CookieUtils.cdp_specific_cookie_properties_from_puppeteer_to_bidi(
                         normalized_cookie,
                         "sourceScheme",
                         "priority",
                         "url"
                       ))

    partition_key = CookieUtils.convert_cookies_partition_key_from_puppeteer_to_bidi(
      normalized_cookie["partitionKey"]
    )
    -> { @user_context.set_cookie(bidi_cookie, source_origin: partition_key).wait }
  end

  AsyncUtils.await_promise_all(*tasks) unless tasks.empty?
end

#set_permission(origin, *permissions) ⇒ void

This method returns an undefined value.

Set permission states for one or more permission descriptors.

Parameters:

  • origin (String, Symbol)
  • permissions (Hash[Symbol | String, untyped])


238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/puppeteer/bidi/browser_context.rb', line 238

def set_permission(origin, *permissions)
  if origin.to_s == '*'
    raise UnsupportedOperationError, 'Origin (*) is not supported by WebDriver BiDi'
  end

  tasks = permissions.map do |permission_entry|
    descriptor = permission_entry[:permission] || permission_entry['permission']
    state = permission_entry[:state] || permission_entry['state']
    raise ArgumentError, 'permission descriptor is required' unless descriptor.is_a?(Hash)
    raise ArgumentError, 'permission state is required' if state.nil?
    descriptor = descriptor.transform_keys(&:to_sym)

    if descriptor[:allowWithoutSanitization] || descriptor[:allow_without_sanitization]
      raise UnsupportedOperationError, 'allowWithoutSanitization is not supported by WebDriver BiDi'
    end
    if descriptor[:panTiltZoom] || descriptor[:pan_tilt_zoom]
      raise UnsupportedOperationError, 'panTiltZoom is not supported by WebDriver BiDi'
    end
    if descriptor[:userVisibleOnly] || descriptor[:user_visible_only]
      raise UnsupportedOperationError, 'userVisibleOnly is not supported by WebDriver BiDi'
    end
    raise ArgumentError, 'permission name is required' if descriptor[:name].nil?

    -> { @user_context.set_permissions(origin.to_s, { name: descriptor[:name] }, state.to_s).wait }
  end

  AsyncUtils.await_promise_all(*tasks) unless tasks.empty?
end

#target_for_frame(frame) ⇒ FrameTarget

Parameters:

Returns:



302
303
304
305
306
307
308
309
310
311
# File 'lib/puppeteer/bidi/browser_context.rb', line 302

def target_for_frame(frame)
  context_id = frame.browsing_context.id
  @frame_targets[context_id] ||= begin
    target = FrameTarget.new(frame)
    frame.browsing_context.once(:closed) do
      @frame_targets.delete(context_id)
    end
    target
  end
end

#targetsArray[PageTarget | FrameTarget]

Get all known targets in this browser context.

Returns:



86
87
88
89
90
# File 'lib/puppeteer/bidi/browser_context.rb', line 86

def targets
  pages.flat_map do |page|
    [page.target] + page.frames.drop(1).map { |frame| target_for_frame(frame) }
  end
end

#wait_for_target(timeout: nil) {|arg0| ... } ⇒ PageTarget, FrameTarget

Wait until a target in this context satisfies the predicate.

Parameters:

  • timeout: (Integer, nil) (defaults to: nil)

Yields:

Yield Parameters:

Yield Returns:

  • (boolish)

Returns:



96
97
98
99
100
101
102
103
104
# File 'lib/puppeteer/bidi/browser_context.rb', line 96

def wait_for_target(timeout: nil, &predicate)
  predicate ||= ->(_target) { true }

  browser.wait_for_target(timeout: timeout) do |target|
    (target.is_a?(PageTarget) || target.is_a?(FrameTarget)) &&
      target.browser_context == self &&
      predicate.call(target)
  end #: PageTarget | FrameTarget
end