Skip to content

Commit

Permalink
remotejs🎉
Browse files Browse the repository at this point in the history
  • Loading branch information
1oid committed Jun 2, 2023
1 parent 9814fab commit fbd8792
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@

# Go workspace file
go.work
remotejs_*
.idea/
go.sum
8 changes: 8 additions & 0 deletions cmd/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
rm -rf remotejs_windows_386.exe remotejs_windows_amd64.exe remotejs_darwin_amd64 remotejs_darwin_arm64
echo "gen windows"
CGO_ENABLED=1 GOOS=windows GOARCH=386 CC="i686-w64-mingw32-gcc" go build --trimpath -ldflags "-s -w" -o remotejs_windows_386.exe main.go
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC="x86_64-w64-mingw32-gcc" go build --trimpath -ldflags "-s -w" -o remotejs_windows_amd64.exe main.go
echo "gen darwin"
go build --trimpath -ldflags "-s -w" -o remotejs_darwin_amd64 main.go
echo "gen darwin arm64"
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 SDKROOT=$(xcrun --sdk macosx --show-sdk-path) go build --trimpath -ldflags "-s -w" -o remotejs_darwin_arm64 main.go
45 changes: 45 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package main

import (
"errors"
"github.com/1oid/remotejs/pkgs/common"
"github.com/1oid/remotejs/pkgs/page"
"github.com/1oid/remotejs/pkgs/web"
"github.com/chromedp/cdproto/runtime"
"github.com/chromedp/chromedp"
"github.com/urfave/cli/v2"
"log"
"os"
)

func runner(c *cli.Context) error {
var tasks = chromedp.Tasks{}
var opts = page.NewOpts(
chromedp.Flag("headless", false))

if common.Vars.Url != "" {
tasks = append(tasks, chromedp.Navigate(common.Vars.Url))
}

if common.Vars.ChromePath != "" {
if _, err := os.Stat(common.Vars.ChromePath); err != nil {
log.Fatal(errors.New("error chrome path"))
}
opts = append(opts, chromedp.ExecPath(common.Vars.ChromePath))
}

if common.Vars.Proxy != "" {
opts = append(opts, chromedp.ProxyServer(common.Vars.Proxy))
}

var ctx = page.LaunchBrowser(tasks, opts, common.Vars.RemoteDebuggingAddr)

web.WebRunner(common.Vars.WebListenPort, func(t string) (*runtime.RemoteObject, error) {
return page.EvaluateCall(ctx, page.CallFrameId, t)
})
return nil
}

func main() {
common.NewRunner(runner)
}
43 changes: 43 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module github.com/1oid/remotejs

go 1.18

