1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-07-05 00:49:00 +02:00

#23 Added NAVIGATE

This commit is contained in:
Tim Voronov
2018-09-25 19:04:07 -04:00
parent 3854bb39ce
commit a6b51a1f40
7 changed files with 181 additions and 28 deletions

View File

@ -14,6 +14,7 @@ import (
"github.com/mafredri/cdp/protocol/emulation"
"github.com/mafredri/cdp/protocol/page"
"github.com/mafredri/cdp/rpcc"
"github.com/pkg/errors"
"strings"
"sync"
"time"
@ -43,7 +44,7 @@ func LoadHtmlDocument(
client := cdp.NewClient(conn)
err := RunBatch(
err := runBatch(
func() error {
return client.Page.Enable(ctx)
},
@ -96,25 +97,9 @@ func LoadHtmlDocument(
return NewHtmlDocument(conn, client, root, broker), nil
}
func waitForLoadEvent(ctx context.Context, client *cdp.Client) error {
loadEventFired, err := client.Page.LoadEventFired(ctx)
if err != nil {
return err
}
_, err = loadEventFired.Recv()
if err != nil {
return err
}
return loadEventFired.Close()
}
func getRootElement(client *cdp.Client) (dom.Node, error) {
args := dom.NewGetDocumentArgs()
args.Depth = PointerInt(1) // lets load the entire document
args.Depth = pointerInt(1) // lets load the entire document
d, err := client.DOM.GetDocument(context.Background(), args)
@ -419,3 +404,18 @@ func (doc *HtmlDocument) WaitForNavigation(timeout values.Int) error {
}
}
}
func (doc *HtmlDocument) Navigate(url values.String) error {
ctx := context.Background()
repl, err := doc.client.Page.Navigate(ctx, page.NewNavigateArgs(url.String()))
if err != nil {
return err
}
if repl.ErrorText != nil {
return errors.New(*repl.ErrorText)
}
return waitForLoadEvent(ctx, doc.client)
}

View File

@ -2,11 +2,11 @@ package eval
import (
"context"
"encoding/json"
"fmt"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/mafredri/cdp"
"github.com/mafredri/cdp/protocol/dom"
"github.com/mafredri/cdp/protocol/runtime"
)
@ -36,15 +36,82 @@ func Eval(client *cdp.Client, exp string, ret bool, async bool) (core.Value, err
}
if out.Result.Type != "undefined" {
var o interface{}
return values.Unmarshal(out.Result.Value)
}
err := json.Unmarshal(out.Result.Value, &o)
return Unmarshal(&out.Result)
}
if err != nil {
return values.None, core.Error(core.ErrUnexpected, err.Error())
func Property(
ctx context.Context,
client *cdp.Client,
id dom.NodeID,
propName string,
) (core.Value, error) {
// get a ref to remote object representing the node
obj, err := client.DOM.ResolveNode(
ctx,
dom.NewResolveNodeArgs().
SetNodeID(id),
)
if err != nil {
return values.None, err
}
if obj.Object.ObjectID == nil {
return values.None, core.Error(core.ErrNotFound, fmt.Sprintf("element %d", id))
}
defer client.Runtime.ReleaseObject(ctx, runtime.NewReleaseObjectArgs(*obj.Object.ObjectID))
res, err := client.Runtime.GetProperties(
ctx,
runtime.NewGetPropertiesArgs(*obj.Object.ObjectID),
)
if err != nil {
return values.None, err
}
if res.ExceptionDetails != nil {
return values.None, res.ExceptionDetails
}
// all props
if propName == "" {
var arr *values.Array
arr = values.NewArray(len(res.Result))
for _, prop := range res.Result {
val, err := Unmarshal(prop.Value)
if err != nil {
return values.None, err
}
arr.Push(val)
}
return values.Parse(o), nil
return arr, nil
}
for _, prop := range res.Result {
if prop.Name == propName {
return Unmarshal(prop.Value)
}
}
return values.None, nil
}
func Unmarshal(obj *runtime.RemoteObject) (core.Value, error) {
if obj == nil {
return values.None, nil
}
if obj.Type != "undefined" {
return values.Unmarshal(obj.Value)
}
return values.None, nil

View File

@ -1,16 +1,18 @@
package browser
import (
"context"
"github.com/mafredri/cdp"
"golang.org/x/sync/errgroup"
)
func PointerInt(input int) *int {
func pointerInt(input int) *int {
return &input
}
type BatchFunc = func() error
type batchFunc = func() error
func RunBatch(funcs ...BatchFunc) error {
func runBatch(funcs ...batchFunc) error {
eg := errgroup.Group{}
for _, f := range funcs {
@ -19,3 +21,23 @@ func RunBatch(funcs ...BatchFunc) error {
return eg.Wait()
}
func contextWithTimeout() (context.Context, context.CancelFunc) {
return context.WithTimeout(context.Background(), DefaultTimeout)
}
func waitForLoadEvent(ctx context.Context, client *cdp.Client) error {
loadEventFired, err := client.Page.LoadEventFired(ctx)
if err != nil {
return err
}
_, err = loadEventFired.Recv()
if err != nil {
return err
}
return loadEventFired.Close()
}