summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/ffdb.py133
1 files changed, 91 insertions, 42 deletions
diff --git a/tools/ffdb.py b/tools/ffdb.py
index 6367c0e3..9734014e 100755
--- a/tools/ffdb.py
+++ b/tools/ffdb.py
@@ -297,6 +297,23 @@ def b2g_app_command(app_command, app_name):
print 'Error! Application "' + app_name + '" was not found! Use the \'list\' command to find installed applications.'
return 1
+def b2g_memory(app_name):
+ apps = b2g_get_appslist()
+ appActor = ''
+ for app in apps:
+ if str(app['localId']) == app_name or app['name'] == app_name or app['manifestURL'] == app_name or app['id'] == app_name:
+ appActor = send_b2g_cmd(webappsActorName, 'getAppActor', { 'manifestURL': app['manifestURL'] })
+ break
+ if 'actor' in appActor:
+ memoryActor = appActor['actor']['memoryActor']
+ measure = send_b2g_cmd(memoryActor, 'measure')
+ for k,v in measure.items():
+ if k != 'from':
+ if k in ['otherSize', 'jsStringsSize', 'jsObjectsSize', 'styleSize', 'jsOtherSize', 'domSize', 'total']: # These are formatted in bytes
+ print k + ': ' + sizeof_fmt(v)
+ else:
+ print k + ': ' + str(v)
+
def b2g_log(app_name, clear=False):
apps = b2g_get_appslist()
appActor = ''
@@ -349,8 +366,67 @@ def b2g_log(app_name, clear=False):
else:
print 'Application "' + sys.argv[2] + '" is not running!'
+def b2g_screenshot(filename):
+ global deviceActorName
+ data_reply = send_b2g_cmd(deviceActorName, 'screenshotToDataURL')
+ data = data_reply['value']
+ if not isinstance(data, basestring): # The device is sending the screenshot in multiple fragments since it's too long to fit in one message?
+ data_get_actor = data['actor']
+ data_len = int(data['length'])
+ data = data['initial']
+ chunk_size = 65000
+ pos = len(data)
+ # Pull and assemble individual screenshot fragments.
+ while pos < data_len:
+ bytes_to_read = min(data_len - pos, chunk_size)
+ data_reply = send_b2g_cmd(data_get_actor, 'substring', { 'start': str(pos), 'end': str(pos + bytes_to_read) })
+ if len(data_reply['substring']) != bytes_to_read:
+ print >> sys.stderr, 'Error! Expected to receive ' + str(bytes_to_read) + ' bytes of image data, but got ' + str(len(data_reply['substring'])) + ' bytes instead!'
+ sys.exit(1)
+ data += data_reply['substring']
+ pos += bytes_to_read
+ send_b2g_cmd(data_get_actor, 'release') # We need to explicitly free the screenshot image string from the device, or the Devtools connection leaks resources!
+
+ # Expected format is "data:image/png;base64,<base64data>"
+ delim = re.search(",", data).start()
+ data_format = data[:delim]
+ if data_format != "data:image/png;base64":
+ print >> sys.stderr, "Error: Received screenshot from device in an unexpected format '" + data_format + "'!"
+ sys.exit(1)
+ data = data[delim+1:]
+
+ binary_data = base64.b64decode(data)
+ open(filename, 'wb').write(binary_data)
+
+ def get_png_image_size(filename):
+ fhandle = open(filename, 'rb')
+ head = fhandle.read(24)
+ if len(head) != 24:
+ return (-1, -1)
+ check = struct.unpack('>i', head[4:8])[0]
+ if check != 0x0d0a1a0a:
+ return (-1, -1)
+ return struct.unpack('>ii', head[16:24])
+
+ width, height = get_png_image_size(filename)
+ if width <= 0 or height <= 0:
+ print >> sys.stderr, "Wrote " + sizeof_fmt(len(binary_data)) + " to file '" + filename + "', but the contents may be corrupted!"
+ else:
+ print "Wrote " + sizeof_fmt(len(binary_data)) + " to file '" + filename + "' (" + str(width) + 'x' + str(height) + ' pixels).'
+
+def b2g_get_description(desc):
+ global deviceActorName
+ data_reply = send_b2g_cmd(deviceActorName, 'getDescription')
+ # First try an exact match to requested desc
+ if desc and desc in data_reply['value']:
+ print desc + ': ' + str(data_reply['value'][desc])
+ else: # Print all with case-insensitive substring search
+ for k,v in data_reply['value'].items():
+ if not desc or desc.lower() in k.lower():
+ print k + ': ' + str(v)
+
def main():
- global b2g_socket, webappsActorName, HOST, PORT, VERBOSE, ADB
+ global b2g_socket, webappsActorName, deviceActorName, HOST, PORT, VERBOSE, ADB
if len(sys.argv) < 2 or '--help' in sys.argv or 'help' in sys.argv or '-v' in sys.argv:
print '''Firefox OS Debug Bridge, a tool for automating FFOS device tasks from the command line.
@@ -369,11 +445,15 @@ def main():
If the --log option is passed, ffdb will start persistently logging the execution of the installed application.
log <app> [--clear]: Starts a persistent log listener that reads web console messages from the given application.
If --clear is passed, the message log for that application is cleared instead.
+ memory <app>: Dumps a memory usage summary for the given application.
navigate <url>: Opens the given web page in the B2G browser.
screenshot [filename.png]: Takes a screenshot of the current contents displayed on the device. If an optional
filename is specified, the screenshot is saved to that file. Otherwise the filename
will be autogenerated.
- get <pref>: Fetches the value of the given developer pref option from the FFOS device and prints it to console.
+ get [pref]: Fetches the value of the given developer pref option from the FFOS device and prints it to console. The parameter pref
+ is optional and may either be the full name of a pref, or a substring to search for. All matching prefs will be printed.
+ If no pref parameter is given, all prefs are printed.
+ NOTE: This function (currently at least) only reports prefs that have been explicitly set and don't have their default value.
set <pref> <value>: Writes the given pref option to the FFOS device and restarts the B2G process on it for the change to take effect.
unset <pref>: Removes the given pref option from the FFOS device and restarts the B2G process on it for the change to take effect.
@@ -381,6 +461,10 @@ def main():
provided for conveniency, and is the same as calling './ffdb.py set devtools.debugger.prompt-connection false'
restore-prompt: Restores the remote debugging connection dialog prompt to its default state.
+ desc [desc]: Fetches the value of the given device description field. These fields are read-only and describe the current system.
+ If the optional desc parameter is omitted, all device descriptions are printed. Otherwise the given description is
+ printed if it is an exact match, or all descriptions containing desc as the substring are printed.
+
Options: Additionally, the following options may be passed to control FFDB execution:
--host <hostname>: Specifies the target network address to connect to. Default: 'localhost'.
@@ -532,6 +616,8 @@ def main():
elif sys.argv[1] == 'log':
clear = '-c' in sys.argv or '-clear' in sys.argv or '--clear' in sys.argv
b2g_log(sys.argv[2], clear)
+ elif sys.argv[1] == 'memory':
+ b2g_memory(sys.argv[2])
elif sys.argv[1] == 'screenshot':
if len(sys.argv) >= 3:
filename = sys.argv[2]
@@ -541,46 +627,7 @@ def main():
else:
filename = time.strftime("screen_%Y%m%d_%H%M%S.png", time.gmtime())
- data_reply = send_b2g_cmd(deviceActorName, 'screenshotToDataURL')
- data = data_reply['value']
- data_get_actor = data['actor']
- data_len = int(data['length'])
- data_str = data['initial']
- delim = re.search(",", data_str).start()
- data_format = data_str[:delim]
- if data_format != "data:image/png;base64":
- print >> sys.stderr, "Error: Received screenshot from device in an unexpected format '" + data_format + "'!"
- sys.exit(1)
- data = data_str[delim+1:]
- chunk_size = 65000
- pos = len(data_str)
- while pos < data_len:
- bytes_to_read = min(data_len - pos, chunk_size)
- data_reply = send_b2g_cmd(data_get_actor, 'substring', { 'start': str(pos), 'end': str(pos + bytes_to_read) })
- if len(data_reply['substring']) != bytes_to_read:
- print >> sys.stderr, 'Error! Expected to receive ' + str(bytes_to_read) + ' bytes of image data, but got ' + str(len(data_reply['substring'])) + ' bytes instead!'
- sys.exit(1)
- data += data_reply['substring']
- pos += bytes_to_read
- send_b2g_cmd(data_get_actor, 'release') # We need to explicitly free the screenshot image string from the device, or the Devtools connection leaks resources!
- binary_data = base64.b64decode(data)
- open(filename, 'wb').write(binary_data)
-
- def get_png_image_size(filename):
- fhandle = open(filename, 'rb')
- head = fhandle.read(24)
- if len(head) != 24:
- return (-1, -1)
- check = struct.unpack('>i', head[4:8])[0]
- if check != 0x0d0a1a0a:
- return (-1, -1)
- return struct.unpack('>ii', head[16:24])
-
- width, height = get_png_image_size(filename)
- if width <= 0 or height <= 0:
- print >> sys.stderr, "Wrote " + sizeof_fmt(len(binary_data)) + " to file '" + filename + "', but the contents may be corrupted!"
- else:
- print "Wrote " + sizeof_fmt(len(binary_data)) + " to file '" + filename + "' (" + str(width) + 'x' + str(height) + ' pixels).'
+ b2g_screenshot(filename)
elif sys.argv[1] == 'get':
b2g_get_pref(sys.argv[2] if len(sys.argv) >= 3 else None)
elif sys.argv[1] == 'set':
@@ -603,6 +650,8 @@ def main():
b2g_set_pref('devtools.debugger.prompt-connection', 'false')
elif sys.argv[1] == 'restore-prompt':
b2g_set_pref('devtools.debugger.prompt-connection', None)
+ elif sys.argv[1] == 'desc':
+ b2g_get_description(sys.argv[2] if len(sys.argv) >= 3 else None)
else:
print "Unknown command '" + sys.argv[1] + "'! Pass --help for instructions."