webkit_remote 0.5.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,5 @@
1
1
  require 'fileutils'
2
2
  require 'net/http'
3
- require 'posix/spawn'
4
3
  require 'tmpdir'
5
4
 
6
5
  module WebkitRemote
@@ -17,13 +16,11 @@ class Process
17
16
  # @option opts [Hash<Symbol, Number>] window set the :left, :top, :width and
18
17
  # :height of the browser window; by default, the browser window is
19
18
  # 256x256 starting at 0,0.
20
- # @option opts [Hash<Symbol, Number>, Boolean] xvfb use Xvfb instead of a
21
- # real screen; set the :display, :width, :height, :depth and :dpi of the
22
- # server, or use the default display number 20, at 1280x1024x32 with
23
- # 72dpi
24
19
  # @option opts [Boolean] allow_popups when true, the popup blocker is
25
20
  # disabled; this is sometimes necessary when driving a Web UI via
26
21
  # JavaScript
22
+ # @option opts [Boolean] headless if true, Chrome runs without any dependency
23
+ # on a display server
27
24
  # @option opts [String] chrome_binary path to the Chrome binary to be used;
28
25
  # by default, the path is automatically detected
29
26
  def initialize(opts = {})
@@ -32,21 +29,11 @@ class Process
32
29
  @running = false
33
30
  @data_dir = Dir.mktmpdir 'webkit-remote'
34
31
  @pid = nil
35
- @xvfb_pid = nil
36
32
  if opts[:window]
37
33
  @window = opts[:window]
38
34
  else
39
35
  @window = { }
40
36
  end
41
- if opts[:xvfb]
42
- @xvfb_cli = xvfb_cli opts
43
- if opts[:xvfb].respond_to? :[]
44
- @window[:width] ||= opts[:xvfb][:width]
45
- @window[:height] ||= opts[:xvfb][:height]
46
- end
47
- else
48
- @xvfb_cli = nil
49
- end
50
37
  @window[:top] ||= 0
51
38
  @window[:left] ||= 0
52
39
  @window[:width] ||= 256
@@ -62,14 +49,7 @@ class Process
62
49
  def start
63
50
  return self if running?
64
51
 
65
- if @xvfb_cli
66
- unless @xvfb_pid = POSIX::Spawn.spawn(*@xvfb_cli)
67
- # The Xvfb launch failed.
68
- return nil
69
- end
70
- end
71
-
72
- unless @pid = POSIX::Spawn.spawn(*@cli)
52
+ unless @pid = ::Process.spawn(*@cli)
73
53
  # The launch failed.
74
54
  stop
75
55
  return nil
@@ -78,7 +58,7 @@ class Process
78
58
  (@timeout * 20).times do
79
59
  # Check if the browser exited.
80
60
  begin
81
- break if status = ::Process.wait(@pid, ::Process::WNOHANG)
61
+ break if ::Process.wait(@pid, ::Process::WNOHANG)
82
62
  rescue SystemCallError # no children
83
63
  break
84
64
  end
@@ -119,18 +99,7 @@ class Process
119
99
  end
120
100
  end
121
101
 
122
- if @xvfb_pid
123
- begin
124
- ::Process.kill 'TERM', @xvfb_pid
125
- ::Process.wait @xvfb_pid
126
- rescue SystemCallError
127
- # Process died on its own.
128
- ensure
129
- @xvfb_pid = nil
130
- end
131
- end
132
-
133
- FileUtils.rm_rf @data_dir if File.exists?(@data_dir)
102
+ FileUtils.rm_rf @data_dir if File.exist?(@data_dir)
134
103
  @running = false
135
104
  self
136
105
  end
@@ -140,7 +109,7 @@ class Process
140
109
 
141
110
  # Remove temporary directory if it's still there at garbage collection time.
142
111
  def finalize
143
- PathUtils.rm_rf @data_dir if File.exists?(@data_dir)
112
+ PathUtils.rm_rf @data_dir if File.exist?(@data_dir)
144
113
  end
145
114
 
146
115
  # Command-line that launches Google Chrome / Chromium
@@ -151,7 +120,6 @@ class Process
151
120
  # The Chromium wiki recommends this page for available flags:
152
121
  # http://peter.sh/experiments/chromium-command-line-switches/
