func SendCustomReturn(target ChromeTargeter, sendCh chan<- *Message, paramRequest *ParamRequest) (*Message, error) {
	data, err := json.Marshal(paramRequest)
	if err != nil {
		return nil, err
	}
	recvCh := make(chan *Message, 1)
	sendMsg := &Message{ReplyCh: recvCh, Id: paramRequest.Id, Data: []byte(data)}
	timeout := time.NewTimer(target.GetApiTimeout())
	defer timeout.Stop()
	select {
	case sendCh <- sendMsg:
	case <-timeout.C:
	case <-target.GetDoneCh():
		return nil, &ChromeDoneErr{}
	}
	timeout.Reset(target.GetApiTimeout())
	var resp *Message
	select {
	case <-timeout.C:
		return nil, &ChromeApiTimeoutErr{}
	case resp = <-recvCh:
	case <-target.GetDoneCh():
		return nil, &ChromeDoneErr{}
	}
	return resp, nil
}
Takes in a ParamRequest and gives back a response channel so the caller can decode as necessary.
package gcdmessage
import (
	"encoding/json"
	"strconv"
	"time"
)
type ChromeTargeter interface {
	GetId() int64
	GetApiTimeout() time.Duration
	GetSendCh() chan *Message
	GetDoneCh() chan struct{}  
}
type Message struct {
	ReplyCh chan *Message   
	Id      int64           
	Data    []byte          
	Method  string          
	Target  ChromeTargeter  
}
type ChromeResponse struct {
	Id     int64       `json:"id"`
	Result interface{} `json:"result"`
}
type ChromeRequest struct {
	Id     int64       `json:"id"`
	Method string      `json:"method"`
	Params interface{} `json:"params,omitempty"`
}
type ChromeErrorResponse struct {
	Id    int64        `json:"id"`     
	Error *ChromeError `json:"error"`  
}
type ChromeError struct {
	Code    int64  `json:"code"`     
	Message string `json:"message"`  
}
type ChromeRequestErr struct {
	Resp *ChromeErrorResponse  
}
func (cerr *ChromeRequestErr) Error() string {
	return "request " + strconv.FormatInt(cerr.Resp.Id, 10) + " failed, code: " + strconv.FormatInt(cerr.Resp.Error.Code, 10) + " msg: " + cerr.Resp.Error.Message
}
type ChromeEmptyResponseErr struct {
}
func (cerr *ChromeEmptyResponseErr) Error() string {
	return "nil response received"
}
type ChromeApiTimeoutErr struct {
}
func (cerr *ChromeApiTimeoutErr) Error() string {
	return "timed out waiting for response from chrome"
}
type ChromeDoneErr struct {
}
func (cerr *ChromeDoneErr) Error() string {
	return "tab is shutting down"
}
type ParamRequest struct {
	Id     int64       `json:"id"`
	Method string      `json:"method"`
	Params interface{} `json:"params,omitempty"`
}