golang-udm-0.1+14.10.20140721/ 0000755 0000153 0177776 00000000000 12363157605 016007 5 ustar pbuser nogroup 0000000 0000000 golang-udm-0.1+14.10.20140721/uploader_test.go 0000644 0000153 0177776 00000014642 12363157415 021216 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright 2014 Canonical Ltd.
*
* Authors:
* Manuel de la Pena: manuel.delapena@canonical.com
*
* This file is part of ubuntu-download-manager.
*
* ubuntu-download-manager is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* ubuntu-download-manager is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package udm
import (
"errors"
"reflect"
"launchpad.net/go-dbus/v1"
. "launchpad.net/gocheck"
)
type UploadSuite struct {
proxy *fakeProxy
upload *FileUpload
msg_args []interface{}
msg_args_err error
started_ch chan bool
started_w watch
canceled_ch chan bool
canceled_w watch
finished_ch chan string
finished_w watch
errors_ch chan error
errors_w watch
progress_ch chan Progress
progress_w watch
}
var _ = Suite(&UploadSuite{})
func (s *UploadSuite) SetUpTest(c *C) {
s.proxy = &fakeProxy{}
s.started_ch = make(chan bool)
s.started_w = newFakeWatch()
s.canceled_ch = make(chan bool)
s.canceled_w = newFakeWatch()
s.finished_ch = make(chan string)
s.finished_w = newFakeWatch()
s.errors_ch = make(chan error)
s.errors_w = newFakeWatch()
s.progress_ch = make(chan Progress)
s.progress_w = newFakeWatch()
s.upload = &FileUpload{nil, s.proxy, "", s.started_ch, s.started_w, s.canceled_ch, s.canceled_w, s.finished_ch, s.finished_w, s.errors_ch, s.errors_w, s.progress_ch, s.progress_w}
readArgs = func(msg *dbus.Message, args ...interface{}) error {
for i, arg := range args {
v := reflect.ValueOf(arg)
e := v.Elem()
switch s.msg_args[i].(type) {
default:
return errors.New("unexpected type")
case bool:
e.SetBool(s.msg_args[i].(bool))
case uint64:
e.SetUint(s.msg_args[i].(uint64))
}
}
return s.msg_args_err
}
}
func (s *UploadSuite) TestProgressError(c *C) {
s.proxy.Result = newDBusError()
progress, err := s.upload.Progress()
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "progress")
c.Assert(progress, Equals, uint64(0))
c.Assert(err, NotNil)
}
func (s *UploadSuite) TestProgress(c *C) {
expected_progress := uint64(98)
s.proxy.Result = newDBusReturn()
s.msg_args = make([]interface{}, 1)
s.msg_args[0] = expected_progress
s.msg_args_err = nil
progress, err := s.upload.Progress()
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "progress")
c.Assert(err, IsNil)
c.Assert(progress, Equals, expected_progress)
}
func (s *UploadSuite) TestMetadataError(c *C) {
s.proxy.Result = newDBusError()
metadata, err := s.upload.Metadata()
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "metadata")
c.Assert(metadata, IsNil)
c.Assert(err, NotNil)
}
func (s *UploadSuite) TestSetThrotthleError(c *C) {
throttle := uint64(9)
s.proxy.Result = newDBusError()
err := s.upload.SetThrottle(throttle)
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "setThrottle")
c.Assert(err, NotNil)
c.Assert(s.proxy.Args[0], Equals, throttle)
}
func (s *UploadSuite) TestSetThrottle(c *C) {
s.proxy.Result = newDBusReturn()
err := s.upload.SetThrottle(uint64(9))
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "setThrottle")
c.Assert(err, IsNil)
}
func (s *UploadSuite) TestThrottle(c *C) {
expected_throttle := uint64(98)
s.proxy.Result = newDBusReturn()
s.msg_args = make([]interface{}, 1)
s.msg_args[0] = expected_throttle
s.msg_args_err = nil
throttle, err := s.upload.Throttle()
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "throttle")
c.Assert(err, IsNil)
c.Assert(throttle, Equals, expected_throttle)
}
func (s *UploadSuite) TestAllowMobileUploadError(c *C) {
s.proxy.Result = newDBusError()
err := s.upload.AllowMobileUpload(true)
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "allowMobileUpload")
c.Assert(err, NotNil)
}
func (s *UploadSuite) TestAllowMobileUpload(c *C) {
expected_allowed := true
s.proxy.Result = newDBusReturn()
err := s.upload.AllowMobileUpload(expected_allowed)
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "allowMobileUpload")
c.Assert(err, IsNil)
c.Assert(s.proxy.Args[0], Equals, expected_allowed)
}
func (s *UploadSuite) TestIsMobileUploadError(c *C) {
s.proxy.Result = newDBusError()
allowed, err := s.upload.IsMobileUpload()
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "isMobileUploadAllowed")
c.Assert(allowed, Equals, false)
c.Assert(err, NotNil)
}
func (s *UploadSuite) TestIsMobileUpload(c *C) {
expected_allowed := true
s.proxy.Result = newDBusReturn()
s.msg_args = make([]interface{}, 1)
s.msg_args[0] = expected_allowed
s.msg_args_err = nil
allowed, err := s.upload.IsMobileUpload()
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "isMobileUploadAllowed")
c.Assert(err, IsNil)
c.Assert(allowed, Equals, expected_allowed)
}
func (s *UploadSuite) TestStartDBusError(c *C) {
s.proxy.Result = newDBusError()
err := s.upload.Start()
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "start")
c.Assert(err, NotNil)
}
func (s *UploadSuite) TestStartError(c *C) {
s.proxy.Result = newDBusReturn()
s.proxy.Err = errors.New("Fake error")
err := s.upload.Start()
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "start")
c.Assert(err, NotNil)
}
func (s *UploadSuite) TestCancelDBusError(c *C) {
s.proxy.Result = newDBusError()
err := s.upload.Cancel()
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "cancel")
c.Assert(err, NotNil)
}
func (s *UploadSuite) TestCancelError(c *C) {
s.proxy.Result = newDBusReturn()
s.proxy.Err = errors.New("Fake error")
err := s.upload.Cancel()
c.Assert(s.proxy.Interface, Equals, UPLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "cancel")
c.Assert(err, NotNil)
}
golang-udm-0.1+14.10.20140721/downloader_test.go 0000644 0000153 0177776 00000022605 12363157415 021537 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright 2014 Canonical Ltd.
*
* Authors:
* Manuel de la Pena: manuel.delapena@canonical.com
*
* This file is part of ubuntu-download-manager.
*
* ubuntu-download-manager is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* ubuntu-download-manager is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package udm
import (
"errors"
"launchpad.net/go-dbus/v1"
. "launchpad.net/gocheck"
"reflect"
)
type DownloadSuite struct {
proxy *fakeProxy
download *FileDownload
msg_args []interface{}
msg_args_err error
started_ch chan bool
started_w watch
paused_ch chan bool
paused_w watch
resumed_ch chan bool
resumed_w watch
canceled_ch chan bool
canceled_w watch
finished_ch chan string
finished_w watch
errors_ch chan error
errors_w watch
progress_ch chan Progress
progress_w watch
}
var _ = Suite(&DownloadSuite{})
func (s *DownloadSuite) SetUpTest(c *C) {
s.proxy = &fakeProxy{}
s.started_ch = make(chan bool)
s.started_w = newFakeWatch()
s.paused_ch = make(chan bool)
s.paused_w = newFakeWatch()
s.resumed_ch = make(chan bool)
s.resumed_w = newFakeWatch()
s.canceled_ch = make(chan bool)
s.canceled_w = newFakeWatch()
s.finished_ch = make(chan string)
s.finished_w = newFakeWatch()
s.errors_ch = make(chan error)
s.errors_w = newFakeWatch()
s.progress_ch = make(chan Progress)
s.progress_w = newFakeWatch()
s.download = &FileDownload{nil, s.proxy, "", s.started_ch, s.started_w, s.paused_ch, s.paused_w, s.resumed_ch, s.resumed_w, s.canceled_ch, s.canceled_w, s.finished_ch, s.finished_w, s.errors_ch, s.errors_w, s.progress_ch, s.progress_w}
readArgs = func(msg *dbus.Message, args ...interface{}) error {
for i, arg := range args {
v := reflect.ValueOf(arg)
e := v.Elem()
switch s.msg_args[i].(type) {
default:
return errors.New("unexpected type")
case bool:
e.SetBool(s.msg_args[i].(bool))
case uint64:
e.SetUint(s.msg_args[i].(uint64))
}
}
return s.msg_args_err
}
}
func (s *DownloadSuite) TestTotalSizeError(c *C) {
s.proxy.Result = newDBusError()
size, err := s.download.TotalSize()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "totalSize")
c.Assert(size, Equals, uint64(0))
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestTotalSize(c *C) {
expected_size := uint64(98)
s.proxy.Result = newDBusReturn()
s.msg_args = make([]interface{}, 1)
s.msg_args[0] = expected_size
s.msg_args_err = nil
size, err := s.download.TotalSize()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "totalSize")
c.Assert(err, IsNil)
c.Assert(size, Equals, expected_size)
}
func (s *DownloadSuite) TestProgressError(c *C) {
s.proxy.Result = newDBusError()
progress, err := s.download.Progress()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "progress")
c.Assert(progress, Equals, uint64(0))
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestProgress(c *C) {
expected_progress := uint64(98)
s.proxy.Result = newDBusReturn()
s.msg_args = make([]interface{}, 1)
s.msg_args[0] = expected_progress
s.msg_args_err = nil
progress, err := s.download.Progress()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "progress")
c.Assert(err, IsNil)
c.Assert(progress, Equals, expected_progress)
}
func (s *DownloadSuite) TestMetadataError(c *C) {
s.proxy.Result = newDBusError()
metadata, err := s.download.Metadata()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "metadata")
c.Assert(metadata, IsNil)
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestSetThrotthleError(c *C) {
throttle := uint64(9)
s.proxy.Result = newDBusError()
err := s.download.SetThrottle(throttle)
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "setThrottle")
c.Assert(err, NotNil)
c.Assert(s.proxy.Args[0], Equals, throttle)
}
func (s *DownloadSuite) TestSetThrottle(c *C) {
s.proxy.Result = newDBusReturn()
err := s.download.SetThrottle(uint64(9))
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "setThrottle")
c.Assert(err, IsNil)
}
func (s *DownloadSuite) TestThrottleError(c *C) {
s.proxy.Result = newDBusError()
size, err := s.download.Throttle()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "throttle")
c.Assert(size, Equals, uint64(0))
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestThrottle(c *C) {
expected_throttle := uint64(98)
s.proxy.Result = newDBusReturn()
s.msg_args = make([]interface{}, 1)
s.msg_args[0] = expected_throttle
s.msg_args_err = nil
throttle, err := s.download.Throttle()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "throttle")
c.Assert(err, IsNil)
c.Assert(throttle, Equals, expected_throttle)
}
func (s *DownloadSuite) TestAllowMobileDownloadError(c *C) {
s.proxy.Result = newDBusError()
err := s.download.AllowMobileDownload(true)
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "allowGSMDownload")
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestAllowMobileDownload(c *C) {
expected_allowed := true
s.proxy.Result = newDBusReturn()
err := s.download.AllowMobileDownload(expected_allowed)
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "allowGSMDownload")
c.Assert(err, IsNil)
c.Assert(s.proxy.Args[0], Equals, expected_allowed)
}
func (s *DownloadSuite) TestSetDestinationDirError(c *C) {
s.proxy.Result = newDBusError()
err := s.download.SetDestinationDir("/new/path")
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "setDestinationDir")
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestSetDestinationDir(c *C) {
expected_dir := "/path/to/use"
s.proxy.Result = newDBusReturn()
err := s.download.SetDestinationDir(expected_dir)
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "setDestinationDir")
c.Assert(err, IsNil)
c.Assert(s.proxy.Args[0], Equals, expected_dir)
}
func (s *DownloadSuite) TestIsMobileDownloadError(c *C) {
s.proxy.Result = newDBusError()
allowed, err := s.download.IsMobileDownload()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "isGSMDownloadAllowed")
c.Assert(allowed, Equals, false)
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestIsMobileDownload(c *C) {
expected_allowed := true
s.proxy.Result = newDBusReturn()
s.msg_args = make([]interface{}, 1)
s.msg_args[0] = expected_allowed
s.msg_args_err = nil
allowed, err := s.download.IsMobileDownload()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "isGSMDownloadAllowed")
c.Assert(err, IsNil)
c.Assert(allowed, Equals, expected_allowed)
}
func (s *DownloadSuite) TestStartDBusError(c *C) {
s.proxy.Result = newDBusError()
err := s.download.Start()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "start")
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestStartError(c *C) {
s.proxy.Result = newDBusReturn()
s.proxy.Err = errors.New("Fake error")
err := s.download.Start()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "start")
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestPauseDBusError(c *C) {
s.proxy.Result = newDBusError()
err := s.download.Pause()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "pause")
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestPauseError(c *C) {
s.proxy.Result = newDBusReturn()
s.proxy.Err = errors.New("Fake error")
err := s.download.Pause()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "pause")
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestResumeDBusError(c *C) {
s.proxy.Result = newDBusError()
err := s.download.Resume()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "resume")
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestResumeError(c *C) {
s.proxy.Result = newDBusReturn()
s.proxy.Err = errors.New("Fake error")
err := s.download.Resume()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "resume")
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestCancelDBusError(c *C) {
s.proxy.Result = newDBusError()
err := s.download.Cancel()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "cancel")
c.Assert(err, NotNil)
}
func (s *DownloadSuite) TestCancelError(c *C) {
s.proxy.Result = newDBusReturn()
s.proxy.Err = errors.New("Fake error")
err := s.download.Cancel()
c.Assert(s.proxy.Interface, Equals, DOWNLOAD_INTERFACE)
c.Assert(s.proxy.MethodName, Equals, "cancel")
c.Assert(err, NotNil)
}
golang-udm-0.1+14.10.20140721/uploader.go 0000644 0000153 0177776 00000024724 12363157430 020156 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright 2014 Canonical Ltd.
*
* Authors:
* Manuel de la Pena: manuel.delapena@canonical.com
*
* This file is part of ubuntu-download-manager.
*
* ubuntu-download-manager is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* ubuntu-download-manager is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
// Package udm provides a go interface to work with the ubuntu download manager
package udm
import (
"errors"
"fmt"
"runtime"
"launchpad.net/go-dbus/v1"
)
const (
UPLOAD_SERVICE = "com.canonical.applications.Uploader"
UPLOAD_INTERFACE = "com.canonical.applications.Upload"
UPLOAD_MANAGER_INTERFACE = "com.canonical.applications.UploadManager"
)
// Upload is the common interface of an upload. It provides all the required
// methods to interact with an upload created by udm.
type Upload interface {
Progress() (uint64, error)
Metadata() (map[string]string, error)
SetThrottle(uint64) error
Throttle() (uint64, error)
AllowMobileUpload(bool) error
IsMobileUpload() (bool, error)
Start() error
Cancel() error
Started() chan bool
UploadProgress() chan Progress
Canceled() chan bool
Finished() chan string
Error() chan error
}
// FileUpload represents a single file being uploaded by udm.
type FileUpload struct {
conn *dbus.Connection
proxy proxy
path dbus.ObjectPath
started chan bool
started_w watch
canceled chan bool
canceled_w watch
finished chan string
finished_w watch
errors chan error
error_w watch
progress chan Progress
progress_w watch
}
func (upload *FileUpload) free() {
// cancel all watches so that goroutines are done and close the
// channels
upload.started_w.Cancel()
upload.canceled_w.Cancel()
upload.finished_w.Cancel()
upload.error_w.Cancel()
upload.progress_w.Cancel()
}
func cleanUploadData(upload *FileUpload) {
upload.free()
}
func newFileUpload(conn *dbus.Connection, path dbus.ObjectPath) (*FileUpload, error) {
proxy := conn.Object(UPLOAD_SERVICE, path)
started_ch := make(chan bool)
started_w, err := connectToSignal(conn, path, UPLOAD_SERVICE, UPLOAD_INTERFACE, "started")
if err != nil {
return nil, err
}
canceled_ch := make(chan bool)
canceled_w, err := connectToSignal(conn, path, UPLOAD_SERVICE, UPLOAD_INTERFACE, "canceled")
if err != nil {
return nil, err
}
finished_ch := make(chan string)
finished_w, err := connectToSignal(conn, path, UPLOAD_SERVICE, UPLOAD_INTERFACE, "finished")
if err != nil {
return nil, err
}
errors_ch := make(chan error)
errors_w, err := connectToSignal(conn, path, UPLOAD_SERVICE, UPLOAD_INTERFACE, "error")
if err != nil {
return nil, err
}
progress_ch := make(chan Progress)
progress_w, err := connectToSignal(conn, path, UPLOAD_SERVICE, UPLOAD_INTERFACE, "progress")
if err != nil {
return nil, err
}
u := FileUpload{conn, proxy, path, started_ch, started_w, canceled_ch, canceled_w, finished_ch, finished_w, errors_ch, errors_w, progress_ch, progress_w}
// connect to the diff signals so that we have nice channels that do
// not expose dbus watchers
u.connectToStarted()
u.connectToCanceled()
u.connectToFinished()
u.connectToError()
u.connectToProgress()
runtime.SetFinalizer(&u, cleanUploadData)
return &u, nil
}
// Process returns the process so far in uploading the file.
func (upload *FileUpload) Progress() (progress uint64, err error) {
reply, err := upload.proxy.Call(UPLOAD_INTERFACE, "progress")
if err != nil {
return 0, err
}
if reply != nil && reply.Type == dbus.TypeError {
return 0, fmt.Errorf("DBus Error: %", reply.ErrorName)
}
if err = readArgs(reply, &progress); err != nil {
return 0, err
}
return progress, nil
}
// Metadata returns the metadata that was provided at creating time to the upload.
func (upload *FileUpload) Metadata() (metadata map[string]string, err error) {
reply, err := upload.proxy.Call(UPLOAD_INTERFACE, "metadata")
if err != nil {
return nil, err
}
if reply != nil && reply.Type == dbus.TypeError {
return nil, fmt.Errorf("DBus Error: %", reply.ErrorName)
}
if err = readArgs(reply, &metadata); err != nil {
return nil, err
}
return metadata, nil
}
// SetThrottle sets the network throttle to be used in the upload.
func (upload *FileUpload) SetThrottle(throttle uint64) (err error) {
reply, err := upload.proxy.Call(UPLOAD_INTERFACE, "setThrottle", throttle)
if err != nil {
return err
}
if reply != nil && reply.Type == dbus.TypeError {
return fmt.Errorf("DBus Error: %", reply.ErrorName)
}
return nil
}
// Throttle returns the network throttle that is currently used in the upload.
func (upload *FileUpload) Throttle() (throttle uint64, err error) {
reply, err := upload.proxy.Call(UPLOAD_INTERFACE, "throttle")
if err != nil {
return 0, err
}
if reply != nil && reply.Type == dbus.TypeError {
return 0, fmt.Errorf("DBus Error: %", reply.ErrorName)
}
if err = readArgs(reply, &throttle); err != nil {
return 0, err
}
return throttle, nil
}
// AllowMobileUpload returns if the upload is allowed to use the mobile
// connection.
func (upload *FileUpload) AllowMobileUpload(allowed bool) (err error) {
reply, err := upload.proxy.Call(UPLOAD_INTERFACE, "allowMobileUpload", allowed)
if err != nil {
return err
}
if reply != nil && reply.Type == dbus.TypeError {
return fmt.Errorf("DBus Error: %", reply.ErrorName)
}
return nil
}
// IsMobileUpload returns if the upload will be performed over the mobile data
// connection.
func (upload *FileUpload) IsMobileUpload() (allowed bool, err error) {
reply, err := upload.proxy.Call(UPLOAD_INTERFACE, "isMobileUploadAllowed", allowed)
if err != nil {
return false, err
}
if reply != nil && reply.Type == dbus.TypeError {
return false, fmt.Errorf("DBus Error: %", reply.ErrorName)
}
if err = readArgs(reply, &allowed); err != nil {
return false, err
}
return allowed, nil
}
func (upload *FileUpload) Start() (err error) {
reply, err := upload.proxy.Call(UPLOAD_INTERFACE, "start")
if err != nil {
return err
}
if reply != nil && reply.Type == dbus.TypeError {
return fmt.Errorf("DBus Error: %", reply.ErrorName)
}
return nil
}
// Cancel cancels an upload that was in process and deletes any local files
// that were created.
func (upload *FileUpload) Cancel() (err error) {
reply, err := upload.proxy.Call(UPLOAD_INTERFACE, "cancel")
if err != nil {
return err
}
if reply != nil && reply.Type == dbus.TypeError {
return fmt.Errorf("DBus Error: %", reply.ErrorName)
}
return nil
}
func (upload *FileUpload) connectToStarted() {
go func() {
for msg := range upload.started_w.Channel() {
var started bool
readArgs(msg, &started)
upload.started <- started
}
close(upload.started)
}()
}
// Started returns a channel that will be used to communicate the started signals.
func (upload *FileUpload) Started() chan bool {
return upload.started
}
func (upload *FileUpload) connectToCanceled() {
go func() {
for msg := range upload.canceled_w.Channel() {
var canceled bool
readArgs(msg, &canceled)
upload.canceled <- canceled
}
close(upload.canceled)
}()
}
// Canceled returns a channel that will be used to communicate the canceled signals.
func (upload *FileUpload) Canceled() chan bool {
return upload.canceled
}
func (upload *FileUpload) connectToFinished() {
go func() {
for msg := range upload.finished_w.Channel() {
var path string
readArgs(msg, &path)
upload.finished <- path
}
close(upload.finished)
}()
}
// Finished returns a channel that will ne used to communicate the finished signals.
func (upload *FileUpload) Finished() chan string {
return upload.finished
}
func (upload *FileUpload) connectToError() {
go func() {
for msg := range upload.error_w.Channel() {
var reason string
readArgs(msg, &reason)
upload.errors <- errors.New(reason)
}
close(upload.errors)
}()
}
// Error returns the channel that will be used to communicate the error signals.
func (upload *FileUpload) Error() chan error {
return upload.errors
}
func (upload *FileUpload) connectToProgress() {
go func() {
for msg := range upload.progress_w.Channel() {
var received uint64
var total uint64
readArgs(msg, &received, &total)
upload.progress <- Progress{received, total}
}
close(upload.progress)
}()
}
// UploadProgress returns a channel that will be used to communicate the progress
// signals.
func (upload *FileUpload) UploadProgress() chan Progress {
return upload.progress
}
type UploadManager struct {
conn *dbus.Connection
proxy *dbus.ObjectProxy
}
// NewUploadManager creates a new manager that can be used to create an upload
// in the udm daemon.
func NewUploadManager() (*UploadManager, error) {
conn, err := dbus.Connect(dbus.SessionBus)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
proxy := conn.Object(UPLOAD_SERVICE, "/")
d := UploadManager{conn, proxy}
return &d, nil
}
func (man *UploadManager) CreateUpload(url string, file string, metadata map[string]interface{}, headers map[string]string) (upload Upload, err error) {
var t map[string]*dbus.Variant
for key, value := range metadata {
t[key] = &dbus.Variant{Value: value}
}
s := struct {
U string
F string
M map[string]*dbus.Variant
HD map[string]string
}{url, file, t, headers}
var path dbus.ObjectPath
reply, err := man.proxy.Call(UPLOAD_MANAGER_INTERFACE, "createUpload", s)
if err != nil {
return nil, err
}
if reply != nil && reply.Type == dbus.TypeError {
return nil, fmt.Errorf("DBus Error: %", reply.ErrorName)
}
if err = readArgs(reply, &path); err != nil {
return nil, err
}
upload, err = newFileUpload(man.conn, path)
return upload, err
}
func (man *UploadManager) CreateMmsUpload(url string, file string, hostname string, port int32) (upload Upload, err error) {
var path dbus.ObjectPath
reply, err := man.proxy.Call(UPLOAD_MANAGER_INTERFACE, "createMmsUpload", url, file, hostname, port)
if err != nil {
return nil, err
}
if reply != nil && reply.Type == dbus.TypeError {
return nil, fmt.Errorf("DBus Error: %", reply.ErrorName)
}
if err = readArgs(reply, &path); err != nil {
return nil, err
}
upload, err = newFileUpload(man.conn, path)
return upload, err
}
golang-udm-0.1+14.10.20140721/common_test.go 0000644 0000153 0177776 00000003775 12363157415 020700 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright 2014 Canonical Ltd.
*
* Authors:
* Manuel de la Pena: manuel.delapena@canonical.com
*
* This file is part of ubuntu-download-manager.
*
* ubuntu-download-manager is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* ubuntu-download-manager is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package udm
import (
"launchpad.net/go-dbus/v1"
. "launchpad.net/gocheck"
"testing"
)
func Test(t *testing.T) { TestingT(t) }
type fakeProxy struct {
Interface string
MethodName string
Args []interface{}
Err error
Result *dbus.Message
}
func (f *fakeProxy) Call(iface, method string, args ...interface{}) (*dbus.Message, error) {
// store the called method and return Result
f.Interface = iface
f.MethodName = method
f.Args = args
if f.Err == nil {
return f.Result, nil
}
return nil, f.Err
}
type FakeWatch struct {
Canceled bool
Ch chan *dbus.Message
}
func newFakeWatch() *FakeWatch {
ch := make(chan *dbus.Message)
fw := FakeWatch{false, ch}
return &fw
}
func (w *FakeWatch) Cancel() error {
w.Canceled = true
return nil
}
func (w *FakeWatch) Channel() chan *dbus.Message {
return w.Ch
}
// returns a new error that can be used in the tests
func newDBusError() *dbus.Message {
msg := dbus.NewMethodCallMessage("com.destination", "/path", "com.interface", "method")
msg.Type = dbus.TypeError
msg.ErrorName = "com.testing.udm"
return msg
}
func newDBusReturn() *dbus.Message {
msg := dbus.NewMethodCallMessage("com.destination", "/path", "com.interface", "method")
msg.Type = dbus.TypeMethodReturn
return msg
}
golang-udm-0.1+14.10.20140721/downloader.go 0000644 0000153 0177776 00000035427 12363157430 020503 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright 2014 Canonical Ltd.
*
* Authors:
* Manuel de la Pena: manuel.delapena@canonical.com
*
* This file is part of ubuntu-download-manager.
*
* ubuntu-download-manager is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* ubuntu-download-manager is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
// Package udm provides a go interface to work with the ubuntu download manager
package udm
import (
"errors"
"fmt"
"launchpad.net/go-dbus/v1"
"runtime"
)
const (
DOWNLOAD_SERVICE = "com.canonical.applications.Downloader"
DOWNLOAD_INTERFACE = "com.canonical.applications.Download"
DOWNLOAD_MANAGER_INTERFACE = "com.canonical.applications.DownloadManager"
)
type hashType string
const (
MD5 hashType = "md5"
SHA1 hashType = "sha1"
SHA224 hashType = "sha224"
SHA256 hashType = "sha256"
SHA384 hashType = "sha384"
SHA512 hashType = "sha512"
)
const (
LOCAL_PATH = "local-path"
OBJECT_PATH = "objectpath"
POST_DOWNLOAD_COMMAND = "post-download-command"
)
// Download is the common interface of a download. It provides all the required
// methods to interact with a download created by udm.
type Download interface {
TotalSize() (uint64, error)
Progress() (uint64, error)
Metadata() (map[string]string, error)
SetThrottle(uint64) error
Throttle() (uint64, error)
AllowMobileDownload(bool) error
SetDestinationDir(string) error
IsMobileDownload() (bool, error)
Start() error
Pause() error
Resume() error
Cancel() error
Started() chan bool
Paused() chan bool
DownloadProgress() chan Progress
Resumed() chan bool
Canceled() chan bool
Finished() chan string
Error() chan error
}
// FileDownload represents a single file being downloaded by udm.
type FileDownload struct {
conn *dbus.Connection
proxy proxy
path dbus.ObjectPath
started chan bool
started_w watch
paused chan bool
paused_w watch
resumed chan bool
resumed_w watch
canceled chan bool
canceled_w watch
finished chan string
finished_w watch
errors chan error
error_w watch
progress chan Progress
progress_w watch
}
func (down *FileDownload) free() {
// cancel all watches so that goroutines are done and close the
// channels
down.started_w.Cancel()
down.paused_w.Cancel()
down.resumed_w.Cancel()
down.canceled_w.Cancel()
down.finished_w.Cancel()
down.error_w.Cancel()
down.progress_w.Cancel()
}
func cleanDownloadData(down *FileDownload) {
down.free()
}
func newFileDownload(conn *dbus.Connection, path dbus.ObjectPath) (*FileDownload, error) {
proxy := conn.Object(DOWNLOAD_SERVICE, path)
started_ch := make(chan bool)
started_w, err := connectToSignal(conn, path, DOWNLOAD_SERVICE, DOWNLOAD_INTERFACE, "started")
if err != nil {
return nil, err
}
paused_ch := make(chan bool)
paused_w, err := connectToSignal(conn, path, DOWNLOAD_SERVICE, DOWNLOAD_INTERFACE, "paused")
if err != nil {
return nil, err
}
resumed_ch := make(chan bool)
resumed_w, err := connectToSignal(conn, path, DOWNLOAD_SERVICE, DOWNLOAD_INTERFACE, "resumed")
if err != nil {
return nil, err
}
canceled_ch := make(chan bool)
canceled_w, err := connectToSignal(conn, path, DOWNLOAD_SERVICE, DOWNLOAD_INTERFACE, "canceled")
if err != nil {
return nil, err
}
finished_ch := make(chan string)
finished_w, err := connectToSignal(conn, path, DOWNLOAD_SERVICE, DOWNLOAD_INTERFACE, "finished")
if err != nil {
return nil, err
}
errors_ch := make(chan error)
errors_w, err := connectToSignal(conn, path, DOWNLOAD_SERVICE, DOWNLOAD_INTERFACE, "error")
if err != nil {
return nil, err
}
progress_ch := make(chan Progress)
progress_w, err := connectToSignal(conn, path, DOWNLOAD_SERVICE, DOWNLOAD_INTERFACE, "progress")
if err != nil {
return nil, err
}
d := FileDownload{conn, proxy, path, started_ch, started_w, paused_ch, paused_w, resumed_ch, resumed_w, canceled_ch, canceled_w, finished_ch, finished_w, errors_ch, errors_w, progress_ch, progress_w}
// connect to the diff signals so that we have nice channels that do
// not expose dbus watchers
d.connectToStarted()
d.connectToPaused()
d.connectToResumed()
d.connectToCanceled()
d.connectToFinished()
d.connectToError()
d.connectToProgress()
runtime.SetFinalizer(&d, cleanDownloadData)
return &d, nil
}
// TotalSize returns the total size of the file being downloaded.
func (down *FileDownload) TotalSize() (size uint64, err error) {
return getUint64Value(down.proxy, DOWNLOAD_INTERFACE, "totalSize")
}
// Process returns the process so far in downloading the file.
func (down *FileDownload) Progress() (progress uint64, err error) {
return getUint64Value(down.proxy, DOWNLOAD_INTERFACE, "progress")
}
// Metadata returns the metadata that was provided at creating time to the download.
func (down *FileDownload) Metadata() (metadata map[string]string, err error) {
return getMetadataMap(down.proxy, DOWNLOAD_INTERFACE, "metadata")
}
// SetThrottle sets the network throttle to be used in the download.
func (down *FileDownload) SetThrottle(throttle uint64) (err error) {
return setUint64Value(down.proxy, DOWNLOAD_INTERFACE, "setThrottle", throttle)
}
// Throttle returns the network throttle that is currently used in the download.
func (down *FileDownload) Throttle() (throttle uint64, err error) {
return getUint64Value(down.proxy, DOWNLOAD_INTERFACE, "throttle")
}
// AllowMobileDownload returns if the download is allow to use the mobile connect
// connection.
func (down *FileDownload) AllowMobileDownload(allowed bool) (err error) {
reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "allowGSMDownload", allowed)
if err != nil {
return err
}
if reply != nil && reply.Type == dbus.TypeError {
return fmt.Errorf("dbus error: %", reply.ErrorName)
}
return nil
}
// SetDestinationDir permits unconfined applications to set the destination
// directory of the download. This method must be called BEFORE the download
// is started else an error will be returned.
func (down *FileDownload) SetDestinationDir(path string) (err error) {
return setStringValue(down.proxy, DOWNLOAD_INTERFACE, "setDestinationDir", path)
}
// IsMobileDownload returns if the download will be performed over the mobile data.
func (down *FileDownload) IsMobileDownload() (allowed bool, err error) {
return getBoolValue(down.proxy, DOWNLOAD_INTERFACE, "isGSMDownloadAllowed")
}
// Start tells udm that the download is ready to be peformed and that the client is
// ready to recieve signals. The following is a common pattern to be used when
// creating downloads in udm.
//
// man, err := udm.NewDownloadManager()
// if err != nil {
// }
//
// // variables used to create the download
//
// url := "http://www.python.org/ftp/python/3.3.3/Python-3.3.3.tar.xz"
// hash := "8af44d33ea3a1528fc56b3a362924500"
// hashAlgo := MD5
// var metadata map[string]interface{}
// var headers map[string]string
//
// // create the download BUT do not start downloading just yet
// down, err := man.CreateDownload(url, hash, hashAlgo, metadata, headers)
//
// // connect routines to the download channels so that we can get the
// // information of the download the channel will not get any data until the
// // Start is called.
//
// started_signal := down.Started()
// go func() {
// <-started_signal
// fmt.Println("Download started")
// }()
// progress_signal := down.DownloadProgress()
// go func() {
// for progress := range p {
// fmt.Printf("Recieved %d out of %d\n", progress.Received, progress.Total)
// }
// }()
//
// finished_signal := down.Finished()
//
// // start download
// down.Start()
//
// // block until we are finished downloading
// <- finished_signal
func (down *FileDownload) Start() (err error) {
reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "start")
if err != nil {
return err
}
if reply != nil && reply.Type == dbus.TypeError {
return fmt.Errorf("dbus error: %", reply.ErrorName)
}
return nil
}
// Pause pauses a download that was started and if not nothing is done.
func (down *FileDownload) Pause() (err error) {
reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "pause")
if err != nil {
return err
}
if reply != nil && reply.Type == dbus.TypeError {
return fmt.Errorf("dbus error: %", reply.ErrorName)
}
return nil
}
// Resumes a download that was paused or does nothing otherwise.
func (down *FileDownload) Resume() (err error) {
reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "resume")
if err != nil {
return err
}
if reply != nil && reply.Type == dbus.TypeError {
return fmt.Errorf("dbus error: %", reply.ErrorName)
}
return nil
}
// Cancel cancels a download that was in process and deletes any local files
// that were created.
func (down *FileDownload) Cancel() (err error) {
reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "cancel")
if err != nil {
return err
}
if reply != nil && reply.Type == dbus.TypeError {
return fmt.Errorf("dbus error: %", reply.ErrorName)
}
return nil
}
func (down *FileDownload) connectToStarted() {
go func() {
for msg := range down.started_w.Channel() {
var started bool
readArgs(msg, &started)
down.started <- started
}
close(down.started)
}()
}
// Started returns a channel that will be used to communicate the started signals.
func (down *FileDownload) Started() chan bool {
return down.started
}
func (down *FileDownload) connectToPaused() {
go func() {
for msg := range down.paused_w.Channel() {
var paused bool
readArgs(msg, &paused)
down.paused <- paused
}
close(down.paused)
}()
}
// Paused returns a channel that will be used to communicate the paused signals.
func (down *FileDownload) Paused() chan bool {
return down.paused
}
func (down *FileDownload) connectToProgress() {
go func() {
for msg := range down.progress_w.Channel() {
var received uint64
var total uint64
readArgs(msg, &received, &total)
down.progress <- Progress{received, total}
}
close(down.progress)
}()
}
// DownloadProgress returns a channel that will be used to communicate the progress
// signals.
func (down *FileDownload) DownloadProgress() chan Progress {
return down.progress
}
func (down *FileDownload) connectToResumed() {
go func() {
for msg := range down.resumed_w.Channel() {
var resumed bool
readArgs(msg, &resumed)
down.resumed <- resumed
}
close(down.resumed)
}()
}
// Resumed returns a channel that will be used to communicate the paused signals.
func (down *FileDownload) Resumed() chan bool {
return down.resumed
}
func (down *FileDownload) connectToCanceled() {
go func() {
for msg := range down.canceled_w.Channel() {
var canceled bool
readArgs(msg, &canceled)
down.canceled <- canceled
}
close(down.canceled)
}()
}
// Canceled returns a channel that will be used to communicate the canceled signals.
func (down *FileDownload) Canceled() chan bool {
return down.canceled
}
func (down *FileDownload) connectToFinished() {
go func() {
for msg := range down.finished_w.Channel() {
var path string
readArgs(msg, &path)
down.finished <- path
}
close(down.finished)
}()
}
// Finished returns a channel that will ne used to communicate the finished signals.
func (down *FileDownload) Finished() chan string {
return down.finished
}
func (down *FileDownload) connectToError() {
go func() {
for msg := range down.error_w.Channel() {
var reason string
readArgs(msg, &reason)
down.errors <- errors.New(reason)
}
close(down.errors)
}()
}
// Error returns the channel that will be used to communicate the error signals.
func (down *FileDownload) Error() chan error {
return down.errors
}
type DownloadManager struct {
conn *dbus.Connection
proxy *dbus.ObjectProxy
}
// NewDownloadManager creates a new manager that can be used to create download in the
// udm daemon.
func NewDownloadManager() (*DownloadManager, error) {
conn, err := dbus.Connect(dbus.SessionBus)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
proxy := conn.Object(DOWNLOAD_SERVICE, "/")
d := DownloadManager{conn, proxy}
return &d, nil
}
// CreateDownload creates a new download in the udm daemon that can be used to get
// a remote resource. Udm allows to pass a hash signature and method that will be
// check once the download has been complited.
//
// The download hash can be one of the the following constants:
//
// MD5
// SHA1
// SHA224
// SHA256
// SHA384
// SHA512
//
// The metadata attribute can be used to pass extra information to the udm daemon
// that will just be considered if the caller is not a apparmor confined application.
//
// LOCAL_PATH => allows to provide the local path for the download.
// OBJECT_PATH => allows to provide the object path to be used in the dbus daemon.
// POST_DOWNLOAD_COMMAND => allows to provide a command that will be executed on the
// download
//
// The headers attribute allows to provide extra headers to be used in the request used
// to perform the download.
func (man *DownloadManager) CreateDownload(url string, hash string, algo hashType, metadata map[string]interface{}, headers map[string]string) (down Download, err error) {
var t map[string]*dbus.Variant
for key, value := range metadata {
t[key] = &dbus.Variant{Value: value}
}
s := struct {
U string
H string
A string
M map[string]*dbus.Variant
HD map[string]string
}{url, hash, string(algo), t, headers}
var path dbus.ObjectPath
reply, err := man.proxy.Call(DOWNLOAD_MANAGER_INTERFACE, "createDownload", s)
if err != nil {
return nil, err
}
if reply != nil && reply.Type == dbus.TypeError {
return nil, fmt.Errorf("dbus error: %", reply.ErrorName)
}
if err = readArgs(reply, &path); err != nil {
return nil, err
}
down, err = newFileDownload(man.conn, path)
return down, err
}
// CreateMmsDownload creates an mms download that will be performed right away. An
// mms download only uses mobile that and an apn proxy to download a multime media
// message.
func (man *DownloadManager) CreateMmsDownload(url string, hostname string, port int32) (down Download, err error) {
var path dbus.ObjectPath
reply, err := man.proxy.Call(DOWNLOAD_MANAGER_INTERFACE, "createMmsDownload", url, hostname, port)
if err != nil {
return nil, err
}
if reply != nil && reply.Type == dbus.TypeError {
return nil, fmt.Errorf("dbus error: %", reply.ErrorName)
}
if err = readArgs(reply, &path); err != nil {
return nil, err
}
down, err = newFileDownload(man.conn, path)
return down, err
}
golang-udm-0.1+14.10.20140721/common.go 0000644 0000153 0177776 00000007375 12363157430 017636 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright 2014 Canonical Ltd.
*
* Authors:
* Manuel de la Pena: manuel.delapena@canonical.com
*
* This file is part of ubuntu-download-manager.
*
* ubuntu-download-manager is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* ubuntu-download-manager is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
// Package udm provides a go interface to work with the ubuntu download manager
package udm
import (
"fmt"
"launchpad.net/go-dbus/v1"
)
// Progress provides how much progress has been performed in a download that was
// already started.
type Progress struct {
Received uint64
Total uint64
}
// internal interface used to simplify testing
type watch interface {
Cancel() error
Channel() chan *dbus.Message
}
// small wrapper used to simplify testing by using the watch interface
type watchWrapper struct {
watch *dbus.SignalWatch
}
func newWatchWrapper(sw *dbus.SignalWatch) *watchWrapper {
w := watchWrapper{sw}
return &w
}
func (w *watchWrapper) Cancel() error {
return w.watch.Cancel()
}
func (w *watchWrapper) Channel() chan *dbus.Message {
return w.watch.C
}
// interface added to simplify testing
type proxy interface {
Call(iface, method string, args ...interface{}) (*dbus.Message, error)
}
var readArgs = func(msg *dbus.Message, args ...interface{}) error {
return msg.Args(args...)
}
func getUint64Value(p proxy, dbusInterface, valueName string) (uint64, error) {
reply, err := p.Call(dbusInterface, valueName)
if err != nil {
return 0, err
}
if reply.Type == dbus.TypeError {
return 0, fmt.Errorf("dbus error: %", reply.ErrorName)
}
var value uint64
if err = readArgs(reply, &value); err != nil {
return 0, err
}
return value, nil
}
func setUint64Value(p proxy, dbusInterface, valueName string, value uint64) error {
reply, err := p.Call(dbusInterface, valueName, value)
if err != nil {
return err
}
if reply.Type == dbus.TypeError {
return fmt.Errorf("dbus error: %", reply.ErrorName)
}
return nil
}
func setStringValue(p proxy, dbusInterface, valueName string, value string) error {
reply, err := p.Call(dbusInterface, valueName, value)
if err != nil {
return err
}
if reply.Type == dbus.TypeError {
return fmt.Errorf("dbus error: %", reply.ErrorName)
}
return nil
}
func getBoolValue(p proxy, dbusInterface, valueName string) (bool, error) {
reply, err := p.Call(dbusInterface, valueName)
if err != nil {
return false, err
}
if reply.Type == dbus.TypeError {
return false, fmt.Errorf("dbus error: %", reply.ErrorName)
}
var value bool
if err = readArgs(reply, &value); err != nil {
return false, err
}
return value, nil
}
func getMetadataMap(p proxy, dbusInterface, valueName string) (metadata map[string]string, err error) {
var value map[string]string
reply, err := p.Call(dbusInterface, valueName)
if err != nil {
return value, err
}
if reply.Type == dbus.TypeError {
return value, fmt.Errorf("dbus error: %", reply.ErrorName)
}
if err = readArgs(reply, &value); err != nil {
return value, err
}
return value, nil
}
func connectToSignal(conn *dbus.Connection, path dbus.ObjectPath, sender, dbusInterface, signal string) (watch, error) {
sw, err := conn.WatchSignal(&dbus.MatchRule{
Type: dbus.TypeSignal,
Sender: sender,
Interface: dbusInterface,
Member: signal,
Path: path})
w := newWatchWrapper(sw)
return w, err
}