line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package WebDriver::Tiny 0.103; |
2
|
|
|
|
|
|
|
|
3
|
40
|
|
|
40
|
|
298445
|
use 5.020; |
|
40
|
|
|
|
|
386
|
|
4
|
40
|
|
|
40
|
|
234
|
use feature qw/lexical_subs postderef signatures/; |
|
40
|
|
|
|
|
79
|
|
|
40
|
|
|
|
|
6826
|
|
5
|
40
|
|
|
40
|
|
280
|
use warnings; |
|
40
|
|
|
|
|
75
|
|
|
40
|
|
|
|
|
1371
|
|
6
|
40
|
|
|
40
|
|
266
|
no warnings 'experimental'; |
|
40
|
|
|
|
|
110
|
|
|
40
|
|
|
|
|
5713
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# https://www.w3.org/TR/webdriver/#elements |
9
|
|
|
|
|
|
|
my sub ELEMENT_ID :prototype() {'element-6066-11e4-a52e-4f735466cecf'} |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# Allow "cute" $drv->('selector') syntax. |
12
|
|
|
|
|
|
|
# |
13
|
|
|
|
|
|
|
# $self->[4] contains a sub ref that closes over a weakened $self that calls |
14
|
|
|
|
|
|
|
# find, i.e. sub { $weak_self->find(@_) }. This sub ref is returned when $self |
15
|
|
|
|
|
|
|
# is invoked as a sub ref thanks to the magic of overloading. We weaken to |
16
|
|
|
|
|
|
|
# avoid a memory leak. The closure is built in new(). |
17
|
40
|
|
|
40
|
|
50447
|
use overload fallback => 1, '&{}' => sub { $_[0][4] }; |
|
40
|
|
|
6
|
|
44968
|
|
|
40
|
|
|
|
|
363
|
|
|
6
|
|
|
|
|
4726
|
|
18
|
|
|
|
|
|
|
|
19
|
40
|
|
|
40
|
|
3404
|
use Carp 1.25 (); |
|
40
|
|
|
|
|
1263
|
|
|
40
|
|
|
|
|
1121
|
|
20
|
40
|
|
|
40
|
|
29073
|
use HTTP::Tiny; |
|
40
|
|
|
|
|
2126772
|
|
|
40
|
|
|
|
|
1687
|
|
21
|
40
|
|
|
40
|
|
31174
|
use JSON::PP (); |
|
40
|
|
|
|
|
567401
|
|
|
40
|
|
|
|
|
1376
|
|
22
|
40
|
|
|
40
|
|
20459
|
use WebDriver::Tiny::Elements; |
|
40
|
|
|
|
|
117
|
|
|
40
|
|
|
|
|
104621
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
our @CARP_NOT = 'WebDriver::Tiny::Elements'; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub import { |
27
|
|
|
|
|
|
|
# https://www.w3.org/TR/webdriver/#sendkeys |
28
|
4
|
|
|
4
|
|
149
|
state $chars = { |
29
|
|
|
|
|
|
|
WD_NULL => 57344, WD_CANCEL => 57345, |
30
|
|
|
|
|
|
|
WD_HELP => 57346, WD_BACK_SPACE => 57347, |
31
|
|
|
|
|
|
|
WD_TAB => 57348, WD_CLEAR => 57349, |
32
|
|
|
|
|
|
|
WD_RETURN => 57350, WD_ENTER => 57351, |
33
|
|
|
|
|
|
|
WD_SHIFT => 57352, WD_CONTROL => 57353, |
34
|
|
|
|
|
|
|
WD_ALT => 57354, WD_PAUSE => 57355, |
35
|
|
|
|
|
|
|
WD_ESCAPE => 57356, WD_SPACE => 57357, |
36
|
|
|
|
|
|
|
WD_PAGE_UP => 57358, WD_PAGE_DOWN => 57359, |
37
|
|
|
|
|
|
|
WD_END => 57360, WD_HOME => 57361, |
38
|
|
|
|
|
|
|
WD_ARROW_LEFT => 57362, WD_ARROW_UP => 57363, |
39
|
|
|
|
|
|
|
WD_ARROW_RIGHT => 57364, WD_ARROW_DOWN => 57365, |
40
|
|
|
|
|
|
|
WD_INSERT => 57366, WD_DELETE => 57367, |
41
|
|
|
|
|
|
|
WD_SEMICOLON => 57368, WD_EQUALS => 57369, |
42
|
|
|
|
|
|
|
WD_NUMPAD0 => 57370, WD_NUMPAD1 => 57371, |
43
|
|
|
|
|
|
|
WD_NUMPAD2 => 57372, WD_NUMPAD3 => 57373, |
44
|
|
|
|
|
|
|
WD_NUMPAD4 => 57374, WD_NUMPAD5 => 57375, |
45
|
|
|
|
|
|
|
WD_NUMPAD6 => 57376, WD_NUMPAD7 => 57377, |
46
|
|
|
|
|
|
|
WD_NUMPAD8 => 57378, WD_NUMPAD9 => 57379, |
47
|
|
|
|
|
|
|
WD_MULTIPLY => 57380, WD_ADD => 57381, |
48
|
|
|
|
|
|
|
WD_SEPARATOR => 57382, WD_SUBTRACT => 57383, |
49
|
|
|
|
|
|
|
WD_DECIMAL => 57384, WD_DIVIDE => 57385, |
50
|
|
|
|
|
|
|
WD_F1 => 57393, WD_F2 => 57394, |
51
|
|
|
|
|
|
|
WD_F3 => 57395, WD_F4 => 57396, |
52
|
|
|
|
|
|
|
WD_F5 => 57397, WD_F6 => 57398, |
53
|
|
|
|
|
|
|
WD_F7 => 57399, WD_F8 => 57400, |
54
|
|
|
|
|
|
|
WD_F9 => 57401, WD_F10 => 57402, |
55
|
|
|
|
|
|
|
WD_F11 => 57403, WD_F12 => 57404, |
56
|
|
|
|
|
|
|
WD_META => 57405, WD_COMMAND => 57405, |
57
|
|
|
|
|
|
|
WD_ZENKAKU_HANKAKU => 57408, |
58
|
|
|
|
|
|
|
}; |
59
|
|
|
|
|
|
|
|
60
|
4
|
|
|
|
|
2288
|
require charnames; |
61
|
|
|
|
|
|
|
|
62
|
4
|
|
|
|
|
125917
|
charnames->import( ':alias' => $chars ); |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# We're a blessed arrayref (for speed) of the following parts: |
66
|
|
|
|
|
|
|
# |
67
|
|
|
|
|
|
|
# $self = [ |
68
|
|
|
|
|
|
|
# 0: HTTP::Tiny instance, |
69
|
|
|
|
|
|
|
# 1: URL of the WebDriver daemon, |
70
|
|
|
|
|
|
|
# 2: Base URL which schemeless get calls are based off, |
71
|
|
|
|
|
|
|
# 3: The capabilities of the WebDriver daemon, |
72
|
|
|
|
|
|
|
# 4: Cached closure of $self for ->() syntax, |
73
|
|
|
|
|
|
|
# ] |
74
|
2
|
|
|
2
|
1
|
197
|
sub new($class, %args) { |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
4
|
|
75
|
|
|
|
|
|
|
Carp::croak qq/$class - Missing required parameter "port"/ |
76
|
2
|
100
|
|
|
|
224
|
unless exists $args{port}; |
77
|
|
|
|
|
|
|
|
78
|
1
|
|
50
|
|
|
7
|
$args{host} //= 'localhost'; |
79
|
1
|
|
50
|
|
|
7
|
$args{path} //= ''; |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
my $self = bless [ |
82
|
|
|
|
|
|
|
HTTP::Tiny->new, |
83
|
|
|
|
|
|
|
"http://$args{host}:$args{port}$args{path}/session", |
84
|
1
|
|
50
|
|
|
5
|
$args{base_url} // '', |
85
|
|
|
|
|
|
|
], $class; |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
my $reply = $self->_req( |
88
|
|
|
|
|
|
|
POST => '', |
89
|
|
|
|
|
|
|
{ capabilities => { alwaysMatch => $args{capabilities} // {} } }, |
90
|
1
|
|
50
|
|
|
125
|
); |
91
|
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
0
|
$self->[1] .= '/' . $reply->{sessionId}; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# Store the capabilities. |
95
|
0
|
|
|
|
|
0
|
$self->[3] = $reply->{capabilities}; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# Numify bool objects, saves memory. |
98
|
0
|
|
|
|
|
0
|
$_ += 0 for grep ref eq 'JSON::PP::Boolean', values $self->[3]->%*; |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# See the overloading at the top of the file for details. |
101
|
0
|
|
|
|
|
0
|
Scalar::Util::weaken( my $weak_self = $self ); |
102
|
0
|
|
|
0
|
|
0
|
$self->[4] = sub { $weak_self->find(@_) }; |
|
0
|
|
|
|
|
0
|
|
103
|
|
|
|
|
|
|
|
104
|
0
|
|
|
|
|
0
|
$self; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
0
|
|
|
0
|
1
|
0
|
sub capabilities($self) { $self->[3] } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
108
|
|
|
|
|
|
|
|
109
|
1
|
|
|
1
|
1
|
84
|
sub html($self) { $self->_req( GET => '/source' ) } |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
110
|
1
|
|
|
1
|
1
|
84
|
sub title($self) { $self->_req( GET => '/title' ) } |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
111
|
1
|
|
|
1
|
1
|
87
|
sub url($self) { $self->_req( GET => '/url' ) } |
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
4
|
|
112
|
|
|
|
|
|
|
|
113
|
2
|
|
|
2
|
1
|
631
|
sub back($self) { $self->_req( POST => '/back' ); $self } |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
7
|
|
114
|
2
|
|
|
2
|
1
|
667
|
sub forward($self) { $self->_req( POST => '/forward' ); $self } |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
11
|
|
|
2
|
|
|
|
|
7
|
|
115
|
2
|
|
|
2
|
1
|
633
|
sub refresh($self) { $self->_req( POST => '/refresh' ); $self } |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
11
|
|
|
2
|
|
|
|
|
5
|
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub status { |
118
|
|
|
|
|
|
|
# /status is the only path without the session prefix, so surpress it. |
119
|
0
|
|
|
0
|
1
|
0
|
local $_[0][1] = substr $_[0][1], 0, rindex $_[0][1], '/session/'; |
120
|
|
|
|
|
|
|
|
121
|
0
|
|
|
|
|
0
|
$_[0]->_req( GET => '/status' ); |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
2
|
|
|
2
|
1
|
179
|
sub alert_accept($self) { $self->_req( POST => '/alert/accept' ); $self } |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
13
|
|
|
2
|
|
|
|
|
13
|
|
|
2
|
|
|
|
|
9
|
|
125
|
2
|
|
|
2
|
1
|
856
|
sub alert_dismiss($self) { $self->_req( POST => '/alert/dismiss' ); $self } |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
7
|
|
126
|
|
|
|
|
|
|
|
127
|
1
|
|
|
1
|
1
|
85
|
sub alert_text($self) { $self->_req( GET => '/alert/text' ) } |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub base_url { |
130
|
8
|
100
|
|
8
|
1
|
717
|
if ( @_ == 2 ) { |
131
|
4
|
|
100
|
|
|
21
|
$_[0][2] = $_[1] // ''; |
132
|
|
|
|
|
|
|
|
133
|
4
|
|
|
|
|
20
|
return $_[0]; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
4
|
|
|
|
|
43
|
$_[0][2]; |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub cookie { |
140
|
4
|
|
|
4
|
1
|
2588
|
my ( $self, $name, $value, @args ) = @_; |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# GET /cookie/{name} isn't supported by ChromeDriver, so get all. |
143
|
4
|
100
|
|
|
|
20
|
return $self->cookies->{$name} if @_ == 2; |
144
|
|
|
|
|
|
|
|
145
|
3
|
|
|
|
|
19
|
$self->_req( POST => '/cookie', |
146
|
|
|
|
|
|
|
{ cookie => { name => $name, value => $value, @args } } ); |
147
|
|
|
|
|
|
|
|
148
|
3
|
|
|
|
|
14
|
$self; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
5
|
|
|
5
|
1
|
2893
|
sub cookie_delete($self, @cookies) { |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
9
|
|
152
|
5
|
100
|
|
|
|
16
|
if (@cookies) { |
153
|
3
|
|
|
|
|
18
|
$self->_req( DELETE => "/cookie/$_" ) for @cookies; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
else { |
156
|
2
|
|
|
|
|
6
|
$self->_req( DELETE => '/cookie' ); |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
5
|
|
|
|
|
16
|
$self; |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub cookies { |
163
|
2
|
|
50
|
2
|
1
|
90
|
my @cookies = @{ $_[0]->_req( GET => '/cookie' ) // [] }; |
|
2
|
|
|
|
|
13
|
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# Map the incorrect key to the correct key. |
166
|
2
|
|
0
|
|
|
6
|
$_->{httpOnly} //= delete $_->{httponly} for @cookies; |
167
|
|
|
|
|
|
|
|
168
|
2
|
|
|
|
|
9
|
+{ map { $_->{name} => $_ } @cookies }; |
|
0
|
|
|
|
|
0
|
|
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# NOTE This method can be called from a driver or a collection of elements. |
172
|
12
|
|
|
12
|
1
|
4755
|
sub find($self, $selector, %args) { |
|
12
|
|
|
|
|
25
|
|
|
12
|
|
|
|
|
21
|
|
|
12
|
|
|
|
|
28
|
|
|
12
|
|
|
|
|
18
|
|
173
|
12
|
|
|
|
|
35
|
state $methods = { |
174
|
|
|
|
|
|
|
css => 'css selector', |
175
|
|
|
|
|
|
|
ecmascript => 'ecmascript', |
176
|
|
|
|
|
|
|
link_text => 'link text', |
177
|
|
|
|
|
|
|
partial_link_text => 'partial link text', |
178
|
|
|
|
|
|
|
xpath => 'xpath', |
179
|
|
|
|
|
|
|
}; |
180
|
|
|
|
|
|
|
|
181
|
12
|
|
100
|
|
|
59
|
my $method = $methods->{ $args{method} // '' } // 'css selector'; |
|
|
|
100
|
|
|
|
|
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# FIXME |
184
|
12
|
50
|
|
|
|
39
|
my $drv = ref $self eq 'WebDriver::Tiny::Elements' ? $self->[0] : $self; |
185
|
|
|
|
|
|
|
|
186
|
12
|
|
|
|
|
18
|
my @ids; |
187
|
|
|
|
|
|
|
|
188
|
12
|
|
50
|
|
|
57
|
for ( 0 .. ( $args{tries} // 5 ) ) { |
189
|
12
|
|
|
|
|
61
|
my $reply = $self->_req( |
190
|
|
|
|
|
|
|
POST => '/elements', |
191
|
|
|
|
|
|
|
{ using => $method, value => "$selector" }, |
192
|
|
|
|
|
|
|
); |
193
|
|
|
|
|
|
|
|
194
|
12
|
|
|
|
|
55
|
@ids = map $_->{+ELEMENT_ID}, @$reply; |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
@ids = grep { |
197
|
0
|
|
|
|
|
0
|
$drv->_req( GET => "/element/$_/displayed" ) |
198
|
12
|
50
|
|
|
|
36
|
} @ids if $args{visible}; |
199
|
|
|
|
|
|
|
|
200
|
12
|
50
|
|
|
|
45
|
last if @ids; |
201
|
|
|
|
|
|
|
|
202
|
0
|
|
0
|
|
|
0
|
select undef, undef, undef, $args{sleep} // .1; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
Carp::croak ref $self, qq/->find failed for $method = "$_[1]"/ |
206
|
12
|
0
|
33
|
|
|
30
|
if !@ids && !exists $args{dies} && !$args{dies}; |
|
|
|
0
|
|
|
|
|
207
|
|
|
|
|
|
|
|
208
|
12
|
50
|
|
|
|
65
|
wantarray ? map { bless [ $drv, $_ ], 'WebDriver::Tiny::Elements' } @ids |
|
0
|
|
|
|
|
0
|
|
209
|
|
|
|
|
|
|
: bless [ $drv, @ids ], 'WebDriver::Tiny::Elements'; |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
my $js = sub($path, $self, $script, @args) { |
213
|
|
|
|
|
|
|
# Currently only takes the first ID in the collection, this should change. |
214
|
|
|
|
|
|
|
$_ = { ELEMENT_ID, $_->[1] } |
215
|
|
|
|
|
|
|
for grep ref eq 'WebDriver::Tiny::Elements', @args; |
216
|
|
|
|
|
|
|
$self->_req( POST => $path, { script => $script, args => \@args } ); |
217
|
|
|
|
|
|
|
}; |
218
|
|
|
|
|
|
|
|
219
|
2
|
|
|
2
|
1
|
113
|
sub js { unshift @_, '/execute/sync'; goto $js } |
|
2
|
|
|
|
|
22
|
|
220
|
1
|
|
|
1
|
1
|
84
|
sub js_async { unshift @_, '/execute/async'; goto $js } |
|
1
|
|
|
|
|
6
|
|
221
|
|
|
|
|
|
|
|
222
|
7
|
|
|
7
|
1
|
5188
|
sub get($self, $url) { |
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
15
|
|
|
7
|
|
|
|
|
10
|
|
223
|
7
|
100
|
|
|
|
90
|
$self->_req( |
224
|
|
|
|
|
|
|
POST => '/url', |
225
|
|
|
|
|
|
|
{ url => $url =~ m(^https?://) ? $url : $self->[2] . $url }, |
226
|
|
|
|
|
|
|
); |
227
|
|
|
|
|
|
|
|
228
|
7
|
|
|
|
|
21
|
$self; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
1
|
|
|
1
|
1
|
88
|
sub screenshot($self, $file = undef) { |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
232
|
1
|
|
|
|
|
566
|
require MIME::Base64; |
233
|
|
|
|
|
|
|
|
234
|
1
|
|
|
|
|
631
|
my $data = MIME::Base64::decode_base64( |
235
|
|
|
|
|
|
|
$self->_req( GET => '/screenshot' ) |
236
|
|
|
|
|
|
|
); |
237
|
|
|
|
|
|
|
|
238
|
1
|
50
|
|
|
|
5
|
if ( defined $file ) { |
239
|
0
|
0
|
|
|
|
0
|
open my $fh, '>', $file or die $!; |
240
|
0
|
|
|
|
|
0
|
print $fh $data; |
241
|
0
|
0
|
|
|
|
0
|
close $fh or die $!; |
242
|
|
|
|
|
|
|
|
243
|
0
|
|
|
|
|
0
|
return $self; |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
1
|
|
|
|
|
3
|
$data; |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
1
|
|
|
1
|
1
|
83
|
sub user_agent($self) { $js->( '/execute/sync', $self, 'return window.navigator.userAgent') } |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
250
|
|
|
|
|
|
|
|
251
|
1
|
|
|
1
|
1
|
90
|
sub window($self) { $self->_req( GET => '/window' ) } |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
252
|
1
|
|
|
1
|
1
|
83
|
sub windows($self) { $self->_req( GET => '/window/handles' ) } |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3
|
|
253
|
|
|
|
|
|
|
|
254
|
2
|
|
|
2
|
1
|
715
|
sub window_close($self) { $self->_req( DELETE => '/window' ); $self } |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
5
|
|
255
|
1
|
|
|
1
|
1
|
84
|
sub window_fullscreen($self) { $self->_req( POST => '/window/fullscreen' ); $self } |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
256
|
2
|
|
|
2
|
1
|
699
|
sub window_maximize($self) { $self->_req( POST => '/window/maximize' ); $self } |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
6
|
|
257
|
0
|
|
|
0
|
0
|
0
|
sub window_minimize($self) { $self->_req( POST => '/window/minimize' ); $self } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
sub window_rect { |
260
|
1
|
|
|
1
|
1
|
617
|
my $self = shift; |
261
|
|
|
|
|
|
|
|
262
|
1
|
50
|
|
|
|
6
|
return $self->_req( GET => '/window/rect' ) unless @_; |
263
|
|
|
|
|
|
|
|
264
|
1
|
|
|
|
|
5
|
$#_ = 3; |
265
|
|
|
|
|
|
|
|
266
|
1
|
|
|
|
|
2
|
my %args; |
267
|
1
|
|
100
|
|
|
20
|
@args{ qw/width height x y/ } = map $_ // 0, @_; |
268
|
|
|
|
|
|
|
|
269
|
1
|
|
|
|
|
6
|
$self->_req( POST => '/window/rect', \%args ); |
270
|
|
|
|
|
|
|
|
271
|
1
|
|
|
|
|
6
|
$self; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
2
|
|
|
2
|
1
|
639
|
sub window_switch($self, $handle) { |
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
2
|
|
275
|
2
|
|
|
|
|
14
|
$self->_req( POST => '/window', { handle => $handle } ); |
276
|
|
|
|
|
|
|
|
277
|
2
|
|
|
|
|
8
|
$self; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
73
|
|
|
73
|
|
139
|
sub _req($self, $method, $path, $args = undef) { |
|
73
|
|
|
|
|
125
|
|
|
73
|
|
|
|
|
131
|
|
|
73
|
|
|
|
|
116
|
|
|
73
|
|
|
|
|
153
|
|
|
73
|
|
|
|
|
105
|
|
281
|
73
|
|
100
|
|
|
1609
|
my $reply = $self->[0]->request( |
282
|
|
|
|
|
|
|
$method, |
283
|
|
|
|
|
|
|
$self->[1] . $path, |
284
|
|
|
|
|
|
|
{ content => JSON::PP::encode_json( $args // {} ) }, |
285
|
|
|
|
|
|
|
); |
286
|
|
|
|
|
|
|
|
287
|
73
|
|
|
|
|
25500
|
my $value = eval { JSON::PP::decode_json( $reply->{content} )->{value} }; |
|
73
|
|
|
|
|
269
|
|
288
|
|
|
|
|
|
|
|
289
|
73
|
100
|
|
|
|
10663
|
unless ( $reply->{success} ) { |
290
|
|
|
|
|
|
|
my $error = $value |
291
|
|
|
|
|
|
|
? $value->{message} || $value->{error} || $reply->{content} |
292
|
1
|
50
|
0
|
|
|
6
|
: $reply->{content}; |
293
|
|
|
|
|
|
|
|
294
|
1
|
|
|
|
|
121
|
Carp::croak ref $self, ' - ', $error; |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
72
|
|
|
|
|
247
|
$value; |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
1
|
50
|
33
|
1
|
|
3
|
sub DESTROY($self) { $self->_req( DELETE => '' ) if $self->[0] && $self->[3] } |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
17
|
|
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
1; |