File Coverage

blib/lib/HTTP/Cookies/MozRepl.pm
Criterion Covered Total %
statement 18 42 42.8
branch 0 10 0.0
condition 0 10 0.0
subroutine 6 9 66.6
pod 3 3 100.0
total 27 74 36.4


line stmt bran cond sub pod time code
1             package HTTP::Cookies::MozRepl;
2 80     80   341 use strict;
  80         97  
  80         2726  
3 80     80   40139 use HTTP::Date qw(time2str);
  80         258359  
  80         4921  
4 80     80   454 use MozRepl::RemoteObject 'as_list';
  80         97  
  80         3193  
5 80     80   31125 use parent 'HTTP::Cookies';
  80         18060  
  80         431  
6 80     80   471872 use Carp qw[croak];
  80         144  
  80         3648  
7              
8 80     80   308 use vars qw[$VERSION];
  80         94  
  80         26010  
9             $VERSION = '0.78';
10              
11             =head1 NAME
12              
13             HTTP::Cookies::MozRepl - retrieve cookies from a live Firefox instance
14              
15             =head1 SYNOPSIS
16              
17             use HTTP::Cookies::MozRepl;
18             my $cookie_jar = HTTP::Cookies::MozRepl->new();
19             # use just like HTTP::Cookies
20              
21             =head1 DESCRIPTION
22              
23             This package overrides the load() and save() methods of HTTP::Cookies
24             so it can work with a live Firefox instance.
25              
26             Note: To use this module, Firefox must be running and it must
27             have the C extension installed.
28              
29             See L.
30              
31             =head1 Reusing an existing connection
32              
33             If you already have an existing connection to Firefox
34             that you want to reuse, just pass the L
35             instance to the cookie jar constructor in the C parameter:
36              
37             my $cookie_jar = HTTP::Cookies::MozRepl->new(
38             repl => $repl
39             );
40              
41             =cut
42              
43             sub load {
44 0     0 1   my ($self,$repl) = @_;
45 0   0       $repl ||= $self->{'file'} || $self->{'repl'} || return;
      0        
46            
47             # Get cookie manager
48 0           my $cookie_manager = $repl->expr(<<'JS');
49             Components.classes["@mozilla.org/cookiemanager;1"]
50             .getService(Components.interfaces.nsICookieManager)
51             JS
52              
53 0           my $nsICookie = $repl->expr(<<'JS');
54             Components.interfaces.nsICookie
55             JS
56              
57 0           my $nsICookieManager = $repl->expr(<<'JS');
58             Components.interfaces.nsICookieManager
59             JS
60 0           $cookie_manager = $cookie_manager->QueryInterface($nsICookieManager);
61            
62 0           my $e = $cookie_manager->{enumerator};
63 0           my $fetch_cookies = $e->bridge->declare(<<'JS', 'list');
64             function(e,nsiCookie) {
65             var r=[];
66             while (e.hasMoreElements()) {
67             var cookie = e.getNext().QueryInterface(nsiCookie);
68             r.push([1,cookie.name,cookie.value,cookie.path,cookie.host,null,null,cookie.isSecure,cookie.expires]);
69             };
70             return r
71             };
72             JS
73             # This could be even more efficient by fetching the whole result
74             # as one huge data structure
75 0           for my $c ($fetch_cookies->($e,$nsICookie)) {
76 0           my @v = as_list $c;
77 0 0         if( $v[8] > 0) {
    0          
78 0           $v[8] -= time;
79             } elsif( $v[8] == 0 ) {
80             # session cookie, we never let it expire within HTTP::Cookie
81 0           $v[8] += 3600; # well, "never"
82             };
83 0           $self->SUPER::set_cookie(@v);
84             };
85              
86             # This code is pure Perl, but involves far too many roundtrips :-(
87             #$e->bridge->queued(sub{
88             # while ($e->hasMoreElements) {
89             # my $cookie = $e->getNext()->QueryInterface($nsICookie);
90             #
91             # my @values = map { $cookie->{$_} } (qw(name value path host isSecure expires));
92             # $self->set_cookie( undef, @values[0, 1, 2, 3, ], undef, undef, $values[ 4 ], time-$values[5], 0 );
93             # };
94             #});
95             }
96              
97             sub set_cookie {
98 0     0 1   my ($self, $version, $key, $val, $path, $domain, $port, $path_spec, $secure, $maxage, $discard, $rest ) = @_;
99 0   0       $rest ||= {};
100 0   0       my $repl = $rest->{repl} || $self->{repl};
101            
102 0           my $uri = URI->new("http://$domain",'http');
103             #$uri->protocol('http'); # ???
104 0           $uri->host($domain);
105 0 0         $uri->path($path) if $path;
106 0 0         $uri->port($port) if $port;
107            
108 0           my $set = $repl->declare(<<'JS');
109             function (host,path,name,value,secure,httponly,session,expiry) {
110             var cookieMgr = Components.classes["@mozilla.org/cookiemanager;1"].getService(Components.interfaces.nsICookieManager2);
111              
112             cookieMgr.add(host,path,name,value,secure,httponly,session,expiry);
113             };
114             JS
115 0 0         $set->($uri->host, $uri->path, $key, $val, 0, 0, 0, $maxage ? time+$maxage : 0);
116             };
117              
118             sub save {
119 0     0 1   croak 'save is not yet implemented'
120             }
121              
122             1;
123              
124             __END__