File Coverage

blib/lib/WWW/Crawl/Chromium.pm
Criterion Covered Total %
statement 15 64 23.4
branch 0 22 0.0
condition 0 15 0.0
subroutine 5 7 71.4
pod n/a
total 20 108 18.5


line stmt bran cond sub pod time code
1             package WWW::Crawl::Chromium;
2            
3 1     1   1574 use strict;
  1         3  
  1         42  
4 1     1   5 use warnings;
  1         2  
  1         55  
5            
6 1     1   583 use parent 'WWW::Crawl';
  1         315  
  1         6  
7            
8 1     1   69 use Carp qw(croak);
  1         2  
  1         69  
9 1     1   1467 use IPC::Run qw(start timeout);
  1         36285  
  1         849  
10            
11             our $VERSION = '0.5';
12             # $VERSION = eval $VERSION;
13            
14             sub _fetch_page {
15 0     0     my ($self, $url) = @_;
16            
17             my $chromium_path = $self->{'chromium_path'}
18             || $self->{'chrome_path'}
19 0   0       || $self->{'chromium'}
20             || 'chromium';
21 0   0       my $timeout = $self->{'chromium_timeout'} // 120;
22 0   0       my $virtual_time_budget = $self->{'chromium_time_budget'} // 20000;
23 0   0       my $proxy = $self->{'proxy'} // 'direct://';
24            
25 0   0       my $chrome_ua = $self->{'agent'} // "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36";
26 0   0       my $retry_count = $self->{'retry_count'} // 0;
27            
28 0           my @base_command = (
29             $chromium_path,
30             '--headless=new',
31             qq{--proxy-server=$proxy},
32             qq{--user-agent=$chrome_ua},
33             '--window-size=1920,1080',
34             '--no-sandbox',
35             '--disable-gpu',
36             '--disable-dev-shm-usage',
37             '--disable-software-rasterizer',
38             '--disable-features=VaapiVideoDecoder',
39             '--disable-site-isolation-trials',
40             '--password-store=basic',
41             '--use-mock-keychain',
42             '--log-level=3',
43             '--no-first-run',
44             '--no-default-browser-check',
45             '--run-all-compositor-stages-before-draw',
46             "--virtual-time-budget=$virtual_time_budget",
47             '--dump-dom',
48             $url,
49             );
50            
51 0           my $result;
52 0           for my $attempt (0 .. $retry_count) {
53 0 0         if ($attempt > 0) {
54 0 0         print STDERR "DEBUG: Retry attempt $attempt for $url\n" if $self->{'debug'};
55 0           sleep 1;
56             }
57            
58 0           $result = $self->_execute_chromium(\@base_command, $timeout);
59 0 0         last if $result->{'success'};
60             }
61            
62 0           return $result;
63             }
64            
65             sub _execute_chromium {
66 0     0     my ($self, $command, $timeout) = @_;
67 0           my @command = @$command;
68            
69 0           my $content = '';
70 0           my $error_output = '';
71 0           my $timed_out = 0;
72 0           my $launch_error = '';
73            
74 0           my $exit_code = 0;
75 0           my $harness = eval {
76 0           start \@command, '<', \undef, '>', \$content, '2>', \$error_output, timeout($timeout);
77             };
78 0 0         if ($@) {
    0          
79 0           $launch_error = $@;
80             } elsif (!$harness) {
81 0           $launch_error = 'Unknown failure starting Chromium';
82             } else {
83 0           eval { $harness->finish; 1 };
  0            
  0            
84 0 0         if ($@) {
85 0 0         if ($@ =~ /timeout/i) {
86 0           $timed_out = 1;
87 0           $harness->kill_kill;
88             } else {
89 0           $launch_error = $@;
90 0           $harness->kill_kill;
91             }
92             } else {
93 0           $exit_code = $? >> 8;
94 0 0         if ($exit_code != 0) {
95 0           $launch_error = "Chromium exited with status $exit_code";
96             }
97             }
98             }
99            
100 0 0         if ($timed_out) {
101             return {
102 0           'success' => 0,
103             'status' => 599,
104             'reason' => "Chromium timeout after ${timeout}s",
105             'content' => '',
106             };
107             }
108            
109 0 0         if ($launch_error ne '') {
110 0           $launch_error =~ s/\s+$//;
111 0   0       my $reason = $error_output || $launch_error;
112             return {
113 0           'success' => 0,
114             'status' => 599,
115             'reason' => $reason,
116             'content' => $content,
117             };
118             }
119            
120 0 0         if ($content eq '') {
121             return {
122 0           'success' => 0,
123             'status' => 599,
124             'reason' => 'Chromium returned empty content',
125             'content' => '',
126             };
127             }
128            
129             return {
130 0           'success' => 1,
131             'status' => 200,
132             'reason' => 'OK',
133             'content' => $content,
134             };
135             }
136            
137             1;
138            
139             __END__