chromedp/input.go
Kenneth Shaw 4145d8367d Addition of chromedp-proxy, fixing SendKeys, more
- Adding chromedp-proxy command to help record chrome sessions
- Changing the headless writeup to point to the knq chrome-headless
  docker image
- Fixing issues with SendKeys action (should correctly work for all
  well known keys)
- Updated to latest Chrome protocol.json and re-generated API
- Other minor fixes
2017-02-07 11:34:35 +07:00

145 lines
3.8 KiB
Go

package chromedp
import (
"context"
"errors"
"time"
"github.com/knq/chromedp/cdp"
"github.com/knq/chromedp/cdp/dom"
"github.com/knq/chromedp/cdp/input"
"github.com/knq/chromedp/kb"
)
// Error types.
var (
ErrInvalidDimensions = errors.New("invalid box dimensions")
)
// MouseAction is a mouse action.
func MouseAction(typ input.MouseType, x, y int64, opts ...MouseOption) Action {
f := input.DispatchMouseEvent(typ, x, y)
for _, o := range opts {
f = o(f)
}
return f
}
// MouseClickXY sends a left mouse button click at the X, Y location.
func MouseClickXY(x, y int64, opts ...MouseOption) Action {
return Tasks{
MouseAction(input.MousePressed, x, y, append(opts, Button(input.ButtonLeft), ClickCount(1))...),
MouseAction(input.MouseReleased, x, y, append(opts, Button(input.ButtonLeft), ClickCount(1))...),
}
}
// MouseActionNode dispatches a mouse event at the center of a specified node.
func MouseActionNode(n *cdp.Node, opts ...MouseOption) Action {
return ActionFunc(func(ctxt context.Context, h cdp.FrameHandler) error {
box, err := dom.GetBoxModel(n.NodeID).Do(ctxt, h)
if err != nil {
return err
}
c := len(box.Content)
if c%2 != 0 {
return ErrInvalidDimensions
}
var x, y int64
for i := 0; i < c; i += 2 {
x += int64(box.Content[i])
y += int64(box.Content[i+1])
}
return MouseClickXY(x/int64(c/2), y/int64(c/2), opts...).Do(ctxt, h)
})
}
// MouseOption is a mouse action option.
type MouseOption func(*input.DispatchMouseEventParams) *input.DispatchMouseEventParams
// Button is a mouse action option to set the button to click.
func Button(button input.ButtonType) MouseOption {
return func(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(button)
}
}
// ButtonString is a mouse action option to set the button to click as a
// string.
func ButtonString(btn string) MouseOption {
return Button(input.ButtonType(btn))
}
// ButtonModifiers is a mouse action option to add additional modifiers for the
// button.
func ButtonModifiers(modifiers ...input.Modifier) MouseOption {
return func(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
for _, m := range modifiers {
p.Modifiers |= m
}
return p
}
}
// ClickCount is a mouse action option to set the click count.
func ClickCount(n int) MouseOption {
return func(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithClickCount(int64(n))
}
}
// KeyAction will synthesize a keyDown, char, and keyUp event for each rune
// contained in keys along with any supplied key options. Well known KeyCode
// runes will not synthesize the char event.
//
// Note: KeyCodeCR and KeyCodeLF are exceptions to the above, and a char of
// KeyCodeCR ('\r') will be synthesized for both.
func KeyAction(keys string, opts ...KeyOption) Action {
return ActionFunc(func(ctxt context.Context, h cdp.FrameHandler) error {
var err error
for _, r := range keys {
for _, k := range kb.Encode(r) {
err = k.Do(ctxt, h)
if err != nil {
return err
}
}
// TODO: move to context
time.Sleep(5 * time.Millisecond)
}
return nil
})
}
// KeyActionNode dispatches a key event on a node.
func KeyActionNode(n *cdp.Node, keys string, opts ...KeyOption) Action {
return ActionFunc(func(ctxt context.Context, h cdp.FrameHandler) error {
err := dom.Focus(n.NodeID).Do(ctxt, h)
if err != nil {
return err
}
return KeyAction(keys, opts...).Do(ctxt, h)
})
}
// KeyOption is a key action option.
type KeyOption func(*input.DispatchKeyEventParams) *input.DispatchKeyEventParams
// KeyModifiers is a key action option to add additional modifiers on the key
// press.
func KeyModifiers(modifiers ...input.Modifier) KeyOption {
return func(p *input.DispatchKeyEventParams) *input.DispatchKeyEventParams {
for _, m := range modifiers {
p.Modifiers |= m
}
return p
}
}