153
122
  [
154
- chrome_env(opts),
155
123
  opts[:chrome_binary] || self.class.chrome_binary,
156
124
  ] + chrome_cli_flags(opts) + [
157
125
  "--remote-debugging-port=#{@port}", # Webkit remote debugging
@@ -164,7 +132,8 @@ class Process
164
132
  chdir: @data_dir,
165
133
  in: '/dev/null',
166
134
  out: File.join(@data_dir, '.stdout'),
167
- err: File.join(@data_dir, '.stderr')
135
+ err: File.join(@data_dir, '.stderr'),
136
+ close_others: true,
168
137
  },
169
138
  ]
170
139
  end
@@ -174,11 +143,12 @@ class Process
174
143
  # @param [Hash] opts options passed to the WebkitRemote::Process constructor
175
144
  # @return [Array<String>] flags used on the command line for launching Chrome
176
145
  def chrome_cli_flags(opts)
146
+ # TODO - look at --data-path --homedir --profile-directory
177
147
  flags = [
178
148
  '--bwsi', # disable extensions, sync, bookmarks
149
+ '--disable-cloud-import', # no talking with the Google servers
179
150
  '--disable-default-apps', # no bundled apps
180
151
  '--disable-extensions', # no extensions
181
- '--disable-java', # no plugins
182
152
  '--disable-logging', # don't trash stdout / stderr
183
153
  '--disable-plugins', # no native content
184
154
  '--disable-prompt-on-repost', # no confirmation dialog on POST refresh
@@ -193,73 +163,15 @@ class Process
193
163
  '--no-default-browser-check', # don't hang when Chrome isn't default
194
164
  '--no-experiments', # not sure this is useful
195
165
  '--no-first-run', # don't show the help UI
196
- '--no-js-randomness', # consistent Date.now() and Math.random()
197
- '--no-message-box', # don't let user scripts show dialogs
198
166
  '--no-service-autorun', # don't mess with autorun settings
199
167
  '--noerrdialogs', # don't hang on error dialogs
200
168
  ]
201
169
  flags << '--disable-popup-blocking' if opts[:allow_popups]
202
- flags
203
- end
204
-
205
- # Environment variables set when launching Chrome.
206
- #
207
- # @param [Hash] opts options passed to the WebkitRemote::Process constructor
208
- # @return [Hash<String, String>] variables to be added to the environment of
209
- # the Chrome process before launching
210
- def chrome_env(opts)
211
- if opts[:xvfb]
212
- if opts[:xvfb].respond_to?(:[]) and opts[:xvfb][:display]
213
- display = opts[:xvfb][:display]
214
- else
215
- display = 20
216
- end
217
- { 'DISPLAY' => ":#{display}.0" }
218
- else
219
- {}
220
- end
221
- end
222
-
223
- # Command-line that launches Xvfb.
224
- #
225
- # @param [Hash] opts options passed to the WebkitRemote::Process constructor
226
- # @return [Array<String>] command line for launching Xvfb
227
- def xvfb_cli(opts)
228
- # The OSX man page for Xvfb:
229
- # http://developer.apple.com/library/mac/documentation/darwin/reference/manpages/man1/Xvfb.1.html
230
-
231
- xvfb_opts = opts[:xvfb]
232
- unless xvfb_opts.respond_to? :[]
233
- xvfb_opts = {}
170
+ if opts[:headless]
171
+ flags << '--headless' # don't create a UI
172
+ flags << '--disable-gpu' # needed for --headless to work at the moment
234
173
  end
235
-
236
- display = xvfb_opts[:display] || 20
237
- width = xvfb_opts[:width] || 1280
238
- height = xvfb_opts[:height] || 1024
239
- depth = xvfb_opts[:depth] || 32
240
- dpi = xvfb_opts[:dpi] || 72
241
-
242
- # https://bugs.freedesktop.org/show_bug.cgi?id=17453
243
- if depth == 32
244
- depth = '24+32'
245
- end
246
-
247
- [
248
- self.class.xvfb_binary,
249
- ":#{display}",
250
- '-screen', '0', "#{width}x#{height}x#{depth}",
251
- '-auth', File.join(@data_dir, '.Xauthority'),
252
- '-c',
253
- '-dpi', dpi.to_s,
254
- '-terminate',
255
- '-wr',
256
- {
257
- chdir: @data_dir,
258
- in: '/dev/null',
259
- out: File.join(@data_dir, '.X_stdout'),
260
- err: File.join(@data_dir, '.X_stderr'),
261
- },
262
- ]
174
+ flags
263
175
  end
