EV-WebKit

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

        What is being asked for. "scheme" is WebKit's own nick for the
        authentication scheme ("http-basic", "http-digest", ...); "realm" is
        the server's realm string, which is what distinguishes two
        challenges from the same host.

    "for_proxy"
        True when the challenge came from a proxy rather than the origin
        server.

    "is_retry"
        True when the credentials you last supplied were rejected. WebKit
        re-asks after every rejection, so a handler that answers with the
        same pair regardless of this loops forever.

    "login($user, $password, persist => $how)"
        Answer the challenge. "persist" is 'for-session' (the default --
        remembered until this instance closes, so the same realm is not
        asked again on every request), 'permanent' (written to the platform
        credential store), or 'none'.

    "cancel"

lib/EV/WebKit.pm  view on Meta::CPAN

        weaken(my $ws = $self);
        $self->_defer(sub { my ($u) = @_; my $b = $ws or return; $b->go($u) }, $nu);
        return undef;   # no second view: the navigation happens in this one
    });

    # HTTP (and proxy) authentication. WITHOUT this connected at all, a 401
    # challenge is answered by nobody: WebKit waits, the navigation resolves
    # 'timeout' after the full instance timeout, and status() is undef -- so the
    # caller cannot even tell a 401 from an unreachable host. Cancelling by
    # default turns that into an immediate, legible failure (the server's own
    # 401 body, with status 401), and a handler can supply credentials instead.
    $self->{on_authenticate} = $o{on_authenticate};
    $view->signal_connect(authenticate => sub {
        my (undef, $req) = @_;
        local $IN_DISPATCH = 1;          # runs nested in WebKit's dispatch frame -- see quit
        my $self = $wself or return 0;   # gone: let WebKit do its default
        return 0 if $self->{_dead};
        my $host = eval { $req->get_host };
        # However the challenge goes unanswered, record WHY: WebKit reports all
        # three the same way, as a bare "Load request cancelled".
        my $note = sub { $self->{_auth_challenge} = { host => $host, why => $_[0] } if defined $host };

lib/EV/WebKit.pm  view on Meta::CPAN

    our $VERSION = '0.04';
    # A WebKitAuthenticationRequest, valid only for the duration of the
    # on_authenticate handler that receives it.
    sub _new { bless { r => $_[1] }, $_[0] }

    sub host      { eval { $_[0]{r}->get_host } }
    sub port      { eval { $_[0]{r}->get_port } }
    sub realm     { eval { $_[0]{r}->get_realm } }
    sub scheme    { eval { $_[0]{r}->get_scheme } }
    sub for_proxy { eval { $_[0]{r}->is_for_proxy } ? 1 : 0 }
    # True when the credentials just supplied were rejected. A handler that
    # ignores it and answers with the same pair again is a loop, since WebKit
    # re-asks after every rejection.
    sub is_retry  { eval { $_[0]{r}->is_retry } ? 1 : 0 }

    sub login {
        my ($s, $user, $pass) = (shift, shift, shift);
        Carp::croak('login: a username and password are required')
            if !defined $user || ref $user || !defined $pass || ref $pass;
        Carp::croak('login: options must be name => value pairs') if @_ % 2;
        my %o = @_;

lib/EV/WebKit.pm  view on Meta::CPAN

What is being asked for. C<scheme> is WebKit's own nick for the authentication
scheme (C<http-basic>, C<http-digest>, ...); C<realm> is the server's realm
string, which is what distinguishes two challenges from the same host.

=item C<for_proxy>

True when the challenge came from a proxy rather than the origin server.

=item C<is_retry>

True when the credentials you last supplied were B<rejected>. WebKit re-asks
after every rejection, so a handler that answers with the same pair regardless
of this loops forever.

=item C<< login($user, $password, persist =E<gt> $how) >>

Answer the challenge. C<persist> is C<'for-session'> (the default -- remembered
until this instance closes, so the same realm is not asked again on every
request), C<'permanent'> (written to the platform credential store), or
C<'none'>.

t/45-auth-popup-viewport.t  view on Meta::CPAN

        on_authenticate => sub {
            my ($a) = @_;
            push @info, { host => $a->host, port => $a->port, realm => $a->realm,
                          scheme => $a->scheme, proxy => $a->for_proxy, retry => $a->is_retry };
            $a->login('u', 'p');
        });
    my ($err, $title, $status);
    $b->go("http://127.0.0.1:$port/secret", sub {
        $err = $_[1]; $title = $b->title; $status = $b->status; EV::break });
    TWK::run_with_timeout(30);
    is($err, undef, 'a handler that supplies credentials lets the load through') or diag $err;
    is($title, 'AUTHED', '...and the server accepted them');
    is($status, 200, '...reporting a 200, not the 401');
    is(scalar @info, 1, 'the handler ran once');
    is($info[0]{host},   '127.0.0.1', 'host is reported');
    is($info[0]{port},   $port,       'port is reported');
    is($info[0]{realm},  'probe',     'realm is reported');
is($info[0]{scheme}, 'http-basic','scheme is reported');
    is($info[0]{proxy},  0,           'for_proxy is false for an origin challenge');
    is($info[0]{retry},  0,           'is_retry is false on the first ask');
    $b->quit;
}
{
    # credentials in the URI are WebKit's own business and must not reach us
    my $fired = 0;
    my $b = EV::WebKit->new(window => [300,200], timeout => 10,
                            on_authenticate => sub { $fired++; $_[0]->cancel });
    my ($err, $title);
    $b->go("http://u:p\@127.0.0.1:$port/secret", sub { $err = $_[1]; $title = $b->title; EV::break });
    TWK::run_with_timeout(30);
    is($err, undef, 'credentials in the URI still work') or diag $err;
    is($title, 'AUTHED', '...reaching the protected page');
    is($fired, 0, '...without the handler being consulted');
    $b->quit;
}
# Fail-closed, and the three unanswered routes each name themselves. Without
# the cancel these still resolve -- with 'timeout', after the full instance
# timeout -- so the elapsed time is what actually pins "failed closed".
for my $case ([die => sub { die "handler exploded\n" }, qr/handler died/],
              [undecided => sub { return },             qr/answered nothing/],
              [cancel => sub { $_[0]->cancel },          qr/handler cancelled it/]) {

t/61-cookies.t  view on Meta::CPAN

            is($err, 'timeout', "$name: uses the module's uniform 'timeout' error")
                or diag("err=" . ($err // '(undef)'));
        }
    }
}

# save_cookies($file, \@uris, $cb): a middle argument that is not an arrayref
# was never looked at again, so save_cookies($file, 'https://one.example/', $cb)
# reported SUCCESS having snapshotted every uri the instance had visited --
# the opposite scope from the one asked for, into a file that holds
# credentials. cookies($uri, $cb), the sibling, takes a bare string, which is
# exactly where that spelling comes from.
{
    require File::Temp;
    my $sc = EV::WebKit->new(window => [200,150], ephemeral => 1, timeout => 10);
    $sc->mock_scheme('sc', sub { ('<p>x</p>', 'text/html') });
    my $ready = 0;
    $sc->go('sc://a', sub { $ready = 1; EV::break });
    TWK::run_with_timeout(20);
    ok($ready, 'premise: the instance has navigated somewhere');



( run in 0.964 second using v1.01-cache-2.11-cpan-007c89162af )