Class: Selenium::WebDriver::Safari::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/selenium/webdriver/safari/server.rb

Constant Summary collapse

SOCKET_LOCK_TIMEOUT =
45
HEADERS =
<<-HEADERS
HTTP/1.1 %d %s
Content-Type: text/html; charset=utf-8
Server: safaridriver-ruby
HEADERS

Instance Method Summary collapse

Constructor Details

#initialize(port, command_timeout) ⇒ Server

Returns a new instance of Server.



27
28
29
30
# File 'lib/selenium/webdriver/safari/server.rb', line 27

def initialize(port, command_timeout)
  @port = port
  @command_timeout = command_timeout
end

Instance Method Details

#encode_form_component(str) ⇒ Object



161
162
163
164
165
166
167
168
# File 'lib/selenium/webdriver/safari/server.rb', line 161

def encode_form_component(str)
  if URI.respond_to?(:encode_www_form_component) # >= 1.9
    URI.encode_www_form_component(str)
  else
    # best effort for 1.8
    str.gsub(":", '%3A').gsub('/', '%2F')
  end
end

#htmlObject



104
105
106
# File 'lib/selenium/webdriver/safari/server.rb', line 104

def html
  "<!DOCTYPE html><script>#{Safari.resource_path.join('client.js').read}</script>"
end

#process_handshakeObject



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/selenium/webdriver/safari/server.rb', line 131

def process_handshake
  @ws = @server.accept
  hs  = WebSocket::Handshake::Server.new

  req = ''
  until hs.finished?
    data = @ws.getc || next

    req << data.chr
    hs << data
  end

  unless hs.valid?
    if req.include? "favicon.ico"
      @ws.close
      process_handshake
      return
    else
      raise Error::WebDriverError, "#{hs.error}: #{req}"
    end
  end

  @ws.write(hs.to_s)
  @ws.flush

  puts "handshake complete, v#{hs.version}" if $DEBUG
  @server.close
  @version = hs.version
end

#process_initial_http_requestObject



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/selenium/webdriver/safari/server.rb', line 108

def process_initial_http_request
  http = @server.accept

  req = ''
  until req.include?("\r\n\r\n")
    req << http.read(1)
  end

  if !req.include?("?url=")
    http << HEADERS % [302, 'Moved Temporarily']
    http << "Location: #{uri}?url=#{encode_form_component ws_uri}\r\n"
    http << "\r\n\r\n"
    http.close

    process_initial_http_request
  else
    http << HEADERS % [200, 'OK']
    http << "\r\n\r\n"
    http << html
    http.close
  end
end

#receiveObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/selenium/webdriver/safari/server.rb', line 56

def receive
  @frame ||= WebSocket::Frame::Incoming::Server.new(:version => @version)

  until msg = @frame.next
    end_time = Time.now + @command_timeout

    begin
      data = @ws.read_nonblock(1)
    rescue Errno::EWOULDBLOCK, Errno::EAGAIN
      now = Time.now
      if now >= end_time
        raise Error::TimeOutError, "timed out waiting for Safari to respond"
      end

      IO.select([@ws], nil, nil, end_time - now)
      retry
    end

    @frame << data
  end

  puts "<<< #{msg}" if $DEBUG

  JSON.parse msg.to_s
end

#send(command) ⇒ Object



46
47
48
49
50
51
52
53
54
# File 'lib/selenium/webdriver/safari/server.rb', line 46

def send(command)
  json = JSON.generate(command)
  puts ">>> #{json}" if $DEBUG

  frame = WebSocket::Frame::Outgoing::Server.new(:version => @version, :data => json, :type => :text)

  @ws.write frame.to_s
  @ws.flush
end

#startObject



32
33
34
35
36
37
38
39
# File 'lib/selenium/webdriver/safari/server.rb', line 32

def start
  Platform.exit_hook { stop } # make sure we don't leave the server running

  socket_lock.locked do
    find_free_port
    start_server
  end
end

#stopObject



41
42
43
44
# File 'lib/selenium/webdriver/safari/server.rb', line 41

def stop
  @server.close if @server && !@server.closed?
  @ws.close if @ws && !@ws.closed?
end

#uriObject



86
87
88
# File 'lib/selenium/webdriver/safari/server.rb', line 86

def uri
  "http://#{Platform.localhost}:#{@port}"
end

#wait_for_connectionObject



90
91
92
93
94
# File 'lib/selenium/webdriver/safari/server.rb', line 90

def wait_for_connection
  # TODO: timeouts / non-blocking accept
  process_initial_http_request
  process_handshake
end

#ws_uriObject



82
83
84
# File 'lib/selenium/webdriver/safari/server.rb', line 82

def ws_uri
  "ws://#{Platform.localhost}:#{@port}/wd"
end