Corion / WWW-Mechanize-Chrome

automate the Chrome browser
https://metacpan.org/release/WWW-Mechanize-Chrome
Artistic License 2.0
30 stars 12 forks source link

Can't locate object method "port" via package "URI::_generic" at .../perl/5.28.1/WWW/Mechanize/Chrome.pm line 1033. #61

Open maxbriliant opened 3 years ago

maxbriliant commented 3 years ago
#!/usr/bin/perl
use warnings;
use WWW::Mechanize::Chrome;
use Log::Log4perl qw(:easy);

my $mech = WWW::Mechanize::Chrome->new();

=> Can't locate object method "port" via package "URI::_generic" at .../perl/5.28.1/WWW/Mechanize/Chrome.pm line 1033.

=> LINES 1009 - 1034

sub _spawn_new_chrome_instance( $self, $options ) {
    my $class = ref $self;
    my @cmd = $class->build_command_line( $options );
    $self->log('debug', "Spawning for $options->{ connection_style }", \@cmd);
    (my( $pid , $to_chrome, $from_chrome, $chrome_stdout ))
        = $self->spawn_child( $options->{ connection_style }, @cmd );
    $options->{ writer_fh } = $to_chrome;
    $options->{ reader_fh } = $from_chrome;
    $self->{pid} = $pid;
    $self->{ kill_pid } = 1;
    if( $options->{ connection_style } eq 'pipe') {
        $options->{ writer_fh } = $to_chrome;
        $options->{ reader_fh } = $from_chrome;

    } else {
        if( $chrome_stdout ) {
            # Synchronously wait for the URL we can connect to
            # Maybe this should become part of the transport, or a second
            # class to asynchronously wait on a filehandle?!
            $options->{ endpoint } = $self->read_devtools_url( $chrome_stdout );
            close $chrome_stdout;

            # set up host/port here so it can be used later by other instances
            my $ws = URI->new( $options->{endpoint});

            ###### LINE 1033 #######
            $options->{port} = $ws->port;
            ######################
            $options->{host} = $ws->host;

Is this a temporary Bug or did I just miss to install the certain module?

Installed modules are: Algorithm::Diff Algorithm::Loops App::cpanminus CAM::PDF CGI Capture::Tiny Class::Accessor Class::Method::Modifiers Crypt::RC4 Data::Dump Devel::Cycle Devel::Symdump ExtUtils::Config ExtUtils::Helpers ExtUtils::InstallPaths Filter::signatures Font::TTF Future Future::HTTP HTML::Form HTML::Selector::XPath HTTP::Daemon HTTP::Request::AsCGI HTTP::Server::Simple IO::Async IO::String Image::Info Imager Imager::File::PNG JSON Log::Log4perl MRO::Compat Metrics::Any Module::Build Module::Build::Tiny Mojolicious Moo Net::Async::WebSocket Object::Import PDF::API2 PadWalker Path::Tiny Perl PerlX::Maybe Pod::Coverage Protocol::WebSocket Role::Tiny Socket Spiffy Struct::Dumb Sub::Quote Sub::Uplevel Test::Base Test::Deep Test::Exception Test::Fatal Test::HTTP::LocalServer Test::Identity Test::Memory::Cycle Test::Metrics::Any Test::Needs Test::NoWarnings Test::Output Test::Pod Test::Pod::Coverage Test::Refcount Test::RequiresInternet Test::Taint Test::Warn Test::Warnings Test::Without::Module Text::Diff Text::Levenshtein Text::Levenshtein::Damerau Text::PDF URI URI::ws WWW::Mechanize WWW::Mechanize::Chrome install libwww::perl local::lib

Greetings, Mx

Corion commented 3 years ago

Can you please post the version of the URI module you have? Maybe there was a change there...

perl -MURI -e "print URI->VERSION"

Locally I have URI 5.09 and it works here.

Also, what version of WWW::Mechanize::Chrome are you using?

maxbriliant commented 3 years ago

Hey Max, Thanks for the Quick Reply here.

5.09 is the version of my URI 0.67 is the version of WWW::Mechanize::Chrome

    .../Perl5/WWW/Mechanize/Chrome.pm
    Installed: 0.67
    CPAN:      0.67  up to date
    Max Maischein (CORION)
    corion@cpan.org

Somehow the used Perl library - is located in /home/$USER/perl5/.. That might be a hint to some miss-configuration?

Greetings, Max

Corion commented 3 years ago

These are the versions that I expect. Maybe the output of Chrome is unexpected in some way...

Can you please run your test program with the logging level set to trace? If you don't have a small program, the following should produce the output of Chrome to the console as well:

#!perl
use strict;
use warnings;

use WWW::Mechanize::Chrome;
use Log::Log4perl ':easy';

Log::Log4perl->easy_init($TRACE);

my $mech = WWW::Mechanize::Chrome->new(
        autodie => 1,
);

# I don't expect to get here...
print "Program completed OK\n";

Actually, this problem occurs (for me now too) when an instance of Chrome is still open and Chrome was not launched with the --remote-debugging-port option.

The following program creates a separate Chrome instance that does not share cookies etc. and should always start for you. I think I will have to improve the error message for when there is no ws:// URL found anyway....

#!perl
use strict;
use warnings;

use File::Temp 'tempdir';
use WWW::Mechanize::Chrome;
use Log::Log4perl ':easy';

Log::Log4perl->easy_init($TRACE);

my $tempdir = tempdir( CLEANUP => 1 );

my $mech = WWW::Mechanize::Chrome->new(
        autodie => 1,
        data_directory => $tempdir,
);

# I don't expect to get here...
print "Program completed OK\n";
maxbriliant commented 3 years ago

I believe, we have the same output here -

2021/08/15 22:18:46 Spawning for websocket $VAR1 = [
          '/bin/google-chrome',
          '--remote-debugging-port=0',
          '--remote-debugging-address=127.0.0.1',
          '--enable-automation',
          '--no-first-run',
          '--mute-audio',
          '--no-zygote',
          '--no-sandbox',
          '--safebrowsing-disable-auto-update',
          '--disable-background-networking',
          '--disable-breakpad',
          '--disable-client-side-phishing-detection',
          '--disable-component-update',
          '--disable-hang-monitor',
          '--disable-prompt-on-repost',
          '--disable-sync',
          '--disable-translate',
          '--disable-web-resources',
          '--disable-default-apps',
          '--disable-infobars',
          '--disable-popup-blocking',
          '--disable-gpu',
          '--disable-save-password-bubble',
          'about:blank'
        ];
2021/08/15 22:18:46 Spawned child as 16502, communicating via websocket
Can't locate object method "port" via package "URI::_generic" at /usr/local/share/perl/5.28.1/WWW/Mechanize/Chrome.pm line 1033.

Letting Perl open a fresh Chrome Session does the Trick - Maybe i'll get the Job done, though - My intention is to listen on and read my open Tabs to count and log certain pages in a service manner.

The Open Remote Debugging Port Chrome Sessions are handled by Mechanize::Chrome with the same Error in line 1033.

Greetings, Max

Corion commented 2 years ago

The following program works for me, connecting to a running Chrome instance (and for this test, also launching the Chrome instance):

#!perl
use strict;
use warnings;
use Test::More;

use WWW::Mechanize::Chrome;
use Log::Log4perl ':easy';

Log::Log4perl->easy_init($TRACE);

# Launch our local Chromium, to get a current session
system("chromium '--remote-debugging-port=9222' '--remote-debugging-address=127.0.0.1' '--enable-automation' &"
) == 0
    or die;

# Give Chrome time to start up
sleep 2;

# And now try to connect to it, without crashing
my $ok = eval {
    my $mech = WWW::Mechanize::Chrome->new(
            autodie => 1,
            port => 9222,
    );

    $mech->get('https://google.com');
    1;
};
my $error = $@;
is $ok, 1, "We connected to Chromium";
is $error, '', "No error while connecting";

done_testing;

The trick is that the second instance needs to know the debug port used by the first instance.