This commit is contained in:
2022-05-17 01:56:44 +03:00
commit 3a9b8c8468
117 changed files with 7175 additions and 0 deletions
+25
View File
@@ -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"]
+18
View File
@@ -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/*
+1
View File
@@ -0,0 +1 @@
devtools
+187
View File
@@ -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
}
+176
View File
@@ -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"})
}
+12
View File
@@ -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
)
+12
View File
@@ -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=
+23
View File
@@ -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()))
}
+93
View File
@@ -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
+62
View File
@@ -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/*
+12
View File
@@ -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"]
+21
View File
@@ -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/*
+86
View File
@@ -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
+47
View File
@@ -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/*
+20
View File
@@ -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/*
+36
View File
@@ -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
+16
View File
@@ -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"]
+53
View File
@@ -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
+12
View File
@@ -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"]
+10
View File
@@ -0,0 +1,10 @@
{
"firefox": {
"default": "@@VERSION@@",
"versions": {
"@@VERSION@@": {
"image": ["/usr/bin/geckodriver"@@DRIVER_ARGS@@]
}
}
}
}
+94
View File
@@ -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
+11
View File
@@ -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"]
+16
View File
@@ -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/*
+85
View File
@@ -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
+62
View File
@@ -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/*
+1
View File
@@ -0,0 +1 @@
cmd/prism/prism
+64
View File
@@ -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"]
+3
View File
@@ -0,0 +1,3 @@
module github.com/aerokube/webkit-images/prism
go 1.17
+150
View File
@@ -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)
}
}
+74
View File
@@ -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
+11
View File
@@ -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"]
+14
View File
@@ -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/*
+85
View File
@@ -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
+60
View File
@@ -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/*