<commit_before>// Remote Selenium client implementation.
// See https://www.w3.org/TR/webdriver for the protocol.

package selenium

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"mime"
	"net/http"
	"strings"
	"time"

	"github.com/blang/semver"
)

// Errors returned by Selenium server.
var remoteErrors = map[int]string{
	6:  "invalid session ID",
	7:  "no such element",
	8:  "no such frame",
	9:  "unknown command",
	10: "stale element reference",
	11: "element not visible",
	12: "invalid element state",
	13: "unknown error",
	15: "element is not selectable",
	17: "javascript error",
	19: "xpath lookup error",
	21: "timeout",
	23: "no such window",
	24: "invalid cookie domain",
	25: "unable to set cookie",
	26: "unexpected alert open",
	27: "no alert open",
	28: "script timeout",
	29: "invalid element coordinates",
	32: "invalid selector",
}

const (
	// Success is status code that indicates the method was successful.
	Success = 0
	// DefaultURLPrefix is the default HTTP endpoint that offers the WebDriver
	// API.
	DefaultURLPrefix = "http://127.0.0.1:4444/wd/hub"
	// JSONType is JSON content type.
	JSONType = "application/json"
)

type remoteWD struct {
	id, urlPrefix string
	capabilities  Capabilities

	w3cCompatible  bool
	browser        string
	browserVersion semver.Version
}

// HTTPClient is the default client to use to communicate with the WebDriver
// server.
var HTTPClient = http.DefaultClient

func newRequest(method string, url string, data []byte) (*http.Request, error) {
	request, err := http.NewRequest(method, url, bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}
	request.Header.Add("Accept", JSONType)

	return request, nil
}

func isRedirect(response *http.Response) bool {
	switch response.StatusCode {
	case 301, 302, 303, 307:
		return true
	}
	return false
}

func (wd *remoteWD) requestURL(template string, args ...interface{}) string {
	return wd.urlPrefix + fmt.Sprintf(template, args...)
}

// TODO(minusnine): provide a "sessionURL" function that prepends the
// /session/<id> URL prefix and replace most requestURL (and voidCommand) calls
// with it.

type serverReply struct {
	SessionID *string // SessionID can be nil.
	Value     json.RawMessage

	// The following fields were used prior to Selenium 3.0 for error state and
	// in ChromeDriver for additional information.
	Status int
	State  string

	Error
}

// Error contains information about a failure of a command.
type Error struct {
	Err        string `json:"error"`
	Message    string `json:"message"`
	Stacktrace string `json:"stacktrace"`
}

// Error implements the error interface.
func (e *Error) Error() string {
	return fmt.Sprintf("%s: %s", e.Err, e.Message)
}

