Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

executable file 414 lines (344 sloc) 42.082 kB
#!/usr/bin/env python
"""
Copyright (c) 2011 Sencha Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import atexit
import base64
import os
import re
import readline
import socket
from subprocess import Popen, PIPE, STDOUT
import sys
import tempfile
import time
_OPTION_HELP = "-h"
_OPTION_SKIP = "-n"
_TARGET_PACKAGE = 'com.sencha.eventrecorder'
_TARGET_ACTIVITY = _TARGET_PACKAGE + '/.App'
_STANDARD_PACKAGE = 'android.intent.action'
_ADB_PORT = 5037
_LOG_FILTER = 'EventRecorder'
_INTENT_JAVASCRIPT = "JAVASCRIPT"
_INTENT_RECORD = "RECORD"
_INTENT_SCREEN = "SCREEN"
_INTENT_STOP = "STOP"
_INTENT_TEXT_INPUT = "TEXT_INPUT"
_INTENT_URL = "URL"
_INTENT_VIEW = "VIEW"
_REPLY_DONE = 'done'
_REPLY_READY = 'ready'
class ExitCode:
Help = -10
Normal = 0
AdbNotFound = 5
NoDevices = 15
DeviceToolFailed = 25
MultipleDevices = 35
Aborted = 45
WrongUsage = 55
UnknownDevice = 65
_g_state = {
'exitCode': ExitCode.Normal,
'error': '',
'targetDevice': '',
'testName': ''
}
_g_base64Apk = b"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"
def exitCode():
return _g_state['exitCode']
def setExitCode(err):
global _g_state
_g_state['exitCode'] = err
def error():
return _g_state['error']
def setError(err):
global _g_state
_g_state['error'] = err
def targetDevice():
return _g_state['targetDevice']
def testName():
return _g_state['testName']
def setTargetDevice(id):
global _g_state
_g_state['targetDevice'] = id
def setTestName(name):
global _g_state
_g_state['testName'] = name
def startAdbConnection():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('127.0.0.1', _ADB_PORT))
sendData(sock, 'host:transport:' + targetDevice())
return readOkay(sock), sock
def clearLogcat():
cmd = ' logcat -c '
fullCmd = 'adb '
if targetDevice():
fullCmd += '-s ' + targetDevice() + ' '
fullCmd += cmd
proc = Popen(fullCmd, shell=True, stdout=PIPE, stderr=STDOUT)
time.sleep(1)
proc.kill()
def waitForReply(type):
cmd = ' logcat ' + _LOG_FILTER + ':V *:S'
fullCmd = 'adb '
if targetDevice():
fullCmd += '-s ' + targetDevice() + ' '
fullCmd += cmd
proc = Popen(fullCmd, shell=True, stdout=PIPE, stderr=STDOUT)
while True:
line = proc.stdout.readline()
if re.match(r'^[A-Z]/' + _LOG_FILTER, line):
line = re.sub(r'[A-Z]/' + _LOG_FILTER + '(\b)*\((\s)*(\d)+\): ', '', line)
line = re.sub(r'Console: ', '', line)
line = re.sub(r':(\d)+(\b)*', '', line)
line = re.sub(r'\r\n', '', line)
if (line.startswith("#")):
print line
continue
try:
reply = eval(line)
except Exception as e:
setExitCode(ExitCode.Aborted)
setError('Error in protocol: unrecognized message "' + line + '"')
raise e
error = reply['error']
if error:
setExitCode(ExitCode.Aborted)
setError(error)
raise Exception()
if reply['type'] == type:
proc.kill()
clearLogcat()
return reply
def printUsage():
app = os.path.basename(sys.argv[0])
print "Usage: ", app, "<name> [options]\t- record test <name>"
print "Options: <device>\t- use <device> serial number as target"
print " ", _OPTION_SKIP, "\t- keep existing tool on the device (advanced)"
def printCommandHelp():
print "\tYou can open an URL or execute JavaScript code on the remote device.\n" \
"\tAn URL is assumed if it starts with 'www.', 'http://' or 'ftp://',\n" \
"\tJavaScript code is assumed otherwise.\n" \
"\t\n" \
"\tAvailable special commands:\n" \
"\t\ts | screen - Capture screen (excludes status and title bars).\n" \
"\t\tEnter | Return - Finish recording."
def readData(socket, max = 4096):
return socket.recv(max)
def readOkay(socket):
data = socket.recv(4)
return data[0] == 'O' and data[1] == 'K' and data[2] == 'A' and data[3] == 'Y'
def sendData(sock, str):
return sock.sendall('%04X%s' % (len(str), str))
def execute(cmd):
fullCmd = 'adb '
if targetDevice():
fullCmd += '-s ' + targetDevice() + ' '
fullCmd += cmd
proc = Popen(fullCmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
proc.stdin.close()
proc.wait()
def startAdbServer():
execute('start-server')
def query(cmd):
fullCmd = 'adb '
if targetDevice():
fullCmd += '-s ' + targetDevice() + ' '
fullCmd += cmd
proc = Popen(fullCmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
output = proc.stdout.read()
proc.stdin.close()
proc.wait()
return output
def devices():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect(('127.0.0.1', _ADB_PORT))
except Exception as e:
setError('Unable to connect to port %d: %s' % (port, e))
return None
sendData(sock, 'host:devices')
if readOkay(sock):
readData(sock, 4) # payload size in hex
data = readData(sock)
reply = ""
while len(data):
reply += data
data = readData(sock)
sock.close()
devices = re.sub('List of devices attached\s+', '', reply)
devices = devices.splitlines()
list = []
for elem in devices:
if elem.find('device') != -1:
list.append(re.sub(r'\s*device', '', elem))
return list
# adb server not running
sock.close()
return None
def isAdbAvailable():
return query('version').startswith('Android Debug Bridge')
def shell(cmd):
ok, sock = startAdbConnection()
if not ok:
return None
sendData(sock, 'shell:' + cmd)
if readOkay(sock):
data = readData(sock)
result = ""
while len(data):
result += data
data = readData(sock)
sock.close()
return result
else:
endConnection(sock)
return None
def sendIntent(intent, package=_TARGET_PACKAGE, data=''):
clearLogcat()
cmd = 'am start -a ' + package + '.' + intent + ' -n ' + _TARGET_ACTIVITY
if data:
cmd += " -d '" + data + "'"
shell(cmd)
def pull(remote, local):
execute('pull ' + remote + ' ' + local)
def uninstall(apk):
reply = shell('pm uninstall ' + apk)
if reply:
return reply.find('Success') != -1
else:
return False
def install(apk):
reply = query('install ' + apk).strip().split('\n')[-1]
ok = False
if reply == 'Success':
ok = True
return ok, reply
def installDeviceTool():
uninstall(_TARGET_PACKAGE);
file = tempfile.NamedTemporaryFile()
file.write(base64.b64decode(_g_base64Apk))
file.flush()
ok, reply = install(file.name)
file.close()
return ok, reply
def openUrlOrExecuteJS(expr):
fullUrlRe = r'^(ftp|http|https)://(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(/|/([\w#!:.?+=&%@!-/]))?'
if expr.startswith('www') and re.match(fullUrlRe, 'http://' + expr):
sendIntent(_INTENT_URL, data=base64.b64encode('http://' + expr))
elif re.match(fullUrlRe, expr):
sendIntent(_INTENT_URL, data=base64.b64encode(expr))
else:
sendIntent(_INTENT_JAVASCRIPT, data=base64.b64encode(expr))
def sendTextInput(text):
sendIntent(_INTENT_TEXT_INPUT, data=base64.b64encode(text))
def inputLoop():
historyFile = os.path.join(os.environ["HOME"], '.eventrecorder-history')
try:
readline.read_history_file(historyFile)
except IOError:
pass
atexit.register(readline.write_history_file, historyFile)
del historyFile
expr = ""
while True:
expr = raw_input('>>> ').strip()
if expr == 's' or expr == 'screen':
sendIntent(_INTENT_SCREEN)
elif expr.startswith('t '):
sendTextInput(expr[2:])
elif expr.startswith('text '):
sendTextInput(expr[5:])
elif expr == 'h' or expr == 'help':
printCommandHelp()
elif expr == '':
raise Exception()
else:
openUrlOrExecuteJS(expr)
def main():
args = sys.argv[1:]
if _OPTION_HELP in args:
printUsage()
return ExitCode.Help
if not isAdbAvailable():
print "'adb' not found, please add its location to $PATH."
return ExitCode.AdbNotFound
startAdbServer()
deviceList = devices()
if not deviceList or len(deviceList) == 0:
print "No attached devices."
return ExitCode.NoDevices
elif len(args) == 1 and len(deviceList) > 1:
print "Multiple devices attached, one must be specified."
return ExitCode.MultipleDevices
elif len(args) > 3 or len(args) == 0:
printUsage()
return ExitCode.WrongUsage
elif len(args) == 2 and args[1] != _OPTION_SKIP:
if args[1] not in deviceList:
print "Device not found."
return ExitCode.UnknownDevice
else:
setTargetDevice(args[1])
elif len(args) == 3:
if args[1] not in deviceList and args[2] not in deviceList:
print "Device not found."
return ExitCode.UnknownDevice
elif args[1] in deviceList:
setTargetDevice(args[1])
else:
setTargetDevice(args[2])
else:
setTargetDevice(deviceList[0])
setTestName(args[0])
print "EventRecorder - Remote Web Application Test Recorder for Android."
print "Target device is " + targetDevice() + "."
if not _OPTION_SKIP in args:
print "Installing device tool..."
ok, error = installDeviceTool()
if not ok:
print "Device tool installation failed -", error
return ExitCode.DeviceToolFailed
try:
print "Launching device tool..."
sendIntent(_INTENT_VIEW, _STANDARD_PACKAGE)
reply = waitForReply(_REPLY_READY)
sendIntent(_INTENT_RECORD)
reply = waitForReply(_REPLY_READY)
print "Recording... [press Enter key when done, type 'h' or 'help' for instructions]"
try:
inputLoop()
except:
print "Stopping recording..."
sendIntent(_INTENT_STOP)
reply = waitForReply(_REPLY_DONE)
localFileName = testName() + '.py'
print "Fetching playback file as '" + localFileName + "'..."
prefix = reply['filesPath']
script = reply['testScriptFile']
remoteFileName = prefix + '/' + script
pull(remoteFileName, localFileName)
print "Done."
except Exception as e:
code = exitCode()
if code == ExitCode.Aborted:
print _g_state['error']
return code
if __name__ == "__main__":
sys.exit(main())
Jump to Line
Something went wrong with that request. Please try again.