264
176
 
265
177
  # Path to a Google Chrome / Chromium binary.
@@ -297,20 +209,6 @@ class Process
297
209
  @chrome_binary ||= nil
298
210
  end
299
211
  @chrome_binary = false
300
-
301
- # Path to the Xvfb virtual X server binary.
302
- #
303
- # @return [String] full-qualified path to a binary that launches Xvfb.
304
- def self.xvfb_binary
305
- return @xvfb_binary unless @xvfb_binary == false
306
-
307
- path = `which Xvfb`
308
- unless path.empty?
309
- @xvfb_binary = path.strip
310
- end
311
- @xvfb_binary ||= nil
312
- end
313
- @xvfb_binary = false
314
212
  end # class WebkitRemote::Browser
315
213
 
316
214
  end # namespace WebkitRemote
@@ -8,9 +8,9 @@ module WebkitRemote
8
8
  # WebKit process; the client will automatically stop the process when
9
9
  # closed
10
10
  def self.local(opts = {})
11
- # Use Xvfb if no desktop is available.
12
- if !opts.has_key?(:xvfb) && (!ENV['DISPLAY'] || ENV['DISPLAY'].empty?)
13
- opts = { xvfb: true }.merge! opts
11
+ # Use headless if no desktop is available.
12
+ if !opts.has_key?(:headless) && (!ENV['DISPLAY'] || ENV['DISPLAY'].empty?)
13
+ opts = { headless: true }.merge! opts
14
14
  end
15
15
  process = WebkitRemote::Process.new opts
16
16
 
@@ -25,7 +25,7 @@
25
25
  };
26
26
  var keyEventDetails = function (event) {
27
27
  return "keyCode: " + event.keyCode + " charCode: " + event.charCode +
28
- " keyIdentifier: " + event.keyIdentifier + " text: " + event.text +
28
+ " key: " + event.key + " text: " + event.text +
29
29
  " repeat: " + event.repeat + " shift: " + event.shiftKey +
30
30
  " ctrl: " + event.ctrlKey + " alt: " + event.altKey +
31
31
  " meta: " + event.metaKey;
@@ -52,4 +52,3 @@
52
52
  </script>
53
53
  </body>
54
54
  </html>
55
-
@@ -17,7 +17,7 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
17
17
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
18
18
  require 'webkit_remote'
19
19
 
20
- require 'debugger'
20
+ require 'byebug'
21
21
  require 'pp'
22
22
  require 'thread'
23
23
  Thread.abort_on_exception = true
@@ -2,7 +2,7 @@ require File.expand_path('../helper.rb', File.dirname(__FILE__))
2
2
 
3
3
  describe WebkitRemote::Browser do
4
4
  before :each do
5
- @process = WebkitRemote::Process.new port: 9669, xvfb: true
5
+ @process = WebkitRemote::Process.new port: 9669, headless: true
6
6
  @process.start
7
7
  end
8
8
  after :each do
@@ -26,9 +26,6 @@ describe WebkitRemote::Client::Console do
26
26
  lambda {
27
27
  @client.wait_for type: WebkitRemote::Event::ConsoleMessage
28
28
  }.must_raise ArgumentError
29
- lambda {
30
- @client.wait_for type: WebkitRemote::Event::ConsoleMessageRepeated
31
- }.must_raise ArgumentError
32
29
  lambda {
33
30
  @client.wait_for type: WebkitRemote::Event::ConsoleCleared
34
31
  }.must_raise ArgumentError
@@ -43,9 +40,6 @@ describe WebkitRemote::Client::Console do
43
40
  @message_events = @events.select do |event|
44
41
  event.kind_of? WebkitRemote::Event::ConsoleMessage
45
42
  end
46
- @repeat_events = @events.select do |event|
47
- event.kind_of? WebkitRemote::Event::ConsoleMessageRepeated
48
- end
49
43
  @messages = @client.console_messages
50
44
  end
51
45
 
@@ -57,30 +51,28 @@ describe WebkitRemote::Client::Console do
57
51
  @message_events.wont_be :empty?
58
52
  end
59
53
 
60
- it 'receives ConsoleMessageRepeated events' do
61
- @repeat_events.wont_be :empty?
62
- end
63
-
64
54
  it 'collects messages into Client#console_messages' do
65
55
  @message_events[0].message.must_equal @messages[0]
66
56
  @message_events[1].message.must_equal @messages[1]
67
57
  @message_events[2].message.must_equal @messages[2]
68
58
  @message_events[3].message.must_equal @messages[3]
69
- @repeat_events[0].message.must_equal @messages[3]
70
- @repeat_events[1].message.must_equal @messages[3]
71
59
  end
72
60
 
73
61
  it 'parses text correctly' do
74
62
  @messages[0].text.must_equal 'hello ruby'
75
- @messages[0].params.must_equal ['hello ruby']
76
63
  @messages[0].level.must_equal :warning
77
- @messages[0].count.must_equal 1
78
64
  @messages[0].reason.must_equal :console_api
79
- @messages[0].type.must_equal :log
80
65
  @messages[0].source_url.must_equal fixture_url(:console)
81
66
  @messages[0].source_line.must_equal 7
67
+
68
+ @messages[1].text.must_equal 'stack test'
69
+ @messages[1].level.must_equal :log
70
+ @messages[2].text.must_match(/^params /)
71
+ @messages[2].level.must_equal :error
82
72
  end
83
73
 
74
+ =begin
75
+ TODO(pwnall): Stacks are now available in Runtime.consoleAPICalled
84
76
  it 'parses the stack trace correctly' do
85
77
  @messages[1].text.must_equal 'stack test'
86
78
  @messages[1].level.must_equal :log
@@ -92,6 +84,7 @@ describe WebkitRemote::Client::Console do
92
84
  ]
