google-chrome-client 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/chrome-repl +67 -0
- data/lib/google/chrome/client.rb +186 -0
- metadata +64 -0
data/bin/chrome-repl
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
require 'google/chrome/client'
|
3
|
+
require 'readline'
|
4
|
+
require 'pp'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
def print_log_and_error(data)
|
8
|
+
if data['error']
|
9
|
+
puts data['error']['stack']
|
10
|
+
elsif data['log']
|
11
|
+
if data['log'].kind_of?(String)
|
12
|
+
puts data['log']
|
13
|
+
else
|
14
|
+
pp data['log']
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def print_response(data)
|
20
|
+
if data.empty?
|
21
|
+
puts 'nil'
|
22
|
+
elsif data['success']
|
23
|
+
pp data['success']
|
24
|
+
else
|
25
|
+
print_log_and_error(data)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
extension_id = 'olppoehbaphcegdobmaipllacoammngl'
|
30
|
+
port = 9222
|
31
|
+
script = nil
|
32
|
+
|
33
|
+
parser = OptionParser.new
|
34
|
+
|
35
|
+
parser.on('--port N', Integer) do |n|
|
36
|
+
port = n
|
37
|
+
end
|
38
|
+
|
39
|
+
parser.on('--extension ID') do |s|
|
40
|
+
extension_id = s
|
41
|
+
end
|
42
|
+
|
43
|
+
parser.on('-e SCRIPT') do |s|
|
44
|
+
script = s
|
45
|
+
end
|
46
|
+
|
47
|
+
parser.parse!(ARGV)
|
48
|
+
|
49
|
+
client = Google::Chrome::Client.new('localhost', port)
|
50
|
+
extension = client.extension(extension_id)
|
51
|
+
|
52
|
+
extension.connect do |port|
|
53
|
+
if script
|
54
|
+
extension.post(port, script)
|
55
|
+
client.read_all_response.each do |header, resp|
|
56
|
+
print_log_and_error(resp['data'])
|
57
|
+
end
|
58
|
+
else
|
59
|
+
puts "Protocol version: %s" % client.server_version
|
60
|
+
while ln = Readline.readline('> ', true)
|
61
|
+
extension.post(port, ln)
|
62
|
+
client.read_all_response.each do |header, resp|
|
63
|
+
print_response(resp['data'])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
#
|
2
|
+
# = google/chrome/client.rb
|
3
|
+
#
|
4
|
+
# "Google Chrome Developer Tools Procotol" client library.
|
5
|
+
#
|
6
|
+
# Author:: KATO Kazuyoshi
|
7
|
+
# License:: X11 License
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'socket'
|
11
|
+
require 'json'
|
12
|
+
|
13
|
+
module Google
|
14
|
+
module Chrome
|
15
|
+
class Client
|
16
|
+
#
|
17
|
+
# Create a Client object and establish the debugger connection.
|
18
|
+
#
|
19
|
+
def initialize(host, port)
|
20
|
+
@socket = TCPSocket.open(host, port)
|
21
|
+
handshake
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Read all responses from the server.
|
26
|
+
#
|
27
|
+
def read_all_response
|
28
|
+
result = []
|
29
|
+
|
30
|
+
while IO.select([ @socket ], [], [], 0.1)
|
31
|
+
result << read_response
|
32
|
+
end
|
33
|
+
|
34
|
+
result
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Read one response from the server.
|
39
|
+
#
|
40
|
+
def read_response
|
41
|
+
header = {}
|
42
|
+
|
43
|
+
while ln = @socket.gets
|
44
|
+
case ln
|
45
|
+
when "\r\n"
|
46
|
+
break
|
47
|
+
when /^([A-Za-z-]+):(.*)$/
|
48
|
+
header[$1] = $2.chomp
|
49
|
+
else
|
50
|
+
raise
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
body = JSON.parse(@socket.read(header['Content-Length'].to_i))
|
55
|
+
return header, body
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Send a request.
|
60
|
+
#
|
61
|
+
def request(header, body)
|
62
|
+
write_request(header, body)
|
63
|
+
return read_response
|
64
|
+
end
|
65
|
+
|
66
|
+
def server_version
|
67
|
+
header, resp = request({ 'Tool' => 'DevToolsService' },
|
68
|
+
{ 'command' => 'version' })
|
69
|
+
resp['data']
|
70
|
+
end
|
71
|
+
|
72
|
+
def tabs
|
73
|
+
header, resp = request({ 'Tool' => 'DevToolsService' },
|
74
|
+
{ 'command' => 'list_tabs' })
|
75
|
+
resp['data'].map do |ary|
|
76
|
+
Tab.new(self, ary[0].to_i)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def extension(id)
|
81
|
+
ExtensionPorts.new(self, id)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
def handshake
|
86
|
+
str = "ChromeDevToolsHandshake\r\n"
|
87
|
+
@socket.write(str)
|
88
|
+
if @socket.gets == str
|
89
|
+
;
|
90
|
+
else
|
91
|
+
raise
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def write_request(header, body)
|
96
|
+
str = body.to_json
|
97
|
+
|
98
|
+
header['Content-Length'] = str.length
|
99
|
+
header.each_pair do |k, v|
|
100
|
+
@socket.write("#{k}:#{v}\r\n")
|
101
|
+
end
|
102
|
+
@socket.write("\r\n")
|
103
|
+
@socket.write(str)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Tab
|
108
|
+
@@seq = 1
|
109
|
+
|
110
|
+
def initialize(client, number)
|
111
|
+
@client = client
|
112
|
+
@number = number
|
113
|
+
end
|
114
|
+
|
115
|
+
def request(body)
|
116
|
+
@client.request({ 'Tool' => 'V8Debugger', 'Destination' => @number },
|
117
|
+
body)
|
118
|
+
end
|
119
|
+
|
120
|
+
def attach
|
121
|
+
request({ 'command' => 'attach' })
|
122
|
+
return unless block_given?
|
123
|
+
|
124
|
+
begin
|
125
|
+
yield
|
126
|
+
ensure
|
127
|
+
detach
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def detach
|
132
|
+
request({ 'command' => 'attach' })
|
133
|
+
end
|
134
|
+
|
135
|
+
def debugger_command(command, arguments)
|
136
|
+
h, r = request({
|
137
|
+
'command' => 'debugger_command',
|
138
|
+
'data' => {
|
139
|
+
'seq' => @@seq,
|
140
|
+
'type' => 'request',
|
141
|
+
'command' => command,
|
142
|
+
'arguments' => arguments,
|
143
|
+
}
|
144
|
+
})
|
145
|
+
@@seq += 1
|
146
|
+
|
147
|
+
return h, r
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class ExtensionPorts
|
152
|
+
def initialize(client, id)
|
153
|
+
@client = client
|
154
|
+
@id = id
|
155
|
+
end
|
156
|
+
|
157
|
+
def connect
|
158
|
+
h, r = @client.request({ 'Tool' => 'ExtensionPorts' },
|
159
|
+
{ 'command' => 'connect',
|
160
|
+
'data' => { 'extensionId' => @id } })
|
161
|
+
port = r['data']['portId'].to_i
|
162
|
+
|
163
|
+
if block_given?
|
164
|
+
begin
|
165
|
+
yield(port)
|
166
|
+
ensure
|
167
|
+
disconnect(port)
|
168
|
+
end
|
169
|
+
else
|
170
|
+
return port
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def disconnect(port)
|
175
|
+
@client.request({ 'Tool' => 'ExtensionPorts', 'Destination' => port },
|
176
|
+
{ 'command' => 'disconnect' })
|
177
|
+
end
|
178
|
+
|
179
|
+
def post(port, data)
|
180
|
+
@client.request({ 'Tool' => 'ExtensionPorts', 'Destination' => port },
|
181
|
+
{ 'command' => 'postMessage',
|
182
|
+
'data' => data })
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: google-chrome-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- KATO Kazuyoshi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-14 00:00:00 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: kzys@8-p.info
|
27
|
+
executables:
|
28
|
+
- chrome-repl
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files: []
|
32
|
+
|
33
|
+
files:
|
34
|
+
- lib/google/chrome/client.rb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://8-p.info/chrome-repl/
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: Ruby client of Google Chrome Developer Tools Protocol
|
63
|
+
test_files: []
|
64
|
+
|