init
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
ARG VERSION
|
||||
FROM golang:1.17 as go
|
||||
|
||||
COPY devtools /devtools
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install -y upx-ucl && \
|
||||
cd /devtools && \
|
||||
go test -race && \
|
||||
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" && \
|
||||
upx /devtools/devtools
|
||||
|
||||
FROM selenoid/dev_chrome:$VERSION
|
||||
|
||||
ENV DBUS_SESSION_BUS_ADDRESS=/dev/null
|
||||
COPY --from=go /devtools/devtools /usr/bin/
|
||||
COPY chromedriver /usr/bin/
|
||||
COPY entrypoint.sh /
|
||||
|
||||
RUN chmod +x /usr/bin/chromedriver
|
||||
USER selenium
|
||||
|
||||
EXPOSE 4444
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
@@ -0,0 +1,18 @@
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
ARG VERSION
|
||||
ARG PACKAGE=google-chrome-stable
|
||||
ARG INSTALL_DIR=chrome
|
||||
|
||||
LABEL browser=$PACKAGE:$VERSION
|
||||
|
||||
RUN \
|
||||
curl -s https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
|
||||
echo 'deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main' > /etc/apt/sources.list.d/google.list && \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install iproute2 $PACKAGE=$VERSION && \
|
||||
sed -i -e 's@exec -a "$0" "$HERE/chrome"@& --no-sandbox --disable-gpu@' /opt/google/$INSTALL_DIR/google-chrome && \
|
||||
chown root:root /opt/google/$INSTALL_DIR/chrome-sandbox && \
|
||||
chmod 4755 /opt/google/$INSTALL_DIR/chrome-sandbox && \
|
||||
google-chrome --version && \
|
||||
rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/*
|
||||
@@ -0,0 +1 @@
|
||||
devtools
|
||||
@@ -0,0 +1,187 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/mafredri/cdp/devtool"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
devtoolsBaseDir = "/tmp"
|
||||
slash = "/"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultDevtoolsHost = "127.0.0.1:9222"
|
||||
)
|
||||
|
||||
func root() http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/browser", browser)
|
||||
mux.HandleFunc("/json/protocol", protocol)
|
||||
mux.HandleFunc("/page", page)
|
||||
mux.HandleFunc("/page/", page)
|
||||
mux.HandleFunc("/", browser)
|
||||
return mux
|
||||
}
|
||||
|
||||
func browser(w http.ResponseWriter, r *http.Request) {
|
||||
u, err := getBrowserWebSocketUrl()
|
||||
if err != nil {
|
||||
log.Printf("[BROWSER_URL_ERROR] [%v]", err)
|
||||
return
|
||||
}
|
||||
log.Printf("[BROWSER] [%s]", u.String())
|
||||
proxyWebSocket(w, r, u)
|
||||
}
|
||||
|
||||
func proxyWebSocket(w http.ResponseWriter, r *http.Request, u *url.URL) {
|
||||
u.Scheme = "http"
|
||||
(&httputil.ReverseProxy{
|
||||
Director: func(r *http.Request) {
|
||||
r.Host = "localhost"
|
||||
r.URL = u
|
||||
},
|
||||
}).ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func page(w http.ResponseWriter, r *http.Request) {
|
||||
fragments := strings.Split(r.URL.Path, slash)
|
||||
targetId := ""
|
||||
if len(fragments) == 3 {
|
||||
targetId = fragments[2]
|
||||
}
|
||||
u, err := getPageWebSocketUrl(targetId)
|
||||
if err != nil {
|
||||
log.Printf("[PAGE_URL_ERROR] [%v]", err)
|
||||
return
|
||||
}
|
||||
log.Printf("[PAGE] [%s]", u.String())
|
||||
proxyWebSocket(w, r, u)
|
||||
}
|
||||
|
||||
func protocol(w http.ResponseWriter, r *http.Request) {
|
||||
h, err := devtoolsHost()
|
||||
if err != nil {
|
||||
log.Printf("[DEVTOOLS_HOST_ERROR] [%v]", err)
|
||||
http.Error(w, fmt.Sprintf("Failed to detect devtools host: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
u := &url.URL{
|
||||
Host: h,
|
||||
Scheme: "http",
|
||||
Path: "/json/protocol",
|
||||
}
|
||||
log.Printf("[PROTOCOL] [%s]", u.String())
|
||||
(&httputil.ReverseProxy{
|
||||
Director: func(r *http.Request) {
|
||||
r.Host = "localhost"
|
||||
r.URL = u
|
||||
},
|
||||
}).ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func getBrowserWebSocketUrl() (*url.URL, error) {
|
||||
ctx := context.Background()
|
||||
h, err := devtoolsHost()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to detect devtools port: %v", err)
|
||||
}
|
||||
dt := devtool.New(fmt.Sprintf("http://%s", h))
|
||||
ver, err := dt.Version(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get browser websocket url: %v", err)
|
||||
}
|
||||
|
||||
wsUrl, err := url.Parse(ver.WebSocketDebuggerURL)
|
||||
if err == nil {
|
||||
return wsUrl, nil
|
||||
}
|
||||
return nil, errors.New("browser websocket URL information not found")
|
||||
}
|
||||
|
||||
func getPageWebSocketUrl(targetId string) (*url.URL, error) {
|
||||
ctx := context.Background()
|
||||
h, err := devtoolsHost()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to detect devtools port: %v", err)
|
||||
}
|
||||
dt := devtool.New(fmt.Sprintf("http://%s", h))
|
||||
targets, err := dt.List(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list targets: %v", err)
|
||||
}
|
||||
for _, t := range targets {
|
||||
if (targetId == "" && t.Type == devtool.Page) || targetId == t.ID {
|
||||
wsUrl, err := url.Parse(t.WebSocketDebuggerURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid websocket URL for matched target %s: %v", t.ID, err)
|
||||
}
|
||||
return wsUrl, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("no matching target found")
|
||||
}
|
||||
|
||||
func devtoolsHost() (string, error) {
|
||||
if android {
|
||||
return androidDevtoolsHost()
|
||||
}
|
||||
return detectDevtoolsHost(devtoolsBaseDir), nil
|
||||
}
|
||||
|
||||
func androidDevtoolsHost() (string, error) {
|
||||
const androidDevtoolsPort = 9333
|
||||
cmd := exec.Command("adb", "forward", fmt.Sprintf("tcp:%d", androidDevtoolsPort), "localabstract:chrome_devtools_remote")
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to forward devtools port: %v", err)
|
||||
}
|
||||
return fmt.Sprintf("localhost:%d", androidDevtoolsPort), nil
|
||||
}
|
||||
|
||||
func detectDevtoolsHost(baseDir string) string {
|
||||
var candidates []string
|
||||
for _, glob := range []string{".com.google.Chrome*", ".org.chromium.Chromium*"} {
|
||||
cds, err := filepath.Glob(filepath.Join(baseDir, glob))
|
||||
if err == nil {
|
||||
candidates = append(candidates, cds...)
|
||||
}
|
||||
|
||||
}
|
||||
for _, c := range candidates {
|
||||
f, err := os.Stat(c)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if !f.IsDir() {
|
||||
continue
|
||||
}
|
||||
portFile := filepath.Join(c, "DevToolsActivePort")
|
||||
data, err := ioutil.ReadFile(portFile)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
lines := strings.Split(string(data), "\n")
|
||||
if len(lines) == 0 {
|
||||
continue
|
||||
}
|
||||
port, err := strconv.Atoi(lines[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return fmt.Sprintf("127.0.0.1:%d", port)
|
||||
}
|
||||
return defaultDevtoolsHost
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
. "github.com/aandryashin/matchers"
|
||||
. "github.com/aandryashin/matchers/httpresp"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/mafredri/cdp"
|
||||
"github.com/mafredri/cdp/protocol/target"
|
||||
"github.com/mafredri/cdp/rpcc"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
srv *httptest.Server
|
||||
devtoolsSrv *httptest.Server
|
||||
)
|
||||
|
||||
func init() {
|
||||
srv = httptest.NewServer(root())
|
||||
listen = srv.Listener.Addr().String()
|
||||
devtoolsSrv = httptest.NewServer(mockDevtoolsMux())
|
||||
defaultDevtoolsHost = devtoolsSrv.Listener.Addr().String()
|
||||
}
|
||||
|
||||
func mockDevtoolsMux() http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
version := func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.Write([]byte(fmt.Sprintf(`{
|
||||
"Browser": "Chrome/72.0.3601.0",
|
||||
"Protocol-Version": "1.3",
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3601.0 Safari/537.36",
|
||||
"V8-Version": "7.2.233",
|
||||
"WebKit-Version": "537.36 (@cfede9db1d154de0468cb0538479f34c0755a0f4)",
|
||||
"webSocketDebuggerUrl": "ws://%s/devtools/browser/b0b8a4fb-bb17-4359-9533-a8d9f3908bd8"
|
||||
}`, defaultDevtoolsHost)))
|
||||
}
|
||||
mux.HandleFunc("/json/version", version)
|
||||
listTargets := func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.Write([]byte(fmt.Sprintf(`[ {
|
||||
"description": "",
|
||||
"devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:9222/devtools/page/one",
|
||||
"id": "one",
|
||||
"title": "Aerokube",
|
||||
"type": "page",
|
||||
"url": "https://www.aerokube.com/",
|
||||
"webSocketDebuggerUrl": "ws://%s/devtools/page/one"
|
||||
}, {
|
||||
"description": "",
|
||||
"devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:9222/devtools/page/two",
|
||||
"id": "two",
|
||||
"title": "Aerokube Selenoid",
|
||||
"type": "page",
|
||||
"url": "https://selenoid.aerokube.com/",
|
||||
"webSocketDebuggerUrl": "ws://%s/devtools/page/two"
|
||||
} ]`, defaultDevtoolsHost, defaultDevtoolsHost)))
|
||||
|
||||
}
|
||||
mux.HandleFunc("/json/list", listTargets)
|
||||
mux.HandleFunc("/json", listTargets)
|
||||
|
||||
mux.HandleFunc("/json/protocol", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.Write([]byte("{}"))
|
||||
})
|
||||
|
||||
upgrader := websocket.Upgrader{
|
||||
CheckOrigin: func(_ *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
devtoolsEcho := func(w http.ResponseWriter, r *http.Request) {
|
||||
//Echo request ID but omit Method
|
||||
c, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer c.Close()
|
||||
for {
|
||||
mt, message, err := c.ReadMessage()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
var req rpcc.Request
|
||||
err = json.Unmarshal(message, &req)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
resp := rpcc.Response{
|
||||
ID: req.ID,
|
||||
}
|
||||
if req.Method == "Target.getTargets" {
|
||||
result := target.GetTargetsReply{
|
||||
TargetInfos: []target.Info{
|
||||
{TargetID: "one", Type: "page"},
|
||||
{TargetID: "two", Type: "page"},
|
||||
},
|
||||
}
|
||||
resBytes, _ := json.Marshal(result)
|
||||
resp.Result = json.RawMessage(resBytes)
|
||||
}
|
||||
output, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = c.WriteMessage(mt, output)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mux.HandleFunc("/devtools/browser/", devtoolsEcho)
|
||||
mux.HandleFunc("/devtools/page/", devtoolsEcho)
|
||||
return mux
|
||||
}
|
||||
|
||||
func TestProtocol(t *testing.T) {
|
||||
u := fmt.Sprintf("http://%s/json/protocol", srv.Listener.Addr().String())
|
||||
resp, err := http.Get(u)
|
||||
AssertThat(t, err, Is{nil})
|
||||
AssertThat(t, resp, Code{200})
|
||||
}
|
||||
|
||||
func TestDevtools(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
browserWs := fmt.Sprintf("ws://%s/", srv.Listener.Addr().String())
|
||||
browserConn, err := rpcc.DialContext(ctx, browserWs)
|
||||
AssertThat(t, err, Is{nil})
|
||||
defer browserConn.Close()
|
||||
|
||||
browserClient := cdp.NewClient(browserConn)
|
||||
targets, err := browserClient.Target.GetTargets(ctx)
|
||||
AssertThat(t, err, Is{nil})
|
||||
AssertThat(t, len(targets.TargetInfos), EqualTo{2})
|
||||
|
||||
defaultPageWs := fmt.Sprintf("ws://%s/page", srv.Listener.Addr().String())
|
||||
defaultPageConn, err := rpcc.DialContext(ctx, defaultPageWs)
|
||||
AssertThat(t, err, Is{nil})
|
||||
defer defaultPageConn.Close()
|
||||
defaultPageClient := cdp.NewClient(defaultPageConn)
|
||||
err = defaultPageClient.Page.Enable(ctx)
|
||||
AssertThat(t, err, Is{nil})
|
||||
|
||||
selectedPageWs := fmt.Sprintf("ws://%s/page/%s", srv.Listener.Addr().String(), targets.TargetInfos[1].TargetID)
|
||||
selectedPageConn, err := rpcc.DialContext(ctx, selectedPageWs)
|
||||
AssertThat(t, err, Is{nil})
|
||||
defer selectedPageConn.Close()
|
||||
selectedPageClient := cdp.NewClient(selectedPageConn)
|
||||
err = selectedPageClient.Page.Enable(ctx)
|
||||
AssertThat(t, err, Is{nil})
|
||||
}
|
||||
|
||||
func TestDetectDevtoolsHost(t *testing.T) {
|
||||
name, _ := ioutil.TempDir("", "devtools")
|
||||
defer os.RemoveAll(name)
|
||||
profilePath := filepath.Join(name, ".org.chromium.Chromium.deadbee")
|
||||
os.MkdirAll(profilePath, os.ModePerm)
|
||||
portFile := filepath.Join(profilePath, "DevToolsActivePort")
|
||||
ioutil.WriteFile(portFile, []byte("12345\n/devtools/browser/6f37c7fe-a0a6-4346-a6e2-80c5da0687f0"), 0644)
|
||||
|
||||
AssertThat(t, detectDevtoolsHost(name), EqualTo{"127.0.0.1:12345"})
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
module github.com/aerokube/devtools
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/aandryashin/matchers v0.0.0-20161126170413-435295ea180e
|
||||
github.com/google/go-cmp v0.2.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/mafredri/cdp v0.23.4
|
||||
golang.org/x/net v0.0.0-20190107210223-45ffb0cd1ba0 // indirect
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
github.com/aandryashin/matchers v0.0.0-20161126170413-435295ea180e h1:ogUKYFNcdYUIBSLibE4+EjbTJazoHr5JsWWx21Lpn8c=
|
||||
github.com/aandryashin/matchers v0.0.0-20161126170413-435295ea180e/go.mod h1:cbmYNkm9xeQlNoWEPtOUcvNok2gSD7ErMnYkRW+eHi8=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/mafredri/cdp v0.23.4 h1:ffp4qq6slfCL4rFWBDeRHapkLE776gER4tX5Z3LS8CY=
|
||||
github.com/mafredri/cdp v0.23.4/go.mod h1:hgdiA0yp1uqhSaDOHJWPgXpMbh+LAfUdD9vbN2AM8gE=
|
||||
golang.org/x/net v0.0.0-20190107210223-45ffb0cd1ba0 h1:1DW40AJQ7AP4nY6ORUGUdkpXyEC9W2GAXcOPaMZK0K8=
|
||||
golang.org/x/net v0.0.0-20190107210223-45ffb0cd1ba0/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var (
|
||||
listen string
|
||||
android bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&listen, "listen", ":7070", "Network address to accept connections")
|
||||
flag.BoolVar(&android, "android", false, "Whether we need to forward Android Emulator devtools port")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
log.Printf("[INIT] [Listening on %s]", listen)
|
||||
log.Fatal(http.ListenAndServe(listen, root()))
|
||||
}
|
||||
Executable
+93
@@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"}
|
||||
DISPLAY_NUM=99
|
||||
export DISPLAY=":$DISPLAY_NUM"
|
||||
|
||||
VERBOSE=${VERBOSE:-""}
|
||||
DRIVER_ARGS=${DRIVER_ARGS:-""}
|
||||
if [ -n "$VERBOSE" ]; then
|
||||
DRIVER_ARGS="$DRIVER_ARGS --verbose"
|
||||
fi
|
||||
|
||||
clean() {
|
||||
if [ -n "$FILESERVER_PID" ]; then
|
||||
kill -TERM "$FILESERVER_PID"
|
||||
fi
|
||||
if [ -n "$XSELD_PID" ]; then
|
||||
kill -TERM "$XSELD_PID"
|
||||
fi
|
||||
if [ -n "$XVFB_PID" ]; then
|
||||
kill -TERM "$XVFB_PID"
|
||||
fi
|
||||
if [ -n "$DRIVER_PID" ]; then
|
||||
kill -TERM "$DRIVER_PID"
|
||||
fi
|
||||
if [ -n "$X11VNC_PID" ]; then
|
||||
kill -TERM "$X11VNC_PID"
|
||||
fi
|
||||
if [ -n "$DEVTOOLS_PID" ]; then
|
||||
kill -TERM "$DEVTOOLS_PID"
|
||||
fi
|
||||
if [ -n "$PULSE_PID" ]; then
|
||||
kill -TERM "$PULSE_PID"
|
||||
fi
|
||||
}
|
||||
|
||||
trap clean SIGINT SIGTERM
|
||||
|
||||
if env | grep -q ROOT_CA_; then
|
||||
mkdir -p $HOME/.pki/nssdb
|
||||
certutil -N --empty-password -d sql:$HOME/.pki/nssdb
|
||||
for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do
|
||||
certname=$(echo -n $e | sed -e 's/ROOT_CA_//')
|
||||
echo ${!e} | base64 -d >/tmp/cert.pem
|
||||
certutil -A -n ${certname} -t "TC,C,T" -i /tmp/cert.pem -d sql:$HOME/.pki/nssdb
|
||||
if cat tmp/cert.pem | grep -q "PRIVATE KEY"; then
|
||||
PRIVATE_KEY_PASS=${PRIVATE_KEY_PASS:-\'\'}
|
||||
openssl pkcs12 -export -in /tmp/cert.pem -clcerts -nodes -out /tmp/key.p12 -passout pass:${PRIVATE_KEY_PASS} -passin pass:${PRIVATE_KEY_PASS}
|
||||
pk12util -d sql:$HOME/.pki/nssdb -i /tmp/key.p12 -W ${PRIVATE_KEY_PASS}
|
||||
rm /tmp/key.p12
|
||||
fi
|
||||
rm /tmp/cert.pem
|
||||
done
|
||||
fi
|
||||
|
||||
/usr/bin/fileserver &
|
||||
FILESERVER_PID=$!
|
||||
|
||||
/usr/bin/devtools &
|
||||
DEVTOOLS_PID=$!
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/xseld &
|
||||
XSELD_PID=$!
|
||||
|
||||
while ip addr | grep inet | grep -q tentative > /dev/null; do sleep 0.1; done
|
||||
|
||||
mkdir -p ~/pulse/.config/pulse
|
||||
echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/pulse/.config/pulse/cookie
|
||||
HOME=$HOME/pulse pulseaudio --start --exit-idle-time=-1
|
||||
HOME=$HOME/pulse pactl load-module module-native-protocol-tcp
|
||||
PULSE_PID=$(ps --no-headers -C pulseaudio -o pid | sed -r 's/( )+//g')
|
||||
|
||||
/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null &
|
||||
XVFB_PID=$!
|
||||
|
||||
retcode=1
|
||||
until [ $retcode -eq 0 ]; do
|
||||
DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1
|
||||
retcode=$?
|
||||
if [ $retcode -ne 0 ]; then
|
||||
echo Waiting X server...
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ENABLE_VNC" == "true" ]; then
|
||||
x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null &
|
||||
X11VNC_PID=$!
|
||||
fi
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/chromedriver --port=4444 --allowed-ips='' --allowed-origins='*' ${DRIVER_ARGS} &
|
||||
DRIVER_PID=$!
|
||||
|
||||
wait
|
||||
@@ -0,0 +1,62 @@
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
ARG VERSION=noop
|
||||
ARG PACKAGE=google-chrome-stable
|
||||
ARG INSTALL_DIR=chrome
|
||||
|
||||
LABEL browser=$PACKAGE:$VERSION
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install gconf-service \
|
||||
libasound2 \
|
||||
libatk1.0-0 \
|
||||
libc6 \
|
||||
libcairo2 \
|
||||
libcups2 \
|
||||
libdbus-1-3 \
|
||||
libexpat1 \
|
||||
libfontconfig1 \
|
||||
libfreetype6 \
|
||||
libgcc1 \
|
||||
libgconf-2-4 \
|
||||
libgdk-pixbuf2.0-0 \
|
||||
libglib2.0-0 \
|
||||
libgtk2.0-0 \
|
||||
libgtk-3-0 \
|
||||
libnspr4 \
|
||||
libnss3 \
|
||||
libpango1.0-0 \
|
||||
libstdc++6 \
|
||||
libx11-6 \
|
||||
libx11-xcb1 \
|
||||
libxcb1 \
|
||||
libxcomposite1 \
|
||||
libxcursor1 \
|
||||
libxdamage1 \
|
||||
libxext6 \
|
||||
libxfixes3 \
|
||||
libxi6 \
|
||||
libxrandr2 \
|
||||
libxrender1 \
|
||||
libxss1 \
|
||||
libxtst6 \
|
||||
ca-certificates \
|
||||
fonts-liberation \
|
||||
libappindicator3-1 \
|
||||
libnss3 \
|
||||
lsb-base \
|
||||
xdg-utils \
|
||||
libcurl4 \
|
||||
iproute2 \
|
||||
curl && \
|
||||
curl -O http://host.docker.internal:8080/google-chrome.deb && \
|
||||
apt-get -y purge curl && \
|
||||
dpkg -i google-chrome.deb && \
|
||||
sed -i -e 's@exec -a "$0" "$HERE/chrome"@& --no-sandbox --disable-gpu@' /opt/google/$INSTALL_DIR/$PACKAGE && \
|
||||
rm google-chrome.deb && \
|
||||
chown root:root /opt/google/$INSTALL_DIR/chrome-sandbox && \
|
||||
chmod 4755 /opt/google/$INSTALL_DIR/chrome-sandbox && \
|
||||
google-chrome --version && \
|
||||
rm -Rf /tmp/* && \
|
||||
rm -Rf /var/lib/apt/lists/*
|
||||
@@ -0,0 +1,12 @@
|
||||
ARG VERSION
|
||||
FROM selenoid/dev_edge:$VERSION
|
||||
|
||||
ENV DBUS_SESSION_BUS_ADDRESS=/dev/null
|
||||
COPY msedgedriver /usr/bin/
|
||||
COPY entrypoint.sh /
|
||||
|
||||
RUN chmod +x /usr/bin/msedgedriver
|
||||
USER selenium
|
||||
|
||||
EXPOSE 4444
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
@@ -0,0 +1,21 @@
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
ARG VERSION
|
||||
ARG PACKAGE=microsoft-edge-stable
|
||||
ARG INSTALL_DIR=msedge
|
||||
|
||||
LABEL browser=$PACKAGE:$VERSION
|
||||
|
||||
RUN \
|
||||
curl -s https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \
|
||||
echo 'deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main' > /etc/apt/sources.list.d/microsoft-edge.list && \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install $PACKAGE=$VERSION && \
|
||||
( \
|
||||
sed -i -e 's@exec -a "$0" "$HERE/msedge"@& --no-sandbox --disable-gpu@' /opt/microsoft/$INSTALL_DIR/$PACKAGE || \
|
||||
sed -i -e 's@exec -a "$0" "$HERE/msedge"@& --no-sandbox --disable-gpu@' /opt/microsoft/$INSTALL_DIR/microsoft-edge \
|
||||
) && \
|
||||
chown root:root /opt/microsoft/$INSTALL_DIR/msedge-sandbox && \
|
||||
chmod 4755 /opt/microsoft/$INSTALL_DIR/msedge-sandbox && \
|
||||
microsoft-edge --version && \
|
||||
rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/*
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"}
|
||||
DISPLAY_NUM=99
|
||||
export DISPLAY=":$DISPLAY_NUM"
|
||||
|
||||
VERBOSE=${VERBOSE:-""}
|
||||
DRIVER_ARGS=${DRIVER_ARGS:-""}
|
||||
if [ -n "$VERBOSE" ]; then
|
||||
DRIVER_ARGS="$DRIVER_ARGS --verbose"
|
||||
fi
|
||||
|
||||
clean() {
|
||||
if [ -n "$FILESERVER_PID" ]; then
|
||||
kill -TERM "$FILESERVER_PID"
|
||||
fi
|
||||
if [ -n "$XSELD_PID" ]; then
|
||||
kill -TERM "$XSELD_PID"
|
||||
fi
|
||||
if [ -n "$PULSE_PID" ]; then
|
||||
kill -TERM "$PULSE_PID"
|
||||
fi
|
||||
if [ -n "$XVFB_PID" ]; then
|
||||
kill -TERM "$XVFB_PID"
|
||||
fi
|
||||
if [ -n "$DRIVER_PID" ]; then
|
||||
kill -TERM "$DRIVER_PID"
|
||||
fi
|
||||
if [ -n "$X11VNC_PID" ]; then
|
||||
kill -TERM "$X11VNC_PID"
|
||||
fi
|
||||
}
|
||||
|
||||
trap clean SIGINT SIGTERM
|
||||
|
||||
if env | grep -q ROOT_CA_; then
|
||||
mkdir -p $HOME/.pki/nssdb
|
||||
certutil -N --empty-password -d sql:$HOME/.pki/nssdb
|
||||
for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do
|
||||
certname=$(echo -n $e | sed -e 's/ROOT_CA_//')
|
||||
echo ${!e} | base64 -d >/tmp/cert.pem
|
||||
certutil -A -n ${certname} -t "TC,C,T" -i /tmp/cert.pem -d sql:$HOME/.pki/nssdb
|
||||
if cat tmp/cert.pem | grep -q "PRIVATE KEY"; then
|
||||
PRIVATE_KEY_PASS=${PRIVATE_KEY_PASS:-\'\'}
|
||||
openssl pkcs12 -export -in /tmp/cert.pem -clcerts -nodes -out /tmp/key.p12 -passout pass:${PRIVATE_KEY_PASS} -passin pass:${PRIVATE_KEY_PASS}
|
||||
pk12util -d sql:$HOME/.pki/nssdb -i /tmp/key.p12 -W ${PRIVATE_KEY_PASS}
|
||||
rm /tmp/key.p12
|
||||
fi
|
||||
rm /tmp/cert.pem
|
||||
done
|
||||
fi
|
||||
|
||||
/usr/bin/fileserver &
|
||||
FILESERVER_PID=$!
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/xseld &
|
||||
XSELD_PID=$!
|
||||
|
||||
mkdir -p ~/pulse/.config/pulse
|
||||
echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/pulse/.config/pulse/cookie
|
||||
HOME=$HOME/pulse pulseaudio --start --exit-idle-time=-1
|
||||
HOME=$HOME/pulse pactl load-module module-native-protocol-tcp
|
||||
PULSE_PID=$(ps --no-headers -C pulseaudio -o pid | sed -r 's/( )+//g')
|
||||
|
||||
/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null &
|
||||
XVFB_PID=$!
|
||||
|
||||
retcode=1
|
||||
until [ $retcode -eq 0 ]; do
|
||||
DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1
|
||||
retcode=$?
|
||||
if [ $retcode -ne 0 ]; then
|
||||
echo Waiting X server...
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ENABLE_VNC" == "true" ]; then
|
||||
x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null &
|
||||
X11VNC_PID=$!
|
||||
fi
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/msedgedriver --port=4444 --allowed-ips='' ${DRIVER_ARGS} &
|
||||
DRIVER_PID=$!
|
||||
|
||||
wait
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
ARG VERSION=noop
|
||||
ARG PACKAGE=microsoft-edge-stable
|
||||
ARG INSTALL_DIR=msedge
|
||||
|
||||
LABEL browser=$PACKAGE:$VERSION
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install libatk-bridge2.0-0 \
|
||||
libatomic1 \
|
||||
libatspi2.0-0 \
|
||||
libcairo-gobject2 \
|
||||
libcolord2 \
|
||||
libepoxy0 \
|
||||
libgbm1 \
|
||||
libgtk-3-0 \
|
||||
libgtk-3-common \
|
||||
liblcms2-2 \
|
||||
librest-0.7-0 \
|
||||
libsoup-gnome2.4-1 \
|
||||
libwayland-client0 \
|
||||
libwayland-cursor0 \
|
||||
libwayland-egl1 \
|
||||
libwayland-server0 \
|
||||
libxkbcommon0 \
|
||||
xdg-utils \
|
||||
ca-certificates \
|
||||
fonts-liberation \
|
||||
libappindicator3-1 \
|
||||
libnss3 \
|
||||
lsb-base \
|
||||
libcurl4 \
|
||||
curl && \
|
||||
curl -O http://host.docker.internal:8080/microsoft-edge.deb && \
|
||||
apt-get -y purge curl && \
|
||||
dpkg -i microsoft-edge.deb && \
|
||||
( \
|
||||
sed -i -e 's@exec -a "$0" "$HERE/msedge"@& --no-sandbox --disable-gpu@' /opt/microsoft/$INSTALL_DIR/$PACKAGE || \
|
||||
sed -i -e 's@exec -a "$0" "$HERE/msedge"@& --no-sandbox --disable-gpu@' /opt/microsoft/$INSTALL_DIR/microsoft-edge \
|
||||
) && \
|
||||
rm microsoft-edge.deb && \
|
||||
chown root:root /opt/microsoft/$INSTALL_DIR/msedge-sandbox && \
|
||||
chmod 4755 /opt/microsoft/$INSTALL_DIR/msedge-sandbox && \
|
||||
microsoft-edge --version && \
|
||||
rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/*
|
||||
@@ -0,0 +1,20 @@
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
ARG VERSION
|
||||
ARG PACKAGE=firefox
|
||||
ARG PPA
|
||||
|
||||
LABEL browser=$PACKAGE:$VERSION
|
||||
|
||||
RUN \
|
||||
( [ "$PPA" != "" ] && \
|
||||
apt-get update && \
|
||||
apt-get install -y software-properties-common && \
|
||||
apt-get update && \
|
||||
add-apt-repository -y $PPA \
|
||||
) || true && \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install iproute2 libavcodec58 $PACKAGE=$VERSION && \
|
||||
( [ "$PACKAGE" != "firefox" ] && ln /usr/bin/$PACKAGE /usr/bin/firefox ) || true && \
|
||||
firefox --version && \
|
||||
rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/*
|
||||
@@ -0,0 +1,36 @@
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
ARG VERSION=noop
|
||||
ARG PACKAGE=firefox
|
||||
ARG PPA=noop
|
||||
|
||||
LABEL browser=$PACKAGE:$VERSION
|
||||
|
||||
RUN \
|
||||
( \
|
||||
( \
|
||||
curl -O http://host.docker.internal:8080/firefox.deb && \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install iproute2 libavcodec58 && \
|
||||
apt-get -y install libgtk-3-0 libstartup-notification0 libdbus-glib-1-2 \
|
||||
) || \
|
||||
( \
|
||||
curl -O http://host.docker.internal:8080/firefox.deb && \
|
||||
dpkg --add-architecture i386 && \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install iproute2 libavcodec58 && \
|
||||
apt-get -y install libc6:i386 libncurses5:i386 libstdc++6:i386 libgtk-3-0:i386 libasound2:i386 libdbus-glib-1-2:i386 libxt6:i386 libatomic1:i386 libcairo-gobject2:i386 libstartup-notification0:i386 libx11-xcb1:i386 && \
|
||||
mkdir flashplayer && \
|
||||
cd flashplayer && \
|
||||
curl -o flashplayer.tar.gz https://fpdownload.adobe.com/pub/flashplayer/pdc/32.0.0.387/flash_player_ppapi_linux.i386.tar.gz && \
|
||||
tar xvzf flashplayer.tar.gz && \
|
||||
cp libpepflashplayer.so /usr/lib/flashplugin-installer/libflashplayer.so && \
|
||||
cd .. && \
|
||||
rm -Rf flashplayer \
|
||||
) \
|
||||
) && \
|
||||
dpkg -i firefox.deb && \
|
||||
( [ "$PACKAGE" != "firefox" ] && ln /usr/bin/$PACKAGE /usr/bin/firefox ) || true && \
|
||||
rm firefox.deb && \
|
||||
firefox --version && \
|
||||
rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* && rm -f firefox*.deb
|
||||
@@ -0,0 +1,16 @@
|
||||
ARG VERSION
|
||||
FROM selenoid/dev_firefox:$VERSION
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install -y openjdk-8-jre-headless && \
|
||||
apt-get clean && \
|
||||
rm -Rf /tmp/*
|
||||
|
||||
COPY selenium-server-standalone.jar /usr/share/selenium/
|
||||
COPY entrypoint.sh /
|
||||
|
||||
USER selenium
|
||||
|
||||
EXPOSE 4444
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"}
|
||||
DISPLAY_NUM=99
|
||||
export DISPLAY=":$DISPLAY_NUM"
|
||||
|
||||
clean() {
|
||||
if [ -n "$FILESERVER_PID" ]; then
|
||||
kill -TERM "$FILESERVER_PID"
|
||||
fi
|
||||
if [ -n "$XSELD_PID" ]; then
|
||||
kill -TERM "$XSELD_PID"
|
||||
fi
|
||||
if [ -n "$XVFB_PID" ]; then
|
||||
kill -TERM "$XVFB_PID"
|
||||
fi
|
||||
if [ -n "$SELENIUM_PID" ]; then
|
||||
kill -TERM "$SELENIUM_PID"
|
||||
fi
|
||||
if [ -n "$X11VNC_PID" ]; then
|
||||
kill -TERM "$X11VNC_PID"
|
||||
fi
|
||||
}
|
||||
|
||||
trap clean SIGINT SIGTERM
|
||||
|
||||
/usr/bin/fileserver &
|
||||
FILESERVER_PID=$!
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/xseld &
|
||||
XSELD_PID=$!
|
||||
|
||||
/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null &
|
||||
XVFB_PID=$!
|
||||
|
||||
retcode=1
|
||||
until [ $retcode -eq 0 ]; do
|
||||
DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1
|
||||
retcode=$?
|
||||
if [ $retcode -ne 0 ]; then
|
||||
echo Waiting X server...
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ENABLE_VNC" == "true" ]; then
|
||||
x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null &
|
||||
X11VNC_PID=$!
|
||||
fi
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/java -Xmx256m -Djava.security.egd=file:/dev/./urandom -jar /usr/share/selenium/selenium-server-standalone.jar -port 4444 -browserTimeout 120 &
|
||||
SELENIUM_PID=$!
|
||||
|
||||
wait
|
||||
@@ -0,0 +1,12 @@
|
||||
ARG VERSION
|
||||
FROM selenoid/dev_firefox:$VERSION
|
||||
|
||||
COPY geckodriver /usr/bin/
|
||||
COPY selenoid /usr/bin/
|
||||
COPY --chown=selenium:root browsers.json /home/selenium/
|
||||
COPY entrypoint.sh /
|
||||
|
||||
USER selenium
|
||||
|
||||
EXPOSE 4444
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"firefox": {
|
||||
"default": "@@VERSION@@",
|
||||
"versions": {
|
||||
"@@VERSION@@": {
|
||||
"image": ["/usr/bin/geckodriver"@@DRIVER_ARGS@@]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+94
@@ -0,0 +1,94 @@
|
||||
#!/bin/bash
|
||||
SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"}
|
||||
DISPLAY_NUM=99
|
||||
export DISPLAY=":$DISPLAY_NUM"
|
||||
|
||||
cp /home/selenium/browsers.json /tmp
|
||||
|
||||
VERBOSE=${VERBOSE:-""}
|
||||
DRIVER_ARGS=${DRIVER_ARGS:-""}
|
||||
if [ -n "$VERBOSE" ]; then
|
||||
DRIVER_ARGS="$DRIVER_ARGS, \"--log\", \"debug\""
|
||||
fi
|
||||
sed -i "s|@@DRIVER_ARGS@@|$DRIVER_ARGS|g" /tmp/browsers.json
|
||||
|
||||
clean() {
|
||||
if [ -n "$FILESERVER_PID" ]; then
|
||||
kill -TERM "$FILESERVER_PID"
|
||||
fi
|
||||
if [ -n "$XSELD_PID" ]; then
|
||||
kill -TERM "$XSELD_PID"
|
||||
fi
|
||||
if [ -n "$PULSE_PID" ]; then
|
||||
kill -TERM "$PULSE_PID"
|
||||
fi
|
||||
if [ -n "$XVFB_PID" ]; then
|
||||
kill -TERM "$XVFB_PID"
|
||||
fi
|
||||
if [ -n "$SELENOID_PID" ]; then
|
||||
kill -TERM "$SELENOID_PID"
|
||||
fi
|
||||
if [ -n "$X11VNC_PID" ]; then
|
||||
kill -TERM "$X11VNC_PID"
|
||||
fi
|
||||
}
|
||||
|
||||
trap clean SIGINT SIGTERM
|
||||
|
||||
/usr/bin/fileserver &
|
||||
FILESERVER_PID=$!
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/xseld &
|
||||
XSELD_PID=$!
|
||||
|
||||
mkdir -p ~/pulse/.config/pulse
|
||||
echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/pulse/.config/pulse/cookie
|
||||
HOME=$HOME/pulse pulseaudio --start --exit-idle-time=-1
|
||||
HOME=$HOME/pulse pactl load-module module-native-protocol-tcp
|
||||
PULSE_PID=$(ps --no-headers -C pulseaudio -o pid | sed -r 's/( )+//g')
|
||||
|
||||
/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null &
|
||||
XVFB_PID=$!
|
||||
|
||||
retcode=1
|
||||
until [ $retcode -eq 0 ]; do
|
||||
DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1
|
||||
retcode=$?
|
||||
if [ $retcode -ne 0 ]; then
|
||||
echo Waiting X server...
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ENABLE_VNC" == "true" ]; then
|
||||
x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null &
|
||||
X11VNC_PID=$!
|
||||
fi
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/selenoid -conf /tmp/browsers.json -disable-docker -timeout 1h -max-timeout 24h -enable-file-upload -capture-driver-logs &
|
||||
SELENOID_PID=$!
|
||||
|
||||
if env | grep -q ROOT_CA_; then
|
||||
while true; do
|
||||
if certDB=$(ls -d /tmp/rust_mozprofile*/cert9.db 2>/dev/null); then
|
||||
break
|
||||
else
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
certdir=$(dirname ${certDB})
|
||||
for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do
|
||||
certname=$(echo -n $e | sed -e 's/ROOT_CA_//')
|
||||
echo ${!e} | base64 -d >/tmp/cert.pem
|
||||
certutil -A -n ${certname} -t "TC,C,T" -i /tmp/cert.pem -d sql:${certdir}
|
||||
if cat tmp/cert.pem | grep -q "PRIVATE KEY"; then
|
||||
PRIVATE_KEY_PASS=${PRIVATE_KEY_PASS:-\'\'}
|
||||
openssl pkcs12 -export -in /tmp/cert.pem -clcerts -nodes -out /tmp/key.p12 -passout pass:${PRIVATE_KEY_PASS} -passin pass:${PRIVATE_KEY_PASS}
|
||||
pk12util -d sql:${certdir} -i /tmp/key.p12 -W ${PRIVATE_KEY_PASS}
|
||||
rm /tmp/key.p12
|
||||
fi
|
||||
rm /tmp/cert.pem
|
||||
done
|
||||
fi
|
||||
|
||||
wait
|
||||
@@ -0,0 +1,11 @@
|
||||
ARG VERSION
|
||||
FROM selenoid/dev_opera:$VERSION
|
||||
|
||||
COPY operadriver_linux64/operadriver /usr/bin/
|
||||
COPY entrypoint.sh /
|
||||
|
||||
RUN chmod +x /usr/bin/operadriver
|
||||
USER selenium
|
||||
|
||||
EXPOSE 4444
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
@@ -0,0 +1,16 @@
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
ARG VERSION
|
||||
ARG PACKAGE=opera-stable
|
||||
|
||||
LABEL browser=$PACKAGE:$VERSION
|
||||
|
||||
RUN \
|
||||
curl -s https://deb.opera.com/archive.key | apt-key add - && \
|
||||
echo 'deb https://deb.opera.com/opera-stable/ stable non-free' > /etc/apt/sources.list.d/opera-blink.list && \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install libgtk-3-0 $PACKAGE=$VERSION && \
|
||||
( [ "$PACKAGE" != "opera-stable" ] && ln /usr/bin/$PACKAGE /usr/bin/opera ) || true && \
|
||||
opera --version && \
|
||||
rm /etc/apt/sources.list.d/$PACKAGE.list && \
|
||||
rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/*
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"}
|
||||
DISPLAY_NUM=99
|
||||
export DISPLAY=":$DISPLAY_NUM"
|
||||
|
||||
VERBOSE=${VERBOSE:-""}
|
||||
DRIVER_ARGS=${DRIVER_ARGS:-""}
|
||||
if [ -n "$VERBOSE" ]; then
|
||||
DRIVER_ARGS="$DRIVER_ARGS --verbose"
|
||||
fi
|
||||
|
||||
clean() {
|
||||
if [ -n "$FILESERVER_PID" ]; then
|
||||
kill -TERM "$FILESERVER_PID"
|
||||
fi
|
||||
if [ -n "$XSELD_PID" ]; then
|
||||
kill -TERM "$XSELD_PID"
|
||||
fi
|
||||
if [ -n "$PULSE_PID" ]; then
|
||||
kill -TERM "$PULSE_PID"
|
||||
fi
|
||||
if [ -n "$XVFB_PID" ]; then
|
||||
kill -TERM "$XVFB_PID"
|
||||
fi
|
||||
if [ -n "$DRIVER_PID" ]; then
|
||||
kill -TERM "$DRIVER_PID"
|
||||
fi
|
||||
if [ -n "$X11VNC_PID" ]; then
|
||||
kill -TERM "$X11VNC_PID"
|
||||
fi
|
||||
}
|
||||
|
||||
trap clean SIGINT SIGTERM
|
||||
|
||||
if env | grep -q ROOT_CA_; then
|
||||
mkdir -p $HOME/.pki/nssdb
|
||||
certutil -N --empty-password -d sql:$HOME/.pki/nssdb
|
||||
for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do
|
||||
certname=$(echo -n $e | sed -e 's/ROOT_CA_//')
|
||||
echo ${!e} | base64 -d >/tmp/cert.pem
|
||||
certutil -A -n ${certname} -t "TC,C,T" -i /tmp/cert.pem -d sql:$HOME/.pki/nssdb
|
||||
if cat tmp/cert.pem | grep -q "PRIVATE KEY"; then
|
||||
PRIVATE_KEY_PASS=${PRIVATE_KEY_PASS:-\'\'}
|
||||
openssl pkcs12 -export -in /tmp/cert.pem -clcerts -nodes -out /tmp/key.p12 -passout pass:${PRIVATE_KEY_PASS} -passin pass:${PRIVATE_KEY_PASS}
|
||||
pk12util -d sql:$HOME/.pki/nssdb -i /tmp/key.p12 -W ${PRIVATE_KEY_PASS}
|
||||
rm /tmp/key.p12
|
||||
fi
|
||||
rm /tmp/cert.pem
|
||||
done
|
||||
fi
|
||||
|
||||
/usr/bin/fileserver &
|
||||
FILESERVER_PID=$!
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/xseld &
|
||||
XSELD_PID=$!
|
||||
|
||||
mkdir -p ~/pulse/.config/pulse
|
||||
echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/pulse/.config/pulse/cookie
|
||||
HOME=$HOME/pulse pulseaudio --start --exit-idle-time=-1
|
||||
HOME=$HOME/pulse pactl load-module module-native-protocol-tcp
|
||||
PULSE_PID=$(ps --no-headers -C pulseaudio -o pid | sed -r 's/( )+//g')
|
||||
|
||||
/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null &
|
||||
XVFB_PID=$!
|
||||
|
||||
retcode=1
|
||||
until [ $retcode -eq 0 ]; do
|
||||
DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1
|
||||
retcode=$?
|
||||
if [ $retcode -ne 0 ]; then
|
||||
echo Waiting X server...
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ENABLE_VNC" == "true" ]; then
|
||||
x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null &
|
||||
X11VNC_PID=$!
|
||||
fi
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/operadriver --port=4444 --whitelisted-ips='' ${DRIVER_ARGS} &
|
||||
DRIVER_PID=$!
|
||||
|
||||
wait
|
||||
@@ -0,0 +1,62 @@
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
ARG VERSION=noop
|
||||
ARG PACKAGE=opera-stable
|
||||
|
||||
LABEL browser=$PACKAGE:$VERSION
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install gconf-service \
|
||||
libasound2 \
|
||||
libatk1.0-0 \
|
||||
libc6 \
|
||||
libcairo2 \
|
||||
libcups2 \
|
||||
libdbus-1-3 \
|
||||
libexpat1 \
|
||||
libfontconfig1 \
|
||||
libfreetype6 \
|
||||
libgcc1 \
|
||||
libgconf-2-4 \
|
||||
libgdk-pixbuf2.0-0 \
|
||||
libglib2.0-0 \
|
||||
libgtk2.0-0 \
|
||||
libgtk-3-0 \
|
||||
libnspr4 \
|
||||
libnss3 \
|
||||
libnotify4 \
|
||||
libpango1.0-0 \
|
||||
libstdc++6 \
|
||||
libx11-6 \
|
||||
libx11-xcb1 \
|
||||
libxcb1 \
|
||||
libxcomposite1 \
|
||||
libxcursor1 \
|
||||
libxdamage1 \
|
||||
libxext6 \
|
||||
libxfixes3 \
|
||||
libxi6 \
|
||||
libxrandr2 \
|
||||
libxrender1 \
|
||||
libxss1 \
|
||||
libxtst6 \
|
||||
debconf \
|
||||
gnupg \
|
||||
libudev1 \
|
||||
ca-certificates \
|
||||
fonts-liberation \
|
||||
libappindicator3-1 \
|
||||
libnss3 \
|
||||
lsb-base \
|
||||
xdg-utils \
|
||||
libcurl4 \
|
||||
curl && \
|
||||
curl -O http://host.docker.internal:8080/opera.deb && \
|
||||
apt-get -y purge curl && \
|
||||
dpkg -i opera.deb && \
|
||||
( [ "$PACKAGE" != "opera-stable" ] && ln /usr/bin/$PACKAGE /usr/bin/opera ) || true && \
|
||||
rm opera.deb && \
|
||||
opera --version && \
|
||||
rm -Rf /tmp/* && \
|
||||
rm -Rf /var/lib/apt/lists/*
|
||||
@@ -0,0 +1 @@
|
||||
cmd/prism/prism
|
||||
@@ -0,0 +1,64 @@
|
||||
FROM ubuntu:20.04 as build
|
||||
|
||||
ARG WEBKIT_VERSION="610.4.3.1.7"
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get -y install --no-install-recommends ca-certificates subversion && \
|
||||
svn checkout https://svn.webkit.org/repository/webkit/tags/Safari-$WEBKIT_VERSION webkit && \
|
||||
mkdir -p /opt/webkit && \
|
||||
cd webkit && \
|
||||
yes | DEBIAN_FRONTEND=noninteractive Tools/gtk/install-dependencies && \
|
||||
cmake -DPORT=GTK -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/webkit -DUSE_WPE_RENDERER=OFF -DENABLE_MINIBROWSER=ON -DENABLE_BUBBLEWRAP_SANDBOX=OFF -DENABLE_GAMEPAD=OFF -DENABLE_SPELLCHECK=OFF -DENABLE_WAYLAND_TARGET=OFF -DUSE_OPENJPEG=OFF -DUSE_SOUP2=ON -GNinja && \
|
||||
ninja && \
|
||||
ninja install && \
|
||||
rm -Rf /var/lib/apt/lists/*
|
||||
|
||||
FROM golang:1.17 as go
|
||||
|
||||
COPY cmd/prism /prism
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install --no-install-recommends -y upx-ucl libx11-dev && \
|
||||
cd /prism && \
|
||||
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" && \
|
||||
upx /prism/prism && \
|
||||
rm -Rf /var/lib/apt/lists/*
|
||||
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
COPY --from=build /opt/webkit /opt/webkit
|
||||
COPY --from=go /prism/prism /usr/bin/
|
||||
|
||||
ENV LD_LIBRARY_PATH /opt/webkit/lib/:${LD_LIBRARY_PATH}
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get -y install --no-install-recommends \
|
||||
libsoup2.4-1 \
|
||||
libgtk-3-0 \
|
||||
libwebp6 \
|
||||
libwebpdemux2 \
|
||||
libsecret-1-0 \
|
||||
libhyphen0 \
|
||||
libwoff1 \
|
||||
libharfbuzz-icu0 \
|
||||
libgstreamer-gl1.0-0 \
|
||||
libopenjp2-7 \
|
||||
libnotify4 \
|
||||
libxslt1.1 \
|
||||
libegl1 && \
|
||||
ldconfig && \
|
||||
apt-get clean && \
|
||||
rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* && \
|
||||
chmod 777 /etc/ssl/certs && \
|
||||
mkdir /tmp/ca-certificates && \
|
||||
chmod 777 /tmp/ca-certificates
|
||||
|
||||
COPY entrypoint.sh /
|
||||
|
||||
USER selenium
|
||||
|
||||
EXPOSE 4444
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
@@ -0,0 +1,3 @@
|
||||
module github.com/aerokube/webkit-images/prism
|
||||
|
||||
go 1.17
|
||||
@@ -0,0 +1,150 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
listen = ":4444"
|
||||
target = "http://localhost:5555"
|
||||
waitTimeout = 30 * time.Second
|
||||
gracePeriod = 30 * time.Second
|
||||
browserName = "safari"
|
||||
browserVersion = "15.0"
|
||||
)
|
||||
|
||||
func wait(ctx context.Context, target string) (*url.URL, error) {
|
||||
for {
|
||||
r, err := http.NewRequest(http.MethodHead, target, http.NoBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new %s request to %s: %v", http.MethodHead, target, err)
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(r.WithContext(ctx))
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
if err, ok := err.(*url.Error); ok {
|
||||
switch err.Err {
|
||||
case context.Canceled, context.DeadlineExceeded:
|
||||
return nil, err
|
||||
default:
|
||||
<-time.After(100 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return r.URL, nil
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
e := make(chan error)
|
||||
go func() {
|
||||
stop := make(chan os.Signal)
|
||||
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
|
||||
select {
|
||||
case err := <-e:
|
||||
log.Fatalf("server: %v", err)
|
||||
case <-stop:
|
||||
cancel()
|
||||
}
|
||||
}()
|
||||
waitCtx, waitCancel := context.WithTimeout(ctx, waitTimeout)
|
||||
defer waitCancel()
|
||||
u, err := wait(waitCtx, target)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("wait target: %v", err))
|
||||
}
|
||||
server := &http.Server{
|
||||
Addr: listen,
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var value map[string]interface{}
|
||||
err := json.NewDecoder(r.Body).Decode(&value)
|
||||
if err != nil && err != io.EOF {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
if _, ok := value["desiredCapabilities"]; ok {
|
||||
delete(value, "desiredCapabilities")
|
||||
}
|
||||
if o, ok := value["capabilities"]; ok {
|
||||
if w3cCapabilities, ok := o.(map[string]interface{}); ok {
|
||||
for _, match := range []string{"alwaysMatch", "firstMatch"} {
|
||||
delete(w3cCapabilities, match)
|
||||
}
|
||||
}
|
||||
}
|
||||
body, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] marshalling capabilities: %v", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
r.Body = ioutil.NopCloser(bytes.NewReader(body))
|
||||
r.ContentLength = int64(len(body))
|
||||
}
|
||||
(&httputil.ReverseProxy{
|
||||
Director: func(r *http.Request) {
|
||||
r.URL.Scheme, r.URL.Host, r.URL.Path = u.Scheme, u.Host, path.Join(u.Path, r.URL.Path)
|
||||
},
|
||||
ModifyResponse: func(resp *http.Response) error {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil
|
||||
}
|
||||
var values map[string]interface{}
|
||||
defer resp.Body.Close()
|
||||
err := json.NewDecoder(resp.Body).Decode(&values)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decode json response: %v", err)
|
||||
}
|
||||
if o, ok := values["value"]; ok {
|
||||
if value, ok := o.(map[string]interface{}); ok {
|
||||
if o, ok := value["capabilities"]; ok {
|
||||
if capabilities, ok := o.(map[string]interface{}); ok {
|
||||
capabilities["browserName"] = browserName
|
||||
capabilities["browserVersion"] = browserVersion
|
||||
delete(capabilities, "platformName")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
buf, err := json.Marshal(&values)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode json response: %v", err)
|
||||
}
|
||||
resp.Header.Del("Server")
|
||||
resp.Header.Del("Content-Length")
|
||||
resp.ContentLength = int64(len(buf))
|
||||
resp.Body = ioutil.NopCloser(bytes.NewReader(buf))
|
||||
return nil
|
||||
},
|
||||
}).ServeHTTP(w, r)
|
||||
}),
|
||||
}
|
||||
go func() {
|
||||
e <- server.ListenAndServe()
|
||||
}()
|
||||
<-ctx.Done()
|
||||
shCtx, shCancel := context.WithTimeout(context.Background(), gracePeriod)
|
||||
defer shCancel()
|
||||
if err := server.Shutdown(shCtx); err != nil {
|
||||
log.Fatalf("graceful shutdown: %v]", err)
|
||||
}
|
||||
}
|
||||
Executable
+74
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"}
|
||||
DISPLAY_NUM=99
|
||||
export DISPLAY=":$DISPLAY_NUM"
|
||||
|
||||
QUIET=${QUIET:-""}
|
||||
DRIVER_ARGS=""
|
||||
if [ -z "$QUIET" ]; then
|
||||
DRIVER_ARGS="--verbose"
|
||||
fi
|
||||
|
||||
clean() {
|
||||
if [ -n "$FILESERVER_PID" ]; then
|
||||
kill -TERM "$FILESERVER_PID"
|
||||
fi
|
||||
if [ -n "$XSELD_PID" ]; then
|
||||
kill -TERM "$XSELD_PID"
|
||||
fi
|
||||
if [ -n "$XVFB_PID" ]; then
|
||||
kill -TERM "$XVFB_PID"
|
||||
fi
|
||||
if [ -n "$DRIVER_PID" ]; then
|
||||
kill -TERM "$DRIVER_PID"
|
||||
fi
|
||||
if [ -n "$PRISM_PID" ]; then
|
||||
kill -TERM "$PRISM_PID"
|
||||
fi
|
||||
if [ -n "$X11VNC_PID" ]; then
|
||||
kill -TERM "$X11VNC_PID"
|
||||
fi
|
||||
}
|
||||
|
||||
trap clean SIGINT SIGTERM
|
||||
|
||||
/usr/bin/fileserver &
|
||||
FILESERVER_PID=$!
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/xseld &
|
||||
XSELD_PID=$!
|
||||
|
||||
if env | grep -q ROOT_CA_; then
|
||||
mkdir -p /tmp/ca-certificates
|
||||
for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do
|
||||
certname=$(echo -n $e | sed -e 's/ROOT_CA_//')
|
||||
echo ${!e} | base64 -d >/tmp/ca-certificates/${certname}.crt
|
||||
done
|
||||
update-ca-certificates --localcertsdir /tmp/ca-certificates
|
||||
fi
|
||||
|
||||
/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" >/dev/null 2>&1 &
|
||||
XVFB_PID=$!
|
||||
|
||||
retcode=1
|
||||
until [ $retcode -eq 0 ]; do
|
||||
DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1
|
||||
retcode=$?
|
||||
if [ $retcode -ne 0 ]; then
|
||||
echo Waiting X server...
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ENABLE_VNC" == "true" ]; then
|
||||
x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null &
|
||||
X11VNC_PID=$!
|
||||
fi
|
||||
|
||||
DISPLAY="$DISPLAY" /opt/webkit/bin/WebKitWebDriver --port=5555 --host=0.0.0.0 ${DRIVER_ARGS} &
|
||||
DRIVER_PID=$!
|
||||
|
||||
/usr/bin/prism &
|
||||
PRISM_PID=$!
|
||||
|
||||
wait
|
||||
@@ -0,0 +1,11 @@
|
||||
ARG VERSION
|
||||
FROM selenoid/dev_yandex:$VERSION
|
||||
|
||||
COPY yandexdriver /usr/bin/
|
||||
COPY entrypoint.sh /
|
||||
|
||||
RUN chmod +x /usr/bin/yandexdriver
|
||||
USER selenium
|
||||
|
||||
EXPOSE 4444
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
@@ -0,0 +1,14 @@
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
ARG VERSION=19.4.2.698-1
|
||||
|
||||
LABEL browser=yandex-browser-beta:$VERSION
|
||||
|
||||
RUN \
|
||||
curl -s https://repo.yandex.ru/yandex-browser/YANDEX-BROWSER-KEY.GPG | apt-key add - && \
|
||||
echo 'deb [arch=amd64] https://repo.yandex.ru/yandex-browser/deb beta main' > /etc/apt/sources.list.d/yandex-browser.list && \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install yandex-browser-beta=$VERSION && \
|
||||
yandex-browser-beta --version && \
|
||||
rm /etc/apt/sources.list.d/yandex-browser.list && \
|
||||
rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/*
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"}
|
||||
DISPLAY_NUM=99
|
||||
export DISPLAY=":$DISPLAY_NUM"
|
||||
|
||||
VERBOSE=${VERBOSE:-""}
|
||||
DRIVER_ARGS=${DRIVER_ARGS:-""}
|
||||
if [ -n "$VERBOSE" ]; then
|
||||
DRIVER_ARGS="$DRIVER_ARGS --verbose"
|
||||
fi
|
||||
|
||||
clean() {
|
||||
if [ -n "$FILESERVER_PID" ]; then
|
||||
kill -TERM "$FILESERVER_PID"
|
||||
fi
|
||||
if [ -n "$XSELD_PID" ]; then
|
||||
kill -TERM "$XSELD_PID"
|
||||
fi
|
||||
if [ -n "$XVFB_PID" ]; then
|
||||
kill -TERM "$XVFB_PID"
|
||||
fi
|
||||
if [ -n "$DRIVER_PID" ]; then
|
||||
kill -TERM "$DRIVER_PID"
|
||||
fi
|
||||
if [ -n "$X11VNC_PID" ]; then
|
||||
kill -TERM "$X11VNC_PID"
|
||||
fi
|
||||
if [ -n "$PULSE_PID" ]; then
|
||||
kill -TERM "$PULSE_PID"
|
||||
fi
|
||||
}
|
||||
|
||||
trap clean SIGINT SIGTERM
|
||||
|
||||
if env | grep -q ROOT_CA_; then
|
||||
mkdir -p $HOME/.pki/nssdb
|
||||
certutil -N --empty-password -d sql:$HOME/.pki/nssdb
|
||||
for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do
|
||||
certname=$(echo -n $e | sed -e 's/ROOT_CA_//')
|
||||
echo ${!e} | base64 -d >/tmp/cert.pem
|
||||
certutil -A -n ${certname} -t "TC,C,T" -i /tmp/cert.pem -d sql:$HOME/.pki/nssdb
|
||||
if cat tmp/cert.pem | grep -q "PRIVATE KEY"; then
|
||||
PRIVATE_KEY_PASS=${PRIVATE_KEY_PASS:-\'\'}
|
||||
openssl pkcs12 -export -in /tmp/cert.pem -clcerts -nodes -out /tmp/key.p12 -passout pass:${PRIVATE_KEY_PASS} -passin pass:${PRIVATE_KEY_PASS}
|
||||
pk12util -d sql:$HOME/.pki/nssdb -i /tmp/key.p12 -W ${PRIVATE_KEY_PASS}
|
||||
rm /tmp/key.p12
|
||||
fi
|
||||
rm /tmp/cert.pem
|
||||
done
|
||||
fi
|
||||
|
||||
/usr/bin/fileserver &
|
||||
FILESERVER_PID=$!
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/xseld &
|
||||
XSELD_PID=$!
|
||||
|
||||
mkdir -p ~/pulse/.config/pulse
|
||||
echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/pulse/.config/pulse/cookie
|
||||
HOME=$HOME/pulse pulseaudio --start --exit-idle-time=-1
|
||||
HOME=$HOME/pulse pactl load-module module-native-protocol-tcp
|
||||
PULSE_PID=$(ps --no-headers -C pulseaudio -o pid | sed -r 's/( )+//g')
|
||||
|
||||
/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null &
|
||||
XVFB_PID=$!
|
||||
|
||||
retcode=1
|
||||
until [ $retcode -eq 0 ]; do
|
||||
DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1
|
||||
retcode=$?
|
||||
if [ $retcode -ne 0 ]; then
|
||||
echo Waiting X server...
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ENABLE_VNC" == "true" ]; then
|
||||
x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null &
|
||||
X11VNC_PID=$!
|
||||
fi
|
||||
|
||||
DISPLAY="$DISPLAY" /usr/bin/yandexdriver --port=4444 --allowed-ips='' --allowed-origins='*' ${DRIVER_ARGS} &
|
||||
DRIVER_PID=$!
|
||||
|
||||
wait
|
||||
@@ -0,0 +1,60 @@
|
||||
FROM browsers/base:7.3.6
|
||||
|
||||
ARG VERSION=noop
|
||||
|
||||
LABEL browser=yandex-browser-beta:$VERSION
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install gconf-service \
|
||||
libasound2 \
|
||||
libatk1.0-0 \
|
||||
libc6 \
|
||||
libcairo2 \
|
||||
libcups2 \
|
||||
libdbus-1-3 \
|
||||
libexpat1 \
|
||||
libfontconfig1 \
|
||||
libfreetype6 \
|
||||
libgcc1 \
|
||||
libgconf-2-4 \
|
||||
libgdk-pixbuf2.0-0 \
|
||||
libglib2.0-0 \
|
||||
libgtk2.0-0 \
|
||||
libgtk-3-0 \
|
||||
libnspr4 \
|
||||
libnss3 \
|
||||
libnotify4 \
|
||||
libpango1.0-0 \
|
||||
libstdc++6 \
|
||||
libx11-6 \
|
||||
libx11-xcb1 \
|
||||
libxcb1 \
|
||||
libxcomposite1 \
|
||||
libxcursor1 \
|
||||
libxdamage1 \
|
||||
libxext6 \
|
||||
libxfixes3 \
|
||||
libxi6 \
|
||||
libxrandr2 \
|
||||
libxrender1 \
|
||||
libxss1 \
|
||||
libxtst6 \
|
||||
debconf \
|
||||
gnupg \
|
||||
libudev1 \
|
||||
ca-certificates \
|
||||
fonts-liberation \
|
||||
libappindicator3-1 \
|
||||
libnss3 \
|
||||
lsb-base \
|
||||
xdg-utils \
|
||||
libcurl4 \
|
||||
curl && \
|
||||
curl -O http://apt-repo:8080/yandex-browser.deb && \
|
||||
apt-get -y purge curl && \
|
||||
dpkg -i yandex-browser.deb && \
|
||||
rm yandex-browser.deb && \
|
||||
yandex-browser-beta --version && \
|
||||
rm -Rf /tmp/* && \
|
||||
rm -Rf /var/lib/apt/lists/*
|
||||
Reference in New Issue
Block a user