93
85
  end
94
86
 
87
+ TODO(pwnall): Params are now available as args in Runtime.consoleAPICalled
95
88
  it 'parses parameters correctly' do
96
89
  @messages[2].text.must_match(/^params /)
97
90
  @messages[2].level.must_equal :error
@@ -100,16 +93,11 @@ describe WebkitRemote::Client::Console do
100
93
 
101
94
  @messages[2].params[3].must_be_kind_of WebkitRemote::Client::JsObject
102
95
  @messages[2].params[3].properties['hello'].value.must_equal 'ruby'
103
- @messages[2].params[3].group.name.must_equal nil
104
- end
105
-
106
- it 'parses repeated messages correctly' do
107
- @messages[3].text.must_equal 'one more time'
108
- @messages[3].count.must_equal 3
109
- @repeat_events[0].count.must_equal 2
110
- @repeat_events[1].count.must_equal 3
96
+ @messages[2].params[3].group.name.must_be_nil
111
97
  end
98
+ =end
112
99
 
100
+ =begin
113
101
  describe 'clear_console' do
114
102
  before :all do
115
103
  @client.clear_console
@@ -135,8 +123,11 @@ describe WebkitRemote::Client::Console do
135
123
  @message_events[2].message.params[3].released?.must_equal true
136
124
  end
137
125
  end
126
+ =end
138
127
  end
139
128
 
129
+ =begin
130
+ TODO(pwnall): These events are now available as Log.entryAdded
140
131
  describe 'with console and network events enabled' do
141
132
  before :all do
142
133
  @client.console_events = true
@@ -159,7 +150,7 @@ describe WebkitRemote::Client::Console do
159
150
  end
160
151
 
161
152
  it 'associates messages with network requests' do
162
- @messages[0].text.must_match /not found/i
153
+ @messages[0].text.must_match(/not found/i)
163
154
  @messages[0].network_resource.wont_equal nil
164
155
  @messages[0].network_resource.document_url.
165
156
  must_equal fixture_url(:network)
@@ -169,4 +160,5 @@ describe WebkitRemote::Client::Console do
169
160
  @messages[0].type.must_equal :log
170
161
  end
171
162
  end
163
+ =end
172
164
  end
@@ -57,7 +57,7 @@ describe WebkitRemote::Client::DomNode do
57
57
  describe 'with a selector that does not match' do
58
58
  it 'returns nil' do
59
59
  node = @root.query_selector '#this-id-should-not-exist'
60
- node.must_equal nil
60
+ node.must_be_nil
61
61
  end
62
62
  end
63
63
  end
@@ -1,6 +1,6 @@
1
1
  require File.expand_path('../../helper.rb', File.dirname(__FILE__))
2
2
 
