forked from browserutils/kooky
-
Notifications
You must be signed in to change notification settings - Fork 0
/
find.go
156 lines (135 loc) · 3.25 KB
/
find.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package kooky
import (
"net/http"
"sync"
)
// CookieStore represents a file, directory, etc containing cookies.
//
// Call CookieStore.Close() after using any of its methods.
type CookieStore interface {
http.CookieJar
SubJar(filters ...Filter) (http.CookieJar, error)
ReadCookies(...Filter) ([]*Cookie, error)
Browser() string
Profile() string
IsDefaultProfile() bool
FilePath() string
Close() error
}
// CookieStoreFinder tries to find cookie stores at default locations.
type CookieStoreFinder interface {
FindCookieStores() ([]CookieStore, error)
}
var (
finders = map[string]CookieStoreFinder{}
muFinder sync.RWMutex
)
// RegisterFinder() registers CookieStoreFinder enabling automatic finding of
// cookie stores with FindAllCookieStores() and ReadCookies().
//
// RegisterFinder() is called by init() in the browser subdirectories.
func RegisterFinder(browser string, finder CookieStoreFinder) {
muFinder.Lock()
defer muFinder.Unlock()
if finder != nil {
finders[browser] = finder
}
}
// FindAllCookieStores() tries to find cookie stores at default locations.
//
// FindAllCookieStores() requires registered CookieStoreFinders.
//
// Register cookie store finders for all browsers like this:
//
// import _ "github.com/jeremy-cxf/kooky/browser/all"
//
// Or only a specific browser:
//
// import _ "github.com/jeremy-cxf/kooky/browser/chrome"
func FindAllCookieStores() []CookieStore {
var ret []CookieStore
var wg sync.WaitGroup
wg.Add(len(finders))
c := make(chan []CookieStore)
done := make(chan struct{})
go func() {
for cookieStores := range c {
ret = append(ret, cookieStores...)
}
close(done)
}()
muFinder.RLock()
defer muFinder.RUnlock()
for _, finder := range finders {
go func(finder CookieStoreFinder) {
defer wg.Done()
cookieStores, err := finder.FindCookieStores()
if err == nil && cookieStores != nil {
c <- cookieStores
}
}(finder)
}
wg.Wait()
close(c)
<-done
return ret
}
// ReadCookies() uses registered cookiestore finders to read cookies.
// Erronous reads are skipped.
//
// Register cookie store finders for all browsers like this:
//
// import _ "github.com/jeremy-cxf/kooky/browser/all"
//
// Or only a specific browser:
//
// import _ "github.com/jeremy-cxf/kooky/browser/chrome"
func ReadCookies(filters ...Filter) []*Cookie {
var ret []*Cookie
cs := make(chan []CookieStore)
c := make(chan []*Cookie)
done := make(chan struct{})
// append cookies
go func() {
for cookies := range c {
ret = append(ret, cookies...)
}
close(done)
}()
// read cookies
go func() {
var wgcs sync.WaitGroup
for cookieStores := range cs {
for _, store := range cookieStores {
wgcs.Add(1)
go func(store CookieStore) {
defer wgcs.Done()
cookies, err := store.ReadCookies(filters...)
if err == nil && cookies != nil {
c <- cookies
}
}(store)
}
}
wgcs.Wait()
close(c)
}()
// find cookie store
var wgcsf sync.WaitGroup
muFinder.RLock()
defer muFinder.RUnlock()
wgcsf.Add(len(finders))
for _, finder := range finders {
go func(finder CookieStoreFinder) {
defer wgcsf.Done()
cookieStores, err := finder.FindCookieStores()
if err == nil && cookieStores != nil {
cs <- cookieStores
}
}(finder)
}
wgcsf.Wait()
close(cs)
<-done
return ret
}