require (
github.com/bytedance/sonic v1.9.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/chromedp/cdproto v0.0.0-20230601223857-b9862e644d94 // indirect
github.com/chromedp/chromedp v0.9.1 // indirect
github.com/chromedp/sysutil v1.0.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.2.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/urfave/cli/v2 v2.25.5 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
3 changes: 3 additions & 0 deletions pkgs/common/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package common

var Vars = &VarsOption{}
10 changes: 10 additions & 0 deletions pkgs/common/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package common

type VarsOption struct {
Url string
ChromePath string
Devtools bool
WebListenPort string
Proxy string
RemoteDebuggingAddr string
}
56 changes: 56 additions & 0 deletions pkgs/common/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package common

import (
"github.com/urfave/cli/v2"
"log"
"os"
)

var cliApp *cli.App

func NewRunner(action cli.ActionFunc) {
cliApp.Action = action
err := cliApp.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}

func init() {
cliApp = &cli.App{
Flags: []cli.Flag{
&cli.StringFlag{
Name: "url",
Aliases: []string{"u"},
Usage: "open url when open chrome, default blank url",
Destination: &Vars.Url,
Value: "",
},
&cli.StringFlag{
Name: "chrome-path",
Aliases: []string{"cp"},
Usage: "use specified chrome path",
Destination: &Vars.ChromePath,
Value: "",
},
&cli.StringFlag{
Name: "proxy",
Usage: "set proxy for browser",
Destination: &Vars.Proxy,
Value: "",
},
&cli.StringFlag{
Name: "remote-debug-address",
Usage: "use remote chrome debugging",
Destination: &Vars.RemoteDebuggingAddr,
Value: "",
},
&cli.StringFlag{
Name: "web-listen",
Usage: "web server port",
Destination: &Vars.WebListenPort,
Value: "8088",
},
},
}
}
91 changes: 91 additions & 0 deletions pkgs/page/browser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package page

import (
"context"
"errors"
"github.com/chromedp/cdproto/cdp"
"github.com/chromedp/cdproto/debugger"
"github.com/chromedp/cdproto/runtime"
"github.com/chromedp/chromedp"
"log"
)

var CallFrameId debugger.CallFrameID

func addListener(ctx context.Context) {
chromedp.ListenTarget(ctx, func(ev interface{}) {
switch ev.(type) {
case *debugger.EventPaused:
var d = ev.(*debugger.EventPaused)

if len(d.CallFrames) > 0 {
CallFrameId = d.CallFrames[0].CallFrameID
}
}
})
}

func getContext(ctx context.Context) (*chromedp.Context, error) {
c := chromedp.FromContext(ctx)
// If c is nil, it's not a chromedp context.
// If c.Allocator is nil, NewContext wasn't used properly.
// If c.cancel is nil, Run is being called directly with an allocator
// context.
if c == nil || c.Allocator == nil {
return nil, chromedp.ErrInvalidContext
}
return c, nil
}

func EvaluateCall(ctx context.Context, callFrameId debugger.CallFrameID, expression string) (*runtime.RemoteObject, error) {
c, _ := getContext(ctx)
call := &debugger.EvaluateOnCallFrameParams{
CallFrameID: callFrameId,
Expression: expression,
ObjectGroup: "console",
IncludeCommandLineAPI: true,
ReturnByValue: true,
}
var result, _, err = call.Do(cdp.WithExecutor(ctx, c.Target))
if err != nil {
return nil, err
}
if result == nil {
return nil, errors.New("execute error")
}
if result.Subtype == runtime.SubtypeError {
return nil, errors.New(result.Description)
}
return result, nil

}

func NewOpts(opts ...chromedp.ExecAllocatorOption) []chromedp.ExecAllocatorOption {
return append(chromedp.DefaultExecAllocatorOptions[:], opts...)
}

func LaunchBrowser(tasks chromedp.Tasks, opts []chromedp.ExecAllocatorOption, remote string) context.Context {

var allocCtx context.Context

if remote != "" {
allocCtx, _ = chromedp.NewRemoteAllocator(context.Background(), remote)
} else {
allocCtx, _ = chromedp.NewExecAllocator(context.Background(), opts...)
}
var ctx, _ = chromedp.NewContext(
allocCtx, chromedp.WithLogf(log.Printf))

err := chromedp.Run(ctx)
if err != nil {
log.Fatal(err)
}

chromedp.Run(ctx, tasks, chromedp.ActionFunc(func(ctx context.Context) error {
_, err := debugger.Enable().Do(ctx)
return err
}))
go addListener(ctx)

return ctx
}
34 changes: 34 additions & 0 deletions pkgs/web/web.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package web

import (
"fmt"
"github.com/chromedp/cdproto/runtime"
"github.com/gin-gonic/gin"
"net/http"
)

func WebRunner(port string, callFunc func(t string) (*runtime.RemoteObject, error)) {
gin.SetMode(gin.ReleaseMode)
route := gin.New()
route.Use(gin.Recovery())

route.POST("/remote", func(context *gin.Context) {
evalString := context.PostForm("eval")

if result, err := callFunc(evalString); err != nil {
context.JSON(http.StatusOK, gin.H{
"error": err.Error(),
})
} else {
context.JSON(http.StatusOK, gin.H{
"value": result.Value,
"type": result.Type,
})
}

})

addr := fmt.Sprintf(`0.0.0.0:%s`, port)
fmt.Printf("[*] web server start: %s\n", addr)
route.Run(addr)
}

0 comments on commit fbd8792

Please sign in to comment.