3
- describe WebkitRemote::Client::Console do
3
+ describe WebkitRemote::Client::Input do
4
4
  before :all do
5
5
  @client = WebkitRemote.local port: 9669
6
6
  @client.page_events = true
@@ -12,6 +12,7 @@ describe WebkitRemote::Client::Console do
12
12
  @client.close
13
13
  end
14
14
 
15
+ =begin
15
16
  describe '#mouse_event' do
16
17
  it 'generates a move correctly' do
17
18
  @client.mouse_event :move, 50, 50
@@ -32,12 +33,12 @@ describe WebkitRemote::Client::Console do
32
33
  end
33
34
 
34
35
  it 'generates a second press correctly' do
35
- @client.mouse_event :down, 51, 52, button: :left, clicks: 2,
36
+ @client.mouse_event :down, 51, 52, button: :right, clicks: 2,
36
37
  modifiers: [:alt, :ctrl]
37
38
  events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage
38
39
 
39
40
  events.last.message.text.must_equal(
40
- 'Down. x: 51 y: 52 button: 0 detail: 2 shift: false ctrl: true ' +
41
+ 'Down. x: 51 y: 52 button: 2 detail: 2 shift: false ctrl: true ' +
41
42
  'alt: true meta: false')
42
43
  end
43
44
 
@@ -46,10 +47,11 @@ describe WebkitRemote::Client::Console do
46
47
  events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage
47
48
 
48
49
  events.last.message.text.must_equal(
49
- 'Up. x: 51 y: 52 button: 0 detail: 0 shift: false ctrl: false ' +
50
+ 'Up. x: 51 y: 52 button: 1 detail: 0 shift: false ctrl: false ' +
50
51
  'alt: false meta: true')
51
52
  end
52
53
  end
54
+ =end
53
55
 
54
56
  describe '#key_event' do
55
57
  it 'generates a char correctly' do
@@ -58,42 +60,38 @@ describe WebkitRemote::Client::Console do
58
60
  events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage
59
61
 
60
62
  events.last.message.text.must_equal(
61
- 'KPress. keyCode: 97 charCode: 97 keyIdentifier: text: undefined ' +
63
+ 'KPress. keyCode: 97 charCode: 97 key: text: undefined ' +
62
64
  'repeat: false shift: false ctrl: false alt: false meta: false')
63
65
  end
64
66
 
65
67
  it 'generates a down correctly' do
66
- @client.key_event :down, vkey: 0x41, key_id: 'U+0041'
68
+ @client.key_event :down, vkey: 0x41, key: 'A'
67
69
 
68
70
  events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage
69
71
 
70
72
  events.last.message.text.must_equal(
71
- 'KDown. keyCode: 65 charCode: 0 keyIdentifier: U+0041 ' +
72
- 'text: undefined ' +
73
+ 'KDown. keyCode: 65 charCode: 0 key: A text: undefined ' +
73
74
  'repeat: false shift: false ctrl: false alt: false meta: false')
74
75
  end
75
76
 
76
77
  it 'generates an up correctly' do
77
- @client.key_event :up, vkey: 0x41, key_id: 'U+0041'
78
+ @client.key_event :up, vkey: 0x41, key: 'A'
78
79
 
79
80
  events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage
80
81
 
81
82
  events.last.message.text.must_equal(
82
- 'KUp. keyCode: 65 charCode: 0 keyIdentifier: U+0041 ' +
83
- 'text: undefined ' +
83
+ 'KUp. keyCode: 65 charCode: 0 key: A text: undefined ' +
84
84
  'repeat: false shift: false ctrl: false alt: false meta: false')
85
85
  end
86
86
 
87
87
  it 'generates a raw_down correctly' do
88
- @client.key_event :raw_down, vkey: 0x41, key_id: 'U+0041'
88
+ @client.key_event :raw_down, vkey: 0x41, key: 'A'
89
89
 
90
90
  events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage
91
91
 
92
92
  events.last.message.text.must_equal(
93
- 'KDown. keyCode: 65 charCode: 0 keyIdentifier: U+0041 ' +
94
- 'text: undefined ' +
93
+ 'KDown. keyCode: 65 charCode: 0 key: A text: undefined ' +
95
94
  'repeat: false shift: false ctrl: false alt: false meta: false')
96
95
  end
97
96
  end
98
97
  end
99
-