// execute performs an HTTP request and inspects the returned data for an error
// encoded by the remote end in a JSON structure. If no error is present, the
// entire, raw request payload is returned.
func (wd *remoteWD) execute(method, url string, data []byte) (json.RawMessage, error) {
	debugLog("-> %s %s\n%s", method, filteredURL(url), data)
	request, err := newRequest(method, url, data)
	if err != nil {
		return nil, err
	}

	response, err := HTTPClient.Do(request)
	if err != nil {
		return nil, err
	}

	buf, err := ioutil.ReadAll(response.Body)
	if debugFlag {
		if err == nil {
			// Pretty print the JSON response
			var prettyBuf bytes.Buffer
			if err = json.Indent(&prettyBuf, buf, "", "    "); err == nil && prettyBuf.Len() > 0 {
				buf = prettyBuf.Bytes()
			}
		}
		debugLog("<- %s [%s]\n%s", response.Status, response.Header["Content-Type"], buf)
	}
	if err != nil {
		return nil, errors.New(response.Status)
	}

	fullCType := response.Header.Get("Content-Type")
	cType, _, err := mime.ParseMediaType(fullCType)
	if err != nil {
		return nil, fmt.Errorf("got content type header %q, expected %q", fullCType, JSONType)
	}
	if cType != JSONType {
		return nil, fmt.Errorf("got content type %q, expected %q", cType, JSONType)
	}

	reply := new(serverReply)
	if err := json.Unmarshal(buf, reply); err != nil {
		if response.StatusCode != http.StatusOK {
			return nil, fmt.Errorf("bad server reply status: %s", response.Status)
		}
		return nil, err
	}
	if reply.Err != "" {
		return nil, &reply.Error
	}

	// Handle the W3C-compliant error format. In the W3C spec, the error is
	// embedded in the 'value' field.
	if len(reply.Value) > 0 {
		respErr := new(Error)
		if err := json.Unmarshal(reply.Value, respErr); err == nil && respErr.Err != "" {<commit_msg>Unexport JSONType, which shouldn't be part of the package API<commit_after>// Remote Selenium client implementation.
// See https://www.w3.org/TR/webdriver for the protocol.

package selenium

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"mime"
	"net/http"
	"strings"
	"time"

	"github.com/blang/semver"
)

// Errors returned by Selenium server.
var remoteErrors = map[int]string{
	6:  "invalid session ID",
	7:  "no such element",
	8:  "no such frame",
	9:  "unknown command",
	10: "stale element reference",
	11: "element not visible",
	12: "invalid element state",
	13: "unknown error",
	15: "element is not selectable",
	17: "javascript error",
	19: "xpath lookup error",
	21: "timeout",
	23: "no such window",
	24: "invalid cookie domain",
	25: "unable to set cookie",
	26: "unexpected alert open",
	27: "no alert open",
	28: "script timeout",
	29: "invalid element coordinates",
	32: "invalid selector",
}

const (
	// Success is status code that indicates the method was successful.
	Success = 0
	// DefaultURLPrefix is the default HTTP endpoint that offers the WebDriver
	// API.
	DefaultURLPrefix = "http://127.0.0.1:4444/wd/hub"
	// jsonContentType is JSON content type.
	jsonContentType = "application/json"
)

type remoteWD struct {
	id, urlPrefix string
	capabilities  Capabilities

	w3cCompatible  bool
	browser        string
	browserVersion semver.Version
}

// HTTPClient is the default client to use to communicate with the WebDriver
// server.
var HTTPClient = http.DefaultClient

func newRequest(method string, url string, data []byte) (*http.Request, error) {
	request, err := http.NewRequest(method, url, bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}
	request.Header.Add("Accept", jsonContentType)

	return request, nil
}

func (wd *remoteWD) requestURL(template string, args ...interface{}) string {
	return wd.urlPrefix + fmt.Sprintf(template, args...)
}

// TODO(minusnine): provide a "sessionURL" function that prepends the
// /session/<id> URL prefix and replace most requestURL (and voidCommand) calls
// with it.

type serverReply struct {
	SessionID *string // SessionID can be nil.
	Value     json.RawMessage

	// The following fields were used prior to Selenium 3.0 for error state and
	// in ChromeDriver for additional information.
	Status int
	State  string

	Error
}

// Error contains information about a failure of a command.
type Error struct {
	Err        string `json:"error"`
	Message    string `json:"message"`
	Stacktrace string `json:"stacktrace"`
}

// Error implements the error interface.
func (e *Error) Error() string {
	return fmt.Sprintf("%s: %s", e.Err, e.Message)
}

// execute performs an HTTP request and inspects the returned data for an error
// encoded by the remote end in a JSON structure. If no error is present, the
// entire, raw request payload is returned.
func (wd *remoteWD) execute(method, url string, data []byte) (json.RawMessage, error) {
	debugLog("-> %s %s\n%s", method, filteredURL(url), data)
	request, err := newRequest(method, url, data)
	if err != nil {
		return nil, err
	}

	response, err := HTTPClient.Do(request)
	if err != nil {
		return nil, err
	}

	buf, err := ioutil.ReadAll(response.Body)
	if debugFlag {
		if err == nil {
			// Pretty print the JSON response
			var prettyBuf bytes.Buffer
			if err = json.Indent(&prettyBuf, buf, "", "    "); err == nil && prettyBuf.Len() > 0 {
				buf = prettyBuf.Bytes()
			}
		}
		debugLog("<- %s [%s]\n%s", response.Status, response.Header["Content-Type"], buf)
	}
	if err != nil {
		return nil, errors.New(response.Status)
	}

	fullCType := response.Header.Get("Content-Type")
	cType, _, err := mime.ParseMediaType(fullCType)
	if err != nil {
		return nil, fmt.Errorf("got content type header %q, expected %q", fullCType, jsonContentType)
	}
	if cType != jsonContentType {
		return nil, fmt.Errorf("got content type %q, expected %q", cType, jsonContentType)
	}

	reply := new(serverReply)
	if err := json.Unmarshal(buf, reply); err != nil {
		if response.StatusCode != http.StatusOK {
			return nil, fmt.Errorf("bad server reply status: %s", response.Status)
		}
		return nil, err
	}
	if reply.Err != "" {
		return nil, &reply.Error
	}

	// Handle the W3C-compliant error format. In the W3C spec, the error is
	// embedded in the 'value' field.
	if len(reply.Value) > 0 {
		respErr := new(Error)
		if err := json.Unmarshal(reply.Value, respErr); err == nil && respErr.Err != "" {
{'fraction_non_alphanumeric': 0.1285109228711547, 'fraction_numerical': 0.014043691484618814, 'mean_word_length': 3.7375923970432945, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2577319', 'n_tokens_mistral': 3058, 'n_tokens_neox': 2896, 'n_words': 1010}