func (s Session) SessionStorageGetKeys() ([]string, error) {
	return s.storageGetKeys("session_storage")
}
Get all keys of the storage.
package webdriver
import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"io/ioutil"
)
type WebDriver interface {
	Start() error
	Stop() error
	Status() (*Status, error)
	NewSession(desired, required Capabilities) (*Session, error)
	Sessions() ([]Session, error)
	do(params interface{}, method, urlFormat string, urlParams ...interface{}) (string, []byte, error)
}
type params map[string]interface{}
type Status struct {
	Build Build
	OS    OS
}
type Build struct {
	Version  string
	Revision string
	Time     string
}
type OS struct {
	Arch    string
	Name    string
	Version string
}
type Capabilities map[string]interface{}
type Session struct {
	Id           string
	Capabilities Capabilities
	wd           WebDriver
}
type WindowHandle struct {
	s  *Session
	id string
}
type Size struct {
	Width  int
	Height int
}
type Position struct {
	X int
	Y int
}
type FindElementStrategy string
const (
	ClassName = FindElementStrategy("class name")
	CSS_Selector = FindElementStrategy("css selector")
	ID = FindElementStrategy("id")
	Name = FindElementStrategy("name")
	LinkText = FindElementStrategy("link text")
	PartialLinkText = FindElementStrategy("partial link text")
	TagName = FindElementStrategy("tag name")
	XPath = FindElementStrategy("xpath")
)
type element struct {
	ELEMENT string
}
type WebElement struct {
	s  *Session
	id string
}
type Cookie struct {
	Name   string
	Value  string
	Path   string
	Domain string
	Secure bool
	Expiry int
}
type GeoLocation struct {
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
	Altitude  float64 `json:"altitude"`
}
type LogLevel string
const (
	LogAll     = LogLevel("ALL")
	LogDebug   = LogLevel("DEBUG")
	LogInfo    = LogLevel("INFO")
	LogWarning = LogLevel("WARNING")
	LogSevere  = LogLevel("SEVERE")
	LogOff     = LogLevel("OFF")
)
type LogEntry struct {
	TimeStamp int  
	Level     string
	Message   string
}
type HTML5CacheStatus int
const (
	CacheStatusUncached    = HTML5CacheStatus(0)
	CacheStatusIdle        = HTML5CacheStatus(1)
	CacheStatusChecking    = HTML5CacheStatus(2)
	CacheStatusDownloading = HTML5CacheStatus(3)
	CacheStatusUpdateReady = HTML5CacheStatus(4)
	CacheStatusObsolete    = HTML5CacheStatus(5)
)
func (s Session) GetCapabilities() Capabilities {
	return s.Capabilities
}
func (s Session) Delete() error {
	_, _, err := s.wd.do(nil, "DELETE", "/session/%s", s.Id)
	return err
}
func (s Session) SetTimeouts(typ string, ms int) error {
	p := params{"type": typ, "ms": ms}
	_, _, err := s.wd.do(p, "POST", "/session/%s/timeouts", s.Id)
	return err
}
func (s Session) SetTimeoutsAsyncScript(ms int) error {
	p := params{"ms": ms}
	_, _, err := s.wd.do(p, "POST", "/session/%s/timeouts/async_script", s.Id)
	return err
}
func (s Session) SetTimeoutsImplicitWait(ms int) error {
	p := params{"ms": ms}
	_, _, err := s.wd.do(p, "POST", "/session/%s/timeouts/implicit_wait", s.Id)
	return err
}
func (s Session) GetCurrentWindowHandle() WindowHandle {
	return WindowHandle{&s, "current"}
}
func (s Session) WindowHandle() (WindowHandle, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/window_handle", s.Id)
	if err != nil {
		return WindowHandle{}, err
	}
	var handle string
	err = json.Unmarshal(data, &handle)
	return WindowHandle{&s, handle}, err
}
func (s Session) WindowHandles() ([]WindowHandle, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/window_handles", s.Id)
	if err != nil {
		return nil, err
	}
	var hv []string
	err = json.Unmarshal(data, &hv)
	if err != nil {
		return nil, err
	}
	var handles = make([]WindowHandle, len(hv))
	for i, h := range hv {
		handles[i] = WindowHandle{&s, h}
	}
	return handles, nil
}
func (s Session) GetUrl() (string, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/url", s.Id)
	if err != nil {
		return "", err
	}
	var url string
	err = json.Unmarshal(data, &url)
	return url, err
}
func (s Session) Url(url string) error {
	p := params{"url": url}
	_, _, err := s.wd.do(p, "POST", "/session/%s/url", s.Id)
	return err
}
func (s Session) Forward() error {
	_, _, err := s.wd.do(nil, "POST", "/session/%s/forward", s.Id)
	return err
}
func (s Session) Back() error {
	_, _, err := s.wd.do(nil, "POST", "/session/%s/back", s.Id)
	return err
}
func (s Session) Refresh() error {
	_, _, err := s.wd.do(nil, "POST", "/session/%s/refresh", s.Id)
	return err
}
func (s Session) ExecuteScript(script string, args []interface{}) ([]byte, error) {
	p := params{"script": script, "args": args}
	_, data, err := s.wd.do(p, "POST", "/session/%s/execute", s.Id)
	return data, err
}
func (s Session) ExecuteScriptAsync(script string, args []interface{}) ([]byte, error) {
	p := params{"script": script, "args": args}
	_, data, err := s.wd.do(p, "POST", "/session/%s/execute_async", s.Id)
	return data, err
}
func (s Session) Screenshot() ([]byte, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/screenshot", s.Id)
	if err != nil {
		return nil, err
	}
	reader := bytes.NewBuffer(data[1 : len(data)-1])
	decoder := base64.NewDecoder(base64.StdEncoding, reader)
	return ioutil.ReadAll(decoder)
}
func (s Session) IMEAvailableEngines() ([]string, error) {
	_, data, err := s.wd.do(nil, "GET", "session/%s/ime/available_engines", s.Id)
	if err != nil {
		return nil, err
	}
	var engines []string
	err = json.Unmarshal(data, &engines)
	return engines, err
}
func (s Session) IMEActiveEngine() (string, error) {
	_, data, err := s.wd.do(nil, "GET", "session/%s/ime/active_engine", s.Id)
	if err != nil {
		return "", err
	}
	var engine string
	err = json.Unmarshal(data, &engine)
	return engine, err
}
func (s Session) IsIMEActivated() (bool, error) {
	_, data, err := s.wd.do(nil, "GET", "session/%s/ime/activated", s.Id)
	if err != nil {
		return false, err
	}
	var activated bool
	err = json.Unmarshal(data, &activated)
	return activated, err
}
func (s Session) IMEDeactivate() error {
	_, _, err := s.wd.do(nil, "GET", "session/%s/ime/deactivate", s.Id)
	return err
}
func (s Session) IMEActivate(engine string) error {
	p := params{"engine": engine}
	_, _, err := s.wd.do(p, "POST", "/session/%s/ime/activate", s.Id)
	return err
}
func (s Session) FocusOnFrame(frameId interface{}) error {
	if frameId != nil {
		switch frameId.(type) {
		case string:
		case int:
		case WebElement:
		default:
			return errors.New("invalid frame, must be string|int|nil|WebElement")
		}
	}
	p := params{"id": frameId}
	_, _, err := s.wd.do(p, "POST", "/session/%s/frame", s.Id)
	return err
}
func (s Session) FocusParentFrame() error {
	_, _, err := s.wd.do(nil, "POST", "/session/%s/frame/parent", s.Id)
	return err
}
func (s Session) FocusOnWindow(name string) error {
	p := params{"name": name}
	_, _, err := s.wd.do(p, "POST", "/session/%s/window", s.Id)
	return err
}
func (s Session) CloseCurrentWindow() error {
	_, _, err := s.wd.do(nil, "DELETE", "/session/%s/window", s.Id)
	return err
}
func (w WindowHandle) SetSize(size Size) error {
	p := params{"width": size.Width, "height": size.Height}
	_, _, err := w.s.wd.do(p, "POST", "/session/%s/window/%s/size", w.s.Id, w.id)
	return err
}
func (w WindowHandle) GetSize() (Size, error) {
	_, data, err := w.s.wd.do(nil, "GET", "/session/%s/window/%s/size", w.s.Id, w.id)
	if err != nil {
		return Size{}, err
	}
	var outSize Size
	err = json.Unmarshal(data, &outSize)
	return outSize, err
}
func (w WindowHandle) SetPosition(position Position) error {
	p := params{"x": position.X, "y": position.Y}
	_, _, err := w.s.wd.do(p, "POST", "/session/%s/window/%s/position", w.s.Id, w.id)
	return err
}
func (w WindowHandle) GetPosition() (Position, error) {
	_, data, err := w.s.wd.do(nil, "GET", "/session/%s/window/%s/position", w.s.Id, w.id)
	if err != nil {
		return Position{}, err
	}
	var position Position
	err = json.Unmarshal(data, &position)
	return position, err
}
func (w WindowHandle) MaximizeWindow() error {
	_, _, err := w.s.wd.do(nil, "POST", "/session/%s/window/%s/maximize", w.s.Id, w.id)
	return err
}
func (s Session) GetCookies() ([]Cookie, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/cookie", s.Id)
	if err != nil {
		return nil, err
	}
	var cookies []Cookie
	err = json.Unmarshal(data, &cookies)
	return cookies, err
}
func (s Session) SetCookie(cookie Cookie) error {
	p := params{"cookie": cookie}
	_, _, err := s.wd.do(p, "POST", "/session/%s/cookie", s.Id)
	return err
}
func (s Session) DeleteCookies() error {
	_, _, err := s.wd.do(nil, "DELETE", "/session/%s/cookie", s.Id)
	return err
}
func (s Session) DeleteCookieByName(name string) error {
	_, _, err := s.wd.do(nil, "DELETE", "/session/%s/cookie/%s", s.Id, name)
	return err
}
func (s Session) Source() (string, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/source", s.Id)
	if err != nil {
		return "", err
	}
	var source string
	err = json.Unmarshal(data, &source)
	return source, err
}
func (s Session) Title() (string, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/title", s.Id)
	if err != nil {
		return "", err
	}
	var title string
	err = json.Unmarshal(data, &title)
	return title, err
}
func (s Session) WebElementFromId(id string) WebElement {
	return WebElement{&s, id}
}
func (s Session) FindElement(using FindElementStrategy, value string) (WebElement, error) {
	p := params{"using": using, "value": value}
	_, data, err := s.wd.do(p, "POST", "/session/%s/element", s.Id)
	if err != nil {
		return WebElement{}, err
	}
	var elem element
	err = json.Unmarshal(data, &elem)
	return WebElement{&s, elem.ELEMENT}, err
}
func (s Session) FindElements(using FindElementStrategy, value string) ([]WebElement, error) {
	p := params{"using": using, "value": value}
	_, data, err := s.wd.do(p, "POST", "/session/%s/elements", s.Id)
	if err != nil {
		return nil, err
	}
	var v []element
	err = json.Unmarshal(data, &v)
	if err != nil {
		return nil, err
	}
	elements := make([]WebElement, len(v))
	for i, elem := range v {
		elements[i] = WebElement{&s, elem.ELEMENT}
	}
	return elements, err
}
func (s Session) GetActiveElement() (WebElement, error) {
	_, data, err := s.wd.do(nil, "POST", "/session/%s/element/active", s.Id)
	if err != nil {
		return WebElement{}, err
	}
	var elem element
	err = json.Unmarshal(data, &elem)
	return WebElement{&s, elem.ELEMENT}, err
}
func (e WebElement) FindElement(using FindElementStrategy, value string) (WebElement, error) {
	p := params{"using": using, "value": value}
	_, data, err := e.s.wd.do(p, "POST", "/session/%s/element/%s/element", e.s.Id, e.id)
	if err != nil {
		return WebElement{}, err
	}
	var elem element
	err = json.Unmarshal(data, &elem)
	return WebElement{e.s, elem.ELEMENT}, err
}
func (e WebElement) FindElements(using FindElementStrategy, value string) ([]WebElement, error) {
	p := params{"using": using, "value": value}
	_, data, err := e.s.wd.do(p, "POST", "/session/%s/element/%s/elements", e.s.Id, e.id)
	if err != nil {
		return nil, err
	}
	var v []element
	err = json.Unmarshal(data, &v)
	if err != nil {
		return nil, err
	}
	elements := make([]WebElement, len(v))
	for i, z := range v {
		elements[i] = WebElement{e.s, z.ELEMENT}
	}
	return elements, err
}
func (e WebElement) Click() error {
	_, _, err := e.s.wd.do(nil, "POST", "/session/%s/element/%s/click", e.s.Id, e.id)
	return err
}
func (e WebElement) Submit() error {
	_, _, err := e.s.wd.do(nil, "POST", "/session/%s/element/%s/submit", e.s.Id, e.id)
	return err
}
func (e WebElement) Text() (string, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/text", e.s.Id, e.id)
	if err != nil {
		return "", err
	}
	var text string
	err = json.Unmarshal(data, &text)
	return text, err
}
func (e WebElement) SendKeys(sequence string) error {
	keys := make([]string, len(sequence))
	for i, k := range sequence {
		keys[i] = string(k)
	}
	p := params{"value": keys}
	_, _, err := e.s.wd.do(p, "POST", "/session/%s/element/%s/value", e.s.Id, e.id)
	return err
}
func (s Session) SendKeysOnActiveElement(sequence string) error {
	keys := make([]string, len(sequence))
	for i, k := range sequence {
		keys[i] = string(k)
	}
	p := params{"value": keys}
	_, _, err := s.wd.do(p, "POST", "/session/%s/keys", s.Id)
	return err
}
func (e WebElement) Name() (string, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/name", e.s.Id, e.id)
	if err != nil {
		return "", err
	}
	var name string
	err = json.Unmarshal(data, &name)
	return name, err
}
func (e WebElement) Clear() error {
	_, _, err := e.s.wd.do(nil, "POST", "/session/%s/element/%s/clear", e.s.Id, e.id)
	return err
}
func (e WebElement) IsSelected() (bool, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/value", e.s.Id, e.id)
	if err != nil {
		return false, err
	}
	var isSelected bool
	err = json.Unmarshal(data, &isSelected)
	return isSelected, err
}
func (e WebElement) IsEnabled() (bool, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/enabled", e.s.Id, e.id)
	if err != nil {
		return false, err
	}
	var isEnabled bool
	err = json.Unmarshal(data, &isEnabled)
	return isEnabled, err
}
func (e WebElement) GetAttribute(name string) (string, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/attribute/%s", e.s.Id, e.id, name)
	if err != nil {
		return "", err
	}
	var attribute string
	err = json.Unmarshal(data, &attribute)
	return attribute, err
}
func (e WebElement) Equal(element WebElement) (bool, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/equal/%s", e.s.Id, e.id, element.id)
	if err != nil {
		return false, err
	}
	var equal bool
	err = json.Unmarshal(data, &equal)
	return equal, err
}
func (e WebElement) IsDisplayed() (bool, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/displayed", e.s.Id, e.id)
	if err != nil {
		return false, err
	}
	var isDisplayed bool
	err = json.Unmarshal(data, &isDisplayed)
	return isDisplayed, err
}
func (e WebElement) GetLocation() (Position, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/location", e.s.Id, e.id)
	if err != nil {
		return Position{}, err
	}
	var position Position
	err = json.Unmarshal(data, &position)
	return position, err
}
func (e WebElement) GetLocationInView() (Position, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/location_in_view", e.s.Id, e.id)
	if err != nil {
		return Position{}, err
	}
	var position Position
	err = json.Unmarshal(data, &position)
	return position, err
}
func (e WebElement) Size() (Size, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/size", e.s.Id, e.id)
	if err != nil {
		return Size{}, err
	}
	var size Size
	err = json.Unmarshal(data, &size)
	return size, err
}
func (e WebElement) GetCssProperty(name string) (string, error) {
	_, data, err := e.s.wd.do(nil, "GET", "/session/%s/element/%s/css/%s", e.s.Id, e.id, name)
	if err != nil {
		return "", err
	}
	var cssProperty string
	err = json.Unmarshal(data, &cssProperty)
	return cssProperty, err
}
type ScreenOrientation string
const (
	LANDSCAPE = iota
	PORTRAIT
)
func (s Session) GetOrientation() (ScreenOrientation, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/orientation", s.Id)
	if err != nil {
		return "", err
	}
	var orientation ScreenOrientation
	err = json.Unmarshal(data, &orientation)
	return orientation, err
}
func (s Session) SetOrientation(orientation ScreenOrientation) error {
	p := params{"orientation": orientation}
	_, _, err := s.wd.do(p, "POST", "/session/%s/orientation", s.Id)
	return err
}
func (s Session) GetAlertText() (string, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/alert_text", s.Id)
	if err != nil {
		return "", err
	}
	var alertText string
	err = json.Unmarshal(data, &alertText)
	return alertText, err
}
func (s Session) SetAlertText(text string) error {
	p := params{"text": text}
	_, _, err := s.wd.do(p, "POST", "/session/%s/alert_text", s.Id)
	return err
}
func (s Session) AcceptAlert() error {
	_, _, err := s.wd.do(nil, "POST", "/session/%s/accept_alert", s.Id)
	return err
}
func (s Session) DismissAlert() error {
	_, _, err := s.wd.do(nil, "POST", "/session/%s/dismiss_alert", s.Id)
	return err
}
func (s Session) MoveTo(element WebElement, xoffset, yoffset int) error {
	p := params{"element": element.id, "xoffset": xoffset, "yoffset": yoffset}
	_, _, err := s.wd.do(p, "POST", "/session/%s/moveto", s.Id)
	return err
}
type MouseButton int
const (
	LeftButton   = MouseButton(0)
	MiddleButton = MouseButton(1)
	RightButton  = MouseButton(2)
)
func (s Session) Click(button MouseButton) error {
	p := params{"button": button}
	_, _, err := s.wd.do(p, "POST", "/session/%s/click", s.Id)
	return err
}
func (s Session) ButtonDown(button MouseButton) error {
	p := params{"button": button}
	_, _, err := s.wd.do(p, "POST", "/session/%s/buttondown", s.Id)
	return err
}
func (s Session) ButtonUp(button MouseButton) error {
	p := params{"button": button}
	_, _, err := s.wd.do(p, "POST", "/session/%s/buttonup", s.Id)
	return err
}
func (s Session) DoubleClick() error {
	_, _, err := s.wd.do(nil, "POST", "/session/%s/doubleclick", s.Id)
	return err
}
func (s Session) TouchClick(element WebElement) error {
	p := params{"element": element.id}
	_, _, err := s.wd.do(p, "POST", "/session/%s/touch/click", s.Id)
	return err
}
func (s Session) TouchDown(x, y int) error {
	p := params{"x": x, "y": y}
	_, _, err := s.wd.do(p, "POST", "/session/%s/touch/down", s.Id)
	return err
}
func (s Session) TouchUp(x, y int) error {
	p := params{"x": x, "y": y}
	_, _, err := s.wd.do(p, "POST", "/session/%s/touch/up", s.Id)
	return err
}
func (s Session) TouchMove(x, y int) error {
	p := params{"x": x, "y": y}
	_, _, err := s.wd.do(p, "POST", "/session/%s/touch/move", s.Id)
	return err
}
func (s Session) TouchScroll(element WebElement, xoffset, yoffset int) error {
	p := params{"element": element.id, "xoffset": xoffset, "yoffset": yoffset}
	_, _, err := s.wd.do(p, "POST", "/session/%s/touch/scroll", s.Id)
	return err
}
func (s Session) TouchDoubleClick(element WebElement) error {
	p := params{"element": element.id}
	_, _, err := s.wd.do(p, "POST", "/session/%s/touch/doubleclick", s.Id)
	return err
}
func (s Session) TouchLongClick(element WebElement) error {
	p := params{"element": element.id}
	_, _, err := s.wd.do(p, "POST", "/session/%s/touch/longclick", s.Id)
	return err
}
func (s Session) TouchFlick(element WebElement, xoffset, yoffset, speed int) error {
	p := params{"element": element.id, "xoffset": xoffset, "yoffset": yoffset, "speed": speed}
	_, _, err := s.wd.do(p, "POST", "/session/%s/touch/flick", s.Id)
	return err
}
func (s Session) TouchFlickAnywhere(xspeed, yspeed int) error {
	p := params{"xspeed": xspeed, "yspeed": yspeed}
	_, _, err := s.wd.do(p, "POST", "/session/%s/touch/flick", s.Id)
	return err
}
func (s Session) GetGeoLocation() (GeoLocation, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/location", s.Id)
	if err != nil {
		return GeoLocation{}, err
	}
	var location GeoLocation
	err = json.Unmarshal(data, &location)
	return location, err
}
func (s Session) SetGeoLocation(location GeoLocation) error {
	p := params{"location": location}
	_, _, err := s.wd.do(p, "POST", "/session/%s/location", s.Id)
	return err
}
func (s Session) storageGetKeys(storageType string) ([]string, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/%s", s.Id, storageType)
	if err != nil {
		return nil, err
	}
	var keys []string
	err = json.Unmarshal(data, &keys)
	return keys, err
}
func (s Session) storageSetKey(storageType, key, value string) error {
	p := params{"key": key, "value": value}
	_, _, err := s.wd.do(p, "POST", "/session/%s/%s", s.Id, storageType)
	return err
}
func (s Session) storageClear(storageType string) error {
	_, _, err := s.wd.do(nil, "DELETE", "/session/%s/%s", s.Id, storageType)
	return err
}
func (s Session) storageGetKey(storageType, key string) (string, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/%s/key/%s", s.Id, storageType, key)
	if err != nil {
		return "", err
	}
	var value string
	err = json.Unmarshal(data, &value)
	return value, err
}
func (s Session) storageRemoveKey(storageType string, key string) error {
	_, _, err := s.wd.do(nil, "DELETE", "/session/%s/%s/key/%s", s.Id, storageType, key)
	return err
}
func (s Session) storageSize(storageType string) (int, error) {
	_, data, err := s.wd.do(nil, "GET", "/session/%s/%s/size", s.Id, storageType)
	if err != nil {
		return -1, err
	}
	var size int
	err = json.Unmarshal(data, &size)
	return size, err
}
func (s Session) LocalStorageGetKeys() ([]string, error) {
	return s.storageGetKeys("local_storage")
}
func (s Session) LocalStorageSetKey(key, value string) error {
	return s.storageSetKey("local_storage", key, value)
}
func (s Session) LocalStorageClear() error {
	return s.storageClear("local_storage")
}
func (s Session) LocalStorageGetKey(key string) (string, error) {
	return s.storageGetKey("local_storage", key)
}
func (s Session) LocalStorageRemoveKey(key string) error {
	return s.storageRemoveKey("local_storage", key)
}
func (s Session) LocalStorageSize() (int, error) {
	return s.storageSize("local_storage")
}