diff options
Diffstat (limited to 'vendor/github.com/getlantern')
27 files changed, 0 insertions, 4767 deletions
diff --git a/vendor/github.com/getlantern/context/LICENSE b/vendor/github.com/getlantern/context/LICENSE deleted file mode 100644 index 5dc6c26..0000000 --- a/vendor/github.com/getlantern/context/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016 Brave New Software Project, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/getlantern/context/README.md b/vendor/github.com/getlantern/context/README.md deleted file mode 100644 index 978c9e0..0000000 --- a/vendor/github.com/getlantern/context/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# context [![Travis CI Status](https://travis-ci.org/getlantern/context.svg?branch=master)](https://travis-ci.org/getlantern/context) [![Coverage Status](https://coveralls.io/repos/getlantern/context/badge.png?branch=master)](https://coveralls.io/r/getlantern/context) - -Provides goroutine-based context state inspired by https://github.com/tylerb/gls -and https://github.com/jtolds/gls. It uses the same basic hack as tylerb's -library, but adds a stack abstraction that allows nested contexts similar to -jtolds' library, but using `Enter()` and `Exit()` instead of callback functions. diff --git a/vendor/github.com/getlantern/context/context.go b/vendor/github.com/getlantern/context/context.go deleted file mode 100644 index c77f129..0000000 --- a/vendor/github.com/getlantern/context/context.go +++ /dev/null @@ -1,309 +0,0 @@ -// Package context provides a mechanism for transparently tracking contextual -// state associated to the current goroutine and even across goroutines. -package context - -import ( - "sync" -) - -// Manager provides the ability to create and access Contexts. -type Manager interface { - // Enter enters a new level on the current Context stack, creating a new Context - // if necessary. - Enter() Context - - // Go starts the given function on a new goroutine but sharing the context of - // the current goroutine (if it has one). - Go(func()) - - // PutGlobal puts the given key->value pair into the global context. - PutGlobal(key string, value interface{}) - - // PutGlobalDynamic puts a key->value pair into the global context where the - // value is generated by a function that gets evaluated at every Read. If the - // value is a map[string]interface{}, we will unpack the map and set each - // contained key->value pair independently. - PutGlobalDynamic(key string, valueFN func() interface{}) - - // AsMap returns a map containing all values from the supplied obj if it is a - // Contextual, plus any addition values from along the stack, plus globals if so - // specified. - AsMap(obj interface{}, includeGlobals bool) Map -} - -type manager struct { - contexts map[uint64]*context - mxContexts sync.RWMutex - global Map - mxGlobal sync.RWMutex -} - -// NewManager creates a new Manager -func NewManager() Manager { - return &manager{ - contexts: make(map[uint64]*context), - global: make(Map), - } -} - -// Contextual is an interface for anything that maintains its own context. -type Contextual interface { - // Fill fills the given Map with all of this Contextual's context - Fill(m Map) -} - -// Map is a map of key->value pairs. -type Map map[string]interface{} - -// Fill implements the method from the Contextual interface. -func (_m Map) Fill(m Map) { - for key, value := range _m { - m[key] = value - } -} - -// Context is a context containing key->value pairs -type Context interface { - // Enter enters a new level on this Context stack. - Enter() Context - - // Go starts the given function on a new goroutine. - Go(fn func()) - - // Exit exits the current level on this Context stack. - Exit() - - // Put puts a key->value pair into the current level of the context stack. - Put(key string, value interface{}) Context - - // PutIfAbsent puts the given key->value pair into the current level of the - // context stack if and only if that key is defined nowhere within the context - // stack (including parent contexts). - PutIfAbsent(key string, value interface{}) Context - - // PutDynamic puts a key->value pair into the current level of the context - // stack where the value is generated by a function that gets evaluated at - // every Read. If the value is a map[string]interface{}, we will unpack the - // map and set each contained key->value pair independently. - PutDynamic(key string, valueFN func() interface{}) Context - - // Fill fills the given map with data from this Context - Fill(m Map) - - // AsMap returns a map containing all values from the supplied obj if it is a - // Contextual, plus any addition values from along the stack, plus globals if - // so specified. - AsMap(obj interface{}, includeGlobals bool) Map -} - -type context struct { - cm *manager - id uint64 - parent *context - branchedFrom *context - data Map - mx sync.RWMutex -} - -type dynval struct { - fn func() interface{} -} - -func (cm *manager) Enter() Context { - return cm.enter(curGoroutineID()) -} - -func (cm *manager) enter(id uint64) *context { - cm.mxContexts.Lock() - parentOrNil := cm.contexts[id] - c := cm.makeContext(id, parentOrNil, nil) - cm.contexts[id] = c - cm.mxContexts.Unlock() - return c -} - -func (cm *manager) exit(id uint64, parent *context) { - cm.mxContexts.Lock() - if parent == nil { - delete(cm.contexts, id) - } else { - cm.contexts[id] = parent - } - cm.mxContexts.Unlock() -} - -func (cm *manager) branch(id uint64, from *context) { - next := cm.makeContext(id, nil, from) - cm.mxContexts.Lock() - cm.contexts[id] = next - cm.mxContexts.Unlock() -} - -func (cm *manager) merge(id uint64) { - cm.mxContexts.Lock() - delete(cm.contexts, id) - cm.mxContexts.Unlock() -} - -func (c *context) Enter() Context { - c.mx.RLock() - id := c.id - c.mx.RUnlock() - return c.cm.enter(id) -} - -func (c *context) Go(fn func()) { - go func() { - id := curGoroutineID() - c.cm.branch(id, c) - fn() - c.cm.merge(id) - }() -} - -func (cm *manager) Go(fn func()) { - c := cm.currentContext() - if c != nil { - c.Go(fn) - } else { - go fn() - } -} - -func (cm *manager) makeContext(id uint64, parent *context, branchedFrom *context) *context { - return &context{ - cm: cm, - id: id, - parent: parent, - branchedFrom: branchedFrom, - data: make(Map), - } -} - -func (c *context) Exit() { - c.mx.RLock() - id := c.id - parent := c.parent - c.mx.RUnlock() - c.cm.exit(id, parent) -} - -func (c *context) Put(key string, value interface{}) Context { - c.mx.Lock() - c.data[key] = value - c.mx.Unlock() - return c -} - -func (c *context) PutIfAbsent(key string, value interface{}) Context { - for ctx := c; ctx != nil; { - ctx.mx.RLock() - _, exists := ctx.data[key] - next := ctx.parent - if next == nil { - next = ctx.branchedFrom - } - ctx.mx.RUnlock() - if exists { - return c - } - ctx = next - } - - // Value not set, set it - return c.Put(key, value) -} - -func (c *context) PutDynamic(key string, valueFN func() interface{}) Context { - value := &dynval{valueFN} - c.mx.Lock() - c.data[key] = value - c.mx.Unlock() - return c -} - -func (cm *manager) PutGlobal(key string, value interface{}) { - cm.mxGlobal.Lock() - cm.global[key] = value - cm.mxGlobal.Unlock() -} - -func (cm *manager) PutGlobalDynamic(key string, valueFN func() interface{}) { - value := &dynval{valueFN} - cm.mxGlobal.Lock() - cm.global[key] = value - cm.mxGlobal.Unlock() -} - -func (c *context) Fill(m Map) { - for ctx := c; ctx != nil; { - ctx.mx.RLock() - fill(m, ctx.data) - next := ctx.parent - if next == nil { - next = ctx.branchedFrom - } - ctx.mx.RUnlock() - ctx = next - } -} - -func (cm *manager) AsMap(obj interface{}, includeGlobals bool) Map { - return cm.currentContext().asMap(cm, obj, includeGlobals) -} - -func (c *context) AsMap(obj interface{}, includeGlobals bool) Map { - return c.asMap(c.cm, obj, includeGlobals) -} - -func (c *context) asMap(cm *manager, obj interface{}, includeGlobals bool) Map { - result := make(Map, 0) - cl, ok := obj.(Contextual) - if ok { - cl.Fill(result) - } - if c != nil { - c.Fill(result) - } - if includeGlobals { - cm.mxGlobal.RLock() - fill(result, cm.global) - cm.mxGlobal.RUnlock() - } - return result -} - -func fill(m Map, from Map) { - if m != nil { - doFill := func(key string, _value interface{}) { - switch value := _value.(type) { - case map[string]interface{}: - for k, v := range value { - m[k] = v - } - default: - m[key] = value - } - } - - for key, value := range from { - _, alreadyRead := m[key] - if !alreadyRead { - switch v := value.(type) { - case *dynval: - doFill(key, v.fn()) - default: - doFill(key, v) - } - } - } - } -} - -func (cm *manager) currentContext() *context { - id := curGoroutineID() - cm.mxContexts.RLock() - c := cm.contexts[id] - cm.mxContexts.RUnlock() - return c -} diff --git a/vendor/github.com/getlantern/context/context_test.go b/vendor/github.com/getlantern/context/context_test.go deleted file mode 100644 index 9fb86f3..0000000 --- a/vendor/github.com/getlantern/context/context_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package context - -import ( - "sync" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestStack(t *testing.T) { - cm := NewManager() - _cm := cm.(*manager) - // Put globals first - cm.PutGlobal("a", -1) // This will get overriden in specific contexts - cm.PutGlobal("ga", "i") - cm.PutGlobalDynamic("gb", func() interface{} { return "ii" }) - cm.PutGlobalDynamic("gm", func() interface{} { return map[string]interface{}{"gm3": "iii", "gm4": "iv"} }) - - // Use a Map as a Contextual - var contextual = Map{ - "a": 0, // This will override whatever is in specific contexts - "contextual": "special", - } - - c := cm.Enter() - c.Put("a", 1) - penultimate := cm.Enter(). - Put("b", 2) - c = cm.Enter(). - PutDynamic("c", func() interface{} { return 4 }). - PutIfAbsent("d", 5). - PutIfAbsent("a", 11) - - // Put something in the penultimate context and make sure it doesn't override - // what's set in the ultimate context - penultimate.Put("c", 3) - - var assertMutex sync.Mutex - doAssertContents := func(expected Map, actual Map, scope string) { - assertMutex.Lock() - assert.Equal(t, expected, actual, scope) - assertMutex.Unlock() - } - - assertContents := func(expected Map) { - doAssertContents(expected, cm.AsMap(nil, false), "AsMapwith(nil, false)") - expected["ga"] = "i" - expected["gb"] = "ii" - expected["gm3"] = "iii" - expected["gm4"] = "iv" - _, exists := expected["a"] - if !exists { - expected["a"] = -1 - } - doAssertContents(expected, cm.AsMap(nil, true), "AsMap(nil, true)") - expected["a"] = 0 - expected["contextual"] = "special" - doAssertContents(expected, cm.AsMap(contextual, true), "AsMapWith(contextual, true)") - delete(expected, "ga") - delete(expected, "gb") - delete(expected, "gm3") - delete(expected, "gm4") - doAssertContents(expected, cm.AsMap(contextual, false), "AsMapWith(contextual, false)") - } - - assertContents(Map{ - "a": 1, - "b": 2, - "c": 4, - "d": 5, - }) - - var wg sync.WaitGroup - wg.Add(1) - cm.Go(func() { - defer cm.Enter().Put("e", 6).Exit() - assertContents(Map{ - "a": 1, - "b": 2, - "c": 4, - "d": 5, - "e": 6, - }) - wg.Done() - }) - wg.Wait() - - wg.Add(1) - cm.Go(func() { - // This goroutine doesn't Exit. Still, we shouldn't leak anything. - wg.Done() - }) - wg.Wait() - - assertContents(Map{ - "a": 1, - "b": 2, - "c": 4, - "d": 5, - }) - - c.Exit() - c = _cm.currentContext() - assert.NotNil(t, c) - assertContents(Map{ - "a": 1, - "b": 2, - "c": 3, - }) - - c.Exit() - c = _cm.currentContext() - assert.NotNil(t, c) - assertContents(Map{ - "a": 1, - }) - - // Last exit - c.Exit() - assert.Nil(t, _cm.currentContext()) - assertContents(Map{}) - - // Exit again, just for good measure - c.Exit() - assert.Nil(t, _cm.currentContext()) - assertContents(Map{}) - - // Spawn a goroutine with no existing contexts - wg.Add(1) - cm.Go(func() { - defer cm.Enter().Put("f", 7).Exit() - assertContents(Map{ - "f": 7, - }) - wg.Done() - }) - wg.Wait() - - _cm.mxContexts.Lock() - assert.Empty(t, _cm.contexts, "No contexts should be left") - _cm.mxContexts.Unlock() -} - -func BenchmarkPut(b *testing.B) { - cm := NewManager() - c := cm.Enter() - b.ResetTimer() - for i := 0; i < b.N; i++ { - c.Put("key", "value") - } -} - -func BenchmarkAsMap(b *testing.B) { - cm := NewManager() - cm.Enter().Put("a", 1).Put("b", 2) - b.ResetTimer() - for i := 0; i < b.N; i++ { - cm.AsMap(nil, true) - } -} diff --git a/vendor/github.com/getlantern/context/gotrack.go b/vendor/github.com/getlantern/context/gotrack.go deleted file mode 100644 index 7f92346..0000000 --- a/vendor/github.com/getlantern/context/gotrack.go +++ /dev/null @@ -1,130 +0,0 @@ -package context - -import ( - "bytes" - "errors" - "fmt" - "runtime" - "strconv" - "sync" -) - -// Sourced https://github.com/bradfitz/http2/blob/dc0c5c000ec33e263612939744d51a3b68b9cece/gotrack.go -var goroutineSpace = []byte("goroutine ") -var littleBuf = sync.Pool{ - New: func() interface{} { - buf := make([]byte, 64) - return &buf - }, -} - -func curGoroutineID() uint64 { - bp := littleBuf.Get().(*[]byte) - defer littleBuf.Put(bp) - b := *bp - b = b[:runtime.Stack(b, false)] - // Parse the 4707 out of "goroutine 4707 [" - b = bytes.TrimPrefix(b, goroutineSpace) - i := bytes.IndexByte(b, ' ') - if i < 0 { - panic(fmt.Sprintf("No space found in %q", b)) - } - b = b[:i] - n, err := parseUintBytes(b, 10, 64) - if err != nil { - panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err)) - } - return n -} - -// parseUintBytes is like strconv.ParseUint, but using a []byte. -func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) { - var cutoff, maxVal uint64 - - if bitSize == 0 { - bitSize = int(strconv.IntSize) - } - - s0 := s - switch { - case len(s) < 1: - err = strconv.ErrSyntax - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - - case 2 <= base && base <= 36: - // valid base; nothing to do - - case base == 0: - // Look for octal, hex prefix. - switch { - case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'): - base = 16 - s = s[2:] - if len(s) < 1 { - err = strconv.ErrSyntax - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - case s[0] == '0': - base = 8 - default: - base = 10 - } - - default: - err = errors.New("invalid base " + strconv.Itoa(base)) - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - - n = 0 - cutoff = cutoff64(base) - maxVal = 1<<uint(bitSize) - 1 - - for i := 0; i < len(s); i++ { - var v byte - d := s[i] - switch { - case '0' <= d && d <= '9': - v = d - '0' - case 'a' <= d && d <= 'z': - v = d - 'a' + 10 - case 'A' <= d && d <= 'Z': - v = d - 'A' + 10 - default: - n = 0 - err = strconv.ErrSyntax - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - if int(v) >= base { - n = 0 - err = strconv.ErrSyntax - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - - if n >= cutoff { - // n*base overflows - n = 1<<64 - 1 - err = strconv.ErrRange - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - n *= uint64(base) - - n1 := n + uint64(v) - if n1 < n || n1 > maxVal { - // n+v overflows - n = 1<<64 - 1 - err = strconv.ErrRange - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - n = n1 - } - - return n, nil -} - -// Return the first number n such that n*base >= 1<<64. -func cutoff64(base int) uint64 { - if base < 2 { - return 0 - } - return (1<<64-1)/uint64(base) + 1 -} diff --git a/vendor/github.com/getlantern/errors/errors.go b/vendor/github.com/getlantern/errors/errors.go deleted file mode 100644 index 8b2b84f..0000000 --- a/vendor/github.com/getlantern/errors/errors.go +++ /dev/null @@ -1,566 +0,0 @@ -/* -Package errors defines error types used across Lantern project. - - n, err := Foo() - if err != nil { - return n, errors.New("Unable to do Foo: %v", err) - } - -or - - n, err := Foo() - return n, errors.Wrap(err) - -New() method will create a new error with err as its cause. Wrap will wrap err, -returning nil if err is nil. If err is an error from Go's standard library, -errors will extract details from that error, at least the Go type name and the -return value of err.Error(). - -One can record the operation on which the error occurred using Op(): - - return n, errors.New("Unable to do Foo: %v", err).Op("FooDooer") - -One can also record additional data: - - return n, errors. - New("Unable to do Foo: %v", err). - Op("FooDooer"). - With("mydata", "myvalue"). - With("moredata", 5) - -When used with github.com/getlantern/ops, Error captures its current context -and propagates that data for use in calling layers. - -When used with github.com/getlantern/golog, Error provides stacktraces: - - Hello World - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) - Caused by: World - at github.com/getlantern/errors.buildCause (errors_test.go:999) - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) - Caused by: orld - Caused by: ld - at github.com/getlantern/errors.buildSubSubCause (errors_test.go:999) - at github.com/getlantern/errors.buildSubCause (errors_test.go:999) - at github.com/getlantern/errors.buildCause (errors_test.go:999) - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) - Caused by: d - -It's the caller's responsibility to avoid race conditions accessing the same -error instance from multiple goroutines. -*/ -package errors - -import ( - "bufio" - "bytes" - "crypto/tls" - "crypto/x509" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "net" - "net/http" - "net/textproto" - "net/url" - "os" - "os/exec" - "reflect" - "runtime" - "strconv" - "strings" - "syscall" - "time" - "unicode" - - "github.com/getlantern/context" - "github.com/getlantern/hidden" - "github.com/getlantern/ops" - "github.com/go-stack/stack" -) - -// Error wraps system and application defined errors in unified structure for -// reporting and logging. It's not meant to be created directly. User New(), -// Wrap() and Report() instead. -type Error interface { - error - context.Contextual - - // ErrorClean returns a non-parameterized version of the error whenever - // possible. For example, if the error text is: - // - // unable to dial www.google.com caused by: i/o timeout - // - // ErrorClean might return: - // - // unable to dial %v caused by: %v - // - // This can be useful when performing analytics on the error. - ErrorClean() string - - // MultiLinePrinter implements the interface golog.MultiLine - MultiLinePrinter() func(buf *bytes.Buffer) bool - - // Op attaches a hint of the operation triggers this Error. Many error types - // returned by net and os package have Op pre-filled. - Op(op string) Error - - // With attaches arbitrary field to the error. keys will be normalized as - // underscore_divided_words, so all characters except letters and numbers will - // be replaced with underscores, and all letters will be lowercased. - With(key string, value interface{}) Error - - // RootCause returns the bottom-most cause of this Error. If the Error - // resulted from wrapping a plain error, the wrapped error will be returned as - // the cause. - RootCause() error -} - -type structured struct { - id uint64 - hiddenID string - data context.Map - context context.Map - wrapped error - cause Error - callStack stack.CallStack -} - -// New creates an Error with supplied description and format arguments to the -// description. If any of the arguments is an error, we use that as the cause. -func New(desc string, args ...interface{}) Error { - return NewOffset(1, desc, args...) -} - -// NewOffset is like New but offsets the stack by the given offset. This is -// useful for utilities like golog that may create errors on behalf of others. -func NewOffset(offset int, desc string, args ...interface{}) Error { - var cause error - for _, arg := range args { - err, isError := arg.(error) - if isError { - cause = err - break - } - } - e := buildError(desc, fmt.Sprintf(desc, args...), nil, Wrap(cause)) - e.attachStack(2 + offset) - return e -} - -// Wrap creates an Error based on the information in an error instance. It -// returns nil if the error passed in is nil, so we can simply call -// errors.Wrap(s.l.Close()) regardless there's an error or not. If the error is -// already wrapped, it is returned as is. -func Wrap(err error) Error { - return wrapSkipFrames(err, 1) -} - -// Fill implements the method from the context.Contextual interface. -func (e *structured) Fill(m context.Map) { - if e != nil { - if e.cause != nil { - // Include data from cause, which supercedes context - e.cause.Fill(m) - } - // Include the context, which supercedes the cause - for key, value := range e.context { - m[key] = value - } - // Now include the error's data, which supercedes everything - for key, value := range e.data { - m[key] = value - } - } -} - -func (e *structured) Op(op string) Error { - e.data["error_op"] = op - return e -} - -func (e *structured) With(key string, value interface{}) Error { - parts := strings.FieldsFunc(key, func(c rune) bool { - return !unicode.IsLetter(c) && !unicode.IsNumber(c) - }) - k := strings.ToLower(strings.Join(parts, "_")) - if k == "error" || k == "error_op" { - // Never overwrite these - return e - } - switch actual := value.(type) { - case string, int, bool, time.Time: - e.data[k] = actual - default: - e.data[k] = fmt.Sprint(actual) - } - return e -} - -func (e *structured) RootCause() error { - if e.cause == nil { - if e.wrapped != nil { - return e.wrapped - } - return e - } - return e.cause.RootCause() -} - -func (e *structured) ErrorClean() string { - return e.data["error"].(string) -} - -// Error satisfies the error interface -func (e *structured) Error() string { - return e.data["error_text"].(string) + e.hiddenID -} - -func (e *structured) MultiLinePrinter() func(buf *bytes.Buffer) bool { - first := true - indent := false - err := e - stackPosition := 0 - switchedCause := false - return func(buf *bytes.Buffer) bool { - if indent { - buf.WriteString(" ") - } - if first { - buf.WriteString(e.Error()) - first = false - indent = true - return true - } - if switchedCause { - fmt.Fprintf(buf, "Caused by: %v", err) - if err.callStack != nil && len(err.callStack) > 0 { - switchedCause = false - indent = true - return true - } - if err.cause == nil { - return false - } - err = err.cause.(*structured) - return true - } - if stackPosition < len(err.callStack) { - buf.WriteString("at ") - call := err.callStack[stackPosition] - fmt.Fprintf(buf, "%+n (%s:%d)", call, call, call) - stackPosition++ - } - if stackPosition >= len(err.callStack) { - switch cause := err.cause.(type) { - case *structured: - err = cause - indent = false - stackPosition = 0 - switchedCause = true - default: - return false - } - } - return err != nil - } -} - -func wrapSkipFrames(err error, skip int) Error { - if err == nil { - return nil - } - - // Look for *structureds - if e, ok := err.(*structured); ok { - return e - } - - var cause Error - // Look for hidden *structureds - hiddenIDs, err2 := hidden.Extract(err.Error()) - if err2 == nil && len(hiddenIDs) > 0 { - // Take the first hidden ID as our cause - cause = get(hiddenIDs[0]) - } - - // Create a new *structured - return buildError("", "", err, cause) -} - -func (e *structured) attachStack(skip int) { - call := stack.Caller(skip) - e.callStack = stack.Trace().TrimBelow(call) - e.data["error_location"] = fmt.Sprintf("%+n (%s:%d)", call, call, call) -} - -func buildError(desc string, fullText string, wrapped error, cause Error) *structured { - e := &structured{ - data: make(context.Map), - // We capture the current context to allow it to propagate to higher layers. - context: ops.AsMap(nil, false), - wrapped: wrapped, - cause: cause, - } - e.save() - - errorType := "errors.Error" - if wrapped != nil { - op, goType, wrappedDesc, extra := parseError(wrapped) - if desc == "" { - desc = wrappedDesc - } - e.Op(op) - errorType = goType - if extra != nil { - for key, value := range extra { - e.data[key] = value - } - } - } - - cleanedDesc := hidden.Clean(desc) - e.data["error"] = cleanedDesc - if fullText != "" { - e.data["error_text"] = hidden.Clean(fullText) - } else { - e.data["error_text"] = cleanedDesc - } - e.data["error_type"] = errorType - - return e -} - -func parseError(err error) (op string, goType string, desc string, extra map[string]string) { - extra = make(map[string]string) - - // interfaces - if _, ok := err.(net.Error); ok { - if opError, ok := err.(*net.OpError); ok { - op = opError.Op - if opError.Source != nil { - extra["remote_addr"] = opError.Source.String() - } - if opError.Addr != nil { - extra["local_addr"] = opError.Addr.String() - } - extra["network"] = opError.Net - err = opError.Err - } - switch actual := err.(type) { - case *net.AddrError: - goType = "net.AddrError" - desc = actual.Err - extra["addr"] = actual.Addr - case *net.DNSError: - goType = "net.DNSError" - desc = actual.Err - extra["domain"] = actual.Name - if actual.Server != "" { - extra["dns_server"] = actual.Server - } - case *net.InvalidAddrError: - goType = "net.InvalidAddrError" - desc = actual.Error() - case *net.ParseError: - goType = "net.ParseError" - desc = "invalid " + actual.Type - extra["text_to_parse"] = actual.Text - case net.UnknownNetworkError: - goType = "net.UnknownNetworkError" - desc = "unknown network" - case syscall.Errno: - goType = "syscall.Errno" - desc = actual.Error() - case *url.Error: - goType = "url.Error" - desc = actual.Err.Error() - op = actual.Op - default: - goType = reflect.TypeOf(err).String() - desc = err.Error() - } - return - } - if _, ok := err.(runtime.Error); ok { - desc = err.Error() - switch err.(type) { - case *runtime.TypeAssertionError: - goType = "runtime.TypeAssertionError" - default: - goType = reflect.TypeOf(err).String() - } - return - } - - // structs - switch actual := err.(type) { - case *http.ProtocolError: - desc = actual.ErrorString - if name, ok := httpProtocolErrors[err]; ok { - goType = name - } else { - goType = "http.ProtocolError" - } - case url.EscapeError, *url.EscapeError: - goType = "url.EscapeError" - desc = "invalid URL escape" - case url.InvalidHostError, *url.InvalidHostError: - goType = "url.InvalidHostError" - desc = "invalid character in host name" - case *textproto.Error: - goType = "textproto.Error" - desc = actual.Error() - case textproto.ProtocolError, *textproto.ProtocolError: - goType = "textproto.ProtocolError" - desc = actual.Error() - - case tls.RecordHeaderError: - goType = "tls.RecordHeaderError" - desc = actual.Msg - extra["header"] = hex.EncodeToString(actual.RecordHeader[:]) - case x509.CertificateInvalidError: - goType = "x509.CertificateInvalidError" - desc = actual.Error() - case x509.ConstraintViolationError: - goType = "x509.ConstraintViolationError" - desc = actual.Error() - case x509.HostnameError: - goType = "x509.HostnameError" - desc = actual.Error() - extra["host"] = actual.Host - case x509.InsecureAlgorithmError: - goType = "x509.InsecureAlgorithmError" - desc = actual.Error() - case x509.SystemRootsError: - goType = "x509.SystemRootsError" - desc = actual.Error() - case x509.UnhandledCriticalExtension: - goType = "x509.UnhandledCriticalExtension" - desc = actual.Error() - case x509.UnknownAuthorityError: - goType = "x509.UnknownAuthorityError" - desc = actual.Error() - case hex.InvalidByteError: - goType = "hex.InvalidByteError" - desc = "invalid byte" - case *json.InvalidUTF8Error: - goType = "json.InvalidUTF8Error" - desc = "invalid UTF-8 in string" - case *json.InvalidUnmarshalError: - goType = "json.InvalidUnmarshalError" - desc = actual.Error() - case *json.MarshalerError: - goType = "json.MarshalerError" - desc = actual.Error() - case *json.SyntaxError: - goType = "json.SyntaxError" - desc = actual.Error() - case *json.UnmarshalFieldError: - goType = "json.UnmarshalFieldError" - desc = actual.Error() - case *json.UnmarshalTypeError: - goType = "json.UnmarshalTypeError" - desc = actual.Error() - case *json.UnsupportedTypeError: - goType = "json.UnsupportedTypeError" - desc = actual.Error() - case *json.UnsupportedValueError: - goType = "json.UnsupportedValueError" - desc = actual.Error() - - case *os.LinkError: - goType = "os.LinkError" - desc = actual.Error() - case *os.PathError: - goType = "os.PathError" - op = actual.Op - desc = actual.Err.Error() - case *os.SyscallError: - goType = "os.SyscallError" - op = actual.Syscall - desc = actual.Err.Error() - case *exec.Error: - goType = "exec.Error" - desc = actual.Err.Error() - case *exec.ExitError: - goType = "exec.ExitError" - desc = actual.Error() - // TODO: limit the length - extra["stderr"] = string(actual.Stderr) - case *strconv.NumError: - goType = "strconv.NumError" - desc = actual.Err.Error() - extra["function"] = actual.Func - case *time.ParseError: - goType = "time.ParseError" - desc = actual.Message - default: - desc = err.Error() - if t, ok := miscErrors[err]; ok { - goType = t - return - } - goType = reflect.TypeOf(err).String() - } - return -} - -var httpProtocolErrors = map[error]string{ - http.ErrHeaderTooLong: "http.ErrHeaderTooLong", - http.ErrShortBody: "http.ErrShortBody", - http.ErrNotSupported: "http.ErrNotSupported", - http.ErrUnexpectedTrailer: "http.ErrUnexpectedTrailer", - http.ErrMissingContentLength: "http.ErrMissingContentLength", - http.ErrNotMultipart: "http.ErrNotMultipart", - http.ErrMissingBoundary: "http.ErrMissingBoundary", -} - -var miscErrors = map[error]string{ - bufio.ErrInvalidUnreadByte: "bufio.ErrInvalidUnreadByte", - bufio.ErrInvalidUnreadRune: "bufio.ErrInvalidUnreadRune", - bufio.ErrBufferFull: "bufio.ErrBufferFull", - bufio.ErrNegativeCount: "bufio.ErrNegativeCount", - bufio.ErrTooLong: "bufio.ErrTooLong", - bufio.ErrNegativeAdvance: "bufio.ErrNegativeAdvance", - bufio.ErrAdvanceTooFar: "bufio.ErrAdvanceTooFar", - bufio.ErrFinalToken: "bufio.ErrFinalToken", - - http.ErrWriteAfterFlush: "http.ErrWriteAfterFlush", - http.ErrBodyNotAllowed: "http.ErrBodyNotAllowed", - http.ErrHijacked: "http.ErrHijacked", - http.ErrContentLength: "http.ErrContentLength", - http.ErrBodyReadAfterClose: "http.ErrBodyReadAfterClose", - http.ErrHandlerTimeout: "http.ErrHandlerTimeout", - http.ErrLineTooLong: "http.ErrLineTooLong", - http.ErrMissingFile: "http.ErrMissingFile", - http.ErrNoCookie: "http.ErrNoCookie", - http.ErrNoLocation: "http.ErrNoLocation", - http.ErrSkipAltProtocol: "http.ErrSkipAltProtocol", - - io.EOF: "io.EOF", - io.ErrClosedPipe: "io.ErrClosedPipe", - io.ErrNoProgress: "io.ErrNoProgress", - io.ErrShortBuffer: "io.ErrShortBuffer", - io.ErrShortWrite: "io.ErrShortWrite", - io.ErrUnexpectedEOF: "io.ErrUnexpectedEOF", - - os.ErrInvalid: "os.ErrInvalid", - os.ErrPermission: "os.ErrPermission", - os.ErrExist: "os.ErrExist", - os.ErrNotExist: "os.ErrNotExist", - - exec.ErrNotFound: "exec.ErrNotFound", - - x509.ErrUnsupportedAlgorithm: "x509.ErrUnsupportedAlgorithm", - x509.IncorrectPasswordError: "x509.IncorrectPasswordError", - - hex.ErrLength: "hex.ErrLength", -} diff --git a/vendor/github.com/getlantern/errors/errors_test.go b/vendor/github.com/getlantern/errors/errors_test.go deleted file mode 100644 index 7c4887a..0000000 --- a/vendor/github.com/getlantern/errors/errors_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package errors - -import ( - "bytes" - "fmt" - "regexp" - "testing" - - "github.com/getlantern/context" - "github.com/getlantern/hidden" - "github.com/getlantern/ops" - "github.com/stretchr/testify/assert" -) - -var ( - replaceNumbers = regexp.MustCompile("[0-9]+") -) - -func TestFull(t *testing.T) { - var firstErr Error - - // Iterate past the size of the hidden buffer - for i := 0; i < len(hiddenErrors)*2; i++ { - op := ops.Begin("op1").Set("ca", 100).Set("cd", 100) - e := New("Hello %v", "There").Op("My Op").With("DaTa_1", 1) - op.End() - if firstErr == nil { - firstErr = e - } - assert.Equal(t, "Hello There", e.Error()[:11]) - op = ops.Begin("op2").Set("ca", 200).Set("cb", 200).Set("cc", 200) - e3 := Wrap(fmt.Errorf("I'm wrapping your text: %v", e)).Op("outer op").With("dATA+1", i).With("cb", 300) - op.End() - assert.Equal(t, e, e3.(*structured).cause, "Wrapping a regular error should have extracted the contained *Error") - m := make(context.Map) - e3.Fill(m) - assert.Equal(t, i, m["data_1"], "Error's data should dominate all") - assert.Equal(t, 200, m["ca"], "Error's context should dominate cause") - assert.Equal(t, 300, m["cb"], "Error's data should dominate its context") - assert.Equal(t, 200, m["cc"], "Error's context should come through") - assert.Equal(t, 100, m["cd"], "Cause's context should come through") - assert.Equal(t, "My Op", e.(*structured).data["error_op"], "Op should be available from cause") - - for _, call := range e3.(*structured).callStack { - t.Logf("at %v", call) - } - } - - e3 := Wrap(fmt.Errorf("I'm wrapping your text: %v", firstErr)).With("a", 2) - assert.Nil(t, e3.(*structured).cause, "Wrapping an *Error that's no longer buffered should have yielded no cause") -} - -func TestNewWithCause(t *testing.T) { - cause := buildCause() - outer := New("Hello %v", cause) - assert.Equal(t, "Hello World", hidden.Clean(outer.Error())) - assert.Equal(t, "Hello %v", outer.(*structured).ErrorClean()) - assert.Equal(t, - "github.com/getlantern/errors.TestNewWithCause (errors_test.go:999)", - replaceNumbers.ReplaceAllString(outer.(*structured).data["error_location"].(string), "999")) - assert.Equal(t, cause, outer.(*structured).cause) - - // Make sure that stacktrace prints out okay - buf := &bytes.Buffer{} - print := outer.MultiLinePrinter() - for { - more := print(buf) - buf.WriteByte('\n') - if !more { - break - } - } - expected := `Hello World - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) -Caused by: World - at github.com/getlantern/errors.buildCause (errors_test.go:999) - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) -Caused by: orld -Caused by: ld - at github.com/getlantern/errors.buildSubSubCause (errors_test.go:999) - at github.com/getlantern/errors.buildSubCause (errors_test.go:999) - at github.com/getlantern/errors.buildCause (errors_test.go:999) - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) -Caused by: d -` - - assert.Equal(t, expected, replaceNumbers.ReplaceAllString(hidden.Clean(buf.String()), "999")) - assert.Equal(t, buildSubSubSubCause(), outer.RootCause()) -} - -func buildCause() Error { - return New("W%v", buildSubCause()) -} - -func buildSubCause() error { - return fmt.Errorf("or%v", buildSubSubCause()) -} - -func buildSubSubCause() error { - return New("l%v", buildSubSubSubCause()) -} - -func buildSubSubSubCause() error { - return fmt.Errorf("d") -} - -func TestWrapNil(t *testing.T) { - assert.Nil(t, doWrapNil()) -} - -func doWrapNil() error { - return Wrap(nil) -} - -func TestHiddenWithCause(t *testing.T) { - e1 := fmt.Errorf("I failed %v", "dude") - e2 := New("I wrap: %v", e1) - e3 := fmt.Errorf("Hiding %v", e2) - // clear hidden buffer - hiddenErrors = make([]*structured, 100) - e4 := Wrap(e3) - e5 := New("I'm really outer: %v", e4) - - buf := &bytes.Buffer{} - print := e5.MultiLinePrinter() - for { - more := print(buf) - buf.WriteByte('\n') - if !more { - break - } - } - fmt.Println(buf.String()) - // We're not asserting the output because we're just making sure that printing - // doesn't panic. If we get to this point without panicking, we're happy. -} diff --git a/vendor/github.com/getlantern/errors/hide.go b/vendor/github.com/getlantern/errors/hide.go deleted file mode 100644 index f10d863..0000000 --- a/vendor/github.com/getlantern/errors/hide.go +++ /dev/null @@ -1,50 +0,0 @@ -package errors - -import ( - "encoding/binary" - "sync" - - "github.com/getlantern/hidden" -) - -var ( - hiddenErrors = make([]*structured, 100) - nextID = uint64(0) - hiddenMutex sync.RWMutex -) - -// This trick saves the error to a ring buffer and embeds a non-printing -// hiddenID in the error's description, so that if the errors is later wrapped -// by a standard error using something like -// fmt.Errorf("An error occurred: %v", thisError), we can subsequently extract -// the error simply using the hiddenID in the string. -func (e *structured) save() { - hiddenMutex.Lock() - b := make([]byte, 8) - binary.BigEndian.PutUint64(b, nextID) - e.id = nextID - e.hiddenID = hidden.ToString(b) - hiddenErrors[idxForID(nextID)] = e - nextID++ - hiddenMutex.Unlock() -} - -func get(hiddenID []byte) Error { - if len(hiddenID) != 8 { - return nil - } - id := binary.BigEndian.Uint64(hiddenID) - hiddenMutex.RLock() - err := hiddenErrors[idxForID(id)] - hiddenMutex.RUnlock() - if err != nil && err.id == id { - // Found it! - return err - } - // buffer has rolled over - return nil -} - -func idxForID(id uint64) int { - return int(id % uint64(len(hiddenErrors))) -} diff --git a/vendor/github.com/getlantern/golog/LICENSE b/vendor/github.com/getlantern/golog/LICENSE deleted file mode 100644 index 3ee0162..0000000 --- a/vendor/github.com/getlantern/golog/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2014 Brave New Software Project, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/getlantern/golog/README.md b/vendor/github.com/getlantern/golog/README.md deleted file mode 100644 index 88fe677..0000000 --- a/vendor/github.com/getlantern/golog/README.md +++ /dev/null @@ -1,6 +0,0 @@ -golog [![Travis CI Status](https://travis-ci.org/getlantern/golog.svg?branch=master)](https://travis-ci.org/getlantern/golog) [![Coverage Status](https://coveralls.io/repos/getlantern/golog/badge.png)](https://coveralls.io/r/getlantern/golog) [![GoDoc](https://godoc.org/github.com/getlantern/golog?status.png)](http://godoc.org/github.com/getlantern/golog) -========== -Provides logging used in many getlantern components. - -[GoDoc](https://godoc.org/github.com/getlantern/golog) - diff --git a/vendor/github.com/getlantern/golog/golog.go b/vendor/github.com/getlantern/golog/golog.go deleted file mode 100644 index 143e904..0000000 --- a/vendor/github.com/getlantern/golog/golog.go +++ /dev/null @@ -1,458 +0,0 @@ -// Package golog implements logging functions that log errors to stderr and -// debug messages to stdout. Trace logging is also supported. -// Trace logs go to stdout as well, but they are only written if the program -// is run with environment variable "TRACE=true". -// A stack dump will be printed after the message if "PRINT_STACK=true". -package golog - -import ( - "bufio" - "bytes" - "fmt" - "io" - "io/ioutil" - "log" - "os" - "path/filepath" - "runtime" - "sort" - "strconv" - "strings" - "sync" - "sync/atomic" - - "github.com/getlantern/errors" - "github.com/getlantern/hidden" - "github.com/getlantern/ops" - "github.com/oxtoacart/bpool" -) - -const ( - // ERROR is an error Severity - ERROR = 500 - - // FATAL is an error Severity - FATAL = 600 -) - -var ( - outs atomic.Value - reporters []ErrorReporter - reportersMutex sync.RWMutex - - bufferPool = bpool.NewBufferPool(200) - - onFatal atomic.Value -) - -// Severity is a level of error (higher values are more severe) -type Severity int - -func (s Severity) String() string { - switch s { - case ERROR: - return "ERROR" - case FATAL: - return "FATAL" - default: - return "UNKNOWN" - } -} - -func init() { - DefaultOnFatal() - ResetOutputs() -} - -func SetOutputs(errorOut io.Writer, debugOut io.Writer) { - outs.Store(&outputs{ - ErrorOut: errorOut, - DebugOut: debugOut, - }) -} - -func ResetOutputs() { - SetOutputs(os.Stderr, os.Stdout) -} - -func GetOutputs() *outputs { - return outs.Load().(*outputs) -} - -// RegisterReporter registers the given ErrorReporter. All logged Errors are -// sent to this reporter. -func RegisterReporter(reporter ErrorReporter) { - reportersMutex.Lock() - reporters = append(reporters, reporter) - reportersMutex.Unlock() -} - -// OnFatal configures golog to call the given function on any FATAL error. By -// default, golog calls os.Exit(1) on any FATAL error. -func OnFatal(fn func(err error)) { - onFatal.Store(fn) -} - -// DefaultOnFatal enables the default behavior for OnFatal -func DefaultOnFatal() { - onFatal.Store(func(err error) { - os.Exit(1) - }) -} - -type outputs struct { - ErrorOut io.Writer - DebugOut io.Writer -} - -// MultiLine is an interface for arguments that support multi-line output. -type MultiLine interface { - // MultiLinePrinter returns a function that can be used to print the - // multi-line output. The returned function writes one line to the buffer and - // returns true if there are more lines to write. This function does not need - // to take care of trailing carriage returns, golog handles that - // automatically. - MultiLinePrinter() func(buf *bytes.Buffer) bool -} - -// ErrorReporter is a function to which the logger will report errors. -// It the given error and corresponding message along with associated ops -// context. This should return quickly as it executes on the critical code -// path. The recommended approach is to buffer as much as possible and discard -// new reports if the buffer becomes saturated. -type ErrorReporter func(err error, linePrefix string, severity Severity, ctx map[string]interface{}) - -type Logger interface { - // Debug logs to stdout - Debug(arg interface{}) - // Debugf logs to stdout - Debugf(message string, args ...interface{}) - - // Error logs to stderr - Error(arg interface{}) error - // Errorf logs to stderr. It returns the first argument that's an error, or - // a new error built using fmt.Errorf if none of the arguments are errors. - Errorf(message string, args ...interface{}) error - - // Fatal logs to stderr and then exits with status 1 - Fatal(arg interface{}) - // Fatalf logs to stderr and then exits with status 1 - Fatalf(message string, args ...interface{}) - - // Trace logs to stderr only if TRACE=true - Trace(arg interface{}) - // Tracef logs to stderr only if TRACE=true - Tracef(message string, args ...interface{}) - - // TraceOut provides access to an io.Writer to which trace information can - // be streamed. If running with environment variable "TRACE=true", TraceOut - // will point to os.Stderr, otherwise it will point to a ioutil.Discared. - // Each line of trace information will be prefixed with this Logger's - // prefix. - TraceOut() io.Writer - - // IsTraceEnabled() indicates whether or not tracing is enabled for this - // logger. - IsTraceEnabled() bool - - // AsStdLogger returns an standard logger - AsStdLogger() *log.Logger -} - -func LoggerFor(prefix string) Logger { - l := &logger{ - prefix: prefix + ": ", - pc: make([]uintptr, 10), - } - - trace := os.Getenv("TRACE") - l.traceOn, _ = strconv.ParseBool(trace) - if !l.traceOn { - prefixes := strings.Split(trace, ",") - for _, p := range prefixes { - if prefix == strings.Trim(p, " ") { - l.traceOn = true - break - } - } - } - if l.traceOn { - l.traceOut = l.newTraceWriter() - } else { - l.traceOut = ioutil.Discard - } - - printStack := os.Getenv("PRINT_STACK") - l.printStack, _ = strconv.ParseBool(printStack) - - return l -} - -type logger struct { - prefix string - traceOn bool - traceOut io.Writer - printStack bool - outs atomic.Value - pc []uintptr - funcForPc *runtime.Func -} - -// attaches the file and line number corresponding to -// the log message -func (l *logger) linePrefix(skipFrames int) string { - runtime.Callers(skipFrames, l.pc) - funcForPc := runtime.FuncForPC(l.pc[0]) - file, line := funcForPc.FileLine(l.pc[0] - 1) - return fmt.Sprintf("%s%s:%d ", l.prefix, filepath.Base(file), line) -} - -func (l *logger) print(out io.Writer, skipFrames int, severity string, arg interface{}) string { - buf := bufferPool.Get() - defer bufferPool.Put(buf) - - linePrefix := l.linePrefix(skipFrames) - writeHeader := func() { - buf.WriteString(severity) - buf.WriteString(" ") - buf.WriteString(linePrefix) - } - if arg != nil { - ml, isMultiline := arg.(MultiLine) - if !isMultiline { - writeHeader() - fmt.Fprintf(buf, "%v", arg) - printContext(buf, arg) - buf.WriteByte('\n') - } else { - mlp := ml.MultiLinePrinter() - first := true - for { - writeHeader() - more := mlp(buf) - if first { - printContext(buf, arg) - first = false - } - buf.WriteByte('\n') - if !more { - break - } - } - } - } - b := []byte(hidden.Clean(buf.String())) - _, err := out.Write(b) - if err != nil { - errorOnLogging(err) - } - if l.printStack { - l.doPrintStack() - } - - return linePrefix -} - -func (l *logger) printf(out io.Writer, skipFrames int, severity string, err error, message string, args ...interface{}) string { - buf := bufferPool.Get() - defer bufferPool.Put(buf) - - linePrefix := l.linePrefix(skipFrames) - buf.WriteString(severity) - buf.WriteString(" ") - buf.WriteString(linePrefix) - fmt.Fprintf(buf, message, args...) - printContext(buf, err) - buf.WriteByte('\n') - b := []byte(hidden.Clean(buf.String())) - _, err2 := out.Write(b) - if err2 != nil { - errorOnLogging(err) - } - if l.printStack { - l.doPrintStack() - } - return linePrefix -} - -func (l *logger) Debug(arg interface{}) { - l.print(GetOutputs().DebugOut, 4, "DEBUG", arg) -} - -func (l *logger) Debugf(message string, args ...interface{}) { - l.printf(GetOutputs().DebugOut, 4, "DEBUG", nil, message, args...) -} - -func (l *logger) Error(arg interface{}) error { - return l.errorSkipFrames(arg, 1, ERROR) -} - -func (l *logger) Errorf(message string, args ...interface{}) error { - return l.errorSkipFrames(errors.NewOffset(1, message, args...), 1, ERROR) -} - -func (l *logger) Fatal(arg interface{}) { - fatal(l.errorSkipFrames(arg, 1, FATAL)) -} - -func (l *logger) Fatalf(message string, args ...interface{}) { - fatal(l.errorSkipFrames(errors.NewOffset(1, message, args...), 1, FATAL)) -} - -func fatal(err error) { - fn := onFatal.Load().(func(err error)) - fn(err) -} - -func (l *logger) errorSkipFrames(arg interface{}, skipFrames int, severity Severity) error { - var err error - switch e := arg.(type) { - case error: - err = e - default: - err = fmt.Errorf("%v", e) - } - linePrefix := l.print(GetOutputs().ErrorOut, skipFrames+4, severity.String(), err) - return report(err, linePrefix, severity) -} - -func (l *logger) Trace(arg interface{}) { - if l.traceOn { - l.print(GetOutputs().DebugOut, 4, "TRACE", arg) - } -} - -func (l *logger) Tracef(message string, args ...interface{}) { - if l.traceOn { - l.printf(GetOutputs().DebugOut, 4, "TRACE", nil, message, args...) - } -} - -func (l *logger) TraceOut() io.Writer { - return l.traceOut -} - -func (l *logger) IsTraceEnabled() bool { - return l.traceOn -} - -func (l *logger) newTraceWriter() io.Writer { - pr, pw := io.Pipe() - br := bufio.NewReader(pr) - - if !l.traceOn { - return pw - } - go func() { - defer func() { - if err := pr.Close(); err != nil { - errorOnLogging(err) - } - }() - defer func() { - if err := pw.Close(); err != nil { - errorOnLogging(err) - } - }() - - for { - line, err := br.ReadString('\n') - if err == nil { - // Log the line (minus the trailing newline) - l.print(GetOutputs().DebugOut, 6, "TRACE", line[:len(line)-1]) - } else { - l.printf(GetOutputs().DebugOut, 6, "TRACE", nil, "TraceWriter closed due to unexpected error: %v", err) - return - } - } - }() - - return pw -} - -type errorWriter struct { - l *logger -} - -// Write implements method of io.Writer, due to different call depth, -// it will not log correct file and line prefix -func (w *errorWriter) Write(p []byte) (n int, err error) { - s := string(p) - if s[len(s)-1] == '\n' { - s = s[:len(s)-1] - } - w.l.print(GetOutputs().ErrorOut, 6, "ERROR", s) - return len(p), nil -} - -func (l *logger) AsStdLogger() *log.Logger { - return log.New(&errorWriter{l}, "", 0) -} - -func (l *logger) doPrintStack() { - var b []byte - buf := bytes.NewBuffer(b) - for _, pc := range l.pc { - funcForPc := runtime.FuncForPC(pc) - if funcForPc == nil { - break - } - name := funcForPc.Name() - if strings.HasPrefix(name, "runtime.") { - break - } - file, line := funcForPc.FileLine(pc) - fmt.Fprintf(buf, "\t%s\t%s: %d\n", name, file, line) - } - if _, err := buf.WriteTo(os.Stderr); err != nil { - errorOnLogging(err) - } -} - -func errorOnLogging(err error) { - fmt.Fprintf(os.Stderr, "Unable to log: %v\n", err) -} - -func printContext(buf *bytes.Buffer, err interface{}) { - // Note - we don't include globals when printing in order to avoid polluting the text log - values := ops.AsMap(err, false) - if len(values) == 0 { - return - } - buf.WriteString(" [") - var keys []string - for key := range values { - keys = append(keys, key) - } - sort.Strings(keys) - for i, key := range keys { - value := values[key] - if i > 0 { - buf.WriteString(" ") - } - buf.WriteString(key) - buf.WriteString("=") - fmt.Fprintf(buf, "%v", value) - } - buf.WriteByte(']') -} - -func report(err error, linePrefix string, severity Severity) error { - var reportersCopy []ErrorReporter - reportersMutex.RLock() - if len(reporters) > 0 { - reportersCopy = make([]ErrorReporter, len(reporters)) - copy(reportersCopy, reporters) - } - reportersMutex.RUnlock() - - if len(reportersCopy) > 0 { - ctx := ops.AsMap(err, true) - ctx["severity"] = severity.String() - for _, reporter := range reportersCopy { - // We include globals when reporting - reporter(err, linePrefix, severity, ctx) - } - } - return err -} diff --git a/vendor/github.com/getlantern/golog/golog_test.go b/vendor/github.com/getlantern/golog/golog_test.go deleted file mode 100644 index bce36e8..0000000 --- a/vendor/github.com/getlantern/golog/golog_test.go +++ /dev/null @@ -1,224 +0,0 @@ -package golog - -import ( - "bytes" - "io" - "io/ioutil" - "os" - "regexp" - "strings" - "sync" - "testing" - "time" - - "github.com/getlantern/errors" - "github.com/getlantern/ops" - - "github.com/stretchr/testify/assert" -) - -var ( - expectedLog = "SEVERITY myprefix: golog_test.go:999 Hello world\nSEVERITY myprefix: golog_test.go:999 Hello true [cvarA=a cvarB=b op=name root_op=name]\n" - expectedErrorLog = `ERROR myprefix: golog_test.go:999 Hello world [cvarC=c cvarD=d error=Hello %v error_location=github.com/getlantern/golog.TestError (golog_test.go:999) error_text=Hello world error_type=errors.Error op=name root_op=name] -ERROR myprefix: golog_test.go:999 at github.com/getlantern/golog.TestError (golog_test.go:999) -ERROR myprefix: golog_test.go:999 at testing.tRunner (testing.go:999) -ERROR myprefix: golog_test.go:999 at runtime.goexit (asm_amd999.s:999) -ERROR myprefix: golog_test.go:999 Caused by: world -ERROR myprefix: golog_test.go:999 at github.com/getlantern/golog.errorReturner (golog_test.go:999) -ERROR myprefix: golog_test.go:999 at github.com/getlantern/golog.TestError (golog_test.go:999) -ERROR myprefix: golog_test.go:999 at testing.tRunner (testing.go:999) -ERROR myprefix: golog_test.go:999 at runtime.goexit (asm_amd999.s:999) -ERROR myprefix: golog_test.go:999 Hello true [cvarA=a cvarB=b cvarC=c error=%v %v error_location=github.com/getlantern/golog.TestError (golog_test.go:999) error_text=Hello true error_type=errors.Error op=name999 root_op=name999] -ERROR myprefix: golog_test.go:999 at github.com/getlantern/golog.TestError (golog_test.go:999) -ERROR myprefix: golog_test.go:999 at testing.tRunner (testing.go:999) -ERROR myprefix: golog_test.go:999 at runtime.goexit (asm_amd999.s:999) -ERROR myprefix: golog_test.go:999 Caused by: Hello -ERROR myprefix: golog_test.go:999 at github.com/getlantern/golog.TestError (golog_test.go:999) -ERROR myprefix: golog_test.go:999 at testing.tRunner (testing.go:999) -ERROR myprefix: golog_test.go:999 at runtime.goexit (asm_amd999.s:999) -` - expectedTraceLog = "TRACE myprefix: golog_test.go:999 Hello world\nTRACE myprefix: golog_test.go:999 Hello true\nTRACE myprefix: golog_test.go:999 Gravy\nTRACE myprefix: golog_test.go:999 TraceWriter closed due to unexpected error: EOF\n" - expectedStdLog = expectedLog -) - -var ( - replaceNumbers = regexp.MustCompile("[0-9]+") -) - -func init() { - ops.SetGlobal("global", "shouldn't show up") -} - -func expected(severity string, log string) string { - return strings.Replace(log, "SEVERITY", severity, -1) -} - -func normalized(log string) string { - return replaceNumbers.ReplaceAllString(log, "999") -} - -func TestReport(t *testing.T) { - SetOutputs(ioutil.Discard, ioutil.Discard) - OnFatal(func(err error) { - // ignore (prevents test from exiting) - }) - - errors := 0 - fatals := 0 - RegisterReporter(func(err error, linePrefix string, severity Severity, ctx map[string]interface{}) { - switch severity { - case ERROR: - errors++ - case FATAL: - fatals++ - } - }) - l := LoggerFor("reporting") - l.Error("Some error") - l.Fatal("Fatal error") - assert.Equal(t, 1, errors) - assert.Equal(t, 1, fatals) -} - -func TestDebug(t *testing.T) { - out := newBuffer() - SetOutputs(ioutil.Discard, out) - l := LoggerFor("myprefix") - l.Debug("Hello world") - defer ops.Begin("name").Set("cvarA", "a").Set("cvarB", "b").End() - l.Debugf("Hello %v", true) - assert.Equal(t, expected("DEBUG", expectedLog), out.String()) -} - -func TestError(t *testing.T) { - out := newBuffer() - SetOutputs(out, ioutil.Discard) - l := LoggerFor("myprefix") - ctx := ops.Begin("name").Set("cvarC", "c") - err := errorReturner() - err1 := errors.New("Hello %v", err) - err2 := errors.New("Hello") - ctx.End() - l.Error(err1) - defer ops.Begin("name2").Set("cvarA", "a").Set("cvarB", "b").End() - l.Errorf("%v %v", err2, true) - t.Log(out.String()) - assert.Equal(t, expectedErrorLog, out.String()) -} - -func errorReturner() error { - defer ops.Begin("name").Set("cvarD", "d").End() - return errors.New("world") -} - -func TestTraceEnabled(t *testing.T) { - originalTrace := os.Getenv("TRACE") - err := os.Setenv("TRACE", "true") - if err != nil { - t.Fatalf("Unable to set trace to true") - } - defer func() { - if err := os.Setenv("TRACE", originalTrace); err != nil { - t.Fatalf("Unable to set TRACE environment variable: %v", err) - } - }() - - out := newBuffer() - SetOutputs(ioutil.Discard, out) - l := LoggerFor("myprefix") - l.Trace("Hello world") - l.Tracef("Hello %v", true) - tw := l.TraceOut() - if _, err := tw.Write([]byte("Gravy\n")); err != nil { - t.Fatalf("Unable to write: %v", err) - } - if err := tw.(io.Closer).Close(); err != nil { - t.Fatalf("Unable to close: %v", err) - } - - // Give trace writer a moment to catch up - time.Sleep(50 * time.Millisecond) - assert.Regexp(t, expected("TRACE", expectedTraceLog), out.String()) -} - -func TestTraceDisabled(t *testing.T) { - originalTrace := os.Getenv("TRACE") - err := os.Setenv("TRACE", "false") - if err != nil { - t.Fatalf("Unable to set trace to false") - } - defer func() { - if err := os.Setenv("TRACE", originalTrace); err != nil { - t.Fatalf("Unable to set TRACE environment variable: %v", err) - } - }() - - out := newBuffer() - SetOutputs(ioutil.Discard, out) - l := LoggerFor("myprefix") - l.Trace("Hello world") - l.Tracef("Hello %v", true) - if _, err := l.TraceOut().Write([]byte("Gravy\n")); err != nil { - t.Fatalf("Unable to write: %v", err) - } - - // Give trace writer a moment to catch up - time.Sleep(50 * time.Millisecond) - - assert.Equal(t, "", out.String(), "Nothing should have been logged") -} - -func TestAsStdLogger(t *testing.T) { - out := newBuffer() - SetOutputs(out, ioutil.Discard) - l := LoggerFor("myprefix") - stdlog := l.AsStdLogger() - stdlog.Print("Hello world") - defer ops.Begin("name").Set("cvarA", "a").Set("cvarB", "b").End() - stdlog.Printf("Hello %v", true) - assert.Equal(t, expected("ERROR", expectedStdLog), out.String()) -} - -// TODO: TraceWriter appears to have been broken since we added line numbers -// func TestTraceWriter(t *testing.T) { -// originalTrace := os.Getenv("TRACE") -// err := os.Setenv("TRACE", "true") -// if err != nil { -// t.Fatalf("Unable to set trace to true") -// } -// defer func() { -// if err := os.Setenv("TRACE", originalTrace); err != nil { -// t.Fatalf("Unable to set TRACE environment variable: %v", err) -// } -// }() -// -// out := newBuffer() -// SetOutputs(ioutil.Discard, out) -// l := LoggerFor("myprefix") -// trace := l.TraceOut() -// trace.Write([]byte("Hello world\n")) -// defer ops.Begin().Set("cvarA", "a").Set("cvarB", "b").End() -// trace.Write([]byte("Hello true\n")) -// assert.Equal(t, expected("TRACE", expectedStdLog), out.String()) -// } - -func newBuffer() *synchronizedbuffer { - return &synchronizedbuffer{orig: &bytes.Buffer{}} -} - -type synchronizedbuffer struct { - orig *bytes.Buffer - mutex sync.RWMutex -} - -func (buf *synchronizedbuffer) Write(p []byte) (int, error) { - buf.mutex.Lock() - defer buf.mutex.Unlock() - return buf.orig.Write(p) -} - -func (buf *synchronizedbuffer) String() string { - buf.mutex.RLock() - defer buf.mutex.RUnlock() - return normalized(buf.orig.String()) -} diff --git a/vendor/github.com/getlantern/hex/hex.go b/vendor/github.com/getlantern/hex/hex.go deleted file mode 100644 index d1270e9..0000000 --- a/vendor/github.com/getlantern/hex/hex.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package hex implements hexadecimal encoding and decoding. It's taken almost -// verbatim from golang/encoding/hex, however it allows using a different set -// of encoding characters than the standard 0-F. -package hex - -import ( - "errors" - "fmt" -) - -// DefaultEncoding behaves just like golang/encoding/hex. -var DefaultEncoding = NewEncoding("0123456789abcdef") - -// An Encoding that uses a specific table of encoding characters. -type Encoding struct { - hextable string -} - -// NewEncoding constructs an Encoding using the given hextable. -func NewEncoding(hextable string) *Encoding { - return &Encoding{hextable} -} - -// EncodedLen returns the length of an encoding of n source bytes. -func EncodedLen(n int) int { return n * 2 } - -// Encode encodes src into EncodedLen(len(src)) -// bytes of dst. As a convenience, it returns the number -// of bytes written to dst, but this value is always EncodedLen(len(src)). -// Encode implements hexadecimal encoding. -func (e *Encoding) Encode(dst, src []byte) int { - for i, v := range src { - dst[i*2] = e.hextable[v>>4] - dst[i*2+1] = e.hextable[v&0x0f] - } - - return len(src) * 2 -} - -// ErrLength results from decoding an odd length slice. -var ErrLength = errors.New("encoding/hex: odd length hex string") - -// InvalidByteError values describe errors resulting from an invalid byte in a hex string. -type InvalidByteError byte - -func (e InvalidByteError) Error() string { - return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e)) -} - -func DecodedLen(x int) int { return x / 2 } - -// Decode decodes src into DecodedLen(len(src)) bytes, returning the actual -// number of bytes written to dst. -// -// If Decode encounters invalid input, it returns an error describing the failure. -func (e *Encoding) Decode(dst, src []byte) (int, error) { - if len(src)%2 == 1 { - return 0, ErrLength - } - - for i := 0; i < len(src)/2; i++ { - a, ok := e.fromHexChar(src[i*2]) - if !ok { - return 0, InvalidByteError(src[i*2]) - } - b, ok := e.fromHexChar(src[i*2+1]) - if !ok { - return 0, InvalidByteError(src[i*2+1]) - } - dst[i] = (a << 4) | b - } - - return len(src) / 2, nil -} - -// fromHexChar converts a hex character into its value and a success flag. -func (e *Encoding) fromHexChar(c byte) (byte, bool) { - for i, ch := range []byte(e.hextable) { - if ch == c { - return byte(i), true - } - } - - return 0, false -} - -// EncodeToString returns the hexadecimal encoding of src. -func (e *Encoding) EncodeToString(src []byte) string { - dst := make([]byte, EncodedLen(len(src))) - e.Encode(dst, src) - return string(dst) -} - -// DecodeString returns the bytes represented by the hexadecimal string s. -func (e *Encoding) DecodeString(s string) ([]byte, error) { - src := []byte(s) - dst := make([]byte, DecodedLen(len(src))) - _, err := e.Decode(dst, src) - if err != nil { - return nil, err - } - return dst, nil -} diff --git a/vendor/github.com/getlantern/hidden/hidden.go b/vendor/github.com/getlantern/hidden/hidden.go deleted file mode 100644 index 0c52b08..0000000 --- a/vendor/github.com/getlantern/hidden/hidden.go +++ /dev/null @@ -1,66 +0,0 @@ -// Package hidden provides the ability to "hide" binary data in a string using -// a hex encoding with non-printing characters. Hidden data is demarcated with -// a leading and trailing NUL character. -package hidden - -import ( - "bytes" - "fmt" - "regexp" - - "github.com/getlantern/hex" -) - -// 16 non-printing characters -const hextable = "\x01\x02\x03\x04\x05\x06\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17" - -var ( - hexencoding = hex.NewEncoding(hextable) - - re *regexp.Regexp -) - -func init() { - var err error - re, err = regexp.Compile(fmt.Sprintf("\x00[%v]+\x00", hextable)) - if err != nil { - panic(err) - } -} - -// ToString encodes the given data as a hidden string, including leadnig and -// trailing NULs. -func ToString(data []byte) string { - buf := bytes.NewBuffer(make([]byte, 0, 2+hex.EncodedLen(len(data)))) - // Leading NUL - buf.WriteByte(0) - buf.WriteString(hexencoding.EncodeToString(data)) - // Trailing NUL - buf.WriteByte(0) - return buf.String() -} - -// FromString extracts the hidden data from a string, which is expected to -// contain leading and trailing NULs. -func FromString(str string) ([]byte, error) { - return hexencoding.DecodeString(str[1 : len(str)-1]) -} - -// Extract extracts all hidden data from an arbitrary string. -func Extract(str string) ([][]byte, error) { - m := re.FindAllString(str, -1) - result := make([][]byte, 0, len(m)) - for _, s := range m { - b, err := FromString(s) - if err != nil { - return nil, err - } - result = append(result, b) - } - return result, nil -} - -// Clean removes any hidden data from an arbitrary string. -func Clean(str string) string { - return re.ReplaceAllString(str, "") -} diff --git a/vendor/github.com/getlantern/hidden/hidden_test.go b/vendor/github.com/getlantern/hidden/hidden_test.go deleted file mode 100644 index 420ce64..0000000 --- a/vendor/github.com/getlantern/hidden/hidden_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package hidden - -import ( - "encoding/binary" - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestRoundTrip(t *testing.T) { - str := "H" - encoded := ToString([]byte(str)) - rt, err := FromString(encoded) - if assert.NoError(t, err) { - assert.Equal(t, str, string(rt)) - } -} - -func TestExtract(t *testing.T) { - a := []byte("Here is my string") - b := make([]byte, 8) - binary.BigEndian.PutUint64(b, 56) - str := fmt.Sprintf("hidden%s data%s is fun", ToString(a), ToString(b)) - t.Log(str) - out, err := Extract(str) - if assert.NoError(t, err) { - if assert.Len(t, out, 2) { - assert.Equal(t, out, [][]byte{a, b}) - } - } - assert.Equal(t, "hidden data is fun", Clean(str)) -} diff --git a/vendor/github.com/getlantern/ops/ops.go b/vendor/github.com/getlantern/ops/ops.go deleted file mode 100644 index 136302d..0000000 --- a/vendor/github.com/getlantern/ops/ops.go +++ /dev/null @@ -1,154 +0,0 @@ -// Package ops provides a facility for tracking the processing of operations, -// including contextual metadata about the operation and their final success or -// failure. An op is assumed to have succeeded if by the time of calling Exit() -// no errors have been reported. The final status can be reported to a metrics -// facility. -package ops - -import ( - "sync" - "sync/atomic" - - "github.com/getlantern/context" -) - -var ( - cm = context.NewManager() - reporters []Reporter - reportersMutex sync.RWMutex -) - -// Reporter is a function that reports the success or failure of an Op. If -// failure is nil, the Op can be considered successful. -type Reporter func(failure error, ctx map[string]interface{}) - -// Op represents an operation that's being performed. It mimics the API of -// context.Context. -type Op interface { - // Begin marks the beginning of an Op under this Op. - Begin(name string) Op - - // Go starts the given function on a new goroutine. - Go(fn func()) - - // End marks the end of this op, at which point the Op will report its success - // or failure to all registered Reporters. - End() - - // Cancel cancels this op so that even if End() is called later, it will not - // report its success or failure. - Cancel() - - // Set puts a key->value pair into the current Op's context. - Set(key string, value interface{}) Op - - // SetDynamic puts a key->value pair into the current Op's context, where the - // value is generated by a function that gets evaluated at every Read. - SetDynamic(key string, valueFN func() interface{}) Op - - // FailIf marks this Op as failed if the given err is not nil. If FailIf is - // called multiple times, the latest error will be reported as the failure. - // Returns the original error for convenient chaining. - FailIf(err error) error -} - -type op struct { - ctx context.Context - canceled bool - failure atomic.Value -} - -// RegisterReporter registers the given reporter. -func RegisterReporter(reporter Reporter) { - reportersMutex.Lock() - reporters = append(reporters, reporter) - reportersMutex.Unlock() -} - -// Begin marks the beginning of a new Op. -func Begin(name string) Op { - return &op{ctx: cm.Enter().Put("op", name).PutIfAbsent("root_op", name)} -} - -func (o *op) Begin(name string) Op { - return &op{ctx: o.ctx.Enter().Put("op", name).PutIfAbsent("root_op", name)} -} - -func (o *op) Go(fn func()) { - o.ctx.Go(fn) -} - -// Go mimics the method from context.Manager. -func Go(fn func()) { - cm.Go(fn) -} - -func (o *op) Cancel() { - o.canceled = true -} - -func (o *op) End() { - if o.canceled { - return - } - - var reportersCopy []Reporter - reportersMutex.RLock() - if len(reporters) > 0 { - reportersCopy = make([]Reporter, len(reporters)) - copy(reportersCopy, reporters) - } - reportersMutex.RUnlock() - - if len(reportersCopy) > 0 { - var failure error - _failure := o.failure.Load() - ctx := o.ctx.AsMap(_failure, true) - if _failure != nil { - failure = _failure.(error) - _, errorSet := ctx["error"] - if !errorSet { - ctx["error"] = failure.Error() - } - } - for _, reporter := range reportersCopy { - reporter(failure, ctx) - } - } - - o.ctx.Exit() -} - -func (o *op) Set(key string, value interface{}) Op { - o.ctx.Put(key, value) - return o -} - -// SetGlobal puts a key->value pair into the global context, which is inherited -// by all Ops. -func SetGlobal(key string, value interface{}) { - cm.PutGlobal(key, value) -} - -func (o *op) SetDynamic(key string, valueFN func() interface{}) Op { - o.ctx.PutDynamic(key, valueFN) - return o -} - -// SetGlobalDynamic is like SetGlobal but uses a function to derive the value -// at read time. -func SetGlobalDynamic(key string, valueFN func() interface{}) { - cm.PutGlobalDynamic(key, valueFN) -} - -// AsMap mimics the method from context.Manager. -func AsMap(obj interface{}, includeGlobals bool) context.Map { - return cm.AsMap(obj, includeGlobals) -} - -func (o *op) FailIf(err error) error { - if err != nil { - o.failure.Store(err) - } - return err -} diff --git a/vendor/github.com/getlantern/ops/ops_test.go b/vendor/github.com/getlantern/ops/ops_test.go deleted file mode 100644 index 1c16e73..0000000 --- a/vendor/github.com/getlantern/ops/ops_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package ops_test - -import ( - "sync" - "testing" - - "github.com/getlantern/errors" - "github.com/getlantern/ops" - "github.com/stretchr/testify/assert" -) - -func TestSuccess(t *testing.T) { - var reportedFailure error - var reportedCtx map[string]interface{} - report := func(failure error, ctx map[string]interface{}) { - reportedFailure = failure - reportedCtx = ctx - } - - ops.RegisterReporter(report) - ops.SetGlobal("g", "g1") - op := ops.Begin("test_success").Set("a", 1).SetDynamic("b", func() interface{} { return 2 }) - defer op.End() - innerOp := op.Begin("inside") - innerOp.FailIf(nil) - innerOp.End() - - assert.Nil(t, reportedFailure) - expectedCtx := map[string]interface{}{ - "op": "inside", - "root_op": "test_success", - "g": "g1", - "a": 1, - "b": 2, - } - assert.Equal(t, expectedCtx, reportedCtx) -} - -func TestFailure(t *testing.T) { - doTestFailure(t, false) -} - -func TestCancel(t *testing.T) { - doTestFailure(t, true) -} - -func doTestFailure(t *testing.T, cancel bool) { - var reportedFailure error - var reportedCtx map[string]interface{} - report := func(failure error, ctx map[string]interface{}) { - reportedFailure = failure - reportedCtx = ctx - } - - ops.RegisterReporter(report) - op := ops.Begin("test_failure") - var wg sync.WaitGroup - wg.Add(1) - op.Go(func() { - op.FailIf(errors.New("I failed").With("errorcontext", 5)) - wg.Done() - }) - wg.Wait() - if cancel { - op.Cancel() - } - op.End() - - if cancel { - assert.Nil(t, reportedFailure) - assert.Nil(t, reportedCtx) - } else { - assert.Contains(t, reportedFailure.Error(), "I failed") - assert.Equal(t, 5, reportedCtx["errorcontext"]) - } -} diff --git a/vendor/github.com/getlantern/systray/.gitignore b/vendor/github.com/getlantern/systray/.gitignore deleted file mode 100644 index ae7e06b..0000000 --- a/vendor/github.com/getlantern/systray/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -example/example -*~ -*.swp -*.exe -Release -Debug -*.sdf -dll/systray_unsigned.dll -out.txt -.vs -on_exit*.txt diff --git a/vendor/github.com/getlantern/systray/LICENSE b/vendor/github.com/getlantern/systray/LICENSE deleted file mode 100644 index 3ee0162..0000000 --- a/vendor/github.com/getlantern/systray/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2014 Brave New Software Project, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/getlantern/systray/README.md b/vendor/github.com/getlantern/systray/README.md deleted file mode 100644 index 626c132..0000000 --- a/vendor/github.com/getlantern/systray/README.md +++ /dev/null @@ -1,50 +0,0 @@ -Package systray is a cross platfrom Go library to place an icon and menu in the notification area. -Tested on Windows 8, Mac OSX, Ubuntu 14.10 and Debian 7.6. - -## Usage -```go -func main() { - // Should be called at the very beginning of main(). - systray.Run(onReady, onExit) -} - -func onReady() { - systray.SetIcon(icon.Data) - systray.SetTitle("Awesome App") - systray.SetTooltip("Pretty awesome超级棒") - mQuit := systray.AddMenuItem("Quit", "Quit the whole app") - - // Sets the icon of a menu item. Only available on Mac. - mQuit.SetIcon(icon.Data) -} - -func onExit() { - // clean up here -} -``` -Menu item can be checked and / or disabled. Methods except `Run()` can be invoked from any goroutine. See demo code under `example` folder. - -## Platform specific concerns - -### Linux - -```sh -sudo apt-get install libgtk-3-dev libappindicator3-dev -``` -Checked menu item not implemented on Linux yet. - -## Try - -Under `example` folder. -Place tray icon under `icon`, and use `make_icon.bat` or `make_icon.sh`, whichever suit for your os, to convert the icon to byte array. -Your icon should be .ico file under Windows, whereas .ico, .jpg and .png is supported on other platform. - -```sh -go get -go run main.go -``` - -## Credits - -- https://github.com/xilp/systray -- https://github.com/cratonica/trayhost diff --git a/vendor/github.com/getlantern/systray/systray.go b/vendor/github.com/getlantern/systray/systray.go deleted file mode 100644 index d433173..0000000 --- a/vendor/github.com/getlantern/systray/systray.go +++ /dev/null @@ -1,181 +0,0 @@ -/* -Package systray is a cross platfrom Go library to place an icon and menu in the -notification area. -Supports Windows, Mac OSX and Linux currently. -Methods can be called from any goroutine except Run(), which should be called -at the very beginning of main() to lock at main thread. -*/ -package systray - -import ( - "runtime" - "sync" - "sync/atomic" - - "github.com/getlantern/golog" -) - -var ( - hasStarted = int64(0) - hasQuit = int64(0) -) - -// MenuItem is used to keep track each menu item of systray -// Don't create it directly, use the one systray.AddMenuItem() returned -type MenuItem struct { - // ClickedCh is the channel which will be notified when the menu item is clicked - ClickedCh chan struct{} - - // id uniquely identify a menu item, not supposed to be modified - id int32 - // title is the text shown on menu item - title string - // tooltip is the text shown when pointing to menu item - tooltip string - // disabled menu item is grayed out and has no effect when clicked - disabled bool - // checked menu item has a tick before the title - checked bool -} - -var ( - log = golog.LoggerFor("systray") - - systrayReady func() - systrayExit func() - menuItems = make(map[int32]*MenuItem) - menuItemsLock sync.RWMutex - - currentID = int32(-1) -) - -// Run initializes GUI and starts the event loop, then invokes the onReady -// callback. -// It blocks until systray.Quit() is called. -// Should be called at the very beginning of main() to lock at main thread. -func Run(onReady func(), onExit func()) { - runtime.LockOSThread() - atomic.StoreInt64(&hasStarted, 1) - - if onReady == nil { - systrayReady = func() {} - } else { - // Run onReady on separate goroutine to avoid blocking event loop - readyCh := make(chan interface{}) - go func() { - <-readyCh - onReady() - }() - systrayReady = func() { - close(readyCh) - } - } - - // unlike onReady, onExit runs in the event loop to make sure it has time to - // finish before the process terminates - if onExit == nil { - onExit = func() {} - } - systrayExit = onExit - - nativeLoop() -} - -// Quit the systray -func Quit() { - if atomic.LoadInt64(&hasStarted) == 1 && atomic.CompareAndSwapInt64(&hasQuit, 0, 1) { - quit() - } -} - -// AddMenuItem adds menu item with designated title and tooltip, returning a channel -// that notifies whenever that menu item is clicked. -// -// It can be safely invoked from different goroutines. -func AddMenuItem(title string, tooltip string) *MenuItem { - id := atomic.AddInt32(¤tID, 1) - item := &MenuItem{nil, id, title, tooltip, false, false} - item.ClickedCh = make(chan struct{}) - item.update() - return item -} - -// AddSeparator adds a separator bar to the menu -func AddSeparator() { - addSeparator(atomic.AddInt32(¤tID, 1)) -} - -// SetTitle set the text to display on a menu item -func (item *MenuItem) SetTitle(title string) { - item.title = title - item.update() -} - -// SetTooltip set the tooltip to show when mouse hover -func (item *MenuItem) SetTooltip(tooltip string) { - item.tooltip = tooltip - item.update() -} - -// Disabled checkes if the menu item is disabled -func (item *MenuItem) Disabled() bool { - return item.disabled -} - -// Enable a menu item regardless if it's previously enabled or not -func (item *MenuItem) Enable() { - item.disabled = false - item.update() -} - -// Disable a menu item regardless if it's previously disabled or not -func (item *MenuItem) Disable() { - item.disabled = true - item.update() -} - -// Hide hides a menu item -func (item *MenuItem) Hide() { - hideMenuItem(item) -} - -// Show shows a previously hidden menu item -func (item *MenuItem) Show() { - showMenuItem(item) -} - -// Checked returns if the menu item has a check mark -func (item *MenuItem) Checked() bool { - return item.checked -} - -// Check a menu item regardless if it's previously checked or not -func (item *MenuItem) Check() { - item.checked = true - item.update() -} - -// Uncheck a menu item regardless if it's previously unchecked or not -func (item *MenuItem) Uncheck() { - item.checked = false - item.update() -} - -// update propogates changes on a menu item to systray -func (item *MenuItem) update() { - menuItemsLock.Lock() - defer menuItemsLock.Unlock() - menuItems[item.id] = item - addOrUpdateMenuItem(item) -} - -func systrayMenuItemSelected(id int32) { - menuItemsLock.RLock() - item := menuItems[id] - menuItemsLock.RUnlock() - select { - case item.ClickedCh <- struct{}{}: - // in case no one waiting for the channel - default: - } -} diff --git a/vendor/github.com/getlantern/systray/systray.h b/vendor/github.com/getlantern/systray/systray.h deleted file mode 100644 index 36bcf98..0000000 --- a/vendor/github.com/getlantern/systray/systray.h +++ /dev/null @@ -1,14 +0,0 @@ -extern void systray_ready(); -extern void systray_on_exit(); -extern void systray_menu_item_selected(int menu_id); -int nativeLoop(void); - -void setIcon(const char* iconBytes, int length); -void setMenuItemIcon(const char* iconBytes, int length, int menuId); -void setTitle(char* title); -void setTooltip(char* tooltip); -void add_or_update_menu_item(int menuId, char* title, char* tooltip, short disabled, short checked); -void add_separator(int menuId); -void hide_menu_item(int menuId); -void show_menu_item(int menuId); -void quit(); diff --git a/vendor/github.com/getlantern/systray/systray_darwin.m b/vendor/github.com/getlantern/systray/systray_darwin.m deleted file mode 100644 index 91cc0de..0000000 --- a/vendor/github.com/getlantern/systray/systray_darwin.m +++ /dev/null @@ -1,249 +0,0 @@ -#import <Cocoa/Cocoa.h> -#include "systray.h" - -#ifndef NSControlStateValueOff - #define NSControlStateValueOff NSOffState -#endif - -#ifndef NSControlStateValueOn - #define NSControlStateValueOn NSOnState -#endif - -@interface MenuItem : NSObject -{ - @public - NSNumber* menuId; - NSString* title; - NSString* tooltip; - short disabled; - short checked; -} --(id) initWithId: (int)theMenuId - withTitle: (const char*)theTitle - withTooltip: (const char*)theTooltip - withDisabled: (short)theDisabled - withChecked: (short)theChecked; - @end - @implementation MenuItem - -(id) initWithId: (int)theMenuId - withTitle: (const char*)theTitle - withTooltip: (const char*)theTooltip - withDisabled: (short)theDisabled - withChecked: (short)theChecked -{ - menuId = [NSNumber numberWithInt:theMenuId]; - title = [[NSString alloc] initWithCString:theTitle - encoding:NSUTF8StringEncoding]; - tooltip = [[NSString alloc] initWithCString:theTooltip - encoding:NSUTF8StringEncoding]; - disabled = theDisabled; - checked = theChecked; - return self; -} -@end - -@interface AppDelegate: NSObject <NSApplicationDelegate> - - (void) add_or_update_menu_item:(MenuItem*) item; - - (IBAction)menuHandler:(id)sender; - @property (assign) IBOutlet NSWindow *window; - @end - - @implementation AppDelegate -{ - NSStatusItem *statusItem; - NSMenu *menu; - NSCondition* cond; -} - -@synthesize window = _window; - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification -{ - self->statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; - self->menu = [[NSMenu alloc] init]; - [self->menu setAutoenablesItems: FALSE]; - [self->statusItem setMenu:self->menu]; - systray_ready(); -} - -- (void)applicationWillTerminate:(NSNotification *)aNotification -{ - systray_on_exit(); -} - -- (void)setIcon:(NSImage *)image { - statusItem.button.image = image; - [self updateTitleButtonStyle]; -} - -- (void)setTitle:(NSString *)title { - statusItem.button.title = title; - [self updateTitleButtonStyle]; -} - --(void)updateTitleButtonStyle { - if (statusItem.button.image != nil) { - if ([statusItem.button.title length] == 0) { - statusItem.button.imagePosition = NSImageOnly; - } else { - statusItem.button.imagePosition = NSImageLeft; - } - } else { - statusItem.button.imagePosition = NSNoImage; - } -} - - -- (void)setTooltip:(NSString *)tooltip { - statusItem.button.toolTip = tooltip; -} - -- (IBAction)menuHandler:(id)sender -{ - NSNumber* menuId = [sender representedObject]; - systray_menu_item_selected(menuId.intValue); -} - -- (void) add_or_update_menu_item:(MenuItem*) item -{ - NSMenuItem* menuItem; - int existedMenuIndex = [menu indexOfItemWithRepresentedObject: item->menuId]; - if (existedMenuIndex == -1) { - menuItem = [menu addItemWithTitle:item->title action:@selector(menuHandler:) keyEquivalent:@""]; - [menuItem setTarget:self]; - [menuItem setRepresentedObject: item->menuId]; - - } - else { - menuItem = [menu itemAtIndex: existedMenuIndex]; - [menuItem setTitle:item->title]; - } - [menuItem setToolTip:item->tooltip]; - if (item->disabled == 1) { - menuItem.enabled = FALSE; - } else { - menuItem.enabled = TRUE; - } - if (item->checked == 1) { - menuItem.state = NSControlStateValueOn; - } else { - menuItem.state = NSControlStateValueOff; - } -} - -- (void) add_separator:(NSNumber*) menuId -{ - [menu addItem: [NSMenuItem separatorItem]]; -} - -- (void) hide_menu_item:(NSNumber*) menuId -{ - NSMenuItem* menuItem; - int existedMenuIndex = [menu indexOfItemWithRepresentedObject: menuId]; - if (existedMenuIndex == -1) { - return; - } - menuItem = [menu itemAtIndex: existedMenuIndex]; - [menuItem setHidden:TRUE]; -} - -- (void)setMenuItemIcon:(NSArray*)imageAndMenuId { - NSImage* image = [imageAndMenuId objectAtIndex:0]; - NSNumber* menuId = [imageAndMenuId objectAtIndex:1]; - - NSMenuItem* menuItem; - int existedMenuIndex = [menu indexOfItemWithRepresentedObject: menuId]; - if (existedMenuIndex == -1) { - return; - } - menuItem = [menu itemAtIndex: existedMenuIndex]; - menuItem.image = image; -} - -- (void) show_menu_item:(NSNumber*) menuId -{ - NSMenuItem* menuItem; - int existedMenuIndex = [menu indexOfItemWithRepresentedObject: menuId]; - if (existedMenuIndex == -1) { - return; - } - menuItem = [menu itemAtIndex: existedMenuIndex]; - [menuItem setHidden:FALSE]; -} - -- (void) quit -{ - [NSApp terminate:self]; -} - -@end - -int nativeLoop(void) { - AppDelegate *delegate = [[AppDelegate alloc] init]; - [[NSApplication sharedApplication] setDelegate:delegate]; - [NSApp run]; - return EXIT_SUCCESS; -} - -void runInMainThread(SEL method, id object) { - [(AppDelegate*)[NSApp delegate] - performSelectorOnMainThread:method - withObject:object - waitUntilDone: YES]; -} - -void setIcon(const char* iconBytes, int length) { - NSData* buffer = [NSData dataWithBytes: iconBytes length:length]; - NSImage *image = [[NSImage alloc] initWithData:buffer]; - [image setSize:NSMakeSize(18, 18)]; - runInMainThread(@selector(setIcon:), (id)image); -} - -void setMenuItemIcon(const char* iconBytes, int length, int menuId) { - NSData* buffer = [NSData dataWithBytes: iconBytes length:length]; - NSImage *image = [[NSImage alloc] initWithData:buffer]; - [image setSize:NSMakeSize(18, 18)]; - - NSNumber *mId = [NSNumber numberWithInt:menuId]; - runInMainThread(@selector(setMenuItemIcon:), @[image, (id)mId]); -} - -void setTitle(char* ctitle) { - NSString* title = [[NSString alloc] initWithCString:ctitle - encoding:NSUTF8StringEncoding]; - free(ctitle); - runInMainThread(@selector(setTitle:), (id)title); -} - -void setTooltip(char* ctooltip) { - NSString* tooltip = [[NSString alloc] initWithCString:ctooltip - encoding:NSUTF8StringEncoding]; - free(ctooltip); - runInMainThread(@selector(setTooltip:), (id)tooltip); -} - -void add_or_update_menu_item(int menuId, char* title, char* tooltip, short disabled, short checked) { - MenuItem* item = [[MenuItem alloc] initWithId: menuId withTitle: title withTooltip: tooltip withDisabled: disabled withChecked: checked]; - free(title); - free(tooltip); - runInMainThread(@selector(add_or_update_menu_item:), (id)item); -} - -void add_separator(int menuId) { - NSNumber *mId = [NSNumber numberWithInt:menuId]; - runInMainThread(@selector(add_separator:), (id)mId); -} - -void hide_menu_item(int menuId) { - NSNumber *mId = [NSNumber numberWithInt:menuId]; - runInMainThread(@selector(hide_menu_item:), (id)mId); -} - -void show_menu_item(int menuId) { - NSNumber *mId = [NSNumber numberWithInt:menuId]; - runInMainThread(@selector(show_menu_item:), (id)mId); -} - -void quit() { - runInMainThread(@selector(quit), nil); -} diff --git a/vendor/github.com/getlantern/systray/systray_linux.c b/vendor/github.com/getlantern/systray/systray_linux.c deleted file mode 100644 index 72cd614..0000000 --- a/vendor/github.com/getlantern/systray/systray_linux.c +++ /dev/null @@ -1,217 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <limits.h> -#include <libappindicator/app-indicator.h> -#include "systray.h" - -static AppIndicator *global_app_indicator; -static GtkWidget *global_tray_menu = NULL; -static GList *global_menu_items = NULL; -static char temp_file_name[PATH_MAX] = ""; - -typedef struct { - GtkWidget *menu_item; - int menu_id; -} MenuItemNode; - -typedef struct { - int menu_id; - char* title; - char* tooltip; - short disabled; - short checked; -} MenuItemInfo; - -int nativeLoop(void) { - gtk_init(0, NULL); - global_app_indicator = app_indicator_new("systray", "", - APP_INDICATOR_CATEGORY_APPLICATION_STATUS); - app_indicator_set_status(global_app_indicator, APP_INDICATOR_STATUS_ACTIVE); - global_tray_menu = gtk_menu_new(); - app_indicator_set_menu(global_app_indicator, GTK_MENU(global_tray_menu)); - systray_ready(); - gtk_main(); - systray_on_exit(); - return 0; -} - -void _unlink_temp_file() { - if (strlen(temp_file_name) != 0) { - int ret = unlink(temp_file_name); - if (ret == -1) { - printf("failed to remove temp icon file %s: %s\n", temp_file_name, strerror(errno)); - } - temp_file_name[0] = '\0'; - } -} - -// runs in main thread, should always return FALSE to prevent gtk to execute it again -gboolean do_set_icon(gpointer data) { - _unlink_temp_file(); - char *tmpdir = getenv("TMPDIR"); - if (NULL == tmpdir) { - tmpdir = "/tmp"; - } - strncpy(temp_file_name, tmpdir, PATH_MAX-1); - strncat(temp_file_name, "/systray_XXXXXX", PATH_MAX-1); - temp_file_name[PATH_MAX-1] = '\0'; - - GBytes* bytes = (GBytes*)data; - int fd = mkstemp(temp_file_name); - if (fd == -1) { - printf("failed to create temp icon file %s: %s\n", temp_file_name, strerror(errno)); - return FALSE; - } - gsize size = 0; - gconstpointer icon_data = g_bytes_get_data(bytes, &size); - ssize_t written = write(fd, icon_data, size); - close(fd); - if(written != size) { - printf("failed to write temp icon file %s: %s\n", temp_file_name, strerror(errno)); - return FALSE; - } - app_indicator_set_icon_full(global_app_indicator, temp_file_name, ""); - app_indicator_set_attention_icon_full(global_app_indicator, temp_file_name, ""); - g_bytes_unref(bytes); - return FALSE; -} - -void _systray_menu_item_selected(int *id) { - systray_menu_item_selected(*id); -} - -// runs in main thread, should always return FALSE to prevent gtk to execute it again -gboolean do_add_or_update_menu_item(gpointer data) { - MenuItemInfo *mii = (MenuItemInfo*)data; - GList* it; - for(it = global_menu_items; it != NULL; it = it->next) { - MenuItemNode* item = (MenuItemNode*)(it->data); - if(item->menu_id == mii->menu_id){ - gtk_menu_item_set_label(GTK_MENU_ITEM(item->menu_item), mii->title); - break; - } - } - - // menu id doesn't exist, add new item - if(it == NULL) { - GtkWidget *menu_item = gtk_menu_item_new_with_label(mii->title); - int *id = malloc(sizeof(int)); - *id = mii->menu_id; - g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(_systray_menu_item_selected), id); - gtk_menu_shell_append(GTK_MENU_SHELL(global_tray_menu), menu_item); - - MenuItemNode* new_item = malloc(sizeof(MenuItemNode)); - new_item->menu_id = mii->menu_id; - new_item->menu_item = menu_item; - GList* new_node = malloc(sizeof(GList)); - new_node->data = new_item; - new_node->next = global_menu_items; - if(global_menu_items != NULL) { - global_menu_items->prev = new_node; - } - global_menu_items = new_node; - it = new_node; - } - GtkWidget * menu_item = GTK_WIDGET(((MenuItemNode*)(it->data))->menu_item); - gtk_widget_set_sensitive(menu_item, mii->disabled == 1 ? FALSE : TRUE); - gtk_widget_show(menu_item); - - free(mii->title); - free(mii->tooltip); - free(mii); - return FALSE; -} - -gboolean do_add_separator(gpointer data) { - GtkWidget *separator = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(global_tray_menu), separator); - gtk_widget_show(separator); - return FALSE; -} - -// runs in main thread, should always return FALSE to prevent gtk to execute it again -gboolean do_hide_menu_item(gpointer data) { - MenuItemInfo *mii = (MenuItemInfo*)data; - GList* it; - for(it = global_menu_items; it != NULL; it = it->next) { - MenuItemNode* item = (MenuItemNode*)(it->data); - if(item->menu_id == mii->menu_id){ - gtk_widget_hide(GTK_WIDGET(item->menu_item)); - break; - } - } - return FALSE; -} - -// runs in main thread, should always return FALSE to prevent gtk to execute it again -gboolean do_show_menu_item(gpointer data) { - MenuItemInfo *mii = (MenuItemInfo*)data; - GList* it; - for(it = global_menu_items; it != NULL; it = it->next) { - MenuItemNode* item = (MenuItemNode*)(it->data); - if(item->menu_id == mii->menu_id){ - gtk_widget_show(GTK_WIDGET(item->menu_item)); - break; - } - } - return FALSE; -} - -// runs in main thread, should always return FALSE to prevent gtk to execute it again -gboolean do_quit(gpointer data) { - _unlink_temp_file(); - // app indicator doesn't provide a way to remove it, hide it as a workaround - app_indicator_set_status(global_app_indicator, APP_INDICATOR_STATUS_PASSIVE); - gtk_main_quit(); - return FALSE; -} - -void setIcon(const char* iconBytes, int length) { - GBytes* bytes = g_bytes_new_static(iconBytes, length); - g_idle_add(do_set_icon, bytes); -} - -void setTitle(char* ctitle) { - app_indicator_set_label(global_app_indicator, ctitle, ""); - free(ctitle); -} - -void setTooltip(char* ctooltip) { - free(ctooltip); -} - -void setMenuItemIcon(const char* iconBytes, int length, int menuId) { -} - -void add_or_update_menu_item(int menu_id, char* title, char* tooltip, short disabled, short checked) { - MenuItemInfo *mii = malloc(sizeof(MenuItemInfo)); - mii->menu_id = menu_id; - mii->title = title; - mii->tooltip = tooltip; - mii->disabled = disabled; - mii->checked = checked; - g_idle_add(do_add_or_update_menu_item, mii); -} - -void add_separator(int menu_id) { - MenuItemInfo *mii = malloc(sizeof(MenuItemInfo)); - mii->menu_id = menu_id; - g_idle_add(do_add_separator, mii); -} - -void hide_menu_item(int menu_id) { - MenuItemInfo *mii = malloc(sizeof(MenuItemInfo)); - mii->menu_id = menu_id; - g_idle_add(do_hide_menu_item, mii); -} - -void show_menu_item(int menu_id) { - MenuItemInfo *mii = malloc(sizeof(MenuItemInfo)); - mii->menu_id = menu_id; - g_idle_add(do_show_menu_item, mii); -} - -void quit() { - g_idle_add(do_quit, NULL); -} diff --git a/vendor/github.com/getlantern/systray/systray_nonwindows.go b/vendor/github.com/getlantern/systray/systray_nonwindows.go deleted file mode 100644 index 4868b55..0000000 --- a/vendor/github.com/getlantern/systray/systray_nonwindows.go +++ /dev/null @@ -1,99 +0,0 @@ -// +build !windows - -package systray - -/* -#cgo linux pkg-config: gtk+-3.0 appindicator3-0.1 -#cgo darwin CFLAGS: -DDARWIN -x objective-c -fobjc-arc -#cgo darwin LDFLAGS: -framework Cocoa - -#include "systray.h" -*/ -import "C" - -import ( - "unsafe" -) - -func nativeLoop() { - C.nativeLoop() -} - -func quit() { - C.quit() -} - -// SetIcon sets the systray icon. -// iconBytes should be the content of .ico for windows and .ico/.jpg/.png -// for other platforms. -func SetIcon(iconBytes []byte) { - cstr := (*C.char)(unsafe.Pointer(&iconBytes[0])) - C.setIcon(cstr, (C.int)(len(iconBytes))) -} - -// SetTitle sets the systray title, only available on Mac. -func SetTitle(title string) { - C.setTitle(C.CString(title)) -} - -// SetTooltip sets the systray tooltip to display on mouse hover of the tray icon, -// only available on Mac and Windows. -func SetTooltip(tooltip string) { - C.setTooltip(C.CString(tooltip)) -} - -func addOrUpdateMenuItem(item *MenuItem) { - var disabled C.short - if item.disabled { - disabled = 1 - } - var checked C.short - if item.checked { - checked = 1 - } - C.add_or_update_menu_item( - C.int(item.id), - C.CString(item.title), - C.CString(item.tooltip), - disabled, - checked, - ) -} - -// SetIcon sets the icon of a menu item. Only available on Mac. -// iconBytes should be the content of .ico/.jpg/.png -func (item *MenuItem) SetIcon(iconBytes []byte) { - cstr := (*C.char)(unsafe.Pointer(&iconBytes[0])) - C.setMenuItemIcon(cstr, (C.int)(len(iconBytes)), C.int(item.id)) -} - -func addSeparator(id int32) { - C.add_separator(C.int(id)) -} - -func hideMenuItem(item *MenuItem) { - C.hide_menu_item( - C.int(item.id), - ) -} - -func showMenuItem(item *MenuItem) { - C.show_menu_item( - C.int(item.id), - ) -} - -//export systray_ready -func systray_ready() { - systrayReady() -} - -//export systray_on_exit -func systray_on_exit() { - systrayExit() -} - -//export systray_menu_item_selected -func systray_menu_item_selected(cID C.int) { - systrayMenuItemSelected(int32(cID)) -} diff --git a/vendor/github.com/getlantern/systray/systray_windows.go b/vendor/github.com/getlantern/systray/systray_windows.go deleted file mode 100644 index ae9c838..0000000 --- a/vendor/github.com/getlantern/systray/systray_windows.go +++ /dev/null @@ -1,721 +0,0 @@ -// +build windows - -package systray - -import ( - "crypto/md5" - "encoding/hex" - "io/ioutil" - "os" - "path/filepath" - "sort" - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -// Helpful sources: https://github.com/golang/exp/blob/master/shiny/driver/internal/win32 - -var ( - k32 = windows.NewLazySystemDLL("Kernel32.dll") - s32 = windows.NewLazySystemDLL("Shell32.dll") - u32 = windows.NewLazySystemDLL("User32.dll") - pGetModuleHandle = k32.NewProc("GetModuleHandleW") - pShellNotifyIcon = s32.NewProc("Shell_NotifyIconW") - pCreatePopupMenu = u32.NewProc("CreatePopupMenu") - pCreateWindowEx = u32.NewProc("CreateWindowExW") - pDefWindowProc = u32.NewProc("DefWindowProcW") - pDeleteMenu = u32.NewProc("DeleteMenu") - pDestroyWindow = u32.NewProc("DestroyWindow") - pDispatchMessage = u32.NewProc("DispatchMessageW") - pGetCursorPos = u32.NewProc("GetCursorPos") - pGetMenuItemID = u32.NewProc("GetMenuItemID") - pGetMessage = u32.NewProc("GetMessageW") - pInsertMenuItem = u32.NewProc("InsertMenuItemW") - pLoadIcon = u32.NewProc("LoadIconW") - pLoadImage = u32.NewProc("LoadImageW") - pLoadCursor = u32.NewProc("LoadCursorW") - pPostMessage = u32.NewProc("PostMessageW") - pPostQuitMessage = u32.NewProc("PostQuitMessage") - pRegisterClass = u32.NewProc("RegisterClassExW") - pRegisterWindowMessage = u32.NewProc("RegisterWindowMessageW") - pSetForegroundWindow = u32.NewProc("SetForegroundWindow") - pSetMenuInfo = u32.NewProc("SetMenuInfo") - pSetMenuItemInfo = u32.NewProc("SetMenuItemInfoW") - pShowWindow = u32.NewProc("ShowWindow") - pTrackPopupMenu = u32.NewProc("TrackPopupMenu") - pTranslateMessage = u32.NewProc("TranslateMessage") - pUnregisterClass = u32.NewProc("UnregisterClassW") - pUpdateWindow = u32.NewProc("UpdateWindow") -) - -// Contains window class information. -// It is used with the RegisterClassEx and GetClassInfoEx functions. -// https://msdn.microsoft.com/en-us/library/ms633577.aspx -type wndClassEx struct { - Size, Style uint32 - WndProc uintptr - ClsExtra, WndExtra int32 - Instance, Icon, Cursor, Background windows.Handle - MenuName, ClassName *uint16 - IconSm windows.Handle -} - -// Registers a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function. -// https://msdn.microsoft.com/en-us/library/ms633587.aspx -func (w *wndClassEx) register() error { - w.Size = uint32(unsafe.Sizeof(*w)) - res, _, err := pRegisterClass.Call(uintptr(unsafe.Pointer(w))) - if res == 0 { - return err - } - return nil -} - -// Unregisters a window class, freeing the memory required for the class. -// https://msdn.microsoft.com/en-us/library/ms644899.aspx -func (w *wndClassEx) unregister() error { - res, _, err := pUnregisterClass.Call( - uintptr(unsafe.Pointer(w.ClassName)), - uintptr(w.Instance), - ) - if res == 0 { - return err - } - return nil -} - -// Contains information that the system needs to display notifications in the notification area. -// Used by Shell_NotifyIcon. -// https://msdn.microsoft.com/en-us/library/windows/desktop/bb773352(v=vs.85).aspx -// https://msdn.microsoft.com/en-us/library/windows/desktop/bb762159 -type notifyIconData struct { - Size uint32 - Wnd windows.Handle - ID, Flags, CallbackMessage uint32 - Icon windows.Handle - Tip [128]uint16 - State, StateMask uint32 - Info [256]uint16 - Timeout, Version uint32 - InfoTitle [64]uint16 - InfoFlags uint32 - GuidItem windows.GUID - BalloonIcon windows.Handle -} - -func (nid *notifyIconData) add() error { - const NIM_ADD = 0x00000000 - res, _, err := pShellNotifyIcon.Call( - uintptr(NIM_ADD), - uintptr(unsafe.Pointer(nid)), - ) - if res == 0 { - return err - } - return nil -} - -func (nid *notifyIconData) modify() error { - const NIM_MODIFY = 0x00000001 - res, _, err := pShellNotifyIcon.Call( - uintptr(NIM_MODIFY), - uintptr(unsafe.Pointer(nid)), - ) - if res == 0 { - return err - } - return nil -} - -func (nid *notifyIconData) delete() error { - const NIM_DELETE = 0x00000002 - res, _, err := pShellNotifyIcon.Call( - uintptr(NIM_DELETE), - uintptr(unsafe.Pointer(nid)), - ) - if res == 0 { - return err - } - return nil -} - -// Contains information about a menu item. -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647578(v=vs.85).aspx -type menuItemInfo struct { - Size, Mask, Type, State uint32 - ID uint32 - SubMenu, Checked, Unchecked windows.Handle - ItemData uintptr - TypeData *uint16 - Cch uint32 - Item windows.Handle -} - -// The POINT structure defines the x- and y- coordinates of a point. -// https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx -type point struct { - X, Y int32 -} - -// Contains information about loaded resources -type winTray struct { - instance, - icon, - cursor, - window, - menu windows.Handle - - loadedImages map[string]windows.Handle - nid *notifyIconData - wcex *wndClassEx - - wmSystrayMessage, - wmTaskbarCreated uint32 - - visibleItems []uint32 -} - -// Loads an image from file and shows it in tray. -// LoadImage: https://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx -// Shell_NotifyIcon: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762159(v=vs.85).aspx -func (t *winTray) setIcon(src string) error { - const IMAGE_ICON = 1 // Loads an icon - const LR_LOADFROMFILE = 0x00000010 // Loads the stand-alone image from the file - const NIF_ICON = 0x00000002 - - // Save and reuse handles of loaded images - h, ok := t.loadedImages[src] - if !ok { - srcPtr, err := windows.UTF16PtrFromString(src) - if err != nil { - return err - } - res, _, err := pLoadImage.Call( - 0, - uintptr(unsafe.Pointer(srcPtr)), - IMAGE_ICON, - 64, - 64, - LR_LOADFROMFILE, - ) - if res == 0 { - return err - } - h = windows.Handle(res) - t.loadedImages[src] = h - } - - t.nid.Icon = h - t.nid.Flags |= NIF_ICON - t.nid.Size = uint32(unsafe.Sizeof(*t.nid)) - - return t.nid.modify() -} - -// Sets tooltip on icon. -// Shell_NotifyIcon: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762159(v=vs.85).aspx -func (t *winTray) setTooltip(src string) error { - const NIF_TIP = 0x00000004 - b, err := windows.UTF16FromString(src) - if err != nil { - return err - } - copy(t.nid.Tip[:], b[:]) - t.nid.Flags |= NIF_TIP - t.nid.Size = uint32(unsafe.Sizeof(*t.nid)) - - return t.nid.modify() -} - -var wt winTray - -// WindowProc callback function that processes messages sent to a window. -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx -func (t *winTray) wndProc(hWnd windows.Handle, message uint32, wParam, lParam uintptr) (lResult uintptr) { - const ( - WM_COMMAND = 0x0111 - WM_DESTROY = 0x0002 - WM_ENDSESSION = 0x16 - WM_RBUTTONUP = 0x0205 - WM_LBUTTONUP = 0x0202 - ) - switch message { - case WM_COMMAND: - menuId := int32(wParam) - if menuId != -1 { - systrayMenuItemSelected(menuId) - } - case WM_DESTROY: - // same as WM_ENDSESSION, but throws 0 exit code after all - defer pPostQuitMessage.Call(uintptr(int32(0))) - fallthrough - case WM_ENDSESSION: - if t.nid != nil { - t.nid.delete() - } - systrayExit() - case t.wmSystrayMessage: - switch lParam { - case WM_RBUTTONUP, WM_LBUTTONUP: - t.showMenu() - } - case t.wmTaskbarCreated: // on explorer.exe restarts - t.nid.add() - default: - // Calls the default window procedure to provide default processing for any window messages that an application does not process. - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms633572(v=vs.85).aspx - lResult, _, _ = pDefWindowProc.Call( - uintptr(hWnd), - uintptr(message), - uintptr(wParam), - uintptr(lParam), - ) - } - return -} - -func (t *winTray) initInstance() error { - const IDI_APPLICATION = 32512 - const IDC_ARROW = 32512 // Standard arrow - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx - const SW_HIDE = 0 - const CW_USEDEFAULT = 0x80000000 - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx - const ( - WS_CAPTION = 0x00C00000 - WS_MAXIMIZEBOX = 0x00010000 - WS_MINIMIZEBOX = 0x00020000 - WS_OVERLAPPED = 0x00000000 - WS_SYSMENU = 0x00080000 - WS_THICKFRAME = 0x00040000 - - WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX - ) - // https://msdn.microsoft.com/en-us/library/windows/desktop/ff729176 - const ( - CS_HREDRAW = 0x0002 - CS_VREDRAW = 0x0001 - ) - const NIF_MESSAGE = 0x00000001 - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644931(v=vs.85).aspx - const WM_USER = 0x0400 - - const ( - className = "SystrayClass" - windowName = "" - ) - - t.wmSystrayMessage = WM_USER + 1 - - taskbarEventNamePtr, _ := windows.UTF16PtrFromString("TaskbarCreated") - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644947 - res, _, err := pRegisterWindowMessage.Call( - uintptr(unsafe.Pointer(taskbarEventNamePtr)), - ) - t.wmTaskbarCreated = uint32(res) - - t.loadedImages = make(map[string]windows.Handle) - - instanceHandle, _, err := pGetModuleHandle.Call(0) - if instanceHandle == 0 { - return err - } - t.instance = windows.Handle(instanceHandle) - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms648072(v=vs.85).aspx - iconHandle, _, err := pLoadIcon.Call(0, uintptr(IDI_APPLICATION)) - if iconHandle == 0 { - return err - } - t.icon = windows.Handle(iconHandle) - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms648391(v=vs.85).aspx - cursorHandle, _, err := pLoadCursor.Call(0, uintptr(IDC_ARROW)) - if cursorHandle == 0 { - return err - } - t.cursor = windows.Handle(cursorHandle) - - classNamePtr, err := windows.UTF16PtrFromString(className) - if err != nil { - return err - } - - windowNamePtr, err := windows.UTF16PtrFromString(windowName) - if err != nil { - return err - } - - t.wcex = &wndClassEx{ - Style: CS_HREDRAW | CS_VREDRAW, - WndProc: windows.NewCallback(t.wndProc), - Instance: t.instance, - Icon: t.icon, - Cursor: t.cursor, - Background: windows.Handle(6), // (COLOR_WINDOW + 1) - ClassName: classNamePtr, - IconSm: t.icon, - } - if err := t.wcex.register(); err != nil { - return err - } - - windowHandle, _, err := pCreateWindowEx.Call( - uintptr(0), - uintptr(unsafe.Pointer(classNamePtr)), - uintptr(unsafe.Pointer(windowNamePtr)), - uintptr(WS_OVERLAPPEDWINDOW), - uintptr(CW_USEDEFAULT), - uintptr(CW_USEDEFAULT), - uintptr(CW_USEDEFAULT), - uintptr(CW_USEDEFAULT), - uintptr(0), - uintptr(0), - uintptr(t.instance), - uintptr(0), - ) - if windowHandle == 0 { - return err - } - t.window = windows.Handle(windowHandle) - - pShowWindow.Call( - uintptr(t.window), - uintptr(SW_HIDE), - ) - - pUpdateWindow.Call( - uintptr(t.window), - ) - - t.nid = ¬ifyIconData{ - Wnd: windows.Handle(t.window), - ID: 100, - Flags: NIF_MESSAGE, - CallbackMessage: t.wmSystrayMessage, - } - t.nid.Size = uint32(unsafe.Sizeof(*t.nid)) - - return t.nid.add() -} - -func (t *winTray) createMenu() error { - const MIM_APPLYTOSUBMENUS = 0x80000000 // Settings apply to the menu and all of its submenus - - menuHandle, _, err := pCreatePopupMenu.Call() - if menuHandle == 0 { - return err - } - t.menu = windows.Handle(menuHandle) - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647575(v=vs.85).aspx - mi := struct { - Size, Mask, Style, Max uint32 - Background windows.Handle - ContextHelpID uint32 - MenuData uintptr - }{ - Mask: MIM_APPLYTOSUBMENUS, - } - mi.Size = uint32(unsafe.Sizeof(mi)) - - res, _, err := pSetMenuInfo.Call( - uintptr(t.menu), - uintptr(unsafe.Pointer(&mi)), - ) - if res == 0 { - return err - } - return nil -} - -func (t *winTray) addOrUpdateMenuItem(menuId int32, title string, disabled, checked bool) error { - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647578(v=vs.85).aspx - const ( - MIIM_FTYPE = 0x00000100 - MIIM_STRING = 0x00000040 - MIIM_ID = 0x00000002 - MIIM_STATE = 0x00000001 - ) - const MFT_STRING = 0x00000000 - const ( - MFS_CHECKED = 0x00000008 - MFS_DISABLED = 0x00000003 - ) - titlePtr, err := windows.UTF16PtrFromString(title) - if err != nil { - return err - } - - mi := menuItemInfo{ - Mask: MIIM_FTYPE | MIIM_STRING | MIIM_ID | MIIM_STATE, - Type: MFT_STRING, - ID: uint32(menuId), - TypeData: titlePtr, - Cch: uint32(len(title)), - } - if disabled { - mi.State |= MFS_DISABLED - } - if checked { - mi.State |= MFS_CHECKED - } - mi.Size = uint32(unsafe.Sizeof(mi)) - - // We set the menu item info based on the menuID - res, _, err := pSetMenuItemInfo.Call( - uintptr(t.menu), - uintptr(menuId), - 0, - uintptr(unsafe.Pointer(&mi)), - ) - - if res == 0 { - t.addToVisibleItems(menuId) - position := t.getVisibleItemIndex(menuId) - res, _, err = pInsertMenuItem.Call( - uintptr(t.menu), - uintptr(position), - 1, - uintptr(unsafe.Pointer(&mi)), - ) - if res == 0 { - t.delFromVisibleItems(menuId) - return err - } - } - - return nil -} - -func (t *winTray) addSeparatorMenuItem(menuId int32) error { - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647578(v=vs.85).aspx - const ( - MIIM_FTYPE = 0x00000100 - MIIM_ID = 0x00000002 - MIIM_STATE = 0x00000001 - ) - const MFT_SEPARATOR = 0x00000800 - - mi := menuItemInfo{ - Mask: MIIM_FTYPE | MIIM_ID | MIIM_STATE, - Type: MFT_SEPARATOR, - ID: uint32(menuId), - } - - mi.Size = uint32(unsafe.Sizeof(mi)) - - t.addToVisibleItems(menuId) - position := t.getVisibleItemIndex(menuId) - - res, _, err := pInsertMenuItem.Call( - uintptr(t.menu), - uintptr(position), - 1, - uintptr(unsafe.Pointer(&mi)), - ) - if res == 0 { - return err - } - - return nil -} - -func (t *winTray) hideMenuItem(menuId int32) error { - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647629(v=vs.85).aspx - const MF_BYCOMMAND = 0x00000000 - const ERROR_SUCCESS syscall.Errno = 0 - - res, _, err := pDeleteMenu.Call( - uintptr(t.menu), - uintptr(uint32(menuId)), - MF_BYCOMMAND, - ) - if res == 0 && err.(syscall.Errno) != ERROR_SUCCESS { - return err - } - t.delFromVisibleItems(menuId) - - return nil -} - -func (t *winTray) showMenu() error { - const ( - TPM_BOTTOMALIGN = 0x0020 - TPM_LEFTALIGN = 0x0000 - ) - p := point{} - res, _, err := pGetCursorPos.Call(uintptr(unsafe.Pointer(&p))) - if res == 0 { - return err - } - pSetForegroundWindow.Call(uintptr(t.window)) - - res, _, err = pTrackPopupMenu.Call( - uintptr(t.menu), - TPM_BOTTOMALIGN|TPM_LEFTALIGN, - uintptr(p.X), - uintptr(p.Y), - 0, - uintptr(t.window), - 0, - ) - if res == 0 { - return err - } - - return nil -} - -func (t *winTray) delFromVisibleItems(val int32) { - for i, itemval := range t.visibleItems { - if uint32(val) == itemval { - t.visibleItems = append(t.visibleItems[:i], t.visibleItems[i+1:]...) - break - } - } -} - -func (t *winTray) addToVisibleItems(val int32) { - newvisible := append(t.visibleItems, uint32(val)) - sort.Slice(newvisible, func(i, j int) bool { return newvisible[i] < newvisible[j] }) - t.visibleItems = newvisible -} - -func (t *winTray) getVisibleItemIndex(val int32) int { - for i, itemval := range t.visibleItems { - if uint32(val) == itemval { - return i - } - } - return -1 -} - -func nativeLoop() { - if err := wt.initInstance(); err != nil { - log.Errorf("Unable to init instance: %v", err) - return - } - - if err := wt.createMenu(); err != nil { - log.Errorf("Unable to create menu: %v", err) - return - } - - defer func() { - pDestroyWindow.Call(uintptr(wt.window)) - wt.wcex.unregister() - }() - - go systrayReady() - - // Main message pump. - m := &struct { - WindowHandle windows.Handle - Message uint32 - Wparam uintptr - Lparam uintptr - Time uint32 - Pt point - }{} - for { - ret, _, err := pGetMessage.Call(uintptr(unsafe.Pointer(m)), 0, 0, 0) - - // If the function retrieves a message other than WM_QUIT, the return value is nonzero. - // If the function retrieves the WM_QUIT message, the return value is zero. - // If there is an error, the return value is -1 - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx - switch int32(ret) { - case -1: - log.Errorf("Error at message loop: %v", err) - return - case 0: - return - default: - pTranslateMessage.Call(uintptr(unsafe.Pointer(m))) - pDispatchMessage.Call(uintptr(unsafe.Pointer(m))) - } - } -} - -func quit() { - const WM_CLOSE = 0x0010 - - pPostMessage.Call( - uintptr(wt.window), - WM_CLOSE, - 0, - 0, - ) -} - -// SetIcon sets the systray icon. -// iconBytes should be the content of .ico for windows and .ico/.jpg/.png -// for other platforms. -func SetIcon(iconBytes []byte) { - bh := md5.Sum(iconBytes) - dataHash := hex.EncodeToString(bh[:]) - iconFilePath := filepath.Join(os.TempDir(), "systray_temp_icon_"+dataHash) - - if _, err := os.Stat(iconFilePath); os.IsNotExist(err) { - if err := ioutil.WriteFile(iconFilePath, iconBytes, 0644); err != nil { - log.Errorf("Unable to write icon data to temp file: %v", err) - return - } - } - - if err := wt.setIcon(iconFilePath); err != nil { - log.Errorf("Unable to set icon: %v", err) - return - } -} - -// SetTitle sets the systray title, only available on Mac. -func SetTitle(title string) { - // do nothing -} - -// SetIcon sets the icon of a menu item. Only available on Mac. -func (item *MenuItem) SetIcon(iconBytes []byte) { - // do nothing -} - -// SetTooltip sets the systray tooltip to display on mouse hover of the tray icon, -// only available on Mac and Windows. -func SetTooltip(tooltip string) { - if err := wt.setTooltip(tooltip); err != nil { - log.Errorf("Unable to set tooltip: %v", err) - return - } -} - -func addOrUpdateMenuItem(item *MenuItem) { - err := wt.addOrUpdateMenuItem(item.id, item.title, item.disabled, item.checked) - if err != nil { - log.Errorf("Unable to addOrUpdateMenuItem: %v", err) - return - } -} - -func addSeparator(id int32) { - err := wt.addSeparatorMenuItem(id) - if err != nil { - log.Errorf("Unable to addSeparator: %v", err) - return - } -} - -func hideMenuItem(item *MenuItem) { - err := wt.hideMenuItem(item.id) - if err != nil { - log.Errorf("Unable to hideMenuItem: %v", err) - return - } -} - -func showMenuItem(item *MenuItem) { - addOrUpdateMenuItem(item) -} diff --git a/vendor/github.com/getlantern/systray/systray_windows_test.go b/vendor/github.com/getlantern/systray/systray_windows_test.go deleted file mode 100644 index 7cb6c75..0000000 --- a/vendor/github.com/getlantern/systray/systray_windows_test.go +++ /dev/null @@ -1,132 +0,0 @@ -// +build windows - -package systray - -import ( - "io/ioutil" - "runtime" - "sync/atomic" - "testing" - "time" - "unsafe" - - "golang.org/x/sys/windows" -) - -const iconFilePath = "example/icon/iconwin.ico" - -func TestBaseWindowsTray(t *testing.T) { - systrayReady = func() {} - systrayExit = func() {} - - runtime.LockOSThread() - - if err := wt.initInstance(); err != nil { - t.Fatalf("initInstance failed: %s", err) - } - - if err := wt.createMenu(); err != nil { - t.Fatalf("createMenu failed: %s", err) - } - - defer func() { - pDestroyWindow.Call(uintptr(wt.window)) - wt.wcex.unregister() - }() - - if err := wt.setIcon(iconFilePath); err != nil { - t.Errorf("SetIcon failed: %s", err) - } - - if err := wt.setTooltip("Cyrillic tooltip тест:)"); err != nil { - t.Errorf("SetIcon failed: %s", err) - } - - var id int32 = 0 - err := wt.addOrUpdateMenuItem(atomic.AddInt32(&id, 1), "Simple enabled", false, false) - if err != nil { - t.Errorf("mergeMenuItem failed: %s", err) - } - err = wt.addOrUpdateMenuItem(atomic.AddInt32(&id, 1), "Simple disabled", true, false) - if err != nil { - t.Errorf("mergeMenuItem failed: %s", err) - } - err = wt.addSeparatorMenuItem(atomic.AddInt32(&id, 1)) - if err != nil { - t.Errorf("addSeparatorMenuItem failed: %s", err) - } - err = wt.addOrUpdateMenuItem(atomic.AddInt32(&id, 1), "Simple checked enabled", false, true) - if err != nil { - t.Errorf("mergeMenuItem failed: %s", err) - } - err = wt.addOrUpdateMenuItem(atomic.AddInt32(&id, 1), "Simple checked disabled", true, true) - if err != nil { - t.Errorf("mergeMenuItem failed: %s", err) - } - - err = wt.hideMenuItem(1) - if err != nil { - t.Errorf("hideMenuItem failed: %s", err) - } - - err = wt.hideMenuItem(100) - if err == nil { - t.Error("hideMenuItem failed: must return error on invalid item id") - } - - err = wt.addOrUpdateMenuItem(2, "Simple disabled update", true, false) - if err != nil { - t.Errorf("mergeMenuItem failed: %s", err) - } - - time.AfterFunc(1*time.Second, quit) - - m := struct { - WindowHandle windows.Handle - Message uint32 - Wparam uintptr - Lparam uintptr - Time uint32 - Pt point - }{} - for { - ret, _, err := pGetMessage.Call(uintptr(unsafe.Pointer(&m)), 0, 0, 0) - res := int32(ret) - if res == -1 { - t.Errorf("win32 GetMessage failed: %v", err) - return - } else if res == 0 { - break - } - pTranslateMessage.Call(uintptr(unsafe.Pointer(&m))) - pDispatchMessage.Call(uintptr(unsafe.Pointer(&m))) - } -} - -func TestWindowsRun(t *testing.T) { - onReady := func() { - b, err := ioutil.ReadFile(iconFilePath) - if err != nil { - t.Fatalf("Can't load icon file: %v", err) - } - SetIcon(b) - SetTitle("Test title с кириллицей") - - bSomeBtn := AddMenuItem("Йа кнопко", "") - bSomeBtn.Check() - AddSeparator() - bQuit := AddMenuItem("Quit", "Quit the whole app") - go func() { - <-bQuit.ClickedCh - t.Log("Quit reqested") - Quit() - }() - time.AfterFunc(1*time.Second, Quit) - } - - onExit := func() { - t.Log("Exit success") - } - - Run(onReady, onExit) -} |