rubycdp / ferrum

Headless Chrome Ruby API
https://ferrum.rubycdp.com
MIT License
1.74k stars 123 forks source link

Not getting execution_id for frame #235

Closed hkmaly closed 8 months ago

hkmaly commented 2 years ago

Is there anything you can do with (i)frame not getting execution_id if, based on running the script with FERRUM_DEBUG=true, the Runtime.executionContextCreated never happens for that frame? Or is that chromium bug?

(Note: Found a workaround how to do what I needed without accessing frame, but I'm still interested ...)

route commented 2 years ago

You better provide log, because it's hard to figure out without data

hkmaly commented 2 years ago

Sorry, I don't want to public the page it's happening on and it's apparent it's caused by something specific it does as it works on other pages. (And it does a LOT of things. Including creating three frames despite only one being visible in DOM.)

But looking into the source, I noticed that only way how execution_id can be filled is as reaction on Runtime.executionContextCreated ... and that one is never called ...

route commented 2 years ago

I helpless here then.

rubendinho commented 2 years ago

I'm getting the Runtime.executionContextCreated to fire but it's not setting an execution_id for child frames. This happens when running the browser in head-ful mode, but is working find in headless mode.

skyeagle commented 1 year ago

We have hit the same issue, execution_id is not getting set in headful mode.

It's easy to reproduce with the following spec:

HEADLESS=false bundle exec rspec spec/frame_spec.rb

Can we re-open this issue? I would be happy to provide any additional information for further investigation if needed. Thanks!

route commented 1 year ago

@skyeagle can you show the error you are getting running the command you provided?

skyeagle commented 1 year ago

@skyeagle can you show the error you are getting running the command you provided?

Sure thing

  1) Ferrum::Frame supports selection by index
     Failure/Error: expect(frame.url).to end_with("/ferrum/slow")

     NoMethodError:
       undefined method `url' for nil:NilClass
     # ./spec/frame_spec.rb:16:in

There is chrome's version on Mac OS X M1

Version 109.0.5414.87 (Official Build) (arm64)

Thank you for taking a look!

hkmaly commented 1 year ago

... I was running the browser in head-ful mode ...

KevUp commented 1 year ago

Also seeing issue when running Capybara / Cuprite tests in head-ful mode, fine in headless.

test is using within_frame frame do block

/Users/UpstilK/.rvm/gems/ruby-3.1.2/gems/ferrum-0.13/lib/ferrum/page.rb:414: warning: Capybara::Cuprite::Page#execution_id! at /Users/UpstilK/.rvm/rubies/ruby-3.1.2/lib/ruby/3.1.0/forwardable.rb:138 forwarding to private method NilClass#execution_id!

NoMethodError: undefined method `execution_id!' for nil:NilClass

  unless defined?(methods.each)
                         ^^^^^

/Users/UpstilK/.rvm/rubies/ruby-3.1.2/lib/ruby/3.1.0/forwardable.rb:236:in execution_id!' /Users/UpstilK/.rvm/gems/ruby-3.1.2/gems/ferrum-0.13/lib/ferrum/page.rb:414:inblock in inject_extensions' /Users/UpstilK/.rvm/gems/ruby-3.1.2/gems/ferrum-0.13/lib/ferrum/page.rb:407:in each' /Users/UpstilK/.rvm/gems/ruby-3.1.2/gems/ferrum-0.13/lib/ferrum/page.rb:407:ininject_extensions' /Users/UpstilK/.rvm/gems/ruby-3.1.2/gems/cuprite-0.14.3/lib/capybara/cuprite/page.rb:119:in switch_to_frame' /Users/UpstilK/.rvm/rubies/ruby-3.1.2/lib/ruby/3.1.0/forwardable.rb:238:inswitch_to_frame' /Users/UpstilK/.rvm/gems/ruby-3.1.2/gems/cuprite-0.14.3/lib/capybara/cuprite/driver.rb:107:in switch_to_frame' /Users/UpstilK/.rvm/gems/ruby-3.1.2/gems/capybara-3.38.0/lib/capybara/session.rb:410:inswitch_to_frame' /Users/UpstilK/.rvm/gems/ruby-3.1.2/gems/capybara-3.38.0/lib/capybara/session.rb:448:in within_frame' /Users/UpstilK/.rvm/gems/ruby-3.1.2/gems/capybara-3.38.0/lib/capybara/dsl.rb:52:incall' /Users/UpstilK/.rvm/gems/ruby-3.1.2/gems/capybara-3.38.0/lib/capybara/dsl.rb:52:in `within_frame'

infernalmaster commented 1 year ago

I'm using chrome Version 114.0.5735.133 (Official Build) (arm64) and also have same issue (iframe access do not work in headless and non-headless mode). I tried to debug and notices that Page.frameAttached was triggered for iframe but after that event Page.frameDetached removed iframe from page.driver.browser.page.frames.

I found similar issue for puppeteer https://github.com/puppeteer/puppeteer/issues/2548. There was proposed flag --disable-features=site-per-process but ferrum already has it in lib/ferrum/browser/options/chrome.rb

Also there was a link to some chromium issue https://bugs.chromium.org/p/chromium/issues/detail?id=924937#c13

Looks like puppeteer implemented that change in this PR https://github.com/puppeteer/puppeteer/pull/7556 but it would requires multiple changes in out case.

So I also checked capybara and found that they use --disable-site-isolation-trials and it helped.

Right now my cuprit initialization looks like that

Capybara.register_driver(:cuprite) do |app|
  Capybara::Cuprite::Driver.new(app,
    headless: Capybara.headless?,
    inspector: true,
    timeout: 30,
    process_timeout: 30,
    browser_options: Hash.new.tap do |hash|
      hash['no-sandbox'] = nil if Capybara.no_sandbox?

      # iframe also works with old headless mode
      hash['headless'] = 'new' if Capybara.headless?

      # Required for cuprite to work with iframes
      hash['disable-site-isolation-trials'] = nil
route commented 8 months ago

It should work now in the master as I merged work on disable-site-isolation-trials

o0101 commented 4 months ago

@infernalmaster this is excellent research, thank you. 😄