diff options
author | Zhen Wang <zhenw@google.com> | 2015-08-28 09:54:29 -0700 |
---|---|---|
committer | Zhen Wang <zhenw@google.com> | 2015-08-28 14:43:25 -0700 |
commit | 46b43bff003ceda46cf9a5d40a47f7674996d2e0 (patch) | |
tree | 1cd106acefcd7fc603515093c15fdee9f5d1eea6 | |
parent | ee56b2f0e03cfbab8f4c8070311f3e17adffbfdb (diff) | |
download | chromium-trace-46b43bff003ceda46cf9a5d40a47f7674996d2e0.tar.gz |
Update after moving the code to Catapult
Change-Id: I0b9e15f8d5743811f3a722e7a692e89e7e36734e
Signed-off-by: Zhen Wang <zhenw@google.com>
560 files changed, 42228 insertions, 19925 deletions
@@ -1,4 +1,2 @@ *.pyc trace.html -flat_script.js -trace-viewer/.git/ @@ -1,22 +1,13 @@ -The trace-viewer directory contains code from: +Systrace is now part of Catapult project. The catapult directory contains code +from: - http://trace-viewer.googlecode.com/svn/trunk/ + https://github.com/catapult-project/catapult.git The file UPSTREAM_REVISION contains the upstream revision number that was last -pulled. Changes should be made upstream and then pulled into the trace-viewer +pulled. Changes should be made upstream and then pulled into the catapult directory. The update.py script should be used to pull the latest upstream code, update -the UPSTREAM_REVISION file, and package the CSS and Javascript files into -style.css and script.js, respectively. These generated files are being checked -into the git repository, and they get embedded in each trace HTML file that -systrace.py generates. - -To make development of trace-viewer code in the context of systrace easier, -systrace supports arguments to generate HTML files that link to files in a -trace-viewer development directory rather than embedding the JS and CSS in the -HTML. Do take advantage of this, you should check out the trace-viewer code in -a new directory (e.g. trace-viewer-dev) and use systrace as follows: - - $ ./systrace.py --link-assets --asset-dir trace-viewer-dev - +the UPSTREAM_REVISION file, and generate systrace_trace_viewer.html. The +generated file is checked into the git repository, and they get embedded in each +trace HTML file that systrace.py generates. diff --git a/UPSTREAM_REVISION b/UPSTREAM_REVISION index f5f9c961..8fc4fb19 100644 --- a/UPSTREAM_REVISION +++ b/UPSTREAM_REVISION @@ -1 +1 @@ -26595c9da43a4982f5e7aa30a10e778735b8e337 +7600f2db8d6c0dfe13763c5d463aeb8e2ed66e5e diff --git a/agents/__init__.py b/agents/__init__.py deleted file mode 100644 index 8cc6cfda..00000000 --- a/agents/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file.
\ No newline at end of file diff --git a/catapult/PRESUBMIT.py b/catapult/PRESUBMIT.py index c95868ea..68ef74e3 100644 --- a/catapult/PRESUBMIT.py +++ b/catapult/PRESUBMIT.py @@ -24,7 +24,7 @@ _EXCLUDED_PATHS = ( r'.*LICENSE$', r'.*OWNERS$', r'.*README\.md$', - r'^dashboard[\\\/]third_party[\\\/].*', + r'^dashboard[\\\/]dashboard[\\\/]templates[\\\/].*', r'^experimental[\\\/]heatmap[\\\/].*', r'^perf_insights[\\\/]test_data[\\\/].*', r'^perf_insights[\\\/]third_party[\\\/].*', @@ -61,7 +61,7 @@ def CheckChange(input_api, output_api): results = [] try: sys.path += [input_api.PresubmitLocalPath()] - from build import js_checks + from catapult_build import js_checks results += input_api.canned_checks.PanProjectChecks( input_api, output_api, excluded_paths=_EXCLUDED_PATHS) results += input_api.canned_checks.RunPylint( diff --git a/catapult/bin/run_dev_server b/catapult/bin/run_dev_server index 2ef5b368..57102ecf 100755 --- a/catapult/bin/run_dev_server +++ b/catapult/bin/run_dev_server @@ -10,5 +10,5 @@ if __name__ == '__main__': catapult_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) sys.path.append(catapult_path) - from build import dev_server + from catapult_build import dev_server sys.exit(dev_server.Main(sys.argv)) diff --git a/catapult/bin/run_py_tests b/catapult/bin/run_py_tests index 6aaecc63..ffe02248 100755 --- a/catapult/bin/run_py_tests +++ b/catapult/bin/run_py_tests @@ -10,5 +10,5 @@ if __name__ == '__main__': catapult_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) sys.path.append(catapult_path) - from build import run_py_tests + from catapult_build import run_py_tests sys.exit(run_py_tests.Main(sys.argv)) diff --git a/catapult/bin/run_tests b/catapult/bin/run_tests index 069351bf..3d6f0595 100755 --- a/catapult/bin/run_tests +++ b/catapult/bin/run_tests @@ -21,5 +21,5 @@ _TESTS = [ if __name__ == '__main__': catapult_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) sys.path.append(catapult_path) - from build import test_runner + from catapult_build import test_runner sys.exit(test_runner.Main('project', _TESTS, sys.argv)) diff --git a/catapult/build/__init__.py b/catapult/catapult_build/__init__.py index 78442fd7..78442fd7 100644 --- a/catapult/build/__init__.py +++ b/catapult/catapult_build/__init__.py diff --git a/catapult/catapult_build/appengine_deploy.py b/catapult/catapult_build/appengine_deploy.py new file mode 100644 index 00000000..e0927026 --- /dev/null +++ b/catapult/catapult_build/appengine_deploy.py @@ -0,0 +1,55 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# TODO(qyearsley): Add a step to vulcanize each template HTML file. +# TODO(qyearsley): Add a step to put static files in a versioned +# directory and modify app.yaml and request_handler as needed. + +import subprocess +import sys +import tempfile + +from catapult_build import module_finder +from catapult_build import temp_deployment_dir + + +def AppcfgUpdate(paths, app_id): + """Deploys a new version of an App Engine app from a temporary directory. + + Args: + paths: List of paths to files and directories that should be linked + (or copied) in the deployment directory. + app_id: The application ID to use. + """ + try: + import appcfg # pylint: disable=unused-variable + except ImportError: + # TODO(qyearsley): Put the App Engine SDK in the path with the + # binary dependency manager. + print 'This script requires the App Engine SDK to be in PYTHONPATH.' + sys.exit(1) + with temp_deployment_dir.TempDeploymentDir(paths) as temp_dir: + print 'Deploying from "%s".' % temp_dir + _Run([ + module_finder.FindModule('appcfg'), + '--application=%s' % app_id, + '--version=%s' % _VersionName(), + 'update', + temp_dir, + ]) + + +def _VersionName(): + is_synced = not _Run(['git', 'diff', 'master']).strip() + deployment_type = 'clean' if is_synced else 'dev' + email = _Run(['git', 'config', '--get', 'user.email']) + username = email[0:email.find('@')] + commit_hash = _Run(['git', 'rev-parse', '--short=8', 'HEAD']).strip() + return '%s-%s-%s' % (deployment_type, username, commit_hash) + + +def _Run(command): + proc = subprocess.Popen(command, stdout=subprocess.PIPE) + output, _ = proc.communicate() + return output diff --git a/catapult/catapult_build/appengine_dev_server.py b/catapult/catapult_build/appengine_dev_server.py new file mode 100644 index 00000000..27dda86d --- /dev/null +++ b/catapult/catapult_build/appengine_dev_server.py @@ -0,0 +1,33 @@ +#!/usr/bin/python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import subprocess +import sys + +from catapult_build import module_finder +from catapult_build import temp_deployment_dir + + +def DevAppserver(paths, args): + """Starts a dev server for an App Engine app. + + Args: + paths: List of paths to files and directories that should be linked + (or copied) in the deployment directory. + args: List of additional arguments to pass to the dev server. + """ + try: + import dev_appserver # pylint: disable=unused-variable + except ImportError: + # TODO(qyearsley): Put the App Engine SDK in the path with the + # binary dependency manager. + print 'This script requires the App Engine SDK to be in PYTHONPATH.' + sys.exit(1) + with temp_deployment_dir.TempDeploymentDir(paths) as temp_dir: + print 'Running dev server on "%s".' % temp_dir + subprocess.call( + [module_finder.FindModule('dev_appserver')] + args + [temp_dir] + ) diff --git a/catapult/build/dev_server.py b/catapult/catapult_build/dev_server.py index c8807a95..1c566423 100644 --- a/catapult/build/dev_server.py +++ b/catapult/catapult_build/dev_server.py @@ -18,16 +18,24 @@ from webapp2 import Route, RedirectHandler from perf_insights_build import perf_insights_dev_server_config from tracing_build import tracing_dev_server_config -_UNIT_TEST_HTML = """<html><body> +_MAIN_HTML = """<html><body> <h1>Run Unit Tests</h1> <ul> %s </ul> +<h1>Quick links</h1> +<ul> +%s +</ul> </body></html> """ -_UNIT_TEST_LINK = '<li><a href="%s">%s</a></li>' +_QUICK_LINKS = [ + ('Trace File Viewer', '/tracing_examples/trace_viewer.html'), + ('Perf Insights Viewer', '/perf_insights_examples/perf_insights_viewer.html') +] +_LINK_ITEM = '<li><a href="%s">%s</a></li>' def _GetFilesIn(basedir): data_files = [] @@ -128,10 +136,14 @@ class SimpleDirectoryHandler(webapp2.RequestHandler): class TestOverviewHandler(webapp2.RequestHandler): def get(self, *args, **kwargs): # pylint: disable=unused-argument - links = [] + test_links = [] for name, path in kwargs.pop('pds').iteritems(): - links.append(_UNIT_TEST_LINK % (path, name)) - self.response.out.write(_UNIT_TEST_HTML % '\n'.join(links)) + test_links.append(_LINK_ITEM % (path, name)) + quick_links = [] + for name, path in _QUICK_LINKS: + quick_links.append(_LINK_ITEM % (path, name)) + self.response.out.write(_MAIN_HTML % ('\n'.join(test_links), + '\n'.join(quick_links))) def CreateApp(pds, args): diff --git a/catapult/build/dev_server_unittest.py b/catapult/catapult_build/dev_server_unittest.py index faa50d51..d8651747 100644 --- a/catapult/build/dev_server_unittest.py +++ b/catapult/catapult_build/dev_server_unittest.py @@ -6,7 +6,7 @@ import json import unittest -from build import dev_server +from catapult_build import dev_server from perf_insights_build import perf_insights_dev_server_config from tracing_build import tracing_dev_server_config import webapp2 diff --git a/catapult/build/fixjsstyle b/catapult/catapult_build/fixjsstyle index 36bc61b5..36bc61b5 100755 --- a/catapult/build/fixjsstyle +++ b/catapult/catapult_build/fixjsstyle diff --git a/catapult/build/fixjsstyle.py b/catapult/catapult_build/fixjsstyle.py index a9d1ebdd..a9d1ebdd 100644 --- a/catapult/build/fixjsstyle.py +++ b/catapult/catapult_build/fixjsstyle.py diff --git a/catapult/build/gjslint b/catapult/catapult_build/gjslint index 617b475c..617b475c 100755 --- a/catapult/build/gjslint +++ b/catapult/catapult_build/gjslint diff --git a/catapult/build/gjslint.py b/catapult/catapult_build/gjslint.py index 6f9eff96..6f9eff96 100644 --- a/catapult/build/gjslint.py +++ b/catapult/catapult_build/gjslint.py diff --git a/catapult/build/js_checks.py b/catapult/catapult_build/js_checks.py index 27fda75f..d755192b 100644 --- a/catapult/build/js_checks.py +++ b/catapult/catapult_build/js_checks.py @@ -175,7 +175,11 @@ class JSChecker(object): def RunChecks(input_api, output_api, excluded_paths=None): - file_filter=None - if excluded_paths: - file_filter = lambda x: any(re.match(p, x) for p in excluded_paths) - return JSChecker(input_api, output_api, file_filter=file_filter).RunChecks() + + def ShouldCheck(affected_file): + if not excluded_paths: + return True + path = affected_file.LocalPath() + return not any(re.match(pattern, path) for pattern in excluded_paths) + + return JSChecker(input_api, output_api, file_filter=ShouldCheck).RunChecks() diff --git a/catapult/catapult_build/module_finder.py b/catapult/catapult_build/module_finder.py new file mode 100644 index 00000000..6a83ac3f --- /dev/null +++ b/catapult/catapult_build/module_finder.py @@ -0,0 +1,19 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import imp + +def FindModule(name): + """Gets the path of the named module. + + This is useful for cases where we want to use subprocess.call on a module we + have imported, and safer than using __file__ since that can point to .pyc + files. + + Args: + name: the string name of a module (e.g. 'dev_appserver') + Returns: + The path to the module. + """ + return imp.find_module(name)[1] diff --git a/catapult/build/run_dev_server_tests.py b/catapult/catapult_build/run_dev_server_tests.py index 42dd6d5a..42dd6d5a 100644 --- a/catapult/build/run_dev_server_tests.py +++ b/catapult/catapult_build/run_dev_server_tests.py diff --git a/catapult/build/run_py_tests.py b/catapult/catapult_build/run_py_tests.py index c481cc0c..c481cc0c 100644 --- a/catapult/build/run_py_tests.py +++ b/catapult/catapult_build/run_py_tests.py diff --git a/catapult/catapult_build/temp_deployment_dir.py b/catapult/catapult_build/temp_deployment_dir.py new file mode 100644 index 00000000..6b99d46b --- /dev/null +++ b/catapult/catapult_build/temp_deployment_dir.py @@ -0,0 +1,36 @@ +#!/usr/bin/python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import contextlib +import os +import tempfile + + +@contextlib.contextmanager +def TempDeploymentDir(paths): + """Sets up and tears down a directory for deploying an app.""" + try: + deployment_dir = tempfile.mkdtemp(prefix='deploy-') + _PopulateDeploymentDir(deployment_dir, paths) + yield deployment_dir + finally: + _CleanUp(deployment_dir) + + +def _PopulateDeploymentDir(deployment_dir, paths): + """Fills the deployment directory with symlinks.""" + for path in paths: + destination = os.path.join(deployment_dir, os.path.basename(path)) + os.symlink(path, destination) + + +def _CleanUp(deployment_dir): + """Removes a directory that is populated with symlinks.""" + for symlink_name in os.listdir(deployment_dir): + link_path = os.path.join(deployment_dir, symlink_name) + if os.path.islink(link_path): + os.unlink(link_path) + os.rmdir(deployment_dir) + diff --git a/catapult/build/test_runner.py b/catapult/catapult_build/test_runner.py index b873ab9b..b873ab9b 100644 --- a/catapult/build/test_runner.py +++ b/catapult/catapult_build/test_runner.py diff --git a/catapult/codereview.settings b/catapult/codereview.settings index 68af03a9..0da0c61d 100644 --- a/catapult/codereview.settings +++ b/catapult/codereview.settings @@ -3,3 +3,4 @@ CODE_REVIEW_SERVER: codereview.chromium.org CC_LIST: catapult-reviews@chromium.org VIEW_VC: https://chromium.googlesource.com/external/github.com/catapult-project/catapult/+/ PROJECT: catapult +BUG_PREFIX: # diff --git a/catapult/dashboard/README.md b/catapult/dashboard/README.md index f4299344..14d2ab64 100644 --- a/catapult/dashboard/README.md +++ b/catapult/dashboard/README.md @@ -24,17 +24,22 @@ to both `PATH` and `PYTHONPATH`. ## Running the tests -To run all of the unit tests, you can run `./run_tests.py`. You can +To run all of the unit tests, you can run `bin/run_tests`. You can also pass the import path to the test module to run a particular test, -for example `./run_tests.py dashboard.utils_test`. +for example `bin/run_tests dashboard.utils_test`. ## To run locally -TODO: Fill in this section when a custom dev server script is added. +Run `bin/dev_server`; this sets up a temporary directory, adds links +to required libraries, and calls `dev_appserver.py` on that directory. +By default, this starts a server on localhost:8080. + +To load sample graph or alert data from production, navigate to +`http://localhost:8080/load_from_prod`. ## Deploying to production -To deploy, you can run `./deploy.py`, which prepares the code to be +To deploy, you can run `bin/deploy`, which prepares the code to be deployed and runs `appcfg.py`. This requires having the App Engine SDK directory in your `PATH`. diff --git a/catapult/dashboard/app.yaml b/catapult/dashboard/app.yaml index 3eaa2966..dd52279a 100644 --- a/catapult/dashboard/app.yaml +++ b/catapult/dashboard/app.yaml @@ -48,24 +48,23 @@ handlers: static_dir: dashboard/static/ secure: always -- url: /dashboard/elements/(.*\.html)$ - static_files: dashboard/elements/\1 - upload: dashboard/elements/.*\.html$ +- url: /elements/ + static_dir: dashboard/elements/ secure: always - url: /third_party/polymer/components/(.*)/(.*\.(html|js|css))$ - static_files: third_party/polymer/components/\1/\2 - upload: third_party/polymer/components/.*/.*\.(html|js|css)$ + static_files: polymer/components/\1/\2 + upload: polymer/components/.*/.*\.(html|js|css)$ secure: always - url: /third_party/flot/(.*\.js)$ - static_files: third_party/flot/\1 - upload: third_party/flot/.*\.js$ + static_files: flot/\1 + upload: flot/.*\.js$ secure: always - url: /third_party/jquery/(.*\.js)$ - static_files: third_party/jquery/\1 - upload: third_party/jquery/.*\.js$ + static_files: jquery/\1 + upload: jquery/.*\.js$ secure: always - url: /add_point_queue diff --git a/catapult/dashboard/appengine_config.py b/catapult/dashboard/appengine_config.py index 416e261e..9042df5b 100644 --- a/catapult/dashboard/appengine_config.py +++ b/catapult/dashboard/appengine_config.py @@ -35,13 +35,13 @@ def _AddThirdPartyLibraries(): runtime environment, they must be added with vendor.add. The directories added this way must be inside the App Engine project directory. """ - # The deploy script is expected to add a link to third_party in this directory - # before deploying. If the directory isn't there (e.g. for tests), then ignore - # it; the libraries should be set up in run_tests.py. - third_party_dir = os.path.join(os.path.dirname(__file__), 'third_party') - if os.path.exists(third_party_dir): - for library_dir in dashboard.THIRD_PARTY_LIBRARIES: - vendor.add(os.path.join(third_party_dir, library_dir)) + # The deploy script is expected to add links to third party libraries + # before deploying. If the directories aren't there (e.g. when running tests) + # then just ignore it. + for library_dir in (dashboard.THIRD_PARTY_LIBRARIES + + dashboard.THIRD_PARTY_LIBRARIES_IN_SDK): + if os.path.exists(library_dir): + vendor.add(os.path.join(os.path.dirname(__file__), library_dir)) _AddThirdPartyLibraries() diff --git a/catapult/dashboard/bin/deploy b/catapult/dashboard/bin/deploy new file mode 100755 index 00000000..a495c831 --- /dev/null +++ b/catapult/dashboard/bin/deploy @@ -0,0 +1,33 @@ +#!/usr/bin/python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import argparse +import os +import sys + + +def _AddToPathIfNeeded(path): + if path not in sys.path: + sys.path.insert(0, path) + + +def Main(): + catapult_path = os.path.abspath(os.path.join( + os.path.dirname(__file__), os.path.pardir, os.path.pardir)) + parser = argparse.ArgumentParser() + parser.add_argument('--appid', default='chromeperf') + args = parser.parse_args() + + _AddToPathIfNeeded(os.path.join(catapult_path, 'dashboard')) + import dashboard + paths = dashboard.PathsForDeployment() + + _AddToPathIfNeeded(catapult_path) + from catapult_build import appengine_deploy + appengine_deploy.AppcfgUpdate(paths, app_id=args.appid) + + +if __name__ == '__main__': + Main() diff --git a/catapult/dashboard/bin/dev_server b/catapult/dashboard/bin/dev_server new file mode 100755 index 00000000..52755400 --- /dev/null +++ b/catapult/dashboard/bin/dev_server @@ -0,0 +1,29 @@ +#!/usr/bin/python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import sys + + +def _AddToPathIfNeeded(path): + if path not in sys.path: + sys.path.insert(0, path) + + +def Main(): + catapult_path = os.path.abspath(os.path.join( + os.path.dirname(__file__), os.path.pardir, os.path.pardir)) + + _AddToPathIfNeeded(os.path.join(catapult_path, 'dashboard')) + import dashboard + paths = dashboard.PathsForDeployment() + + _AddToPathIfNeeded(catapult_path) + from catapult_build import appengine_dev_server + appengine_dev_server.DevAppserver(paths, sys.argv[1:]) + + +if __name__ == '__main__': + Main() diff --git a/catapult/dashboard/run_tests.py b/catapult/dashboard/bin/run_tests index b5451cd7..4ada1922 100755 --- a/catapult/dashboard/run_tests.py +++ b/catapult/dashboard/bin/run_tests @@ -6,45 +6,56 @@ """Runs the unit test suite for perf dashboard.""" import argparse -import dev_appserver import logging import os import sys import unittest -_DASHBOARD_PARENT = os.path.join(os.path.dirname(__file__)) -_DASHBOARD = os.path.join(_DASHBOARD_PARENT, 'dashboard') +_CATAPULT = os.path.abspath( + os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)) + + +def _AddToPathIfNeeded(path): + if path not in sys.path: + sys.path.insert(0, path) def _GetTests(args): loader = unittest.TestLoader() if args.tests: return loader.loadTestsFromNames(args.tests) - return loader.discover(_DASHBOARD, pattern='*_test.py') + dashboard_package_path = os.path.join(_CATAPULT, 'dashboard', 'dashboard') + return loader.discover(dashboard_package_path, pattern='*_test.py') def _FixPath(): + try: + import dev_appserver + except ImportError: + # TODO(qyearsley): Put the App Engine SDK in the path with the + # binary dependency manager. + print 'This script requires the App Engine SDK to be in PYTHONPATH.' + sys.exit(1) dev_appserver.fix_sys_path() - sys.path.insert(0, os.path.dirname(__file__)) - # Loading __init__.py when importing dashboard adds libraries to sys.path. - import dashboard # pylint: disable=unused-variable + _AddToPathIfNeeded(os.path.join(_CATAPULT, 'dashboard')) + import dashboard + for library in dashboard.THIRD_PARTY_LIBRARIES: + _AddToPathIfNeeded(os.path.join(_CATAPULT, 'third_party', library)) -def main(): +def Main(): _FixPath() parser = argparse.ArgumentParser(description='Run the test suite.') parser.add_argument('tests', nargs='*', help='Fully-qualified test name.') parser.add_argument('-v', '--verbose', action='store_true') args = parser.parse_args() tests = _GetTests(args) - runner_verbosity = 2 if not args.verbose: - runner_verbosity = 1 logging.basicConfig(format='', level=logging.CRITICAL) - runner = unittest.TextTestRunner(verbosity=runner_verbosity) + runner = unittest.TextTestRunner(verbosity=2) result = runner.run(tests) return 0 if result.wasSuccessful() else 1 if __name__ == '__main__': - sys.exit(main()) + sys.exit(Main()) diff --git a/catapult/dashboard/cron.yaml b/catapult/dashboard/cron.yaml new file mode 100644 index 00000000..5e046f02 --- /dev/null +++ b/catapult/dashboard/cron.yaml @@ -0,0 +1,65 @@ +# Scheduled Tasks with Cron +# https://developers.google.com/appengine/docs/python/config/cron + +cron: + +- description: Start and restart bisect jobs. + url: /auto_bisect + schedule: every 1 hours + +- description: Mark alerts as recovered, and associate alerts with groups. + url: /auto_triage + schedule: every 6 hours + +- description: Update metadata from unit-info.json, etc. + url: /update_test_metadata + schedule: every 24 hours + +- description: Send e-mails with daily anomaly summaries. + url: /email_summary + schedule: every 24 hours + +- description: Send data stoppage alert emails. + url: /send_stoppage_alert_emails + schedule: every 24 hours + +- description: Run the mapreduce job to mark tests as deprecated. + url: /mr_deprecate_tests + # If you update the time below, also update the constant in mr.py. + schedule: every 48 hours + +- description: Update bugs with completed bisect job results. + url: /update_bug_with_results + schedule: every 15 minutes + +- description: Delete expired layered_cache.CachedPickledString entities. + url: /delete_expired_entities + schedule: every 24 hours + +- description: Update the test suite data used on the /report page. + url: /update_test_suites + schedule: every 20 minutes + +# Scheduled backup. +# If you add new datastore kinds and want them to be backed up, +# you must add kind=argument to the URL below. Backups are available at: +# https://appengine.google.com/datastore/admin?&app_id=s~chromeperf +# See: https://cloud.google.com/appengine/articles/scheduled_backups +- description: Back up all entities in the datastore. + url: "/_ah/datastore_admin/backup.create?name=ScheduledBackup\ +&kind=Master\ +&kind=Bot\ +&kind=Test\ +&kind=Row\ +&kind=Sheriff\ +&kind=AnomalyConfig\ +&kind=Anomaly\ +&kind=StoppageAlert\ +&kind=IpWhitelist\ +&kind=BotWhitelist\ +&kind=BugLabelPatterns\ +&kind=MultipartEntity\ +&kind=PartEntity" + schedule: every saturday 05:00 + target: ah-builtin-python-bundle + diff --git a/catapult/dashboard/dashboard/__init__.py b/catapult/dashboard/dashboard/__init__.py index 8299513f..886727a1 100644 --- a/catapult/dashboard/dashboard/__init__.py +++ b/catapult/dashboard/dashboard/__init__.py @@ -2,28 +2,70 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# Add required third-party libraries to sys.path. - import os -import sys -_THIRD_PARTY_DIR = os.path.join( - os.path.dirname(__file__), os.path.pardir, os.path.pardir, 'third_party') +# Directories in catapult/third_party required by dashboard. THIRD_PARTY_LIBRARIES = [ 'apiclient', 'beautifulsoup4', - 'httplib2', 'graphy', 'mapreduce', 'mock', - 'oauth2client', 'pipeline', - 'six', 'uritemplate', 'webtest', + 'flot', + 'jquery', + 'polymer', +] + +# Libraries bundled with the App Engine SDK. +THIRD_PARTY_LIBRARIES_IN_SDK = [ + 'httplib2', + 'oauth2client', + 'six', +] + +# Files and directories in catapult/dashboard. +DASHBOARD_FILES = [ + 'appengine_config.py', + 'app.yaml', + 'dashboard', + 'index.yaml', + 'mapreduce.yaml', + 'queue.yaml', ] -for library_dir in THIRD_PARTY_LIBRARIES: - sys.path.insert(0, os.path.join(_THIRD_PARTY_DIR, library_dir)) +def PathsForDeployment(): + """Returns a list of paths to things required for deployment. + + This list is used when building a temporary deployment directory; + each of the items in this list will have a corresponding file or + directory with the same basename in the deployment directory. + """ + paths = [] + + catapult_path = os.path.abspath(os.path.join( + os.path.dirname(__file__), os.path.pardir, os.path.pardir)) + dashboard_dir = os.path.join(catapult_path, 'dashboard') + for name in DASHBOARD_FILES: + paths.append(os.path.join(dashboard_dir, name)) + + try: + import dev_appserver + except ImportError: + # The App Engine SDK is assumed to be in PYTHONPATH when setting + # up the deployment directory, but isn't available in production. + # (But this function shouldn't be called in production anyway.) + pass + for path in dev_appserver.EXTRA_PATHS: + if os.path.basename(path) in THIRD_PARTY_LIBRARIES_IN_SDK: + paths.append(path) + + third_party_dir = os.path.join(catapult_path, 'third_party') + for library_dir in THIRD_PARTY_LIBRARIES: + paths.append(os.path.join(third_party_dir, library_dir)) + + return paths diff --git a/catapult/dashboard/dashboard/add_point_queue_test.py b/catapult/dashboard/dashboard/add_point_queue_test.py index 185bcea9..e85fa906 100644 --- a/catapult/dashboard/dashboard/add_point_queue_test.py +++ b/catapult/dashboard/dashboard/add_point_queue_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for add_point module.""" - import unittest from dashboard import add_point_queue @@ -20,7 +18,6 @@ class GetOrCreateAncestorsTest(testing_common.TestCase): self.SetCurrentUser('foo@bar.com', is_admin=True) def testGetOrCreateAncestors_GetsExistingEntities(self): - """Tests that _GetOrCreateAncestors doesn't add if entity already exists.""" master_key = graph_data.Master(id='ChromiumPerf', parent=None).put() bot_key = graph_data.Bot(id='win7', parent=master_key).put() suite_key = graph_data.Test(id='dromaeo', parent=bot_key).put() @@ -36,7 +33,6 @@ class GetOrCreateAncestorsTest(testing_common.TestCase): self.assertEqual(3, len(graph_data.Test.query().fetch())) def testGetOrCreateAncestors_CreatesAllExpectedEntities(self): - """Tests that _GetOrCreateAncestors adds if entity already exists.""" parent = add_point_queue._GetOrCreateAncestors( 'ChromiumPerf', 'win7', 'dromaeo/dom/modify') self.assertEqual('modify', parent.key.id()) diff --git a/catapult/dashboard/dashboard/add_point_test.py b/catapult/dashboard/dashboard/add_point_test.py index e59c600d..128054ce 100644 --- a/catapult/dashboard/dashboard/add_point_test.py +++ b/catapult/dashboard/dashboard/add_point_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for add_point module.""" - import json import math import unittest diff --git a/catapult/dashboard/dashboard/alerts_test.py b/catapult/dashboard/dashboard/alerts_test.py index 525a8bdc..4d21ca9d 100644 --- a/catapult/dashboard/dashboard/alerts_test.py +++ b/catapult/dashboard/dashboard/alerts_test.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for alerts module.""" import unittest import webapp2 diff --git a/catapult/dashboard/dashboard/associate_alerts_test.py b/catapult/dashboard/dashboard/associate_alerts_test.py index 670ed956..f1e621ab 100644 --- a/catapult/dashboard/dashboard/associate_alerts_test.py +++ b/catapult/dashboard/dashboard/associate_alerts_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for associate_alerts module.""" - import json import unittest diff --git a/catapult/dashboard/dashboard/auto_bisect.py b/catapult/dashboard/dashboard/auto_bisect.py index b95b0092..3b32a245 100644 --- a/catapult/dashboard/dashboard/auto_bisect.py +++ b/catapult/dashboard/dashboard/auto_bisect.py @@ -28,8 +28,6 @@ _UNBISECTABLE_SUITES = [ 'v8', ] -_FORCED_RECIPE_BOTS = ['linux_perf_bisect'] - class AutoBisectHandler(request_handler.RequestHandler): """URL endpoint for a cron job to automatically run bisects.""" @@ -80,11 +78,6 @@ def _RestartBisect(bisect_job): Args: bisect_job: TryJob entity with initialized bot name and config. """ - if bisect_job.use_buildbucket and (bisect_job.bot_name not in - _FORCED_RECIPE_BOTS): - # Buildbucket bisects other than thos in _FORCED_RECIPE_BOTS are not - # automatically retried. - return try: new_bisect_job = _MakeBisectTryJob( bisect_job.bug_id, bisect_job.run_count) @@ -154,6 +147,8 @@ def _MakeBisectTryJob(bug_id, run_count=0): if not bisect_bot or '_' not in bisect_bot: raise NotBisectableError('Could not select a bisect bot.') + use_recipe = bool(start_try_job.GetBisectDirectorForTester(bisect_bot)) + new_bisect_config = start_try_job.GetBisectConfig( bisect_bot=bisect_bot, master_name=test.master_name, @@ -165,8 +160,8 @@ def _MakeBisectTryJob(bug_id, run_count=0): max_time_minutes=20, truncate_percent=25, bug_id=bug_id, - original_bot_name=test.bot_name, - use_archive='true') + use_archive='true', + use_buildbucket=use_recipe) if 'error' in new_bisect_config: raise NotBisectableError('Could not make a valid config.') @@ -174,9 +169,6 @@ def _MakeBisectTryJob(bug_id, run_count=0): config_python_string = 'config = %s\n' % json.dumps( new_bisect_config, sort_keys=True, indent=2, separators=(',', ': ')) - # Forcing recipe by default for linux bisects. - use_buildbucket = bisect_bot in _FORCED_RECIPE_BOTS - bisect_job = try_job.TryJob( bot=bisect_bot, config=config_python_string, @@ -184,7 +176,7 @@ def _MakeBisectTryJob(bug_id, run_count=0): master_name=test.master_name, internal_only=test.internal_only, job_type='bisect', - use_buildbucket=use_buildbucket) + use_buildbucket=use_recipe) return bisect_job diff --git a/catapult/dashboard/dashboard/auto_bisect_test.py b/catapult/dashboard/dashboard/auto_bisect_test.py index 8fcd9a8e..1b287dc1 100644 --- a/catapult/dashboard/dashboard/auto_bisect_test.py +++ b/catapult/dashboard/dashboard/auto_bisect_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit test for auto_bisect module.""" - import datetime import sys import unittest @@ -13,6 +11,8 @@ import webapp2 import webtest from dashboard import auto_bisect +from dashboard import start_try_job +from dashboard import stored_object from dashboard import testing_common from dashboard import utils from dashboard.models import anomaly @@ -23,6 +23,12 @@ class AutoBisectTest(testing_common.TestCase): def setUp(self): super(AutoBisectTest, self).setUp() + stored_object.Set( + start_try_job._TESTER_DIRECTOR_MAP_KEY, + { + 'linux_perf_tester': 'linux_perf_bisector', + 'win64_nv_tester': 'linux_perf_bisector', + }) app = webapp2.WSGIApplication( [('/auto_bisect', auto_bisect.AutoBisectHandler)]) self.testapp = webtest.TestApp(app) @@ -85,6 +91,14 @@ class AutoBisectTest(testing_common.TestCase): class StartNewBisectForBugTest(testing_common.TestCase): + def setUp(self): + super(StartNewBisectForBugTest, self).setUp() + stored_object.Set( + start_try_job._TESTER_DIRECTOR_MAP_KEY, + { + 'linux_perf_tester': 'linux_perf_bisector', + 'win64_nv_tester': 'linux_perf_bisector', + }) @mock.patch.object(auto_bisect.start_try_job, 'PerformBisect') def testStartNewBisectForBug_StartsBisect(self, mock_perform_bisect): diff --git a/catapult/dashboard/dashboard/auto_triage_test.py b/catapult/dashboard/dashboard/auto_triage_test.py index deaf30db..bf7bfa52 100644 --- a/catapult/dashboard/dashboard/auto_triage_test.py +++ b/catapult/dashboard/dashboard/auto_triage_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for auto_triage module.""" - import unittest import mock diff --git a/catapult/dashboard/dashboard/bench_find_anomalies_test.py b/catapult/dashboard/dashboard/bench_find_anomalies_test.py index bad4b31e..4bd6b238 100644 --- a/catapult/dashboard/dashboard/bench_find_anomalies_test.py +++ b/catapult/dashboard/dashboard/bench_find_anomalies_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for bench_find_anomalies_test module.""" - import unittest from mapreduce import test_support diff --git a/catapult/dashboard/dashboard/bisect_stats_test.py b/catapult/dashboard/dashboard/bisect_stats_test.py index b4f10921..85808791 100644 --- a/catapult/dashboard/dashboard/bisect_stats_test.py +++ b/catapult/dashboard/dashboard/bisect_stats_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for bisect_stats module.""" - import unittest import mock diff --git a/catapult/dashboard/dashboard/bot_whitelist_test.py b/catapult/dashboard/dashboard/bot_whitelist_test.py index e296a003..9d305802 100644 --- a/catapult/dashboard/dashboard/bot_whitelist_test.py +++ b/catapult/dashboard/dashboard/bot_whitelist_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for bot_whitelist module.""" - import unittest import webapp2 diff --git a/catapult/dashboard/dashboard/buildbucket_job.py b/catapult/dashboard/dashboard/buildbucket_job.py index 6c2e5a02..8142fdc4 100644 --- a/catapult/dashboard/dashboard/buildbucket_job.py +++ b/catapult/dashboard/dashboard/buildbucket_job.py @@ -6,22 +6,20 @@ import re -_BISECT_CONTROLLER_BUILDER_NAME = 'linux_perf_bisector' - class BisectJob(object): """A buildbot bisect job started and monitored through buildbucket.""" - def __init__(self, good_revision, bad_revision, test_command, + def __init__(self, bisect_director, good_revision, bad_revision, test_command, metric, repeats, truncate, timeout_minutes, bug_id, gs_bucket, - original_bot_name, builder_host=None, builder_port=None, + recipe_tester_name, builder_host=None, builder_port=None, test_type='perf'): if not all([good_revision, bad_revision, test_command, metric, - repeats, timeout_minutes, original_bot_name]): + repeats, timeout_minutes, recipe_tester_name]): raise ValueError('At least one of the values required for BisectJob ' 'construction was not given or was given with a None ' 'value.') - self.builder_name = BisectJob.GetBuilderForPlatform(original_bot_name) + self.bisect_director = bisect_director self.good_revision = good_revision self.bad_revision = bad_revision self.command = BisectJob.EnsureCommandPath(test_command) @@ -34,7 +32,7 @@ class BisectJob(object): self.builder_host = builder_host self.builder_port = builder_port self.test_type = test_type - self.original_bot_name = original_bot_name + self.recipe_tester_name = recipe_tester_name @staticmethod def EnsureCommandPath(command): @@ -46,13 +44,6 @@ class BisectJob(object): return old_perf_path_regex_win.sub(r'src\\tools\\perf', command) return command - @staticmethod - def GetBuilderForPlatform(platform): - """Maps builder names to the platforms they can bisect.""" - if 'linux' in platform.lower() or 'win' in platform.lower(): - return _BISECT_CONTROLLER_BUILDER_NAME - raise NotImplementedError('Unsupported platform: ' + platform) - def GetBuildParameters(self): """Prepares a nested dict containing the bisect config.""" # TODO(robertocn): Some of these should be optional. @@ -69,11 +60,11 @@ class BisectJob(object): 'gs_bucket': self.gs_bucket, 'builder_host': self.builder_host, 'builder_port': self.builder_port, - 'original_bot_name': self.original_bot_name, + 'recipe_tester_name': self.recipe_tester_name, } properties = {'bisect_config': bisect_config} parameters = { - 'builder_name': self.builder_name, + 'builder_name': self.bisect_director, 'properties': properties, } return parameters diff --git a/catapult/dashboard/dashboard/buildbucket_job_status_test.py b/catapult/dashboard/dashboard/buildbucket_job_status_test.py index a01a9102..faba4181 100644 --- a/catapult/dashboard/dashboard/buildbucket_job_status_test.py +++ b/catapult/dashboard/dashboard/buildbucket_job_status_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Tests for the buildbucket_job_status request handler.""" - import json import re import unittest diff --git a/catapult/dashboard/dashboard/buildbucket_job_test.py b/catapult/dashboard/dashboard/buildbucket_job_test.py index 67f68ed7..961371af 100644 --- a/catapult/dashboard/dashboard/buildbucket_job_test.py +++ b/catapult/dashboard/dashboard/buildbucket_job_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Tests for dashboard.buildbucket_job.""" - import unittest from dashboard import buildbucket_job @@ -15,7 +13,8 @@ class BuildbucketJobTest(testing_common.TestCase): def setUp(self): super(BuildbucketJobTest, self).setUp() self._args_base = { - 'original_bot_name': 'chrome-rel-linux', + 'bisect_director': 'linux_perf_bisector', + 'recipe_tester_name': 'linux_perf_bisect', 'good_revision': '1', 'bad_revision': '2', 'test_command': 'tools/perf/dummy_command', @@ -54,12 +53,5 @@ class BuildbucketJobTest(testing_common.TestCase): job = buildbucket_job.BisectJob(**self._args_base) _ = job.GetBuildParameters() - def testUnsupportedPlatform(self): - self._args_base['original_bot_name'] = 'MSDOS' - with self.assertRaises(NotImplementedError): - job = buildbucket_job.BisectJob(**self._args_base) - _ = job.GetBuildParameters() - - if __name__ == '__main__': unittest.main() diff --git a/catapult/dashboard/dashboard/buildbucket_service_test.py b/catapult/dashboard/dashboard/buildbucket_service_test.py index 312e761c..867938bc 100644 --- a/catapult/dashboard/dashboard/buildbucket_service_test.py +++ b/catapult/dashboard/dashboard/buildbucket_service_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Tests for dashboard.buildbucket_service.""" - import json import unittest diff --git a/catapult/dashboard/dashboard/change_internal_only_test.py b/catapult/dashboard/dashboard/change_internal_only_test.py index 1bd49d9d..7bceb813 100644 --- a/catapult/dashboard/dashboard/change_internal_only_test.py +++ b/catapult/dashboard/dashboard/change_internal_only_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for alerts module.""" - import unittest import webapp2 diff --git a/catapult/dashboard/dashboard/datastore_hooks_test.py b/catapult/dashboard/dashboard/datastore_hooks_test.py index 72eb093d..503938bd 100644 --- a/catapult/dashboard/dashboard/datastore_hooks_test.py +++ b/catapult/dashboard/dashboard/datastore_hooks_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for datastore_hooks module.""" - import unittest import mock diff --git a/catapult/dashboard/dashboard/debug_alert_test.py b/catapult/dashboard/dashboard/debug_alert_test.py index 0c5f69d1..62ee3462 100644 --- a/catapult/dashboard/dashboard/debug_alert_test.py +++ b/catapult/dashboard/dashboard/debug_alert_test.py @@ -2,13 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for debug_alert handler. - -Note: This unit test isn't responsible for verifying any aspect of anomaly -detection or use of different anomaly configs; it only checks that the handler -is returning some HTML. -""" - import unittest import mock diff --git a/catapult/dashboard/dashboard/dump_graph_json_test.py b/catapult/dashboard/dashboard/dump_graph_json_test.py index 69710b3f..10205b62 100644 --- a/catapult/dashboard/dashboard/dump_graph_json_test.py +++ b/catapult/dashboard/dashboard/dump_graph_json_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for dump_graph_json module.""" - import json import unittest diff --git a/catapult/dashboard/dashboard/edit_anomalies_test.py b/catapult/dashboard/dashboard/edit_anomalies_test.py index def05eb2..9ac32356 100644 --- a/catapult/dashboard/dashboard/edit_anomalies_test.py +++ b/catapult/dashboard/dashboard/edit_anomalies_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for edit_anomalies_test module.""" - import json import unittest diff --git a/catapult/dashboard/dashboard/edit_anomaly_configs_test.py b/catapult/dashboard/dashboard/edit_anomaly_configs_test.py index 3b13f6ef..ef265bbe 100644 --- a/catapult/dashboard/dashboard/edit_anomaly_configs_test.py +++ b/catapult/dashboard/dashboard/edit_anomaly_configs_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for edit_anomaly_configs module.""" - import unittest import webapp2 diff --git a/catapult/dashboard/dashboard/edit_bug_labels_test.py b/catapult/dashboard/dashboard/edit_bug_labels_test.py index 3461ecd8..ce99fd9d 100644 --- a/catapult/dashboard/dashboard/edit_bug_labels_test.py +++ b/catapult/dashboard/dashboard/edit_bug_labels_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for edit_bug_labels module.""" - import unittest import webapp2 @@ -31,8 +29,7 @@ class EditBugLabelsTest(testing_common.TestCase): super(EditBugLabelsTest, self).tearDown() self.UnsetCurrentUser() - def testBugLabelPattern(self): - """Tests adding and removing a BugLabelPattern.""" + def testBugLabelPattern_AddAndRemove(self): self.testapp.post('/edit_bug_labels', { 'action': 'add_buglabel_pattern', 'buglabel_to_add': 'Performance-1', diff --git a/catapult/dashboard/dashboard/edit_config_handler_test.py b/catapult/dashboard/dashboard/edit_config_handler_test.py index d30ef383..bcb4e916 100644 --- a/catapult/dashboard/dashboard/edit_config_handler_test.py +++ b/catapult/dashboard/dashboard/edit_config_handler_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Tests for edit_config_handler module.""" - import unittest import webapp2 diff --git a/catapult/dashboard/dashboard/edit_sheriffs_test.py b/catapult/dashboard/dashboard/edit_sheriffs_test.py index dbca40d8..edd7e93c 100644 --- a/catapult/dashboard/dashboard/edit_sheriffs_test.py +++ b/catapult/dashboard/dashboard/edit_sheriffs_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for edit_sheriffs module.""" - import unittest import webapp2 @@ -54,7 +52,6 @@ class EditSheriffsTest(testing_common.TestCase): stoppage_alert_delay=stoppage_alert_delay).put() def testPost_AddNewSheriff(self): - """Tests creating a new Sheriff entity.""" self.testapp.post('/edit_sheriffs', { 'add-edit': 'add', 'add-name': 'New Sheriff', @@ -72,7 +69,6 @@ class EditSheriffsTest(testing_common.TestCase): self.assertTrue(sheriffs[0].summarize) def testPost_EditExistingSheriff(self): - """Tests editing the email, url, and summarize properties of a Sheriff.""" self._AddSampleTestData() self._AddSheriff('Old Sheriff') self.testapp.post('/edit_sheriffs', { @@ -104,7 +100,6 @@ class EditSheriffsTest(testing_common.TestCase): self.assertIsNone(ddd.sheriff) def testEditSheriff_EditPatternsList(self): - """Tests editing the patterns list of a Sheriff.""" self._AddSampleTestData() self._AddSheriff('Sheriff', patterns=['*/*/*/*']) self.testapp.post('/edit_sheriffs', { @@ -129,7 +124,6 @@ class EditSheriffsTest(testing_common.TestCase): self.assertEqual(sheriff_entity.key, ddd.sheriff) def testPost_EditSheriffWithNoXSRFToken_NoChangeIsMade(self): - """Tests that editing cannot be done without an xsrf token.""" self._AddSheriff('Sheriff', patterns=['*/*/*']) self.testapp.post('/edit_sheriffs', { 'add-edit': 'edit', @@ -140,8 +134,7 @@ class EditSheriffsTest(testing_common.TestCase): sheriff_entity = sheriff.Sheriff.query().fetch()[0] self.assertEqual(['*/*/*'], sheriff_entity.patterns) - def testPost_WithInvalidActionParameter_ShowsErrorMessage(self): - """If an invalid value is given for "add-edit", an error page is shown.""" + def testPost_WithInvalidAddEditParameter_ShowsErrorMessage(self): response = self.testapp.post('/edit_sheriffs', { 'add-edit': '', 'xsrf_token': xsrf.GenerateToken(users.get_current_user()), @@ -185,7 +178,6 @@ class EditSheriffsTest(testing_common.TestCase): self.assertIn(expected_message, response.body) def testGet_SheriffDataIsEmbeddedOnPage(self): - """Sheriff data should be embedded on the page in a JS variable.""" self._AddSheriff('Foo Sheriff', email='foo@x.org', patterns=['*/*/*/*']) self._AddSheriff('Bar Sheriff', summarize=True, stoppage_alert_delay=5, patterns=['x/y/z', 'a/b/c']) diff --git a/catapult/dashboard/dashboard/edit_site_config_test.py b/catapult/dashboard/dashboard/edit_site_config_test.py index ee94de37..fc13a774 100644 --- a/catapult/dashboard/dashboard/edit_site_config_test.py +++ b/catapult/dashboard/dashboard/edit_site_config_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for edit_site_config module.""" - import unittest import webapp2 diff --git a/catapult/dashboard/dashboard/edit_test_owners_test.py b/catapult/dashboard/dashboard/edit_test_owners_test.py index 0ee556b5..2906493f 100644 --- a/catapult/dashboard/dashboard/edit_test_owners_test.py +++ b/catapult/dashboard/dashboard/edit_test_owners_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Tests for dashboard.edit_test_owners.""" - import unittest import webapp2 diff --git a/catapult/dashboard/dashboard/elements/alert-remove-box-test.html b/catapult/dashboard/dashboard/elements/alert-remove-box-test.html index 3c6ce6de..d39dcc67 100644 --- a/catapult/dashboard/dashboard/elements/alert-remove-box-test.html +++ b/catapult/dashboard/dashboard/elements/alert-remove-box-test.html @@ -7,7 +7,7 @@ <script src="//cdnjs.cloudflare.com/ajax/libs/mocha/2.2.1/mocha.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/chai/2.1.1/chai.min.js"></script> <link rel="import" href="/components/polymer/polymer.html"> - <link rel="import" href="/components/alert-remove-box.html"> + <link rel="import" href="alert-remove-box.html"> </head> <body> <div id="mocha"></div> diff --git a/catapult/dashboard/dashboard/elements/alert-remove-box.html b/catapult/dashboard/dashboard/elements/alert-remove-box.html index e85432fa..9c7917f3 100644 --- a/catapult/dashboard/dashboard/elements/alert-remove-box.html +++ b/catapult/dashboard/dashboard/elements/alert-remove-box.html @@ -3,44 +3,33 @@ The alert-remove-box element provides the functionality of dis-associating an alert from an issue on the issue tracker. --> <link rel="import" href="/dashboard/elements/xhr-element.html"> -<link rel="import" href="/third_party/polymer/components/core-icon-button/core-icon-button.html"> <link rel="import" href="/third_party/polymer/components/paper-spinner/paper-spinner.html"> +<link rel="import" href="xhr-element.html"> + <polymer-element name="alert-remove-box" attributes="xsrfToken key"> <template> <style> - - /* By default, the size of a core-icon-button is quite large; - * to make it smaller we need to make the core-icon inside of - * it smaller. */ - #icon::shadow core-icon[role=img] { - height: 14px; - width: 14px; - padding: 1px; - margin: 1px; - } - - #icon { + .close-icon { padding: 1px; margin: 1px; + cursor: pointer; } - #spinner { + .spinner { height: 14px; width: 14px; } - #spinner::shadow .circle { - border-color: #4285f4; - } - - #spinner:not([active]) { + .spinner:not([active]) { display: none; } </style> <xhr-element id="xhr"></xhr-element> - <core-icon-button id="icon" icon="close" hidden?="{{loading}}" on-click="{{onRemoveBug}}"></core-icon-button> - <paper-spinner id="spinner" active?="{{loading}}"></paper-spinner> + <div class="close-icon" hidden?="{{loading}}" on-click="{{onRemoveBug}}"> + ❌ <!-- cross mark U+274C --> + </div> + <paper-spinner class="spinner" active?="{{loading}}"></paper-spinner> </template> <script> 'use strict'; diff --git a/catapult/dashboard/dashboard/elements/alerts-table.html b/catapult/dashboard/dashboard/elements/alerts-table.html index 5352d0e4..11551468 100644 --- a/catapult/dashboard/dashboard/elements/alerts-table.html +++ b/catapult/dashboard/dashboard/elements/alerts-table.html @@ -1,9 +1,9 @@ <link rel="import" href="/third_party/polymer/components/paper-button/paper-button.html"> -<link rel="import" href="/dashboard/elements/bisect-status.html"> -<link rel="import" href="/dashboard/elements/bug-info-span.html"> -<link rel="import" href="/dashboard/elements/revision-range.html"> -<link rel="import" href="/dashboard/elements/triage-dialog.html"> +<link rel="import" href="bisect-status.html"> +<link rel="import" href="bug-info-span.html"> +<link rel="import" href="revision-range.html"> +<link rel="import" href="triage-dialog.html"> <link rel="import" href="/static/uri.html"> <polymer-element name="alerts-table" @@ -190,12 +190,11 @@ background-color: transparent !important; } - /* The graph-icon elements are for links to view associated graphs. */ - .graph-icon { + /* The graph-link elements are for links to view associated graphs. */ + .graph-link, .graph-link:visited { vertical-align: middle; - opacity: 0.6; - height: 14px; - width: 14px; + font-size: 1.2em; + color: #222; } /* The kd-button class is used for the numbers next to rows @@ -309,8 +308,8 @@ </td> <td> - <a href="{{dashboard_link}}" target="_blank"> - <core-icon class="graph-icon" icon="launch" alt="Open Graph"></core-icon> + <a href="{{dashboard_link}}" class="graph-link" target="_blank"> + 📈 <!-- chart with upwards trend character U+1F4C8 --> </a> </td> @@ -684,9 +683,9 @@ /** * Callback for the click event for a column header. - * @param {Event} event - * @param {number} detail - * @param {Element} sender + * @param {Event} event Clicked event. + * @param {Object} detail Detail Object. + * @param {Element} sender Element that invoked the event. */ columnHeaderClicked: function(event, detail, sender) { this.sortBy = sender.id; @@ -804,7 +803,7 @@ * revision range for alerts with ranges [110, 120] and [120, 130] is * [120, 120]. * - * @param {Array.<Object>} alerts + * @param {Array.<Object>} alerts List of alerts. * @return {?Object} An object containing start and end revision, * or null if the checked alerts don't overlap. */ @@ -838,9 +837,9 @@ * falls within the given range. * Precondition: start <= end, and for each alert in the given list, * start_revision <= end_revision. - * @param {Array.<Object>} alerts - * @param {number} start - * @param {number} end + * @param {Array.<Object>} alerts List of alerts. + * @param {number} start Start revision. + * @param {number} end End revision. * @param {Array.<Object>} Alerts that have an overlapping revision range. */ getOverlappingAlerts: function(alerts, start, end) { @@ -988,7 +987,7 @@ /** * Handles the 'triaged' event sent by the triage dialog; updates the UI * for alerts that have been triaged. - * @param {Event} e + * @param {Event} e The event for button click. */ onTriaged: function(e) { var triagedKeys = e.detail.alerts.map(function(alert) { diff --git a/catapult/dashboard/dashboard/elements/bisect-button.html b/catapult/dashboard/dashboard/elements/bisect-button.html index 262a274e..ac04f47b 100644 --- a/catapult/dashboard/dashboard/elements/bisect-button.html +++ b/catapult/dashboard/dashboard/elements/bisect-button.html @@ -1,5 +1,5 @@ <link rel="import" href="/third_party/polymer/components/paper-button/paper-button.html"> -<link rel="import" href="/dashboard/elements/bisect-form.html"> +<link rel="import" href="bisect-form.html"> <link rel="import" href="/static/bisect_utils.html"> @@ -79,7 +79,7 @@ */ onBisect: function() { this.$.bisect.show(); - }, + } }); })(); </script> diff --git a/catapult/dashboard/dashboard/elements/bisect-form.html b/catapult/dashboard/dashboard/elements/bisect-form.html index 0f2b5073..f981c9f7 100644 --- a/catapult/dashboard/dashboard/elements/bisect-form.html +++ b/catapult/dashboard/dashboard/elements/bisect-form.html @@ -5,8 +5,9 @@ the bisect process after the user clicks on the bisect button. <link rel="import" href="/third_party/polymer/components/paper-button/paper-button.html"> <link rel="import" href="/third_party/polymer/components/paper-dialog/paper-action-dialog.html"> <link rel="import" href="/third_party/polymer/components/paper-spinner/paper-spinner.html"> -<link rel="import" href="/dashboard/elements/base-form.html"> -<link rel="import" href="/dashboard/elements/xhr-element.html"> + +<link rel="import" href="base-form.html"> +<link rel="import" href="xhr-element.html"> <polymer-element name="bisect-form" extends="base-form" attributes="xsrfToken testPath @@ -48,10 +49,6 @@ the bisect process after the user clicks on the bisect button. color: #fff; } - paper-spinner::shadow .circle { - border-color: #4285f4; - } - .error { color: #dd4b39; } @@ -131,10 +128,6 @@ the bisect process after the user clicks on the bisect button. </p> </td> </tr> - <tr> - <td>Use recipe (beta):</td> - <td><input type="checkbox" checked="{{useRecipe}}"></td> - </tr> </table> </form> @@ -228,10 +221,9 @@ the bisect process after the user clicks on the bisect button. 'max_time_minutes': this.MAX_TIME_MINUTES, 'truncate_percent': this.TRUNCATE_PERCENT, 'use_archive': this.useArchive ? 'true' : '', - 'use_recipe': this.useRecipe ? 'true' : '', 'master': this.master, 'internal_only': this.internalOnly, - 'bisect_mode': this.BISECT_MODE, + 'bisect_mode': this.BISECT_MODE }; if (this.bugId) { params['bug_id'] = this.bugId; diff --git a/catapult/dashboard/dashboard/elements/bisect-status-test.html b/catapult/dashboard/dashboard/elements/bisect-status-test.html index ed1bdb79..90ea6392 100644 --- a/catapult/dashboard/dashboard/elements/bisect-status-test.html +++ b/catapult/dashboard/dashboard/elements/bisect-status-test.html @@ -3,7 +3,7 @@ <head> <title>bisect-status demo</title> <link rel="import" href="//www.polymer-project.org/0.5/components/polymer/polymer.html"> - <link rel="import" href="/dashboard/elements/bisect-status.html"> + <link rel="import" href="bisect-status.html"> </head> <body> <p>Status: started <bisect-status status="started"></bisect-status></p> diff --git a/catapult/dashboard/dashboard/elements/bug-info-span-test.html b/catapult/dashboard/dashboard/elements/bug-info-span-test.html index ba02fe6a..ed3522d2 100644 --- a/catapult/dashboard/dashboard/elements/bug-info-span-test.html +++ b/catapult/dashboard/dashboard/elements/bug-info-span-test.html @@ -3,7 +3,7 @@ <head> <title>bug-info-span demo</title> <link rel="import" href="//www.polymer-project.org/0.5/components/polymer/polymer.html"> - <link rel="import" href="/dashboard/elements/bug-info-span.html"> + <link rel="import" href="bug-info-span.html"> </head> <body> <p>Untriaged: <bug-info-span></bug-info-span> diff --git a/catapult/dashboard/dashboard/elements/bug-info-span.html b/catapult/dashboard/dashboard/elements/bug-info-span.html index 4461c45c..31cfe6e5 100644 --- a/catapult/dashboard/dashboard/elements/bug-info-span.html +++ b/catapult/dashboard/dashboard/elements/bug-info-span.html @@ -2,7 +2,7 @@ The bug-info-span is a in-line element showing a bug ID with link, etc. TODO(qyearsley): Expand this element and use it in chart-tooltip. --> -<link rel="import" href="/dashboard/elements/alert-remove-box.html"> +<link rel="import" href="alert-remove-box.html"> <polymer-element name="bug-info-span"> <template> @@ -23,7 +23,7 @@ TODO(qyearsley): Expand this element and use it in chart-tooltip. bugId: null, xsrfToken: null, recovered: false, - key: null, + key: null } }); </script> diff --git a/catapult/dashboard/dashboard/elements/bug-info.html b/catapult/dashboard/dashboard/elements/bug-info.html index 2affb23c..7436d8a8 100644 --- a/catapult/dashboard/dashboard/elements/bug-info.html +++ b/catapult/dashboard/dashboard/elements/bug-info.html @@ -1,4 +1,4 @@ -<link rel="import" href="/dashboard/elements/bisect-button.html"> +<link rel="import" href="bisect-button.html"> <polymer-element name="bug-info"> <template> diff --git a/catapult/dashboard/dashboard/elements/chart-container.html b/catapult/dashboard/dashboard/elements/chart-container.html index aeccc4b9..70f7ccb5 100644 --- a/catapult/dashboard/dashboard/elements/chart-container.html +++ b/catapult/dashboard/dashboard/elements/chart-container.html @@ -8,9 +8,10 @@ triaging functionality in the chart. <link rel="import" href="/third_party/polymer/components/core-icon/core-icon.html"> <link rel="import" href="/third_party/polymer/components/paper-button/paper-button.html"> -<link rel="import" href="/dashboard/elements/chart-legend.html"> -<link rel="import" href="/dashboard/elements/chart-slider.html"> -<link rel="import" href="/dashboard/elements/chart-tooltip.html"> +<link rel="import" href="chart-legend.html"> +<link rel="import" href="chart-slider.html"> +<link rel="import" href="chart-title.html"> +<link rel="import" href="chart-tooltip.html"> <link rel="import" href="/static/graph.html"> <link rel="import" href="/static/testselection.html"> <link rel="import" href="/static/uri.html"> @@ -144,7 +145,7 @@ triaging functionality in the chart. <div id="container" compact?="{{showCompact}}"> <div id="top-bar" horizontal layout> <div flex horizontal center-justified layout> - <h3 id="chart-title">{{chartTitle}}</h3> + <chart-title id="title" seriesGroupList={{seriesGroupList}}></chart-title> </div> <div horizontal layout center> <paper-button id="close-chart" on-click="{{closeChartClicked}}"> @@ -301,8 +302,8 @@ triaging functionality in the chart. /** * Formats numbers in a human-readable way. - * @param {number|string} val - * @return {string} + * @param {number|string} val A number or string. + * @return {string} A string. */ function formatNumber(val) { var num = Number(val); @@ -317,9 +318,9 @@ triaging functionality in the chart. * Deep compares two dictionary parameters. * This function converts dictionary parameters to sorted list of pairs * of key and values and compares their JSON string. - * @param {Object} param1 - * @param {Object} param2 - * @return {boolean} + * @param {Object} param1 An object. + * @param {Object} param2 An object. + * @return {boolean} True if equal, otherwise false. */ function graphParamEquals(param1, param2) { if (!param1 || !param2) { @@ -354,7 +355,16 @@ triaging functionality in the chart. lineWidth: 2, opacity: 1, fill: 0.2, - shadowSize: 3, + shadowSize: 3 + }, + + DEFAULT_JSON_PROPERTIES: { + annotations: { + series: {} + }, + data: {}, + error_bars: {}, + warning: null }, /** @@ -396,8 +406,7 @@ triaging functionality in the chart. // List of indices of series which are selected and will be plotted. this.indicesToGraph = []; - // Text to display above this chart and next to the y-axis. - this.chartTitle = ''; + // Text to display next to the y-axis. this.chartYAxisLabel = ''; // Y-axis delta of current zoom selection, as an absolute number @@ -447,14 +456,7 @@ triaging functionality in the chart. this.showDelta = false; // The data fetched from the graph_json handler for this chart. - this.json = { - annotations: { - series: {} - }, - data: {}, - error_bars: {}, - warning: null, - }; + this.json = deepCopy(this.DEFAULT_JSON_PROPERTIES); // Chart options to be given when initializing the Flot chart. // See: https://github.com/flot/flot/blob/master/API.md#plot-options @@ -479,7 +481,7 @@ triaging functionality in the chart. }, selection: { mode: 'y' - }, + } }; // List of XMLHttpRequests sent for graph json. @@ -499,6 +501,9 @@ triaging functionality in the chart. this.$.legend.addEventListener( 'seriesgroupclosed', this.onSeriesGroupClosed.bind(this), true); + this.$.title.addEventListener( + 'titleclicked', this.onTitleClicked.bind(this), true); + window.addEventListener('resize', this.resizeHandler); this.initializePlotEventListeners(); @@ -568,7 +573,7 @@ triaging functionality in the chart. for (var j = 0; j < selectedTraces.length; j++) { var testData = { name: selectedTraces[j], - selected: true, + selected: true }; seriesGroup.tests.push(testData); } @@ -587,7 +592,7 @@ triaging functionality in the chart. this.sendGraphJsonRequest(unSelectedTestPathDict, false); } this.updateSlider(); - this.updateChartTitle(); + this.$.title.update(); }, /** @@ -773,7 +778,7 @@ triaging functionality in the chart. * function replaces the existing test in its series group * with passed |test|, or inserts if it doesn't exist. * - * @param {Object} seriesGroup + * @param {Object} seriesGroup A series group object. * @param {Object} newTest Contains information about a series * displayed in chart-legend. */ @@ -965,7 +970,7 @@ triaging functionality in the chart. * @param {Object} detail The detail object given when firing the * event. This is set in graph.js and it contains 'start_rev' and * 'end_rev'. - * @param {Object} sender + * @param {Object} sender Object that invoked the event. */ onRevisionRange: function(event, detail, sender) { var newGraphParams = deepCopy(this.graphParams); @@ -1141,32 +1146,7 @@ triaging functionality in the chart. } this.updateChart(); - this.updateChartTitle(); - }, - - /** - * Sets the title of the chart based on the current state of the chart. - */ - updateChartTitle: function() { - var testPaths = []; - var selectedTestPaths = []; - for (var i = 0; i < this.seriesGroupList.length; i++) { - var tests = this.seriesGroupList[i].tests; - for (var j = 0; j < tests.length; j++) { - var test = tests[j]; - if (test.path) { - if (test.selected) { - selectedTestPaths.push(test.path); - } - testPaths.push(test.path); - } - } - var testPath = this.seriesGroupList[i].path; - if (testPaths.indexOf(testPath) == -1) { - testPaths.push(testPath); - } - } - this.chartTitle = graph.makeChartTitle(testPaths, selectedTestPaths); + this.$.title.update(); }, /** @@ -1278,7 +1258,7 @@ triaging functionality in the chart. * responsibilities: constructing this.revisionMap and actually * changing the X-values. These could be separated out. * - * @param {Array.<Object>} data + * @param {Array.<Object>} data Flot graph data. */ createFixedXAxis: function(data) { // Make a map of all revisions for all data series to a series index @@ -1386,7 +1366,7 @@ triaging functionality in the chart. * Formats numbers that are displayed at ticks on the Y-axis. * @param {(number|string)} val A Y-value. * @param {Object} axis Not used. - * @return {string} + * @return {string} A string. */ formatYAxis: function(val, axis) { return formatNumber(val); @@ -1503,6 +1483,23 @@ triaging functionality in the chart. }, /** + * Handler for 'titleclicked' event fired from chart-title. + * This function clears out current chart data and re-adds a + * series group from the test path created from clicked title + * parts. + */ + onTitleClicked: function(event, detail, sender) { + var titleParts = event.detail.titleParts; + var partIndex = event.detail.partIndex; + var testPath = titleParts.slice(0, partIndex + 1).join('/'); + this.json = deepCopy(this.DEFAULT_JSON_PROPERTIES); + this.seriesGroupList = []; + this.indicesToGraph = []; + this.addSeriesGroup([[testPath, []]], true); + this.fireChartStateChangedEvent(this.seriesGroupList); + }, + + /** * Handler for 'mouseleave' event, hides the tooltip. */ onMouseLeave: function(event) { @@ -1514,8 +1511,8 @@ triaging functionality in the chart. * made. * For more information about selection in flot, see: * http://www.flotcharts.org/flot/jquery.flot.selection.js - * @param {Event} event - * @param {Object} ranges + * @param {Event} event Event object. + * @param {Object} ranges Object containing the selected range. */ onPlotSelected: function(event, ranges) { this.selecting = false; @@ -1524,8 +1521,8 @@ triaging functionality in the chart. /** * Handler for 'plotselecting' event, fired repeatedly when selecting. - * @param {Event} event - * @param {Object} ranges + * @param {Event} event Event object. + * @param {Object} ranges An object containing the selected range. */ onPlotSelecting: function(event, ranges) { if (!ranges) { @@ -1555,9 +1552,9 @@ triaging functionality in the chart. /** * Handler for the 'plotclick' event, fired when the chart is clicked. - * @param {Event} event + * @param {Event} event Event object. * @param {Object} pos An object which contains the keys "x" and "y". - * @param {Object} item + * @param {Object} item An object of the item clicked, null otherwise. */ onPlotClick: function(event, pos, item) { if (this.lastSelectedDelta) { @@ -1719,9 +1716,9 @@ triaging functionality in the chart. * Handler for the 'plothover' event, fired when the mouse is hovering * over the plot area. If the user is hovering over a point, we want to * show the tooltip for that point. - * @param {Event} event - * @param {Object} pos - * @param {Object} item + * @param {Event} event Event object. + * @param {Object} pos Position object. + * @param {Object} item Item being hovered over. */ onPlotHover: function(event, pos, item) { // If the current tooltip is sticky, just leave it. @@ -1752,7 +1749,7 @@ triaging functionality in the chart. * `this.chart.getData()`. * @param {number} dataIndex The index of the data in the series. * @param {Array=} opt_alerts Array of alerts. - * @param {Array=} opt_triaged + * @param {Array=} opt_triaged A boolean. */ showTooltip: function( flotSeriesIndex, dataIndex, opt_alerts, opt_triaged) { @@ -2114,7 +2111,7 @@ triaging functionality in the chart. /** * Handler for resize event. - * @param {Event} event + * @param {Event} event Event object. */ onResize: function(event) { // Try not to resize graphs until the user has stopped resizing @@ -2339,7 +2336,7 @@ triaging functionality in the chart. state.push([seriesGroup.path, selected]); }); return state; - }, + } }); })(); </script> diff --git a/catapult/dashboard/dashboard/elements/chart-legend.html b/catapult/dashboard/dashboard/elements/chart-legend.html index 59bd3dbc..5c5a22ca 100644 --- a/catapult/dashboard/dashboard/elements/chart-legend.html +++ b/catapult/dashboard/dashboard/elements/chart-legend.html @@ -9,7 +9,7 @@ Attributes: <link rel="import" href="/third_party/polymer/components/paper-progress/paper-progress.html"> <link rel="import" href="/third_party/polymer/components/paper-shadow/paper-shadow.html"> -<link rel="import" href="/dashboard/elements/tooltip-test-description.html"> +<link rel="import" href="tooltip-test-description.html"> <polymer-element name="chart-legend" attributes="seriesGroupList indicesToGraph showCompact @@ -51,17 +51,8 @@ Attributes: visibility: hidden; } - core-icon-button { - height: 18px; - width: 18px; + .close-icon { cursor: pointer; - margin: 0 0 0 3px; - padding: 0; - } - - core-icon-button::shadow core-icon { - height: 18px; - width: 18px; } .test-name { @@ -214,8 +205,9 @@ Attributes: checked="{{seriesGroup.selection == 'all'}}" hidden?="{{seriesGroup.tests.length == 0}}"> <span flex four></span> - <core-icon-button icon="close" - on-click="{{onCloseSeriesGroupClicked}}"></core-icon-button> + <div class="close-icon" on-click="{{onCloseSeriesGroupClicked}}"> + ❌ <!-- cross mark U+274C --> + </div> </div> <core-selector class="list" selected="{{multiSelected}}" multi> @@ -480,7 +472,7 @@ Attributes: /** * Handler for the click event of the select all traces button. * Updates this.indicesToGraph to contain all traces. - * @param {Event} opt_noEvent The click event, not used. + * @param {Event=} opt_noEvent The click event, not used. */ onSelectAll: function(opt_noEvent) { this.indicesToGraph = []; @@ -498,7 +490,7 @@ Attributes: /** * Handler for the click event of the deselect all traces button. - * @param {Event} opt_noEvent The click event, not used. + * @param {Event=} opt_noEvent The click event, not used. */ onDeselectAll: function(opt_noEvent) { this.indicesToGraph = []; @@ -517,7 +509,7 @@ Attributes: * Handler for the click event of the select core traces button. * Selects only the core traces (i.e. important and ref traces). * Note: The property 'coreTraces' is set in graph.js. - * @param {Event} opt_event The click event, not used. + * @param {Event=} opt_event The click event, not used. */ onSelectCore: function(opt_noEvent) { this.indicesToGraph = []; @@ -571,7 +563,7 @@ Attributes: toggleLegend: function() { this.$['collapsible-legend'].toggle(); this.collapseLegend = !this.collapseLegend; - }, + } }); </script> </polymer-element> diff --git a/catapult/dashboard/dashboard/elements/chart-title.html b/catapult/dashboard/dashboard/elements/chart-title.html new file mode 100644 index 00000000..4586bfb5 --- /dev/null +++ b/catapult/dashboard/dashboard/elements/chart-title.html @@ -0,0 +1,156 @@ +<polymer-element name="chart-title" attributes="seriesGroupList"> + <template> + <style> + .title { + color: #424242; + text-decoration: none; + } + + .title:hover { + color: #4184f3; + text-decoration: underline; + } + + .title[disabled] { + color: #8d8d8d; + text-decoration: none; + cursor: default; + } + </style> + + <h3> + <template repeat="{{part, partIndex in titleParts}}"> + <a class="title disabled" href="javascript:void(0);" + on-click="{{onClicked}}" disabled?="{{partIndex == currentIndex}}" + class="title"> + {{part}} + </a> + <span hidden?="{{partIndex == titleParts.length - 1}}">/</span> + </template> + </h3> + + </template> + <script> + 'use strict'; + Polymer('chart-title', { + + /** + * Sets the title of the chart based on the current state of the chart. + */ + update: function() { + var testPaths = this.getTestPaths(); + var title = this.makeTitleFromTestPaths(testPaths); + var selectedSeries = this.getFirstSelectedSeries(); + + var parts = title.split('/'); + // First part of the title groups together of master, bot and test + // suite. + var firstPart = parts.slice(0, 3).join('/'); + this.titleParts = [firstPart].concat(parts.slice(3)); + + // Determine the current selected index which will be disabled for + // selection. + if (selectedSeries) { + this.titleParts.push(selectedSeries); + this.currentIndex = this.titleParts.length - 2; + } else { + this.currentIndex = this.titleParts.length - 1; + } + }, + + onClicked: function(event) { + var model = event.target.templateInstance.model; + if (model.partIndex == this.currentIndex) { + return; + } + this.fire('titleclicked', { + titleParts: this.titleParts, + partIndex: model.partIndex + }); + + this.currentIndex = model.partIndex; + }, + + /** + * Makes a string to use as a chart title, based on a set of test paths. + * @param {Array.<string>} testPaths An list of test paths. + * @return {string} The longest test path that is the prefix + */ + makeTitleFromTestPaths: function(testPaths) { + if (testPaths.length == 1) { + return testPaths[0]; + } + + var prefix = ''; + if (testPaths.length > 1) { + prefix = this.longestCommonTestPathPrefix(testPaths); + } + if (testPaths.indexOf(prefix) >= 0) { + return prefix; + } + return prefix ? prefix + '/...' : '...'; + }, + + getTestPaths: function() { + var testPaths = []; + for (var i = 0; i < this.seriesGroupList.length; i++) { + testPaths.push(this.seriesGroupList[i].path); + } + return testPaths; + }, + + getFirstSelectedSeries: function() { + for (var i = 0; i < this.seriesGroupList.length; i++) { + var testPath = this.seriesGroupList[i].path; + var parts = testPath.split('/'); + var lastPart = parts[parts.length - 1]; + var tests = this.seriesGroupList[i].tests; + for (var j = 0; j < tests.length; j++) { + var test = tests[j]; + if (test.name == lastPart) { + return null; + } else if (test.selected) { + return test.name; + } + } + } + return null; + }, + + /** + * @param {Array.<string>} testPaths An list of test paths. + * @return {string} The longest test path that is the prefix + */ + longestCommonTestPathPrefix: function(testPaths) { + var partArrays = testPaths.map(function(path) { + return path.split('/'); + }); + return this.longestCommonSubArray(partArrays).join('/'); + }, + + /** + * @param {Array.<Array>} arrays An Array of Arrays. + * @return {Array} The longest Array such that all Arrays in the input + * contain this Array as a prefix. + */ + longestCommonSubArray: function(arrays) { + if (arrays.length == 0) { + return []; + } + var shortestLength = Math.min.apply(window, arrays.map(function(a) { + return a.length; + })); + for (var prefixLength = 0; prefixLength <= shortestLength; + prefixLength++) { + var value = arrays[0][prefixLength]; + for (var i = 1; i < arrays.length; i++) { + if (arrays[i][prefixLength] != value) { + return arrays[0].slice(0, prefixLength); + } + } + } + return arrays[0].slice(0, shortestLength); + } + }); + </script> +</polymer-element> diff --git a/catapult/dashboard/dashboard/elements/chart-tooltip.html b/catapult/dashboard/dashboard/elements/chart-tooltip.html index 2c3c081d..3ee8815c 100644 --- a/catapult/dashboard/dashboard/elements/chart-tooltip.html +++ b/catapult/dashboard/dashboard/elements/chart-tooltip.html @@ -3,13 +3,13 @@ The chart-tooltip element is the box that is shown when you hover over or click on a point on a graph. It shows more detailed information about the point that was just clicked. --> -<link rel="import" href="/dashboard/elements/alert-remove-box.html"> -<link rel="import" href="/dashboard/elements/bisect-button.html"> -<link rel="import" href="/dashboard/elements/trace-button.html"> -<link rel="import" href="/dashboard/elements/triage-dialog.html"> - <link rel="import" href="/third_party/polymer/components/paper-dialog/paper-action-dialog.html"> +<link rel="import" href="alert-remove-box.html"> +<link rel="import" href="bisect-button.html"> +<link rel="import" href="trace-button.html"> +<link rel="import" href="triage-dialog.html"> + <polymer-element name="chart-tooltip" attributes="testPath value bugId pointId revisions links alerts xsrfToken"> @@ -25,10 +25,6 @@ was just clicked. margin: 0px; padding: 0px; } - - #tooltip::shadow #scroller { - padding: 10px 10px 0 10px; - } </style> <div id="container"> diff --git a/catapult/dashboard/dashboard/elements/custom-tooltip.html b/catapult/dashboard/dashboard/elements/custom-tooltip.html index d0aaedb5..3be83208 100644 --- a/catapult/dashboard/dashboard/elements/custom-tooltip.html +++ b/catapult/dashboard/dashboard/elements/custom-tooltip.html @@ -31,15 +31,6 @@ Example usage: .message-content { margin: 3px; } - - .message-content a, .message-content /deep/ a { - color: #EADE90; - text-decoration: none; - } - - .message-content a:hover, .message-content /deep/ a:hover { - text-decoration: underline; - } </style> <paper-shadow z="3"> @@ -76,7 +67,7 @@ Example usage: * See: https://goo.gl/QIYbsB */ eventDelegates: { - 'core-resize': 'positionChanged', + 'core-resize': 'positionChanged' }, ready: function() { @@ -160,7 +151,7 @@ Example usage: */ show: function() { this.opened = true; - }, + } }); </script> </polymer-element> diff --git a/catapult/dashboard/dashboard/elements/editable-list.html b/catapult/dashboard/dashboard/elements/editable-list.html index caa76b34..7be1208c 100644 --- a/catapult/dashboard/dashboard/elements/editable-list.html +++ b/catapult/dashboard/dashboard/elements/editable-list.html @@ -1,4 +1,4 @@ -<link rel="import" href="/dashboard/elements/xhr-element.html"> +<link rel="import" href="xhr-element.html"> <polymer-element name="editable-list" attributes="xsrfToken"> <template> @@ -155,7 +155,7 @@ var params = { item: item['name'], - action: 'remove', + action: 'remove' }; if (subItem) { params['sub_item'] = subItem['name']; @@ -194,7 +194,7 @@ } var params = { item: itemValue, - action: 'add', + action: 'add' }; if (subItemValue) { params['sub_item'] = subItemValue; @@ -217,7 +217,7 @@ var itemMap = this.getItemByValue(itemValue); if (!itemMap) { itemMap = { - 'name': itemValue, + 'name': itemValue }; this.editable_list.push(itemMap); this.editable_list.sort(this.itemCompare); @@ -228,7 +228,7 @@ itemMap['sub_items'] = []; } itemMap['sub_items'].push({ - 'name': subItemValue, + 'name': subItemValue }); itemMap.sort(this.itemCompare); } @@ -246,8 +246,7 @@ } } return null; - }, - + } }); </script> </polymer-element> diff --git a/catapult/dashboard/dashboard/elements/login-warning-test.html b/catapult/dashboard/dashboard/elements/login-warning-test.html index 2b74af8b..57b253b7 100644 --- a/catapult/dashboard/dashboard/elements/login-warning-test.html +++ b/catapult/dashboard/dashboard/elements/login-warning-test.html @@ -7,7 +7,7 @@ <script src="//cdnjs.cloudflare.com/ajax/libs/mocha/2.2.1/mocha.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/chai/2.1.1/chai.min.js"></script> <link rel="import" href="//www.polymer-project.org/0.5/components/polymer/polymer.html"> - <link rel="import" href="/dashboard/elements/login-warning.html"> + <link rel="import" href="login-warning.html"> </head> <body> <div id="mocha"></div> diff --git a/catapult/dashboard/dashboard/elements/quick-log.html b/catapult/dashboard/dashboard/elements/quick-log.html index c47be529..a5659ce0 100644 --- a/catapult/dashboard/dashboard/elements/quick-log.html +++ b/catapult/dashboard/dashboard/elements/quick-log.html @@ -1,6 +1,7 @@ -<link rel="import" href="/dashboard/elements/xhr-element.html"> <link rel="import" href="/third_party/polymer/components/core-icon-button/core-icon-button.html"> +<link rel="import" href="xhr-element.html"> + <polymer-element name="quick-log" attributes="logLabel logNamespace logName logFilter loadOnReady expandOnReady xsrfToken"> @@ -193,8 +194,8 @@ * Initializes log parameters and send a request to get logs. * @param {string} logLabel The label of log handle for * expanding log container. - * @param {string} logNamespace - * @param {string} logName + * @param {string} logNamespace Namespace name. + * @param {string} logName Log name. * @param {string} logFilter A regex string to filter logs. */ initialize: function(logLabel, logNamespace, logName, logFilter) { diff --git a/catapult/dashboard/dashboard/elements/report-container.html b/catapult/dashboard/dashboard/elements/report-container.html index fc2e3754..1981b262 100644 --- a/catapult/dashboard/dashboard/elements/report-container.html +++ b/catapult/dashboard/dashboard/elements/report-container.html @@ -1,4 +1,4 @@ -<link rel="import" href="/dashboard/elements/test-picker.html"> +<link rel="import" href="test-picker.html"> <link rel="import" href="/static/uri.html"> <polymer-element name="report-container" attributes="hasChart"> @@ -37,7 +37,7 @@ /** * On 'uriload' event, adds charts from the current query parameters. - * @param {Object} event + * @param {Object} event Event object. */ onUriLoad: function(event) { var params = event.detail.params; @@ -191,7 +191,7 @@ '<span style="color: red;">Failed to save report</span>', messageConfig); } - }, + } }); </script> </polymer-element> diff --git a/catapult/dashboard/dashboard/elements/revision-range-test.html b/catapult/dashboard/dashboard/elements/revision-range-test.html index 4a6d3af3..1296c2d6 100644 --- a/catapult/dashboard/dashboard/elements/revision-range-test.html +++ b/catapult/dashboard/dashboard/elements/revision-range-test.html @@ -7,7 +7,7 @@ <script src="//cdnjs.cloudflare.com/ajax/libs/mocha/2.2.1/mocha.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/chai/2.1.1/chai.min.js"></script> <link rel="import" href="//www.polymer-project.org/0.5/components/polymer/polymer.html"> - <link rel="import" href="/dashboard/elements/revision-range.html"> + <link rel="import" href="revision-range.html"> </head> <body> <div id="mocha"></div> diff --git a/catapult/dashboard/dashboard/elements/test-picker.html b/catapult/dashboard/dashboard/elements/test-picker.html index 2bb9891e..696bfce7 100644 --- a/catapult/dashboard/dashboard/elements/test-picker.html +++ b/catapult/dashboard/dashboard/elements/test-picker.html @@ -1,8 +1,8 @@ -<link rel="import" href="/dashboard/elements/autocomplete-box.html"> -<link rel="import" href="/dashboard/elements/xhr-element.html"> <link rel="import" href="/third_party/polymer/components/core-icon-button/core-icon-button.html"> <link rel="import" href="/third_party/polymer/components/paper-button/paper-button.html"> +<link rel="import" href="autocomplete-box.html"> +<link rel="import" href="xhr-element.html"> <link rel="import" href="/static/testselection.html"> <polymer-element name="test-picker" attributes="hasChart"> @@ -98,7 +98,7 @@ placeholder: this.BOT_LABEL, disabled: true, multi: true - }, + } ]; }, @@ -290,7 +290,7 @@ var subtestItems = this.getSubtestItems(subtestDict); this.selectionModels.push({ placeholder: this.SUBTEST_LABEL, - datalist: subtestItems, + datalist: subtestItems }); } @@ -320,7 +320,7 @@ var subtestNames = Object.keys(subtestDict).sort(); for (var i = 0; i < subtestNames.length; i++) { subtestItems.push({ - name: subtestNames[i], + name: subtestNames[i] }); } return subtestItems; @@ -458,13 +458,13 @@ }, /** - * Converts links in markdown format to HTML links (anchor elements). - * @param {string} text - * @return {string} + * Converts a link in markdown format to a HTML link (anchor elements). + * @param {string} text A link in markdown format. + * @return {string} A hyperlink string. */ convertMarkdownLinks: function(text) { return text.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2">$1</a>'); - }, + } }); </script> </polymer-element> diff --git a/catapult/dashboard/dashboard/elements/trace-button.html b/catapult/dashboard/dashboard/elements/trace-button.html index 1d72876f..59cdd415 100644 --- a/catapult/dashboard/dashboard/elements/trace-button.html +++ b/catapult/dashboard/dashboard/elements/trace-button.html @@ -1,6 +1,6 @@ <link rel="import" href="/third_party/polymer/components/paper-button/paper-button.html"> -<link rel="import" href="/dashboard/elements/trace-form.html"> +<link rel="import" href="trace-form.html"> <link rel="import" href="/static/bisect_utils.html"> <polymer-element name="trace-button" attributes="traceInfo bugId xsrfToken"> @@ -72,7 +72,7 @@ */ onTrace: function() { this.$.trace.show(); - }, + } }); })(); </script> diff --git a/catapult/dashboard/dashboard/elements/trace-form.html b/catapult/dashboard/dashboard/elements/trace-form.html index ed17286a..92dc822a 100644 --- a/catapult/dashboard/dashboard/elements/trace-form.html +++ b/catapult/dashboard/dashboard/elements/trace-form.html @@ -5,8 +5,9 @@ the trace process after the user clicks on the trace button. <link rel="import" href="/third_party/polymer/components/paper-button/paper-button.html"> <link rel="import" href="/third_party/polymer/components/paper-dialog/paper-action-dialog.html"> <link rel="import" href="/third_party/polymer/components/paper-spinner/paper-spinner.html"> -<link rel="import" href="/dashboard/elements/base-form.html"> -<link rel="import" href="/dashboard/elements/xhr-element.html"> + +<link rel="import" href="base-form.html"> +<link rel="import" href="xhr-element.html"> <polymer-element name="trace-form" extends="base-form" attributes="xsrfToken testPath @@ -47,10 +48,6 @@ the trace process after the user clicks on the trace button. background: #4285f4; color: #fff; } - - paper-spinner::shadow .circle { - border-color: #4285f4; - } </style> <form on-submit="{{onSendToTrybot}}"> diff --git a/catapult/dashboard/dashboard/elements/triage-dialog.html b/catapult/dashboard/dashboard/elements/triage-dialog.html index 3ce171a6..bb18acce 100644 --- a/catapult/dashboard/dashboard/elements/triage-dialog.html +++ b/catapult/dashboard/dashboard/elements/triage-dialog.html @@ -4,8 +4,9 @@ on an alert, or clicks on a "triage" button on the alerts page. It allows the --> <link rel="import" href="/third_party/polymer/components/paper-button/paper-button.html"> <link rel="import" href="/third_party/polymer/components/paper-dialog/paper-action-dialog.html"> -<link rel="import" href="/dashboard/elements/base-form.html"> -<link rel="import" href="/dashboard/elements/xhr-element.html"> + +<link rel="import" href="base-form.html"> +<link rel="import" href="xhr-element.html"> <polymer-element name="triage-dialog" extends="base-form" attributes="xsrfToken alerts"> @@ -44,10 +45,6 @@ on an alert, or clicks on a "triage" button on the alerts page. It allows the color: #fff; } - paper-spinner::shadow .circle { - border-color: #4285f4; - } - fieldset { border: 1px solid #ebebeb; } @@ -181,7 +178,7 @@ on an alert, or clicks on a "triage" button on the alerts page. It allows the var bugTitle = this.getBugTitle(); var data = [ {name: 'keys', value: this.alertKeys.join(',')}, - {name: 'summary', value: bugTitle}, + {name: 'summary', value: bugTitle} ]; this.bugWindow = this.openAndPost('/file_bug', data, 'edit_bugs'); }, @@ -244,7 +241,7 @@ on an alert, or clicks on a "triage" button on the alerts page. It allows the var params = { 'keys': this.alertKeys, 'new_start_revision': info.startRevision, - 'new_end_revision': info.endRevision, + 'new_end_revision': info.endRevision }; this.loading = true; this.$.xhr.send('/edit_anomalies', this.xsrfToken, params, @@ -276,7 +273,7 @@ on an alert, or clicks on a "triage" button on the alerts page. It allows the /** * Returns a default bug title to use when filing a new bug. - * @return {string} + * @return {string} The bug title. */ getBugTitle: function() { if (this.alerts[0].percent_changed) { diff --git a/catapult/dashboard/dashboard/email_sheriff_test.py b/catapult/dashboard/dashboard/email_sheriff_test.py index 130ebb9d..de1ff49e 100644 --- a/catapult/dashboard/dashboard/email_sheriff_test.py +++ b/catapult/dashboard/dashboard/email_sheriff_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for email_sheriff module.""" - import sys import unittest import urllib diff --git a/catapult/dashboard/dashboard/email_summary_test.py b/catapult/dashboard/dashboard/email_summary_test.py index 6db89d59..c0c69853 100644 --- a/catapult/dashboard/dashboard/email_summary_test.py +++ b/catapult/dashboard/dashboard/email_summary_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for email_summary module.""" - import datetime import unittest diff --git a/catapult/dashboard/dashboard/email_template_test.py b/catapult/dashboard/dashboard/email_template_test.py index b1aa577b..7ca39a78 100644 --- a/catapult/dashboard/dashboard/email_template_test.py +++ b/catapult/dashboard/dashboard/email_template_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for email_template module.""" - import unittest from dashboard import email_template diff --git a/catapult/dashboard/dashboard/file_bug_test.py b/catapult/dashboard/dashboard/file_bug_test.py index 75a65167..a3cac0a6 100644 --- a/catapult/dashboard/dashboard/file_bug_test.py +++ b/catapult/dashboard/dashboard/file_bug_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for file_bug module.""" - import json import unittest diff --git a/catapult/dashboard/dashboard/find_anomalies_test.py b/catapult/dashboard/dashboard/find_anomalies_test.py index f29d6000..35873d73 100644 --- a/catapult/dashboard/dashboard/find_anomalies_test.py +++ b/catapult/dashboard/dashboard/find_anomalies_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for find_anomalies module.""" - import sys import unittest @@ -194,8 +192,7 @@ class ProcessAlertsTest(testing_common.TestCase): mock.MagicMock(return_value=[ _MakeSampleChangePoint(10011, 100, 50) ])) - def testProcessTest_DownImprovementDirection_IsImprovementPropertySet(self): - """Tests the Anomaly improvement direction when lower is better.""" + def testProcessTest_ImprovementMarkedAsImprovement(self): self._AddDataForTests() test = utils.TestKey( 'ChromiumGPU/linux-release/scrolling_benchmark/ref').get() @@ -242,7 +239,6 @@ class ProcessAlertsTest(testing_common.TestCase): ])) @mock.patch.object(find_anomalies.email_sheriff, 'EmailSheriff') def testProcessTest_InternalOnlyTest(self, mock_email_sheriff): - """Verifies that internal-only tests are processed.""" self._AddDataForTests() test = utils.TestKey( 'ChromiumGPU/linux-release/scrolling_benchmark/ref').get() @@ -320,7 +316,6 @@ class ProcessAlertsTest(testing_common.TestCase): self.assertEqual(len(new_anomalies), 1) def testProcessTest_CreatesAnAnomaly(self): - """Tests that a particular anomaly is created for a sample data series.""" testing_common.AddTests( ['ChromiumGPU'], ['linux-release'], { 'scrolling_benchmark': {'ref': {}}, diff --git a/catapult/dashboard/dashboard/find_change_points_exp_test.py b/catapult/dashboard/dashboard/find_change_points_exp_test.py index 19741cb6..07494238 100644 --- a/catapult/dashboard/dashboard/find_change_points_exp_test.py +++ b/catapult/dashboard/dashboard/find_change_points_exp_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for find_change_points_exp module.""" - import unittest from google.appengine.ext import ndb diff --git a/catapult/dashboard/dashboard/find_change_points_test.py b/catapult/dashboard/dashboard/find_change_points_test.py index b1c5a5eb..a9fb45a3 100644 --- a/catapult/dashboard/dashboard/find_change_points_test.py +++ b/catapult/dashboard/dashboard/find_change_points_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for find_change_points module.""" - import unittest from dashboard import find_change_points @@ -110,8 +108,8 @@ class FindChangePointsTest(unittest.TestCase): self.assertTrue(self._PassesThresholds(left, 5, multiple_of_std_dev=7)) self.assertTrue(self._PassesThresholds(right, 5, multiple_of_std_dev=7)) - def testZeroMedian(self): - """The _ZeroMedian function adjusts values so that the median is zero.""" + def testZeroMedian_ReturnsValuesWithMedianEqualToZero(self): + # The _ZeroMedian function adjusts values so that the median is zero. self.assertEqual([0, 0, 1], find_change_points._ZeroMedian([1, 1, 2])) self.assertEqual([-0.5, 0.5], find_change_points._ZeroMedian([45, 46])) @@ -155,7 +153,6 @@ class FindChangePointsTest(unittest.TestCase): self.assertEqual(expected_indexes, actual_indexes) def testFindChangePoints_ShortSequences(self): - """Tests the behavior of FindChangePoints on some short sequences.""" self._AssertFindsChangePoints( [1, 1, 1, 5, 5, 5, 5, 9, 9, 9], [3], max_window_size=10, min_segment_size=3) @@ -172,8 +169,7 @@ class FindChangePointsTest(unittest.TestCase): [1, 1, 5, 5, 5, 5, 9, 9, 9, 9, 9], [6], max_window_size=11, min_segment_size=3) - def testChangePoint(self): - """Tests MakeChangePoint and conversion to dict.""" + def testChangePoint_CanBeMadeAndConvertedToDict(self): series = list(enumerate([4, 4, 4, 8, 8, 8, 8])) change_point = find_change_points.MakeChangePoint(series, 3) self.assertEqual( diff --git a/catapult/dashboard/dashboard/find_step_test.py b/catapult/dashboard/dashboard/find_step_test.py index 12a09193..767b8bb2 100644 --- a/catapult/dashboard/dashboard/find_step_test.py +++ b/catapult/dashboard/dashboard/find_step_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for find_step module.""" - import math import unittest diff --git a/catapult/dashboard/dashboard/graph_csv_test.py b/catapult/dashboard/dashboard/graph_csv_test.py index bec54122..e3236953 100644 --- a/catapult/dashboard/dashboard/graph_csv_test.py +++ b/catapult/dashboard/dashboard/graph_csv_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for graph_csv module.""" - import csv import StringIO import unittest diff --git a/catapult/dashboard/dashboard/graph_json.py b/catapult/dashboard/dashboard/graph_json.py index d07a639e..25f7de86 100644 --- a/catapult/dashboard/dashboard/graph_json.py +++ b/catapult/dashboard/dashboard/graph_json.py @@ -503,7 +503,7 @@ def _GetTestPathFromDict(test_path_dict): selected_traces = test_path_dict[test_path] if not selected_traces: sub_test_dict = _GetSubTestDict([test_path]) - selected_traces = _GetSubTestTraces(test_path, sub_test_dict) + selected_traces = _GetTraces(test_path, sub_test_dict) for trace in selected_traces: if trace == parent_test_name: test_paths_with_rows.append(test_path) @@ -530,7 +530,7 @@ def _GetUnselectedTestPathFromDict(test_path_dict): parent_test_name = test_path.split('/')[-1] selected_traces = test_path_dict[test_path] # Add sub-tests not in selected traces. - unselected_traces = _GetSubTestTraces(test_path, sub_test_dict) + unselected_traces = _GetTraces(test_path, sub_test_dict) for trace in unselected_traces: if trace not in selected_traces: if trace == parent_test_name: @@ -562,7 +562,7 @@ def _GetSubTestDict(test_paths): return subtests -def _GetSubTestTraces(test_path, sub_test_dict): +def _GetTraces(test_path, sub_test_dict): """Gets summary and sub-test traces directly underneath test_path. Args: @@ -575,12 +575,33 @@ def _GetSubTestTraces(test_path, sub_test_dict): traces = [] test_parts = test_path.split('/') test_suite_path = '/'.join(test_parts[0:3]) - target_trace = test_parts[-1] if test_suite_path not in sub_test_dict: return [] sub_test_tree = sub_test_dict[test_suite_path] + if len(test_parts) > 3: + return _GetSubTestTraces(test_parts, sub_test_tree) + + for key, value in sub_test_tree.iteritems(): + if value['has_rows']: + traces.append(key) + return traces + + +def _GetSubTestTraces(test_parts, sub_test_tree): + """Gets summary and sub-test traces after the test suite. + + Args: + test_parts: List of parts of a test path. + sub_test_tree: Nested dictionary of test data (see list_tests.GetSubTests). + + Returns: + List of trace names. + """ + traces = [] + target_trace = test_parts[-1] + for part in test_parts[3:-1]: if part in sub_test_tree: sub_test_tree = sub_test_tree[part]['sub_tests'] diff --git a/catapult/dashboard/dashboard/graph_json_test.py b/catapult/dashboard/dashboard/graph_json_test.py index 952310f6..1d4ddf44 100644 --- a/catapult/dashboard/dashboard/graph_json_test.py +++ b/catapult/dashboard/dashboard/graph_json_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for graph_json module.""" - import datetime import json import unittest @@ -153,8 +151,7 @@ class GraphJsonTest(testing_common.TestCase): self.assertEqual(rev, col['data'][index][0]) self.assertEqual(rev * 2, col['data'][index][1]) - def testBasicRequest(self): - """Tests the post method of the request handler.""" + def testPost_ValidRequest(self): self._AddTestColumns(start_rev=15700, end_rev=16000, step=1) graphs = { 'test_path_dict': { @@ -169,13 +166,12 @@ class GraphJsonTest(testing_common.TestCase): self.CheckFlotJson(flot_json_str, 150, 2, 15850, 16000, step=1) self.assertEqual('*', response.headers.get('Access-Control-Allow-Origin')) - # Errors are reported when the request is invalid. + def testPost_InvalidRequest_ReportsError(self): self.testapp.post('/graph_json', {}, status=500) self.testapp.post('/graph_json', {'graphs': ''}, status=500) self.testapp.post('/graph_json', {'graphs': '{}'}, status=500) - def testRequest_LongTestPathWithSelected(self): - """Tests the post method of the request handler.""" + def testPost_LongTestPathWithSelected(self): self._AddLongTestColumns(start_rev=15700, end_rev=16000, step=1) graphs = { 'test_path_dict': { @@ -189,8 +185,7 @@ class GraphJsonTest(testing_common.TestCase): flot_json_str = response.body self.CheckFlotJson(flot_json_str, 150, 1, 15850, 16000, step=1) - def testRequest_LongTestPathWithUnSelected(self): - """Tests the post method of the request handler.""" + def testPost_LongTestPathWithUnSelected(self): self._AddLongTestColumns(start_rev=15700, end_rev=16000, step=1) graphs = { 'test_path_dict': { @@ -203,8 +198,7 @@ class GraphJsonTest(testing_common.TestCase): flot_json_str = response.body self.CheckFlotJson(flot_json_str, 150, 1, 15850, 16000, step=1) - def testRequest_LongTestPathWithUnSelectedAndNoSubTest_NoGraphData(self): - """Tests the post method of the request handler.""" + def testPost_LongTestPathWithUnSelectedAndNoSubTest_NoGraphData(self): self._AddLongTestColumns(start_rev=15700, end_rev=16000, step=1) graphs = { 'test_path_dict': { @@ -218,6 +212,20 @@ class GraphJsonTest(testing_common.TestCase): flot = json.loads(flot_json_str) self.assertEqual(0, len(flot['data'])) + def testRequest_NoSubTest_ShowsSummaryTests(self): + """Tests the post method of the request handler.""" + self._AddTestColumns(start_rev=15700, end_rev=16000, step=1) + graphs = { + 'test_path_dict': { + 'ChromiumGPU/winXP/dromaeo': [], + } + } + # If the request is valid, a valid response will be returned. + response = self.testapp.post( + '/graph_json', {'graphs': json.dumps(graphs)}) + flot_json_str = response.body + self.CheckFlotJson(flot_json_str, 150, 2, 15850, 16000, step=1) + def testGetGraphJsonNoArgs(self): self._AddTestColumns(start_rev=16047) flot_json_str = graph_json.GetGraphJson( diff --git a/catapult/dashboard/dashboard/graph_revisions_test.py b/catapult/dashboard/dashboard/graph_revisions_test.py index 1f68773d..093c9edc 100644 --- a/catapult/dashboard/dashboard/graph_revisions_test.py +++ b/catapult/dashboard/dashboard/graph_revisions_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for graph_revisions module.""" - import datetime import json import unittest diff --git a/catapult/dashboard/dashboard/group_report_test.py b/catapult/dashboard/dashboard/group_report_test.py index 5c315bf9..5bf8cfb9 100644 --- a/catapult/dashboard/dashboard/group_report_test.py +++ b/catapult/dashboard/dashboard/group_report_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for group_report module.""" - import unittest import webapp2 @@ -115,7 +113,6 @@ class GroupReportTest(testing_common.TestCase): self.assertEqual(3, len(alert_list)) def testGet_WithInvalidRevParameter_ShowsError(self): - """Tests a request to /group_report with the rev parameter.""" response = self.testapp.get('/group_report?rev=foo') self.assertIn('error', response.body) self.assertIn('Invalid rev', response.body) diff --git a/catapult/dashboard/dashboard/issue_tracker_service_test.py b/catapult/dashboard/dashboard/issue_tracker_service_test.py index 6be309d5..42218ba1 100644 --- a/catapult/dashboard/dashboard/issue_tracker_service_test.py +++ b/catapult/dashboard/dashboard/issue_tracker_service_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for issue_tracker_service module.""" - import unittest import mock diff --git a/catapult/dashboard/dashboard/layered_cache_test.py b/catapult/dashboard/dashboard/layered_cache_test.py index f9f2de1a..c1d5d0ff 100644 --- a/catapult/dashboard/dashboard/layered_cache_test.py +++ b/catapult/dashboard/dashboard/layered_cache_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for layered_cache module.""" - import cPickle import datetime import unittest diff --git a/catapult/dashboard/dashboard/list_monitored_tests_test.py b/catapult/dashboard/dashboard/list_monitored_tests_test.py index b1615b23..f3bbc71b 100644 --- a/catapult/dashboard/dashboard/list_monitored_tests_test.py +++ b/catapult/dashboard/dashboard/list_monitored_tests_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for edit_sheriffs module.""" - import json import unittest @@ -43,8 +41,7 @@ class ListMonitoredTestsTest(testing_common.TestCase): id=name, email=email, url=url, internal_only=internal_only, summarize=summarize, patterns=patterns or []).put() - def testGet_ValidSheriff(self): - """A list of monitored tests can be requested for a Sheriff.""" + def testGet_ValidSheriff_ReturnsJSONListOfTests(self): self._AddSheriff('X', patterns=['*/*/Suite1/*']) self._AddSampleTestData() response = self.testapp.get( diff --git a/catapult/dashboard/dashboard/list_tests_test.py b/catapult/dashboard/dashboard/list_tests_test.py index 3cdc3716..21a9db88 100644 --- a/catapult/dashboard/dashboard/list_tests_test.py +++ b/catapult/dashboard/dashboard/list_tests_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for list_tests module.""" - import json import unittest @@ -63,7 +61,6 @@ class ListTestsTest(testing_common.TestCase): self.testbed.deactivate() def testGetSubTests_FetchAndCacheBehavior(self): - """Tests the behavior of GetSubTests and interaction with layered cache.""" self._AddSampleData() # Set the has_rows flag to true on two of the Test entities. @@ -139,12 +136,8 @@ class ListTestsTest(testing_common.TestCase): self.assertEqual(expected, json.loads(response.body)) def testGetSubTests_ReturnsOnlyNonDeprecatedTests(self): - """Checks that only data not marked as deprecated is returned. - - Sub-tests with the same name may be deprecated on one bot (indicating that - that bot has not sent data recently with that name and not deprecated on - another bot. - """ + # Sub-tests with the same name may be deprecated on only one bot, and not + # deprecated on another bot; only non-deprecated tests should be returned. self._AddSampleData() # Set the deprecated flag to True for one test on one platform. @@ -196,8 +189,7 @@ class ListTestsTest(testing_common.TestCase): } self.assertEqual(expected, json.loads(response.body)) - def testGetSubTests_InternalData(self): - """Checks that internal data is not returned for unauthorized users.""" + def testGetSubTests_InternalData_OnlyReturnedForAuthorizedUsers(self): # When the user has a an internal account, internal-only data is given. self.SetCurrentUser('foo@google.com') self._AddSampleData() diff --git a/catapult/dashboard/dashboard/load_from_prod.py b/catapult/dashboard/dashboard/load_from_prod.py index d44aafda..d7a2aefc 100644 --- a/catapult/dashboard/dashboard/load_from_prod.py +++ b/catapult/dashboard/dashboard/load_from_prod.py @@ -12,6 +12,7 @@ import json import os import urllib +from google.appengine.api import app_identity from google.appengine.api import urlfetch from google.appengine.ext import ndb from google.appengine.ext.ndb import model @@ -20,10 +21,7 @@ from dashboard import datastore_hooks from dashboard import request_handler from dashboard import update_test_suites -# The documentation says that the app id should be -# app_identity.get_application_id(), but that returns 'auto'. The dev_appserver -# only seems to be able to access the data if the app id is 'dev~auto'. -_DEV_APP_ID = 'dev~auto' +_DEV_APP_ID = 'dev~' + app_identity.get_application_id() _PROD_DUMP_GRAPH_JSON_URL = 'https://chromeperf.appspot.com/dump_graph_json' diff --git a/catapult/dashboard/dashboard/main_test.py b/catapult/dashboard/dashboard/main_test.py index 066918c9..948b2fdb 100644 --- a/catapult/dashboard/dashboard/main_test.py +++ b/catapult/dashboard/dashboard/main_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit test for 'main' module (the request handler for the front page).""" - import unittest import mock @@ -29,8 +27,8 @@ class MainTest(testing_common.TestCase): @mock.patch( 'google.appengine.api.urlfetch.fetch', mock.MagicMock(return_value=testing_common.FakeResponseObject(500, ''))) - def testGet_BugRequestFails_PageIsShown(self): - """Even if the recent bugs list can't be fetched, the page should load.""" + def testGet_BugRequestFails_PageIsStillShown(self): + # Even if the recent bugs list can't be fetched, the page should load. response = self.testapp.get('/') self.assertIn('<html>', response.body) diff --git a/catapult/dashboard/dashboard/math_utils_test.py b/catapult/dashboard/dashboard/math_utils_test.py index 7856fd9e..77196489 100644 --- a/catapult/dashboard/dashboard/math_utils_test.py +++ b/catapult/dashboard/dashboard/math_utils_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for math_utils module.""" - import math import unittest diff --git a/catapult/dashboard/dashboard/migrate_test_names_test.py b/catapult/dashboard/dashboard/migrate_test_names_test.py index c270cc74..7abb67e8 100644 --- a/catapult/dashboard/dashboard/migrate_test_names_test.py +++ b/catapult/dashboard/dashboard/migrate_test_names_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for migrate_test_names module.""" - import unittest import webapp2 @@ -112,8 +110,7 @@ class MigrateTestNamesTest(testing_common.TestCase): actual = [t.test_path for t in tests] self.assertEqual(expected, actual) - def testPost_MigrateTraceLevelTestForSeveralGraphs(self): - """Tests that one trace can be renamed for several graphs.""" + def testPost_MigrateTraceLevelTest(self): self._AddMockData() self.testapp.post('/migrate_test_names', { 'old_pattern': '*/*/*/*/t', @@ -163,7 +160,6 @@ class MigrateTestNamesTest(testing_common.TestCase): self._CheckTests(expected_tests) def testPost_MigrateChartLevelTest(self): - """Tests that a graph can be renamed and its traces will be migrated.""" self._AddMockData() self.testapp.post('/migrate_test_names', { @@ -190,7 +186,6 @@ class MigrateTestNamesTest(testing_common.TestCase): self._CheckTests(expected_tests) def testPost_MigrateSuiteLevelTest(self): - """Tests that a test suite can be renamed and traces will be migrated.""" self._AddMockData() self.testapp.post('/migrate_test_names', { @@ -217,7 +212,6 @@ class MigrateTestNamesTest(testing_common.TestCase): self._CheckTests(expected_tests) def testPost_MigrateSeriesToChartLevelTest(self): - """Tests that a Test's rows can be migrated up to the parent Test.""" self._AddMockData() self.testapp.post('/migrate_test_names', { @@ -227,8 +221,11 @@ class MigrateTestNamesTest(testing_common.TestCase): self.ExecuteTaskQueueTasks( '/migrate_test_names', migrate_test_names._TASK_QUEUE_NAME) + # The Row and Anomaly entities have been moved. self._CheckRows('ChromiumPerf/mac/SunSpider/Total') self._CheckAnomalies('ChromiumPerf/mac/SunSpider/Total') + + # There is no SunSpider/Total/time any more. expected_tests = [ 'SunSpider', 'SunSpider/3d-cube', @@ -243,7 +240,6 @@ class MigrateTestNamesTest(testing_common.TestCase): self._CheckTests(expected_tests) def testPost_MigrationFinished_EmailsSheriff(self): - """Tests that an email is sent about a migrated test.""" self._AddMockData() # Add a sheriff for one test. @@ -295,7 +291,7 @@ class MigrateTestNamesTest(testing_common.TestCase): 'migrated to ChromiumPerf/win7/moz/read_operations_browser', body) self.assertIn('sheriffed by Perf Sheriff Win', body) - def testGetNewTestPathWithAsterisks(self): + def testGetNewTestPath_WithAsterisks(self): self.assertEqual( 'A/b/c/X', migrate_test_names._GetNewTestPath('A/b/c/d', '*/*/*/X')) @@ -306,7 +302,7 @@ class MigrateTestNamesTest(testing_common.TestCase): 'A/b/c', migrate_test_names._GetNewTestPath('A/b/c/d', '*/*/*')) - def testGetNewTestPathWithBrackets(self): + def testGetNewTestPath_WithBrackets(self): # Brackets are just used to delete parts of names, no other functionality. self.assertEqual( 'A/b/c/x', @@ -321,7 +317,7 @@ class MigrateTestNamesTest(testing_common.TestCase): 'A/b/c/d', migrate_test_names._GetNewTestPath('AA/bb/cc/dd', '[A]/[b]/[c]/[d]')) - def testGetNewTestPathShorterOrLonger(self): + def testGetNewTestPath_NewPathHasDifferentLength(self): self.assertEqual( 'A/b/c', migrate_test_names._GetNewTestPath('A/b/c/d', 'A/*/c')) @@ -332,7 +328,7 @@ class MigrateTestNamesTest(testing_common.TestCase): migrate_test_names.BadInputPatternError, migrate_test_names._GetNewTestPath, 'A/b/c', 'A/b/c/*') - def testGetNewTestPathInvalidArgs(self): + def testGetNewTestPath_InvalidArgs(self): self.assertRaises( AssertionError, migrate_test_names._GetNewTestPath, 'A/b/*/d', 'A/b/c/d') diff --git a/catapult/dashboard/dashboard/models/alert_group_test.py b/catapult/dashboard/dashboard/models/alert_group_test.py index f3afe4d1..5cf8a5f5 100644 --- a/catapult/dashboard/dashboard/models/alert_group_test.py +++ b/catapult/dashboard/dashboard/models/alert_group_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for anomaly module.""" - import unittest from google.appengine.ext import ndb @@ -80,7 +78,6 @@ class AnomalyGroupingTest(testing_common.TestCase): return anomalies def testUpdateAnomalyBugId_UpdatesGroupOfAnomaly(self): - """Tests that updating an alert's bug ID can put it in another group.""" anomalies = self._AddAnomalies() # At first, two anomalies are in separate groups, and the second anomaly @@ -95,7 +92,6 @@ class AnomalyGroupingTest(testing_common.TestCase): self.assertEqual(anomalies[1].bug_id, anomalies[2].bug_id) def testMarkAnomalyInvalid_AnomalyIsRemovedFromGroup(self): - """Tests that marking an alert invalid removes it from its group.""" anomalies = self._AddAnomalies() # At first, two anomalies are in the same group. @@ -115,7 +111,6 @@ class AnomalyGroupingTest(testing_common.TestCase): self.assertEqual(4000, group.end_revision) def testUpdateAnomalyRevisionRange_UpdatesGroupRevisionRange(self): - """Tests that updating an anomaly's revision range updates its group.""" anomalies = self._AddAnomalies() # Add another anomaly to the same group as the first two anomalies, @@ -138,7 +133,6 @@ class AnomalyGroupingTest(testing_common.TestCase): self.assertEqual(3020, group.end_revision) def testUpdateGroup_InvalidRange_PropertiesAreUpdated(self): - """Tests that a group's properties updated when its range is invalid.""" anomalies = self._AddAnomalies() # Add another anomaly to the same group as the first two anomalies @@ -195,7 +189,6 @@ class StoppageAlertGroupingTest(testing_common.TestCase): return [foo_alert_key.get(), bar_alert_key.get()] def testStoppageAlertGroup_GroupAssignedUponCreation(self): - """In CreateStoppageAlert, a group should be found and and assigned.""" foo_test, bar_test = self._AddStoppageAlerts() self.assertIsNotNone(foo_test.group) self.assertIsNotNone(bar_test.group) @@ -241,8 +234,7 @@ class GroupAlertsTest(testing_common.TestCase): test.put() return [scrolling_test, tab_capture_test] - def testGroupAlerts_WithNoAssociation(self): - """Tests the GroupAlerts function creating AlertGroup.""" + def testGroupAlerts_WithNoAssociation_MakesNewGroup(self): sheriffs = self._AddSheriffs() tests = self._AddTests() @@ -267,12 +259,17 @@ class GroupAlertsTest(testing_common.TestCase): revision_range=(1000, 2000), test=tests[0], sheriff_key=sheriffs[0], bug_id=None, is_improvement=False) test_suite = 'scrolling_benchmark' + alert_group.GroupAlerts( [regression_anomaly, improvement_anomaly], test_suite, 'Anomaly') - self.assertEqual(regression_anomaly.bug_id, None) + + # The regression Anomaly was not grouped with a group that has a bug ID, + # so the bug ID is not changed. + self.assertIsNone(regression_anomaly.bug_id) # Improvement Anomaly should not be auto-triaged. self.assertIsNone(improvement_anomaly.group) + alert_groups = alert_group.AlertGroup.query().fetch() self.assertEqual(3, len(alert_groups)) self.assertEqual( @@ -282,7 +279,6 @@ class GroupAlertsTest(testing_common.TestCase): self.assertEqual(alert_groups[2].test_suites, [test_suite]) def testGroupAlerts_WithExistingGroup(self): - """Tests the GroupAlerts function associating anomalies with group.""" sheriffs = self._AddSheriffs() tests = self._AddTests() @@ -309,6 +305,7 @@ class GroupAlertsTest(testing_common.TestCase): alert_group.GroupAlerts( [regression_anomaly, improvement_anomaly], 'tab_capture', 'Anomaly') + # The regression Anomaly's bug ID is changed because it has been grouped. self.assertEqual(104, regression_anomaly.bug_id) self.assertEqual(tab_capture_group, regression_anomaly.group) diff --git a/catapult/dashboard/dashboard/models/alert_test.py b/catapult/dashboard/dashboard/models/alert_test.py index 23e1db89..75dd947c 100644 --- a/catapult/dashboard/dashboard/models/alert_test.py +++ b/catapult/dashboard/dashboard/models/alert_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for alert module.""" - import unittest from dashboard import testing_common @@ -16,11 +14,9 @@ class AlertTest(testing_common.TestCase): """Test case for some functions in anomaly.""" def testGetBotNamesFromAlerts_EmptyList_ReturnsEmptySet(self): - """Tests that an empty set is returned when nothing is passed.""" self.assertEqual(set(), alert.GetBotNamesFromAlerts([])) def testGetBotNamesFromAlerts_RemovesDuplicates(self): - """Tests that duplicates are removed from the result.""" testing_common.AddTests( ['SuperGPU'], ['Bot1'], {'foo': {'bar': {}}}) anomaly.Anomaly(test=utils.TestKey('SuperGPU/Bot1/foo/bar')).put() @@ -30,8 +26,7 @@ class AlertTest(testing_common.TestCase): self.assertEqual(2, len(anomalies)) self.assertEqual(1, len(bot_names)) - def testGetBotNamesFromAlerts_TypicalCase(self): - """Tests that we can get the name of the bots for a list of anomalies.""" + def testGetBotNamesFromAlerts_ReturnsBotNames(self): testing_common.AddTests( ['SuperGPU'], ['Bot1', 'Bot2', 'Bot3'], {'foo': {'bar': {}}}) anomaly.Anomaly(test=utils.TestKey('SuperGPU/Bot1/foo/bar')).put() diff --git a/catapult/dashboard/dashboard/models/anomaly_config_test.py b/catapult/dashboard/dashboard/models/anomaly_config_test.py index 2cd21872..3aa129cd 100644 --- a/catapult/dashboard/dashboard/models/anomaly_config_test.py +++ b/catapult/dashboard/dashboard/models/anomaly_config_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for anomaly_config module.""" - import unittest import mock diff --git a/catapult/dashboard/dashboard/models/bug_label_patterns_test.py b/catapult/dashboard/dashboard/models/bug_label_patterns_test.py index 0c0cfa73..ac1347b0 100644 --- a/catapult/dashboard/dashboard/models/bug_label_patterns_test.py +++ b/catapult/dashboard/dashboard/models/bug_label_patterns_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for bug_label_patterns module.""" - import unittest from dashboard import testing_common diff --git a/catapult/dashboard/dashboard/models/graph_data_test.py b/catapult/dashboard/dashboard/models/graph_data_test.py index f8e849c6..496eeb44 100644 --- a/catapult/dashboard/dashboard/models/graph_data_test.py +++ b/catapult/dashboard/dashboard/models/graph_data_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for graph_data module.""" - import unittest from dashboard import testing_common diff --git a/catapult/dashboard/dashboard/models/internal_only_model_test.py b/catapult/dashboard/dashboard/models/internal_only_model_test.py index 03a69dda..21a23439 100644 --- a/catapult/dashboard/dashboard/models/internal_only_model_test.py +++ b/catapult/dashboard/dashboard/models/internal_only_model_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for internal_only_model module.""" - import unittest import mock diff --git a/catapult/dashboard/dashboard/models/sheriff_test.py b/catapult/dashboard/dashboard/models/sheriff_test.py index c826934b..dc900b79 100644 --- a/catapult/dashboard/dashboard/models/sheriff_test.py +++ b/catapult/dashboard/dashboard/models/sheriff_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for sheriff module.""" - import unittest from dashboard import testing_common diff --git a/catapult/dashboard/dashboard/models/stoppage_alert_test.py b/catapult/dashboard/dashboard/models/stoppage_alert_test.py index 259358f4..7e9e33bc 100644 --- a/catapult/dashboard/dashboard/models/stoppage_alert_test.py +++ b/catapult/dashboard/dashboard/models/stoppage_alert_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for sheriff module.""" - import unittest from dashboard import testing_common diff --git a/catapult/dashboard/dashboard/mr_test.py b/catapult/dashboard/dashboard/mr_test.py index 825192c9..cf04cc40 100644 --- a/catapult/dashboard/dashboard/mr_test.py +++ b/catapult/dashboard/dashboard/mr_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for mr (mapreduce) module.""" - import datetime import unittest @@ -72,8 +70,7 @@ class MrTest(testing_common.TestCase): return trace_a, trace_b, suite - def testDeprecateTestsMapper_TraceUpdated(self): - """Tests basic functionality of DeprecateTestsMapper.""" + def testDeprecateTestsMapper_UpdatesTest(self): trace_a, trace_b, suite = self._AddMockDataForDeprecatedTests() for operation in mr.DeprecateTestsMapper(trace_a): @@ -85,8 +82,7 @@ class MrTest(testing_common.TestCase): self.assertFalse(trace_b.deprecated) self.assertFalse(suite.deprecated) - def testDeprecateTestsMapper_SuiteUpdated(self): - """Tests that DeprecateTestsMapper deprecates suites.""" + def testDeprecateTestsMapper_AllSubtestsDeprecated_UpdatesSuite(self): (trace_a, trace_b, suite) = self._AddMockDataForDeprecatedTests() last_b = graph_data.Row.query( graph_data.Row.parent_test == trace_b.key, diff --git a/catapult/dashboard/dashboard/namespaced_stored_object_test.py b/catapult/dashboard/dashboard/namespaced_stored_object_test.py index f3b20d8f..601fa28b 100644 --- a/catapult/dashboard/dashboard/namespaced_stored_object_test.py +++ b/catapult/dashboard/dashboard/namespaced_stored_object_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for namespaced_stored_object module.""" - import unittest from dashboard import namespaced_stored_object diff --git a/catapult/dashboard/dashboard/new_points_test.py b/catapult/dashboard/dashboard/new_points_test.py index 55988a56..0d8dee8e 100644 --- a/catapult/dashboard/dashboard/new_points_test.py +++ b/catapult/dashboard/dashboard/new_points_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for new_points module.""" - import datetime import re import unittest diff --git a/catapult/dashboard/dashboard/post_data_handler_test.py b/catapult/dashboard/dashboard/post_data_handler_test.py index 01c093e2..a84d2228 100644 --- a/catapult/dashboard/dashboard/post_data_handler_test.py +++ b/catapult/dashboard/dashboard/post_data_handler_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit test for post_data_handler module.""" - import json import unittest diff --git a/catapult/dashboard/dashboard/quick_logger_test.py b/catapult/dashboard/dashboard/quick_logger_test.py index 4248d08b..5d5f44f1 100644 --- a/catapult/dashboard/dashboard/quick_logger_test.py +++ b/catapult/dashboard/dashboard/quick_logger_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for quick_logger module.""" - import unittest from dashboard import quick_logger @@ -12,8 +10,7 @@ from dashboard import testing_common class QuickLoggerTest(testing_common.TestCase): - def testQuickLogger(self): - """Tests basic logging.""" + def testQuickLogger_SaveAndGetNewLogEntry(self): template = '{message}{extra}' formatter = quick_logger.Formatter(template, extra='!') logger = quick_logger.QuickLogger('a_namespace', 'a_log_name', formatter) @@ -24,7 +21,6 @@ class QuickLoggerTest(testing_common.TestCase): self.assertEqual(logs[0].message, 'Hello world!') def testQuickLogger_LogSizeAndNumberAtSizeLimit(self): - """Tests quick_logger limits.""" logger = quick_logger.QuickLogger('a_namespace', 'a_log_name') for i in xrange(quick_logger._MAX_NUM_RECORD): logger.Log(str(i%2) * quick_logger._MAX_MSG_SIZE) @@ -33,7 +29,6 @@ class QuickLoggerTest(testing_common.TestCase): self.assertEqual(len(logs), quick_logger._MAX_NUM_RECORD) def testQuickLogger_MultipleLogs_UsesCorrectOrder(self): - """Logger should keep most recent logs.""" logger = quick_logger.QuickLogger('a_namespace', 'a_log_name') for i in xrange(quick_logger._MAX_NUM_RECORD + 10): logger.Log(i) diff --git a/catapult/dashboard/dashboard/report_test.py b/catapult/dashboard/dashboard/report_test.py index 9520ad67..38673ed0 100644 --- a/catapult/dashboard/dashboard/report_test.py +++ b/catapult/dashboard/dashboard/report_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for report module.""" - import json import unittest diff --git a/catapult/dashboard/dashboard/send_stoppage_alert_emails_test.py b/catapult/dashboard/dashboard/send_stoppage_alert_emails_test.py index 70e36b7f..f33ddccc 100644 --- a/catapult/dashboard/dashboard/send_stoppage_alert_emails_test.py +++ b/catapult/dashboard/dashboard/send_stoppage_alert_emails_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for send_stoppage module.""" - import unittest import webapp2 @@ -38,7 +36,6 @@ class EmailSummaryTest(testing_common.TestCase): testing_common.AddRows(test_path, {100}) def testGet_ThreeAlertsOneSheriff_EmailSent(self): - """Adds data for the tests below, including several stoppage alerts.""" self._AddSampleData() for name in ('foo', 'bar', 'baz'): test = utils.TestKey('M/b/suite/%s' % name).get() diff --git a/catapult/dashboard/dashboard/set_warning_message_test.py b/catapult/dashboard/dashboard/set_warning_message_test.py index 0bc4d142..3b5e3e2e 100644 --- a/catapult/dashboard/dashboard/set_warning_message_test.py +++ b/catapult/dashboard/dashboard/set_warning_message_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for set_warning_message module.""" - import unittest import webapp2 diff --git a/catapult/dashboard/dashboard/short_uri_test.py b/catapult/dashboard/dashboard/short_uri_test.py index c336328a..ee010d4d 100644 --- a/catapult/dashboard/dashboard/short_uri_test.py +++ b/catapult/dashboard/dashboard/short_uri_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for short_uri module.""" - import json import unittest diff --git a/catapult/dashboard/dashboard/shrink_timestamp_revisions_test.py b/catapult/dashboard/dashboard/shrink_timestamp_revisions_test.py index 851e687b..0ef0a0d1 100644 --- a/catapult/dashboard/dashboard/shrink_timestamp_revisions_test.py +++ b/catapult/dashboard/dashboard/shrink_timestamp_revisions_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for shrink_timestamp_revisions module.""" - import unittest import webapp2 diff --git a/catapult/dashboard/dashboard/start_try_job.py b/catapult/dashboard/dashboard/start_try_job.py index 9d4253fe..bbe0ff1d 100644 --- a/catapult/dashboard/dashboard/start_try_job.py +++ b/catapult/dashboard/dashboard/start_try_job.py @@ -20,6 +20,7 @@ from dashboard import namespaced_stored_object from dashboard import quick_logger from dashboard import request_handler from dashboard import rietveld_service +from dashboard import stored_object from dashboard import update_test_metadata from dashboard import utils from dashboard.models import graph_data @@ -39,6 +40,7 @@ index %(hash_a)s..%(hash_b)s 100644 _BISECT_BOT_MAP_KEY = 'bisect_bot_map' _BUILDER_TYPES_KEY = 'bisect_builder_types' +_TESTER_DIRECTOR_MAP_KEY = 'recipe_tester_director_map' _NON_TELEMETRY_TEST_COMMANDS = { 'angle_perftests': [ @@ -113,10 +115,12 @@ class StartBisectHandler(request_handler.RequestHandler): bug_id = int(self.request.get('bug_id', -1)) master_name = self.request.get('master', 'ChromiumPerf') internal_only = self.request.get('internal_only') == 'true' - use_buildbucket = self.request.get('use_recipe') == 'true' + bisect_bot = self.request.get('bisect_bot') + + use_recipe = bool(GetBisectDirectorForTester(bisect_bot)) bisect_config = GetBisectConfig( - bisect_bot=self.request.get('bisect_bot'), + bisect_bot=bisect_bot, master_name=master_name, suite=self.request.get('suite'), metric=self.request.get('metric'), @@ -128,8 +132,7 @@ class StartBisectHandler(request_handler.RequestHandler): bug_id=bug_id, use_archive=self.request.get('use_archive'), bisect_mode=self.request.get('bisect_mode', 'mean'), - original_bot_name=self.request.get('bisect_bot'), - use_buildbucket=use_buildbucket) + use_buildbucket=use_recipe) if 'error' in bisect_config: return bisect_config @@ -137,19 +140,15 @@ class StartBisectHandler(request_handler.RequestHandler): config_python_string = 'config = %s\n' % json.dumps( bisect_config, sort_keys=True, indent=2, separators=(',', ': ')) - # Forcing recipe by default for linux jobs. - if self.request.get('bisect_bot') == 'linux_perf_bisect': - use_buildbucket = True - bisect_job = try_job.TryJob( - bot=self.request.get('bisect_bot'), + bot=bisect_bot, config=config_python_string, bug_id=bug_id, email=user.email(), master_name=master_name, internal_only=internal_only, job_type='bisect', - use_buildbucket=use_buildbucket) + use_buildbucket=use_recipe) try: result = PerformBisect(bisect_job) @@ -238,13 +237,13 @@ def _PrefillInfo(test_path): def GetBisectConfig( bisect_bot, master_name, suite, metric, good_revision, bad_revision, - repeat_count, max_time_minutes, truncate_percent, bug_id, - original_bot_name=None, use_archive=None, bisect_mode='mean', - use_buildbucket=False): + repeat_count, max_time_minutes, truncate_percent, bug_id, use_archive=None, + bisect_mode='mean', use_buildbucket=False): """Fills in a JSON response with the filled-in config file. Args: - bisect_bot: Bisect bot name. + bisect_bot: Bisect bot name. (This should be either a legacy bisector or a + recipe-enabled tester). master_name: Master name of the test being bisected. suite: Test suite name of the test being bisected. metric: Bisect bot "metric" parameter, in the form "chart/trace". @@ -254,8 +253,6 @@ def GetBisectConfig( max_time_minutes: Max time to run the test. truncate_percent: How many high and low values to discard. bug_id: The Chromium issue tracker bug ID. - original_bot_name: The name of the bot that originated the alert, required - when using buildbucket (i.e. recipe bisect). use_archive: Specifies whether to use build archives or not to bisect. If this is not empty or None, then we want to use archived builds. bisect_mode: What aspect of the test run to bisect on; possible options are @@ -271,8 +268,6 @@ def GetBisectConfig( bisect_bot, suite, metric=metric, use_buildbucket=use_buildbucket) if not command: return {'error': 'Could not guess command for %r.' % suite} - if use_buildbucket and not original_bot_name: - return {'error': 'Original bot name is required for buildbucket jobs.'} try: if not _IsGitHash(good_revision): @@ -304,8 +299,9 @@ def GetBisectConfig( 'builder_type': _BuilderType(master_name, use_archive), 'target_arch': GuessTargetArch(bisect_bot), 'bisect_mode': bisect_mode, - 'original_bot_name': original_bot_name, } + if use_buildbucket: + config_dict['recipe_tester_name'] = bisect_bot return config_dict @@ -329,7 +325,7 @@ def _BuilderType(master_name, use_archive): def GuessTargetArch(bisect_bot): """Return target architecture for the bisect job.""" - if 'x64' in bisect_bot: + if 'x64' in bisect_bot or 'win64' in bisect_bot: return 'x64' elif bisect_bot in ['android_nexus9_perf_bisect']: return 'arm64' @@ -735,9 +731,10 @@ def _MakeBuildbucketBisectJob(bisect_job): 'Recipe only supports bisect jobs at this time.') if not bisect_job.master_name.startswith('ChromiumPerf'): raise request_handler.InvalidInputError( - 'Recipe is only implemented on for tests run on chromium.perf ' + 'Recipe is only implemented for tests run on chromium.perf ' '(and chromium.perf.fyi).') return buildbucket_job.BisectJob( + bisect_director=GetBisectDirectorForTester(config['recipe_tester_name']), good_revision=config['good_revision'], bad_revision=config['bad_revision'], test_command=config['command'], @@ -747,7 +744,7 @@ def _MakeBuildbucketBisectJob(bisect_job): truncate=config['truncate_percent'], bug_id=bisect_job.bug_id, gs_bucket='chrome-perf', - original_bot_name=config['original_bot_name'], + recipe_tester_name=config['recipe_tester_name'], ) @@ -766,3 +763,18 @@ def PerformBuildbucketBisect(bisect_job): e.message), } + +def GetBisectDirectorForTester(bot): + """Maps the name of a tester bot to its corresponding bisect director. + + Args: + bot (str): The name of the tester bot in the tryserver.chromium.perf + waterfall. (e.g. 'linux_perf_tester'). + + Returns: + The name of the bisect director that can use the given tester (e.g. + 'linux_perf_bisector') + """ + recipe_tester_director_mapping = stored_object.Get( + _TESTER_DIRECTOR_MAP_KEY) + return recipe_tester_director_mapping.get(bot) diff --git a/catapult/dashboard/dashboard/start_try_job_test.py b/catapult/dashboard/dashboard/start_try_job_test.py index 569bc4a6..844bb4e4 100644 --- a/catapult/dashboard/dashboard/start_try_job_test.py +++ b/catapult/dashboard/dashboard/start_try_job_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for start_try_job module.""" - import base64 import json import unittest @@ -18,6 +16,7 @@ from google.appengine.ext import ndb from dashboard import namespaced_stored_object from dashboard import rietveld_service from dashboard import start_try_job +from dashboard import stored_object from dashboard import testing_common from dashboard.models import bug_data from dashboard.models import graph_data @@ -42,7 +41,6 @@ _EXPECTED_BISECT_CONFIG_DIFF = """config = { + "good_revision": "215806", + "max_time_minutes": "20", + "metric": "jslib/jslib", -+ "original_bot_name": "win_perf_bisect", + "repeat_count": "20", + "target_arch": "ia32", + "truncate_percent": "25" @@ -326,6 +324,12 @@ class StartBisectTest(testing_common.TestCase): def setUp(self): super(StartBisectTest, self).setUp() + stored_object.Set( + start_try_job._TESTER_DIRECTOR_MAP_KEY, + { + 'linux_perf_tester': 'linux_perf_bisector', + 'win64_nv_tester': 'linux_perf_bisector', + }) app = webapp2.WSGIApplication( [('/start_try_job', start_try_job.StartBisectHandler)]) self.testapp = webtest.TestApp(app) @@ -503,13 +507,12 @@ class StartBisectTest(testing_common.TestCase): 'builder_type': '', 'target_arch': 'ia32', 'bisect_mode': 'mean', - 'original_bot_name': None, }) def testGetConfig_UseBuildbucket_ChangesTelemetryOutputFormat(self): self._TestGetBisectConfig( { - 'bisect_bot': 'linux_perf_bisect', + 'bisect_bot': 'linux_perf_tester', 'master_name': 'ChromiumPerf', 'suite': 'page_cycler.moz', 'metric': 'times/page_load_time', @@ -520,7 +523,6 @@ class StartBisectTest(testing_common.TestCase): 'truncate_percent': '30', 'bug_id': '-1', 'use_archive': 'true', - 'original_bot_name': 'chrome-rel-linux', 'use_buildbucket': True, }, { @@ -538,7 +540,7 @@ class StartBisectTest(testing_common.TestCase): 'builder_type': 'perf', 'target_arch': 'ia32', 'bisect_mode': 'mean', - 'original_bot_name': 'chrome-rel-linux', + 'recipe_tester_name': 'linux_perf_tester', }) def testGetConfig_NonEmptyUseArchiveParameter_GivesNonEmptyBuilderType(self): @@ -573,11 +575,9 @@ class StartBisectTest(testing_common.TestCase): 'builder_type': '', 'target_arch': 'ia32', 'bisect_mode': 'mean', - 'original_bot_name': None, }) - def testGetConfig_Telemetry(self): - """Tests that the right config is returned for a normal Telemetry test.""" + def testGetConfig_TelemetryTest(self): self._TestGetBisectConfig( { 'bisect_bot': 'win_perf_bisect', @@ -606,11 +606,9 @@ class StartBisectTest(testing_common.TestCase): 'builder_type': '', 'target_arch': 'ia32', 'bisect_mode': 'mean', - 'original_bot_name': None, }) - def testGetConfig_BisectModeAsReturnCode(self): - """Tests that the right config is returned for return_code bisect mode.""" + def testGetConfig_BisectModeSetToReturnCode(self): self._TestGetBisectConfig( { 'bisect_bot': 'linux_perf_bisect', @@ -641,7 +639,6 @@ class StartBisectTest(testing_common.TestCase): 'builder_type': '', 'target_arch': 'ia32', 'bisect_mode': 'return_code', - 'original_bot_name': None, }) def _TestGetConfigCommand(self, expected_command, **params_to_override): @@ -663,8 +660,7 @@ class StartBisectTest(testing_common.TestCase): response = start_try_job.GetBisectConfig(**parameters) self.assertEqual(expected_command, response.get('command')) - def testGetConfig_AndroidTelemetry(self): - """Tests that the right config is returned for an android bot.""" + def testGetConfig_AndroidTelemetryTest(self): self._TestGetConfigCommand( ('tools/perf/run_benchmark -v ' '--browser=android-chromium --output-format=buildbot ' @@ -674,7 +670,6 @@ class StartBisectTest(testing_common.TestCase): suite='page_cycler.morejs') def testGetConfig_CCPerftests(self): - """Tests the config returned for a cc_perftests test on linux.""" self._TestGetConfigCommand( ('./out/Release/cc_perftests ' '--test-launcher-print-test-stdio=always'), @@ -682,22 +677,19 @@ class StartBisectTest(testing_common.TestCase): suite='cc_perftests') def testGetConfig_AndroidCCPerftests(self): - """Tests the command returned for cc_perftests tests on android.""" self._TestGetConfigCommand( 'build/android/test_runner.py gtest --release -s cc_perftests', bisect_bot='android_nexus7_perf_bisect', suite='cc_perftests') def testGetConfig_IdbPerf(self): - """Tests the command returned for idb_perf tests on windows.""" self._TestGetConfigCommand( (r'.\out\Release\performance_ui_tests.exe ' '--gtest_filter=IndexedDBTest.Perf'), bisect_bot='win_perf_bisect', suite='idb_perf') - def testGetConfig_Startup(self): - """Tests that a custom flag is added for startup tests.""" + def testGetConfig_Startup_ProfileDirFlagAdded(self): self._TestGetConfigCommand( ('python tools/perf/run_benchmark -v ' '--browser=release --output-format=buildbot ' @@ -707,8 +699,7 @@ class StartBisectTest(testing_common.TestCase): bisect_bot='win_perf_bisect', suite='startup.cold.dirty.blank_page') - def testGetConfig_SessionRestore(self): - """Tests that a custom flag is added for session_restore tests.""" + def testGetConfig_SessionRestore_ProfileDirFlagAdded(self): self._TestGetConfigCommand( ('python tools/perf/run_benchmark -v ' '--browser=release --output-format=buildbot ' @@ -726,16 +717,6 @@ class StartBisectTest(testing_common.TestCase): bisect_bot='linux_perf_bisect', suite='performance_browser_tests') - def testGetConfig_ClankTelemetry(self): - """Tests that the right config is returned for an clank bot.""" - self._TestGetConfigCommand( - ('tools/perf/run_benchmark -v ' - '--browser=android-chrome --output-format=buildbot ' - '--also-run-disabled-tests ' - 'page_cycler.morejs'), - bisect_bot='clankium_nexus4_perf_bisect', - suite='page_cycler.morejs') - def testGuessBisectBot_FetchesNameFromBisectBotMap(self): namespaced_stored_object.Set( start_try_job._BISECT_BOT_MAP_KEY, @@ -764,7 +745,6 @@ class StartBisectTest(testing_common.TestCase): mock.MagicMock(return_value='1234567')) def testPerformBuildbucketBisect(self): self.SetCurrentUser('foo@chromium.org') - # Fake Rietveld auth info cfg = rietveld_service.RietveldConfig( id='default_rietveld_config', client_email='sullivan@chromium.org', @@ -772,11 +752,10 @@ class StartBisectTest(testing_common.TestCase): server_url='https://test-rietveld.appspot.com') cfg.put() - # Create bug. bug_data.Bug(id=12345).put() query_parameters = { - 'bisect_bot': 'linux_perf_bisect', + 'bisect_bot': 'linux_perf_tester', 'suite': 'dromaeo.jslibstylejquery', 'metric': 'jslib/jslib', 'good_revision': '215806', @@ -786,7 +765,6 @@ class StartBisectTest(testing_common.TestCase): 'truncate_percent': '25', 'bug_id': 12345, 'use_archive': '', - 'use_recipe': 'true', 'step': 'perform-bisect', } response = self.testapp.post('/start_try_job', query_parameters) @@ -887,7 +865,7 @@ class StartBisectTest(testing_common.TestCase): bug_data.Bug(id=12345).put() query_parameters = { - 'bisect_bot': 'linux_perf_bisect', + 'bisect_bot': 'linux_perf_tester', 'suite': 'dromaeo.jslibstylejquery', 'metric': 'jslib/jslib', 'good_revision': '215806', @@ -906,8 +884,7 @@ class StartBisectTest(testing_common.TestCase): 'issue_url': '/buildbucket_job_status/1234567'}), response.body) - def testGetConfigWithArchive(self): - """Tests GetConfig method with use_archive attribute set.""" + def testGetBisectconfig_UseArchive(self): self._TestGetBisectConfig( { 'bisect_bot': 'win_perf_bisect', @@ -937,10 +914,9 @@ class StartBisectTest(testing_common.TestCase): 'builder_type': 'perf', 'target_arch': 'ia32', 'bisect_mode': 'mean', - 'original_bot_name': None, }) - def testGetConfigWithTargetArch(self): + def testGetBisectConfig_WithTargetArch(self): self._TestGetBisectConfig( { 'bisect_bot': 'win_x64_perf_bisect', @@ -970,7 +946,6 @@ class StartBisectTest(testing_common.TestCase): 'builder_type': '', 'target_arch': 'x64', 'bisect_mode': 'mean', - 'original_bot_name': None, }) diff --git a/catapult/dashboard/dashboard/static/alerts.html b/catapult/dashboard/dashboard/static/alerts.html index a337f5c1..9dbf83a0 100644 --- a/catapult/dashboard/dashboard/static/alerts.html +++ b/catapult/dashboard/dashboard/static/alerts.html @@ -1,4 +1,4 @@ -<link rel="import" href="/static/uri.html"> +<link rel="import" href="uri.html"> <script> @@ -85,7 +85,7 @@ var alerts = (function() { /** * Updates the table content to include or exclude triaged alerts. - * @param {Event} e + * @param {Event} e The event object. */ var onToggleTriaged_ = function(e) { var params = uri.getAllParameters(); @@ -99,7 +99,7 @@ var alerts = (function() { /** * Updates the table to include or exclude improvement anomalies. - * @param {Event} e + * @param {Event} e The event object. */ var onToggleImprovements_ = function(e) { var params = uri.getAllParameters(); @@ -114,9 +114,9 @@ var alerts = (function() { /** * Finds an element in the DOM and initializes it with some properties. * The element with the given ID is assumed to be an alerts-table element. - * @param {string} id - * @param {Array.<Object>} alertList - * @param {Array.<Object>} extraColumns + * @param {string} id alerts-table ID. + * @param {Array.<Object>} alertList List of alerts. + * @param {Array.<Object>} extraColumns List of extra columns. * @return {Element} The alerts-table element. */ var initializeAlertsTable_ = function(id, alertList, extraColumns) { diff --git a/catapult/dashboard/dashboard/static/graph.html b/catapult/dashboard/dashboard/static/graph.html index 5bf7336c..55c5d565 100644 --- a/catapult/dashboard/dashboard/static/graph.html +++ b/catapult/dashboard/dashboard/static/graph.html @@ -2,8 +2,8 @@ /** * Does a deep copy of the object. - * @param {*} obj - * @return {*} + * @param {*} obj Object to copy. + * @return {*} A copy of the object. */ function deepCopy(obj) { return JSON.parse(JSON.stringify(obj)); @@ -15,26 +15,6 @@ function deepCopy(obj) { var graph = (function() { /** - * Makes a chart title string based on selected test paths. - * @param {Array.<string>} allTestPaths An Array of "Master/bot/subtests/...". - * @param {Array.<string>} selectedTestPaths Another Array of test paths. - * @return {string} New chart title. - */ - var makeChartTitle = function(allTestPaths, selectedTestPaths) { - if (selectedTestPaths.length == 1) { - return selectedTestPaths[0]; - } - if (allTestPaths.length == 1) { - return allTestPaths[0]; - } - // If no items are selected, we still want a descriptive title. - if (selectedTestPaths.length == 0) { - return makeChartTitleFromTestPathList_(allTestPaths); - } - return makeChartTitleFromTestPathList_(selectedTestPaths); - }; - - /** * Returns a hex string color from hash code of a string. This a popular * implementation of generating hash code and spread over rgb color range * http://stackoverflow.com/questions/3426404. @@ -53,8 +33,8 @@ var graph = (function() { * Gets a hash code for a string. * This is used by 'stringToColor' to generate a unique hash code * so that each string will always map to the same color. - * @param {string} str - * @return {number} + * @param {string} str A string to hash. + * @return {number} An integer number. */ var hashCode_ = function(str) { var hash = 0; @@ -66,58 +46,7 @@ var graph = (function() { return hash; }; - /** - * Makes a string to use as a chart title, based on a set of test paths. - * @param {Array.<string>} testPaths An list of test paths. - * @return {string} The longest test path that is the prefix - */ - var makeChartTitleFromTestPathList_ = function(testPaths) { - var prefix = ''; - if (testPaths.length > 1) { - prefix = longestCommonTestPathPrefix_(testPaths); - } - if (testPaths.indexOf(prefix) >= 0) { - return prefix; - } - return prefix ? prefix + '/...' : '...'; - }; - - /** - * @param {Array.<string>} testPaths An list of test paths. - * @return {string} The longest test path that is the prefix - */ - var longestCommonTestPathPrefix_ = function(testPaths) { - var partArrays = testPaths.map(function(path) { - return path.split('/'); - }); - return longestCommonSubArray_(partArrays).join('/'); - }; - - /** - * @param {Array.<Array>} arrays An Array of Arrays. - * @return {Array} The longest Array such that all Arrays in the input - * contain this Array as a prefix. - */ - var longestCommonSubArray_ = function(arrays) { - if (arrays.length == 0) { - return []; - } - var shortestLength = Math.min.apply(window, arrays.map(function(a) { - return a.length; - })); - for (var prefixLength = 0; prefixLength <= shortestLength; prefixLength++) { - var value = arrays[0][prefixLength]; - for (var i = 1; i < arrays.length; i++) { - if (arrays[i][prefixLength] != value) { - return arrays[0].slice(0, prefixLength); - } - } - } - return arrays[0].slice(0, shortestLength); - }; - return { - makeChartTitle: makeChartTitle, stringToColor: stringToColor }; })(); diff --git a/catapult/dashboard/dashboard/static/group_report.html b/catapult/dashboard/dashboard/static/group_report.html index 151d33bb..7675b6e5 100644 --- a/catapult/dashboard/dashboard/static/group_report.html +++ b/catapult/dashboard/dashboard/static/group_report.html @@ -1,4 +1,4 @@ -<link rel="import" href="/static/testselection.html"> +<link rel="import" href="testselection.html"> <script> @@ -16,7 +16,7 @@ var group_report = (function() { /** * Unchecks the checkbox in the alerts-table when a graph is closed. * This is the handler for the 'closeGraph' event, fired by chart-container. - * @param {Event} event + * @param {Event} event The event object. */ var onGraphClose_ = function(event) { // Un-check the alert in the table. @@ -40,7 +40,7 @@ var group_report = (function() { /** * Get series to graph for an alert. - * @param {Object} alert + * @param {Object} alert The alert object. * @return {Array} A two-item Array, which contains a test path and list of * selected series for tests under that test path. */ @@ -139,7 +139,7 @@ var group_report = (function() { * Add graphs for tests in 'alerts' to the given element. * @param {Element} containerElement The element that contains all the chart * UI elements. - * @param {Array.<Object>} alerts + * @param {Array.<Object>} alerts List of alert objects. * @param {boolean} insertBefore True for adding graphs in prepending order. */ var addGraph_ = function(containerElement, alerts, insertBefore) { @@ -174,7 +174,7 @@ var group_report = (function() { /** * On alert checkbox change, remove or add graphs. - * @param {Event} e + * @param {Event} e The event object. */ var onAlertSelectionChange_ = function(e) { // Make a set of all alerts that are checked in the table. @@ -208,7 +208,7 @@ var group_report = (function() { table_ = document.getElementById('alerts-table'); table_['alertList'] = window['ALERT_LIST']; table_['extraColumns'] = [ - {'key': 'percent_changed', 'label': 'Delta %'}, + {'key': 'percent_changed', 'label': 'Delta %'} ]; table_['initialize'](); table_.addEventListener('changeselection', onAlertSelectionChange_, false); diff --git a/catapult/dashboard/dashboard/stats_test.py b/catapult/dashboard/dashboard/stats_test.py index ee794fd4..ba28998c 100644 --- a/catapult/dashboard/dashboard/stats_test.py +++ b/catapult/dashboard/dashboard/stats_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for stats module.""" - import datetime import unittest diff --git a/catapult/dashboard/dashboard/stored_object_test.py b/catapult/dashboard/dashboard/stored_object_test.py index 81cc4a29..be22154a 100644 --- a/catapult/dashboard/dashboard/stored_object_test.py +++ b/catapult/dashboard/dashboard/stored_object_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Tests for dashboard.stored_object.""" - import unittest from google.appengine.api import memcache diff --git a/catapult/dashboard/dashboard/templates/alerts.html b/catapult/dashboard/dashboard/templates/alerts.html index ef6691d4..ba901907 100644 --- a/catapult/dashboard/dashboard/templates/alerts.html +++ b/catapult/dashboard/dashboard/templates/alerts.html @@ -64,10 +64,10 @@ <link rel="import" href="/third_party/polymer/components/polymer/polymer.html"> <link rel="import" href="/third_party/polymer/components/paper-button/paper-button.html"> - <link rel="import" href="/dashboard/elements/select-menu.html"> - <link rel="import" href="/dashboard/elements/alerts-table.html"> - <link rel="import" href="/dashboard/elements/overlay-message.html"> - <link rel="import" href="/dashboard/elements/quick-log.html"> + <link rel="import" href="/elements/select-menu.html"> + <link rel="import" href="/elements/alerts-table.html"> + <link rel="import" href="/elements/overlay-message.html"> + <link rel="import" href="/elements/quick-log.html"> {% endblock %} {% block content %} diff --git a/catapult/dashboard/dashboard/templates/analytics.html b/catapult/dashboard/dashboard/templates/analytics.html index 81f33d71..d2874dd0 100644 --- a/catapult/dashboard/dashboard/templates/analytics.html +++ b/catapult/dashboard/dashboard/templates/analytics.html @@ -7,4 +7,4 @@ ga('create', 'UA-56758330-1', 'auto'); ga('send', 'pageview'); -</script>
\ No newline at end of file +</script> diff --git a/catapult/dashboard/dashboard/templates/bisect_stats.html b/catapult/dashboard/dashboard/templates/bisect_stats.html index f6641145..2cf56e5f 100644 --- a/catapult/dashboard/dashboard/templates/bisect_stats.html +++ b/catapult/dashboard/dashboard/templates/bisect_stats.html @@ -18,7 +18,7 @@ </style> <link rel="import" href="/third_party/polymer/components/polymer/polymer.html"> - <link rel="import" href="/dashboard/elements/quick-log.html"> + <link rel="import" href="/elements/quick-log.html"> {% endblock %} {% block content %} diff --git a/catapult/dashboard/dashboard/templates/edit_test_owners.html b/catapult/dashboard/dashboard/templates/edit_test_owners.html index b0bcb758..4c75799b 100644 --- a/catapult/dashboard/dashboard/templates/edit_test_owners.html +++ b/catapult/dashboard/dashboard/templates/edit_test_owners.html @@ -8,7 +8,7 @@ </script> <link rel="import" href="/third_party/polymer/components/polymer/polymer.html"> - <link rel="import" href="/dashboard/elements/editable-list.html"> + <link rel="import" href="/elements/editable-list.html"> <style> #content { diff --git a/catapult/dashboard/dashboard/templates/group_report.html b/catapult/dashboard/dashboard/templates/group_report.html index 320efe5a..15a6ace5 100644 --- a/catapult/dashboard/dashboard/templates/group_report.html +++ b/catapult/dashboard/dashboard/templates/group_report.html @@ -94,14 +94,14 @@ <link rel="import" href="/third_party/polymer/components/polymer/polymer.html"> <link rel="import" href="/third_party/polymer/components/paper-button/paper-button.html"> - <link rel="import" href="/dashboard/elements/alerts-table.html"> - <link rel="import" href="/dashboard/elements/bug-info.html"> - <link rel="import" href="/dashboard/elements/chart-container.html"> - <link rel="import" href="/dashboard/elements/custom-tooltip.html"> - <link rel="import" href="/dashboard/elements/login-warning.html"> - <link rel="import" href="/dashboard/elements/overlay-message.html"> - <link rel="import" href="/dashboard/elements/quick-log.html"> - <link rel="import" href="/dashboard/elements/triage-dialog.html"> + <link rel="import" href="/elements/alerts-table.html"> + <link rel="import" href="/elements/bug-info.html"> + <link rel="import" href="/elements/chart-container.html"> + <link rel="import" href="/elements/custom-tooltip.html"> + <link rel="import" href="/elements/login-warning.html"> + <link rel="import" href="/elements/overlay-message.html"> + <link rel="import" href="/elements/quick-log.html"> + <link rel="import" href="/elements/triage-dialog.html"> <link rel="import" href="/static/group_report.html"> {% endblock %} diff --git a/catapult/dashboard/dashboard/templates/nav.html b/catapult/dashboard/dashboard/templates/nav.html index e6646c50..5618698a 100644 --- a/catapult/dashboard/dashboard/templates/nav.html +++ b/catapult/dashboard/dashboard/templates/nav.html @@ -19,6 +19,22 @@ } /** + * Opens a window with new GitHub issue, pre-filled with some info. + * @param {string} summary The title of the bug. + * @param {string} comment The description of the bug. + * @param {string} label Label to apply to the bug. + */ + function openGitHubIssueWindow(summary, comment, label) { + var url = 'https://github.com/catapult-project/catapult/issues/new?'; + url += [ + 'title=' + encodeURIComponent(summary), + 'body=' + encodeURIComponent(comment), + 'labels=' + encodeURIComponent(label), + ].join('&'); + window.open(url, '_blank'); + } + + /** * Opens a window to report a general dashboard bug. */ function reportBug() { @@ -34,7 +50,7 @@ description += (os == 'Mac' ? 'Command+Option+J' : 'Ctrl+Shift+J'); description += ' to open):\n\n'; description += 'Please describe the problem:\n'; - openCrBugWindow('', description, ['Performance-Dashboard'], []); + openGitHubIssueWindow('Perf Dashboard: ', description, 'Perf Dashboard'); } /** @@ -59,9 +75,6 @@ return 'unknown'; } - /** - * Opens a window to report a general dashboard bug. - */ function fileIpWhitelistRequest() { var description = 'Please whitelist the following IP addresses ' + 'to send data to the Chrome Perf Dashboard:\n' + @@ -71,9 +84,6 @@ openCrBugWindow('IP Whitelist Request', description, labels, []); } - /** - * Opens a window to report a general dashboard bug. - */ function fileBotWhitelistRequest() { var description = 'Please make the following bots and all their data ' + 'publicly available, with no google.com login required: \n' + @@ -82,9 +92,6 @@ openCrBugWindow('Bot Whitelist Request', description, labels, []); } - /** - * Opens a window to report a general dashboard bug. - */ function fileMonitoringRequest() { var description = 'Please add monitoring for the following tests:\n\n' + 'Test owner (see http://go/perf-test-owners):\n' + diff --git a/catapult/dashboard/dashboard/templates/put_buildbucket_job.html b/catapult/dashboard/dashboard/templates/put_buildbucket_job.html index f0149d47..bdab504b 100644 --- a/catapult/dashboard/dashboard/templates/put_buildbucket_job.html +++ b/catapult/dashboard/dashboard/templates/put_buildbucket_job.html @@ -29,8 +29,8 @@ <label>Test type <input type="text" name="test_type" value="perf"> </label><br/> - <label>Platform - <input type="text" name="platform" value="linux"> + <label>Recipe tester bot name + <input type="text" name="recipe_tester_name" value="linux_perf_tester"> </label><br/> <label>Command <input type="text" name="command" value="xvfb-run -a src/tools/perf/run_benchmark -v --browser=release blink_perf.parser"> diff --git a/catapult/dashboard/dashboard/templates/quick_log_viewer.html b/catapult/dashboard/dashboard/templates/quick_log_viewer.html index bde055e3..a70148fa 100644 --- a/catapult/dashboard/dashboard/templates/quick_log_viewer.html +++ b/catapult/dashboard/dashboard/templates/quick_log_viewer.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block head %} <link rel="import" href="/third_party/polymer/components/polymer/polymer.html"> - <link rel="import" href="/dashboard/elements/quick-log.html"> + <link rel="import" href="/elements/quick-log.html"> <style> #content { diff --git a/catapult/dashboard/dashboard/templates/report.html b/catapult/dashboard/dashboard/templates/report.html index 89bb0ca7..1b7a34d2 100644 --- a/catapult/dashboard/dashboard/templates/report.html +++ b/catapult/dashboard/dashboard/templates/report.html @@ -38,11 +38,11 @@ </script> <link rel="import" href="/third_party/polymer/components/polymer/polymer.html"> - <link rel="import" href="/dashboard/elements/chart-container.html"> - <link rel="import" href="/dashboard/elements/custom-tooltip.html"> - <link rel="import" href="/dashboard/elements/login-warning.html"> - <link rel="import" href="/dashboard/elements/overlay-message.html"> - <link rel="import" href="/dashboard/elements/report-container.html"> + <link rel="import" href="/elements/chart-container.html"> + <link rel="import" href="/elements/custom-tooltip.html"> + <link rel="import" href="/elements/login-warning.html"> + <link rel="import" href="/elements/overlay-message.html"> + <link rel="import" href="/elements/report-container.html"> {% endblock %} {% block content %} diff --git a/catapult/dashboard/dashboard/test_buildbucket.py b/catapult/dashboard/dashboard/test_buildbucket.py index 7288d495..58f9286d 100644 --- a/catapult/dashboard/dashboard/test_buildbucket.py +++ b/catapult/dashboard/dashboard/test_buildbucket.py @@ -24,7 +24,7 @@ class TestBuildbucketHandler(request_handler.RequestHandler): })) return job = buildbucket_job.BisectJob( - self.request.get('platform'), + 'linux_perf_bisector', self.request.get('good_revision'), self.request.get('bad_revision'), self.request.get('command'), @@ -34,6 +34,7 @@ class TestBuildbucketHandler(request_handler.RequestHandler): self.request.get('max_time_minutes'), self.request.get('bug_id'), self.request.get('gs_bucket'), + self.request.get('recipe_tester_name'), self.request.get('builder_host'), self.request.get('builder_port')) diff --git a/catapult/dashboard/dashboard/test_owner_test.py b/catapult/dashboard/dashboard/test_owner_test.py index 81c4467e..36df6e23 100644 --- a/catapult/dashboard/dashboard/test_owner_test.py +++ b/catapult/dashboard/dashboard/test_owner_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for test_owner module.""" - import unittest from dashboard import layered_cache diff --git a/catapult/dashboard/dashboard/ttest_test.py b/catapult/dashboard/dashboard/ttest_test.py index ef02f0f3..bcabf9ce 100644 --- a/catapult/dashboard/dashboard/ttest_test.py +++ b/catapult/dashboard/dashboard/ttest_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for ttest module.""" - import unittest import mock diff --git a/catapult/dashboard/dashboard/units_to_direction_test.py b/catapult/dashboard/dashboard/units_to_direction_test.py index c61a18c7..d3e8f91b 100644 --- a/catapult/dashboard/dashboard/units_to_direction_test.py +++ b/catapult/dashboard/dashboard/units_to_direction_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for units_to_direction module.""" - import unittest from dashboard import testing_common diff --git a/catapult/dashboard/dashboard/update_bug_with_results_test.py b/catapult/dashboard/dashboard/update_bug_with_results_test.py index 44cd4958..a11efee8 100644 --- a/catapult/dashboard/dashboard/update_bug_with_results_test.py +++ b/catapult/dashboard/dashboard/update_bug_with_results_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for update_bug_with_results module.""" - import json import unittest diff --git a/catapult/dashboard/dashboard/update_test_metadata_test.py b/catapult/dashboard/dashboard/update_test_metadata_test.py index 1958bc2e..4bcb22cd 100644 --- a/catapult/dashboard/dashboard/update_test_metadata_test.py +++ b/catapult/dashboard/dashboard/update_test_metadata_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for update_test_metadata module.""" - import base64 import json import unittest diff --git a/catapult/dashboard/dashboard/update_test_suites_test.py b/catapult/dashboard/dashboard/update_test_suites_test.py index 0eda74cd..084ade2f 100644 --- a/catapult/dashboard/dashboard/update_test_suites_test.py +++ b/catapult/dashboard/dashboard/update_test_suites_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for update_test_suites module.""" - import unittest import webapp2 diff --git a/catapult/dashboard/dashboard/utils_test.py b/catapult/dashboard/dashboard/utils_test.py index ba42b7b4..e76b9810 100644 --- a/catapult/dashboard/dashboard/utils_test.py +++ b/catapult/dashboard/dashboard/utils_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for utils module.""" - import unittest from google.appengine.ext import ndb @@ -102,20 +100,17 @@ class UtilsTest(testing_common.TestCase): ] return keys - def testGetMulti_NotLoggedIn_OnlySome(self): - """Tests that GetMulti gets some of the entities when not logged in.""" + def testGetMulti_NotLoggedIn_ReturnsSomeEntities(self): keys = self._PutEntitiesHalfInternal() self.SetCurrentUser('x@hotmail.com') self.assertEqual(len(keys) / 2, len(utils.GetMulti(keys))) - def testGetMulti_LoggedIn(self): - """Tests that GetMulti gets all of the entities when logged in.""" + def testGetMulti_LoggedIn_ReturnsAllEntities(self): keys = self._PutEntitiesHalfInternal() self.SetCurrentUser('x@google.com') self.assertEqual(len(keys), len(utils.GetMulti(keys))) - def testGetMulti_AllExternal(self): - """Tests that GetMulti gets all of the entities when logged in.""" + def testGetMulti_AllExternal_ReturnsAllEntities(self): keys = self._PutEntitiesAllExternal() self.SetCurrentUser('x@hotmail.com') self.assertEqual(len(keys), len(utils.GetMulti(keys))) diff --git a/catapult/dashboard/dashboard/xsrf_test.py b/catapult/dashboard/dashboard/xsrf_test.py index 24537e2b..48731e37 100644 --- a/catapult/dashboard/dashboard/xsrf_test.py +++ b/catapult/dashboard/dashboard/xsrf_test.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for xsrf module.""" - import unittest import webapp2 diff --git a/catapult/dashboard/deploy.py b/catapult/dashboard/deploy.py deleted file mode 100755 index 6c5dffd7..00000000 --- a/catapult/dashboard/deploy.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/python -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# This script uploads a version of the dashboard by creating a temp -# directory and making symlinks in it, then invoking appcfg.py. - -# TODO(qyearsley): Add a step to vulcanize each template HTML file. -# TODO(qyearsley): Add a step to put static files in a versioned -# directory and modify app.yaml and request_handler as needed. - -import appcfg -import argparse -import os -import subprocess -import tempfile - - -def _AppcfgUpdate(app_yaml_dir, appid='chromeperf'): - subprocess.call([ - appcfg.__file__, - '--application=%s' % appid, - '--version=%s' % _VersionName(), - 'update', - app_yaml_dir, - ]) - - -def _MakeDeploymentDir(): - dashboard = os.path.abspath(os.path.dirname(__file__)) - catapult_third_party = os.path.abspath( - os.path.join(dashboard, os.path.pardir, 'third_party')) - deployment_dir = tempfile.mkdtemp(prefix='deploy-') - for name in os.listdir(dashboard): - os.symlink( - os.path.join(dashboard, name), - os.path.join(deployment_dir, name)) - os.symlink( - catapult_third_party, - os.path.join(deployment_dir, 'third_party')) - return deployment_dir - - -def _Cleanup(deployment_dir): - for symlink_name in os.listdir(deployment_dir): - link_path = os.path.join(deployment_dir, symlink_name) - if os.path.islink(link_path): - os.unlink(link_path) - os.rmdir(deployment_dir) - - -def _VersionName(): - is_synced = not _Run(['git', 'diff', 'master']).strip() - deployment_type = 'clean' if is_synced else 'dev' - email = _Run(['git', 'config', '--get', 'user.email']) - username = email[0:email.find('@')] - commit_hash = _Run(['git', 'rev-parse', '--short=8', 'HEAD']).strip() - return '%s-%s-%s' % (deployment_type, username, commit_hash) - - -def _Run(command): - proc = subprocess.Popen(command, stdout=subprocess.PIPE) - output, _ = proc.communicate() - return output - - -def Main(): - parser = argparse.ArgumentParser(description='Build and deploy dashboard.') - parser.add_argument('--appid', default='chromeperf') - args = parser.parse_args() - try: - deployment_dir = _MakeDeploymentDir() - print 'Deploying from "%s".' % deployment_dir - _AppcfgUpdate(deployment_dir, appid=args.appid) - finally: - _Cleanup(deployment_dir) - - -if __name__ == '__main__': - Main() diff --git a/catapult/perf_insights/app.yaml b/catapult/perf_insights/app.yaml index 443032c1..2be88297 100644 --- a/catapult/perf_insights/app.yaml +++ b/catapult/perf_insights/app.yaml @@ -16,3 +16,7 @@ handlers: - url: /upload script: perf_insights.upload.app secure: always + +env_variables: + # Comment out the next line to use the appengine default bucket. + GCS_BUCKET_NAME: 'performance-insights' diff --git a/catapult/perf_insights/bin/run_dev_server_tests b/catapult/perf_insights/bin/run_dev_server_tests index db6b43b0..f8ff601b 100755 --- a/catapult/perf_insights/bin/run_dev_server_tests +++ b/catapult/perf_insights/bin/run_dev_server_tests @@ -10,5 +10,5 @@ if __name__ == '__main__': catapult_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) sys.path.append(catapult_path) - from build import run_dev_server_tests + from catapult_build import run_dev_server_tests sys.exit(run_dev_server_tests.Main(sys.argv + ['--tests=perf_insights'])) diff --git a/catapult/perf_insights/bin/run_tests b/catapult/perf_insights/bin/run_tests index 4621c8e4..49d80a7e 100755 --- a/catapult/perf_insights/bin/run_tests +++ b/catapult/perf_insights/bin/run_tests @@ -22,5 +22,5 @@ if __name__ == '__main__': catapult_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) sys.path.append(catapult_path) - from build import test_runner + from catapult_build import test_runner sys.exit(test_runner.Main('perf_insights', _TESTS, sys.argv)) diff --git a/catapult/perf_insights/bin/wr b/catapult/perf_insights/bin/wr index d9c66c49..922e95a2 100755 --- a/catapult/perf_insights/bin/wr +++ b/catapult/perf_insights/bin/wr @@ -12,7 +12,7 @@ if __name__ == '__main__': sys.path.append(perf_insights_path) pi_report_file = os.path.join(perf_insights_path, - 'perf_insights/ui/wr/weather_report.html') + 'perf_insights/ui/reports/weather_report.html') from perf_insights_build import pi_report_to_html sys.exit(pi_report_to_html.Main(sys.argv, diff --git a/catapult/perf_insights/perf_insights/map_runner.py b/catapult/perf_insights/perf_insights/map_runner.py index af2dafe0..e349e5d0 100644 --- a/catapult/perf_insights/perf_insights/map_runner.py +++ b/catapult/perf_insights/perf_insights/map_runner.py @@ -18,33 +18,34 @@ AUTO_JOB_COUNT = 'auto-job-count' class MapRunner: def __init__(self, trace_handles, map_function_handle, - stop_on_error=False): + stop_on_error=False, progress_reporter=None): self._map_function_handle = map_function_handle self._work_queue = queue.Queue() self._result_queue = queue.Queue() self._stop_on_error = stop_on_error self._abort = False self._failed_run_info_to_dump = None - self._progress_reporter = gtest_progress_reporter.GTestProgressReporter( - sys.stdout) + if progress_reporter is None: + self._progress_reporter = gtest_progress_reporter.GTestProgressReporter( + sys.stdout) + else: + self._progress_reporter = progress_reporter for trace_handle in trace_handles: self._work_queue.put(trace_handle) def _ProcessTrace(self, trace_handle): run_info = trace_handle.run_info subresults = results_module.Results() - # TODO: Modify ProgressReporter API to deal with interleaving runs so - # that we can use self._progress_reporter here. - progress_reporter = gtest_progress_reporter.GTestProgressReporter( - sys.stdout) - progress_reporter.WillRun(run_info) + run_reporter = self._progress_reporter.WillRun(run_info) map_single_trace.MapSingleTrace( subresults, trace_handle, self._map_function_handle) + for v in subresults.all_values: + run_reporter.DidAddValue(v) self._result_queue.put(subresults) had_failure = subresults.DoesRunContainFailure(run_info) - progress_reporter.DidRun(run_info, had_failure) + run_reporter.DidRun(had_failure) if self._stop_on_error and had_failure: self._failed_run_info_to_dump = run_info self._abort = True diff --git a/catapult/perf_insights/perf_insights/map_single_trace.html b/catapult/perf_insights/perf_insights/map_single_trace.html index 6dd30fa6..fa8dc068 100644 --- a/catapult/perf_insights/perf_insights/map_single_trace.html +++ b/catapult/perf_insights/perf_insights/map_single_trace.html @@ -21,19 +21,19 @@ tr.exportTo('pi', function() { var FailureValue = pi.v.FailureValue; - function runAndConvertErrorsToFailureValues(results, run_info, cb, opt_this) { + function runAndConvertErrorsToFailureValues(results, runInfo, cb, opt_this) { try { cb.call(opt_this); } catch (err) { var err = tr.b.normalizeException(err); results.addValue(new FailureValue( - run_info, err.typeName, + runInfo, err.typeName, {description: err.message, stack: err.stack})); } } - function mapSingleTrace(results, run_info, traceData, mapFunction, + function mapSingleTrace(results, runInfo, traceData, mapFunction, opt_metadata) { // Load the model. var model = new tr.Model(); @@ -61,15 +61,15 @@ tr.exportTo('pi', function() { } // Map the function. - var numResultsBeforeMapping = results.all_values.length; + var numResultsBeforeMapping = results.allValues.length; try { - mapFunction(results, run_info, model); + mapFunction(results, runInfo, model); } catch (ex) { ex.name = 'MapFunctionError'; throw ex; } - if (results.all_values.length === numResultsBeforeMapping) { + if (results.allValues.length === numResultsBeforeMapping) { var err = new Error('Mapper did not add any results! ' + 'Add a SkipValue if this was intentional.'); err.name = 'NoResultsAddedError'; diff --git a/catapult/perf_insights/perf_insights/map_single_trace_cmdline.html b/catapult/perf_insights/perf_insights/map_single_trace_cmdline.html index 82e44515..5776c350 100644 --- a/catapult/perf_insights/perf_insights/map_single_trace_cmdline.html +++ b/catapult/perf_insights/perf_insights/map_single_trace_cmdline.html @@ -20,11 +20,11 @@ tr.exportTo('pi', function() { return loadMapFunctionFromFileName(mapFunctionHandle.mapFunctionFileName); // Find the mapper by name. - loadHTML('/perf_insights/perf_insights_full_config.html') + loadHTML('/perf_insights/perf_insights_full_config.html'); var typeInfo = pi.MapFunction.findTypeInfoMatching(function(typeInfo) { return typeInfo.constructor.name === mapFunctionHandle.mapFunctionName; - }) - if (typeInfo === undefined) { + }); + if (typeInfo === undefined) { var err = new Error( 'No mapper registered in perf_insights_full_config named ' + mapFunctionHandle.mapFunctionName); @@ -49,7 +49,8 @@ tr.exportTo('pi', function() { // Verify a mapFunction was defined. var numTypeInfosNow = allTypeInfos.length; if (numTypeInfosNow !== (numTypeInfosBefore + 1)) { - var err = new Error(mapFunctionFileName + ' did not call defineMapFunction'); + var err = new Error(mapFunctionFileName + + ' did not call defineMapFunction'); err.name = 'MapFunctionNotDefinedError'; throw err; } @@ -64,20 +65,20 @@ tr.exportTo('pi', function() { throw new Error('Must provide four arguments'); var options = { - run_info: pi.v.RunInfo.fromDict(JSON.parse(args[0])), + runInfo: pi.v.RunInfo.fromDict(JSON.parse(args[0])), mapFunctionHandle: JSON.parse(args[1]), filenameToMap: args[2], metadata: JSON.parse(args[3]) }; var results = new pi.r.Results(); - results.willRun(options.run_info); + results.willRun(options.runInfo); pi.runAndConvertErrorsToFailureValues( - results, options.run_info, + results, options.runInfo, function() { var mapFunction = getMapFunctionFromMapFunctionHandle( - options.mapFunctionHandle) + options.mapFunctionHandle); // Read the mapfile. try { @@ -88,14 +89,14 @@ tr.exportTo('pi', function() { throw err; } - pi.mapSingleTrace(results, options.run_info, traceData, + pi.mapSingleTrace(results, options.runInfo, traceData, mapFunction, options.metadata); }); - results.didRun(options.run_info); + results.didRun(options.runInfo); results.didFinishAllRuns(); - results.all_values.forEach(function(value) { + results.allValues.forEach(function(value) { valueAsDict = value.asDict(); console.log('MAP_RESULT_VALUE: ' + JSON.stringify(valueAsDict)); }); diff --git a/catapult/perf_insights/perf_insights/wr/__init__.py b/catapult/perf_insights/perf_insights/mappers/__init__.py index 047b03ca..047b03ca 100644 --- a/catapult/perf_insights/perf_insights/wr/__init__.py +++ b/catapult/perf_insights/perf_insights/mappers/__init__.py diff --git a/catapult/perf_insights/perf_insights/mappers/all_mappers.html b/catapult/perf_insights/perf_insights/mappers/all_mappers.html new file mode 100644 index 00000000..2a7991ff --- /dev/null +++ b/catapult/perf_insights/perf_insights/mappers/all_mappers.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<!-- +Copyright (c) 2013 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" + href="/perf_insights/mappers/weather_report_map_function.html"> +<link rel="import" href="/perf_insights/mappers/task_info_map_function.html"> diff --git a/catapult/perf_insights/perf_insights/wr/reduce.html b/catapult/perf_insights/perf_insights/mappers/reduce.html index 4c306c49..4c306c49 100644 --- a/catapult/perf_insights/perf_insights/wr/reduce.html +++ b/catapult/perf_insights/perf_insights/mappers/reduce.html diff --git a/catapult/perf_insights/perf_insights/wr/slice_cost.html b/catapult/perf_insights/perf_insights/mappers/slice_cost.html index 7ceb0224..2b0f1a17 100644 --- a/catapult/perf_insights/perf_insights/wr/slice_cost.html +++ b/catapult/perf_insights/perf_insights/mappers/slice_cost.html @@ -4,7 +4,7 @@ Copyright (c) 2015 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/perf_insights/wr/reduce.html"> +<link rel="import" href="/perf_insights/mappers/reduce.html"> <script> 'use strict'; @@ -56,7 +56,7 @@ tr.exportTo('pi.wr', function() { function getSliceCostReport(model, threadGrouping, railTypeNameByGUID) { var reduce = new pi.wr.StreamingReducer(SliceCostInfo.asReduceTarget); - + function generateDomainCosts(slice) { // V8.Execute events may generate several sliceCostInfo, based on the // origin of the JS being executed. diff --git a/catapult/perf_insights/perf_insights/mappers/task_info_map_function.html b/catapult/perf_insights/perf_insights/mappers/task_info_map_function.html new file mode 100644 index 00000000..f706edcb --- /dev/null +++ b/catapult/perf_insights/perf_insights/mappers/task_info_map_function.html @@ -0,0 +1,115 @@ +<!DOCTYPE HTML> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/perf_insights/map_function.html"> +<link rel="import" href="/perf_insights/value/value.html"> +<link rel="import" href="/tracing/base/units/histogram.html"> +<link rel="import" href="/tracing/model/flow_event.html"> +<link rel="import" href="/tracing/model/slice.html"> + +<script> +tr.exportTo('pie', function() { + // Granularity of the histogram. + var HISTOGRAM_MAX = 250; + var NUM_BINS = 50; + + function taskInfoMapFunction(results, run_info, model) { + addTimeInQueue(results, run_info, model); + addTopLevelTasksDuration(results, run_info, model); + } + + function eatTrailingDigits(str) { + return str && str.replace(/[\d/]*$/, ''); + } + + function histogramsToDict(dict) { + for (var process in dict) { + for (var thread in dict[process]) { + dict[process][thread] = dict[process][thread].asDict(); + } + } + } + + function addTimeInQueue(results, run_info, model) { + var timeInQueue = {}; + model.flowEvents.forEach(function(flowEvent) { + if (!flowEvent.endSlice instanceof tr.model.Slice) + return; + var thread = flowEvent.endSlice && flowEvent.endSlice.parentContainer; + if (!thread) + return; + var process = thread.getProcess(); + if (!process) + return; + var threadName = eatTrailingDigits(thread.name) || 'Unknown'; + var processName = eatTrailingDigits(process.name) || 'Unknown'; + addToHistogram(timeInQueue, processName, threadName, flowEvent.duration); + }); + histogramsToDict(timeInQueue); + results.addValue(new pi.v.DictValue( + run_info, + 'time_spent_in_queue', + timeInQueue)); + } + + function addTopLevelTasksDuration(results, run_info, model) { + var timeInTask = {}; + var cpuTimeInTask = {}; + model.getAllThreads().forEach(function(thread) { + var process = thread.getProcess(); + if (!process) + return; + var threadName = eatTrailingDigits(thread.name) || thread.tid; + var processName = eatTrailingDigits(process.name) || process.pid; + if (!thread.sliceGroup.length) + return; + thread.sliceGroup.slices.forEach(function(slice) { + if (!isTopLevelTask(slice)) + return; + addToHistogram(timeInTask, processName, threadName, slice.duration); + addToHistogram(cpuTimeInTask, processName, threadName, + slice.cpuDuration); + }); + }); + histogramsToDict(timeInTask); + results.addValue(new pi.v.DictValue( + run_info, + 'time_spent_in_top_level_task', + timeInTask)); + histogramsToDict(cpuTimeInTask); + results.addValue(new pi.v.DictValue( + run_info, + 'cpu_time_spent_in_top_level_task', + cpuTimeInTask)); + } + + // A slice is top level if it's on the receiving end of a post task and no + // slice above it is. + function isTopLevelTask(slice) { + if (!slice.inFlowEvents.length) + return false; + return !slice.parentSlice || !isTopLevelTask(slice.parentSlice); + } + + function addToHistogram(dict, processName, threadName, value) { + dict[processName] = dict[processName] || {}; + dict[processName][threadName] = dict[processName][threadName] || + tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, HISTOGRAM_MAX), + NUM_BINS); + dict[processName][threadName].add(value); + } + + pi.MapFunction.register(taskInfoMapFunction); + + // Exporting for tests. + return { + taskInfoMapFunctionForTest: taskInfoMapFunction + }; +}); +</script> diff --git a/catapult/perf_insights/perf_insights/mappers/task_info_map_function_test.html b/catapult/perf_insights/perf_insights/mappers/task_info_map_function_test.html new file mode 100644 index 00000000..ff7b1348 --- /dev/null +++ b/catapult/perf_insights/perf_insights/mappers/task_info_map_function_test.html @@ -0,0 +1,77 @@ +<!DOCTYPE html> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/perf_insights/value/value.html"> +<link rel="import" href="/perf_insights/value/run_info.html"> +<link rel="import" href="/perf_insights/results/results.html"> +<link rel="import" href="/perf_insights/mappers/task_info_map_function.html"> +<link rel="import" href="/tracing/base/units/histogram.html"> +<link rel="import" href="/tracing/core/test_utils.html"> + +<script> +'use strict'; + +tr.b.unittest.testSuite(function() { + var test_utils = tr.c.TestUtils; + + test('taskInfoMapFunctionTest', function() { + var m = test_utils.newModel(function(m) { + var p1 = m.getOrCreateProcess(1); + p1.name = 'Process'; + var t2 = p1.getOrCreateThread(2); + t2.name = 'Thread'; + // t2_s0 is not a top-level, no incoming flow. + var t2_s0 = test_utils.newSliceEx( + { start: 0, duration: 9.7, cpuStart: 0, cpuDuration: 5.3}); + // t2_s1 is not a top-level, no incoming flow. + var t2_s1 = test_utils.newSliceEx( + { start: 11, duration: 20.1, cpuStart: 11, cpuDuration: 8.9 }); + // t2_s2 is a top-level slice: f2 flows into it. + var t2_s2 = test_utils.newSliceEx( + { start: 15, duration: 10.4, cpuStart: 15, cpuDuration: 3.0 }); + // t2_s3 is not a top-level slice because it's a child of t2_s2. + var t2_s3 = test_utils.newSliceEx( + { start: 17, duration: 2.4, cpuStart: 17, cpuDuration: 1.1 }); + t2.sliceGroup.pushSlice(t2_s0); + t2.sliceGroup.pushSlice(t2_s1); + t2.sliceGroup.pushSlice(t2_s2); + t2.sliceGroup.pushSlice(t2_s3); + var f1 = test_utils.newFlowEventEx({ + start: 0, duration: 18.1, startSlice: t2_s0, endSlice: t2_s3 + }); + var f2 = test_utils.newFlowEventEx({ + start: 9, duration: 7.2, startSlice: t2_s0, endSlice: t2_s2 + }); + m.flowEvents.push(f1); + m.flowEvents.push(f2); + }); + + var results = new pi.r.Results(); + var runInfo = new pi.v.RunInfo('my_test.json'); + pie.taskInfoMapFunctionForTest(results, runInfo, m); + + assert.equal(results.allValues.length, 3); + var value = results.allValues[0]; + assert.equal(value.name, 'time_spent_in_queue'); + assert.equal(Object.keys(value.value['Process']).length, 1); + var histogram = tr.b.u.Histogram.fromDict(value.value['Process']['Thread']); + assert.equal(histogram.getBinForValue(7.2).count, 1); + assert.equal(histogram.getBinForValue(18.1).count, 1); + value = results.allValues[1]; + assert.equal(value.name, 'time_spent_in_top_level_task'); + assert.equal(Object.keys(value.value['Process']).length, 1); + histogram = tr.b.u.Histogram.fromDict(value.value['Process']['Thread']); + assert.equal(histogram.getBinForValue(10.4).count, 1); + value = results.allValues[2]; + assert.equal(value.name, 'cpu_time_spent_in_top_level_task'); + assert.equal(Object.keys(value.value['Process']).length, 1); + histogram = tr.b.u.Histogram.fromDict(value.value['Process']['Thread']); + assert.equal(histogram.getBinForValue(3.0).count, 1); + }); +}); + +</script> diff --git a/catapult/perf_insights/perf_insights/wr/thread_grouping.html b/catapult/perf_insights/perf_insights/mappers/thread_grouping.html index 3d76038f..3d76038f 100644 --- a/catapult/perf_insights/perf_insights/wr/thread_grouping.html +++ b/catapult/perf_insights/perf_insights/mappers/thread_grouping.html diff --git a/catapult/perf_insights/perf_insights/wr/thread_grouping_test.html b/catapult/perf_insights/perf_insights/mappers/thread_grouping_test.html index 8fc7e4be..731f5197 100644 --- a/catapult/perf_insights/perf_insights/wr/thread_grouping_test.html +++ b/catapult/perf_insights/perf_insights/mappers/thread_grouping_test.html @@ -8,7 +8,7 @@ found in the LICENSE file. <link rel="import" href="/perf_insights/value/value.html"> <link rel="import" href="/perf_insights/value/run_info.html"> <link rel="import" href="/perf_insights/results/results.html"> -<link rel="import" href="/perf_insights/wr/weather_report_map_function.html"> +<link rel="import" href="/perf_insights/mappers/weather_report_map_function.html"> <link rel="import" href="/tracing/core/test_utils.html"> <link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html"> @@ -16,9 +16,9 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('basicChrome', function() { - var m = tr.e.audits.newChromeModel(function(m) { + var m = tr.e.chrome.ChromeTestUtils.newChromeModel(function(m) { // Browser. m.browserMain.sliceGroup.pushSlice(test_utils.newSliceEx({ name: 'BrowserSlice', diff --git a/catapult/perf_insights/perf_insights/wr/weather_report_map_function.html b/catapult/perf_insights/perf_insights/mappers/weather_report_map_function.html index 681176b2..f1017fdd 100644 --- a/catapult/perf_insights/perf_insights/wr/weather_report_map_function.html +++ b/catapult/perf_insights/perf_insights/mappers/weather_report_map_function.html @@ -6,35 +6,38 @@ found in the LICENSE file. --> <link rel="import" href="/perf_insights/map_function.html"> <link rel="import" href="/perf_insights/value/value.html"> -<link rel="import" href="/perf_insights/wr/slice_cost.html"> -<link rel="import" href="/perf_insights/wr/thread_grouping.html"> +<link rel="import" href="/perf_insights/mappers/slice_cost.html"> +<link rel="import" href="/perf_insights/mappers/thread_grouping.html"> <link rel="import" href="/tracing/base/iteration_helpers.html"> <link rel="import" href="/tracing/extras/chrome/chrome_model_helper.html"> <link rel="import" href="/tracing/extras/rail/rail_interaction_record.html"> +<link rel="import" href="/tracing/extras/rail/rail_score.html"> <link rel="import" href="/tracing/model/ir_coverage.html"> <script> tr.exportTo('pi.wr', function() { function getWeatherReportFromModel(model) { - var railTypeNameByGUID = getRAILTypeNameForEventsByGUID(model); + var railIRs = model.interactionRecords.filter(function(ir) { + return ir instanceof tr.e.rail.RAILInteractionRecord; + }); + + var railTypeNameByGUID = getRAILTypeNameForEventsByGUID(model, railIRs); var threadGrouping = new pi.wr.ThreadGrouping(); threadGrouping.autoInitUsingHelpers(model); + var railScore = new tr.e.rail.RAILScore(railIRs); var wr = { - ir_coverage: tr.model.getIRCoverageFromModel(model), + railScore: railScore.asDict(), + irCoverage: tr.model.getIRCoverageFromModel(model), sliceCosts: pi.wr.getSliceCostReport(model, threadGrouping, railTypeNameByGUID) }; return wr; } - function getRAILTypeNameForEventsByGUID(model) { - var railIRs = model.interactionRecords.filter(function(ir) { - return ir instanceof tr.e.rail.RAILInteractionRecord; - }); - + function getRAILTypeNameForEventsByGUID(model, railIRs) { var railTypeNameByGUID = {}; railIRs.forEach(function applyAssociatedToRTN(ir) { ir.associatedEvents.forEach(function applyEventToRTN(event) { @@ -54,10 +57,9 @@ tr.exportTo('pi.wr', function() { } - function weatherReportMapFunction(results, run_info, model) { + function weatherReportMapFunction(results, runInfo, model) { var wr = pi.wr.getWeatherReportFromModel(model); - results.addValue(new pi.v.DictValue( - run_info, 'wr', pi.wr.getWeatherReportFromModel(model))); + results.addValue(new pi.v.DictValue(runInfo, 'wr', wr)); } pi.MapFunction.register(weatherReportMapFunction); @@ -67,4 +69,4 @@ tr.exportTo('pi.wr', function() { }; }); -</script>
\ No newline at end of file +</script> diff --git a/catapult/perf_insights/perf_insights/wr/weather_report_map_function_test.html b/catapult/perf_insights/perf_insights/mappers/weather_report_map_function_test.html index e8fee75f..e9091c99 100644 --- a/catapult/perf_insights/perf_insights/wr/weather_report_map_function_test.html +++ b/catapult/perf_insights/perf_insights/mappers/weather_report_map_function_test.html @@ -8,7 +8,7 @@ found in the LICENSE file. <link rel="import" href="/perf_insights/results/results.html"> <link rel="import" href="/perf_insights/value/run_info.html"> <link rel="import" href="/perf_insights/value/value.html"> -<link rel="import" href="/perf_insights/wr/weather_report_map_function.html"> +<link rel="import" href="/perf_insights/mappers/weather_report_map_function.html"> <link rel="import" href="/tracing/core/test_utils.html"> <link rel="import" href="/tracing/extras/rail/idle_interaction_record.html"> @@ -16,7 +16,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; var ThreadSlice = tr.model.ThreadSlice; test('basicModelTest', function() { @@ -30,11 +30,11 @@ tr.b.unittest.testSuite(function() { }); var results = new pi.r.Results(); - var run_info = new pi.v.RunInfo('my_test.json'); - pi.wr.weatherReportMapFunction(results, run_info, m); + var runInfo = new pi.v.RunInfo('my_test.json'); + pi.wr.weatherReportMapFunction(results, runInfo, m); - assert.equal(results.all_values.length, 1); - assert.isTrue(results.all_values[0] instanceof pi.v.DictValue); + assert.equal(results.allValues.length, 1); + assert.isTrue(results.allValues[0] instanceof pi.v.DictValue); }); test('basicWrTest', function() { diff --git a/catapult/perf_insights/perf_insights/perf_insights_full_config.html b/catapult/perf_insights/perf_insights/perf_insights_full_config.html index b9542685..66a42741 100644 --- a/catapult/perf_insights/perf_insights/perf_insights_full_config.html +++ b/catapult/perf_insights/perf_insights/perf_insights_full_config.html @@ -5,6 +5,4 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> <link rel="import" href="/perf_insights/perf_insights_full_config.html"> - -<!-- Optional but useful perf_insights cmdline bits are listed here. --> -<link rel="import" href="/perf_insights/wr/weather_report_map_function.html"> +<link rel="import" href="/perf_insights/mappers/all_mappers.html"> diff --git a/catapult/perf_insights/perf_insights/progress_reporter.py b/catapult/perf_insights/perf_insights/progress_reporter.py index b68901ba..b13270e3 100644 --- a/catapult/perf_insights/perf_insights/progress_reporter.py +++ b/catapult/perf_insights/perf_insights/progress_reporter.py @@ -2,17 +2,22 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# Derived from telemetry ProgressReporter. Should stay close in architecture -# to telemetry ProgressReporter. -class ProgressReporter(object): - def WillRun(self, run_info): - pass +class RunReporter(object): + def __init__(self, run_info): + self.run_info = run_info def DidAddValue(self, value): pass - def DidRun(self, run_info, run_failed): + def DidRun(self, run_failed): pass + +# Derived from telemetry ProgressReporter. Should stay close in architecture +# to telemetry ProgressReporter. +class ProgressReporter(object): + def WillRun(self, run_info): + return RunReporter(run_info) + def DidFinishAllRuns(self, results): pass
\ No newline at end of file diff --git a/catapult/perf_insights/perf_insights/results/gtest_progress_reporter.py b/catapult/perf_insights/perf_insights/results/gtest_progress_reporter.py index c0f91739..3c728e32 100644 --- a/catapult/perf_insights/perf_insights/results/gtest_progress_reporter.py +++ b/catapult/perf_insights/perf_insights/results/gtest_progress_reporter.py @@ -8,6 +8,36 @@ from perf_insights import progress_reporter from perf_insights import value as value_module +class GTestRunReporter(progress_reporter.RunReporter): + def __init__(self, run_info, output_stream, timestamp): + super(GTestRunReporter, self).__init__(run_info) + self._output_stream = output_stream + self._timestamp = timestamp + + def _GetMs(self): + assert self._timestamp is not None, 'Did not call WillRun.' + return (time.time() - self._timestamp) * 1000 + + def DidAddValue(self, value): + super(GTestRunReporter, self).DidAddValue(value) + if isinstance(value, value_module.FailureValue): + print >> self._output_stream, value.GetGTestPrintString() + self._output_stream.flush() + elif isinstance(value, value_module.SkipValue): + print >> self._output_stream, '===== SKIPPING TEST %s: %s =====' % ( + value.run_info.display_name, value.reason) + + def DidRun(self, run_failed): + super(GTestRunReporter, self).DidRun(run_failed) + if run_failed: + print >> self._output_stream, '[ FAILED ] %s (%0.f ms)' % ( + self.run_info.display_name, self._GetMs()) + else: + print >> self._output_stream, '[ OK ] %s (%0.f ms)' % ( + self.run_info.display_name, self._GetMs()) + self._output_stream.flush() + + class GTestProgressReporter(progress_reporter.ProgressReporter): """A progress reporter that outputs the progress report in gtest style. @@ -22,38 +52,14 @@ class GTestProgressReporter(progress_reporter.ProgressReporter): def __init__(self, output_stream, output_skipped_tests_summary=False): super(GTestProgressReporter, self).__init__() self._output_stream = output_stream - self._timestamp = None self._output_skipped_tests_summary = output_skipped_tests_summary - def _GetMs(self): - assert self._timestamp is not None, 'Did not call WillRun.' - return (time.time() - self._timestamp) * 1000 - def WillRun(self, run_info): super(GTestProgressReporter, self).WillRun(run_info) print >> self._output_stream, '[ RUN ] %s' % ( run_info.display_name) self._output_stream.flush() - self._timestamp = time.time() - - def DidAddValue(self, value): - super(GTestProgressReporter, self).DidAddValue(value) - if isinstance(value, value_module.FailureValue): - print >> self._output_stream, value.GetGTestPrintString() - self._output_stream.flush() - elif isinstance(value, value_module.SkipValue): - print >> self._output_stream, '===== SKIPPING TEST %s: %s =====' % ( - value.run_info.display_name, value.reason) - - def DidRun(self, run_info, run_failed): - super(GTestProgressReporter, self).DidRun(run_info, run_failed) - if run_failed: - print >> self._output_stream, '[ FAILED ] %s (%0.f ms)' % ( - run_info.display_name, self._GetMs()) - else: - print >> self._output_stream, '[ OK ] %s (%0.f ms)' % ( - run_info.display_name, self._GetMs()) - self._output_stream.flush() + return GTestRunReporter(run_info, self._output_stream, time.time()) def DidFinishAllRuns(self, results): super(GTestProgressReporter, self).DidFinishAllRuns(results) diff --git a/catapult/perf_insights/perf_insights/results/progress_reporter.html b/catapult/perf_insights/perf_insights/results/progress_reporter.html index 228fa6ff..ff710c75 100644 --- a/catapult/perf_insights/perf_insights/results/progress_reporter.html +++ b/catapult/perf_insights/perf_insights/results/progress_reporter.html @@ -14,13 +14,13 @@ tr.exportTo('pi.r', function() { } ProgressReporter.prototype = { - willRun: function(run_info) { + willRun: function(runInfo) { }, didAddValue: function(value) { }, - didRun: function(run_info, run_failed) { + didRun: function(runInfo, run_failed) { }, diff --git a/catapult/perf_insights/perf_insights/results/results.html b/catapult/perf_insights/perf_insights/results/results.html index 29344081..98515103 100644 --- a/catapult/perf_insights/perf_insights/results/results.html +++ b/catapult/perf_insights/perf_insights/results/results.html @@ -12,17 +12,17 @@ found in the LICENSE file. tr.exportTo('pi.r', function() { function Results() { - this.all_values = []; - this._run_ids_that_have_failures = {}; + this.allValues = []; + this.runIdsThatHaveFailures_ = {}; } Results.fromDict = function(dict) { if (dict.runs === undefined) - throw new Error('Expected: run_info'); + throw new Error('Expected: runInfo'); if (dict.values === undefined) - throw new Error('Expected: run_info'); + throw new Error('Expected: runInfo'); - var runInfosById = tr.b.mapItems(dict.runs, function(run_id, dict) { + var runInfosById = tr.b.mapItems(dict.runs, function(runId, dict) { return pi.v.RunInfo.fromDict(dict); }); @@ -31,7 +31,7 @@ tr.exportTo('pi.r', function() { var runInfo = runInfosById[valueDict.run_id]; if (runInfo === undefined) { debugger; - throw new Error('run_info not found'); + throw new Error('runInfo not found'); } var value = pi.v.Value.fromDict(runInfo, valueDict); results.addValue(value); @@ -40,16 +40,16 @@ tr.exportTo('pi.r', function() { } Results.prototype = { - willRun: function(run_info) { + willRun: function(runInfo) { }, addValue: function(value) { if (value instanceof pi.v.FailureValue) - this._run_ids_that_have_failures[value.run_info.run_id] = true; - this.all_values.push(value); + this.runIdsThatHaveFailures_[value.runInfo.runId] = true; + this.allValues.push(value); }, - didRun: function(run_info) { + didRun: function(runInfo) { }, didFinishAllRuns: function() { @@ -60,7 +60,7 @@ tr.exportTo('pi.r', function() { }, get failureValues() { - return this.all_values.filter(function(x) { + return this.allValues.filter(function(x) { return x instanceof pi.v.FailureValue; }); }, @@ -69,10 +69,10 @@ tr.exportTo('pi.r', function() { var failedRunInfos = []; var hasAddedRunInfo = {}; this.failureValues.forEach(function(v) { - if (hasAddedRunInfo[v.run_info.run_id]) + if (hasAddedRunInfo[v.runInfo.runId]) return; - hasAddedRunInfo[v.run_info.run_id] = true; - failedRunInfos.push(v.run_info); + hasAddedRunInfo[v.runInfo.runId] = true; + failedRunInfos.push(v.runInfo); }); return failedRunInfos; }, @@ -80,30 +80,30 @@ tr.exportTo('pi.r', function() { get allRunInfos() { var allRunInfos = []; var hasAddedRunInfo = {}; - this.all_values.forEach(function(v) { - if (hasAddedRunInfo[v.run_info.run_id]) + this.allValues.forEach(function(v) { + if (hasAddedRunInfo[v.runInfo.runId]) return; - hasAddedRunInfo[v.run_info.run_id] = true; - allRunInfos.push(v.run_info); + hasAddedRunInfo[v.runInfo.runId] = true; + allRunInfos.push(v.runInfo); }); return allRunInfos; }, - doesRunContainFailure: function(run_info) { - return this._run_ids_that_have_failures[run_info.run_id] === true; + doesRunContainFailure: function(runInfo) { + return this.runIdsThatHaveFailures_[runInfo.runId] === true; }, get allValuesFromFailureFreeRuns() { - return this.all_values.filter(function(x) { - if (this.doesRunContainFailure(x.run_info)) + return this.allValues.filter(function(x) { + if (this.doesRunContainFailure(x.runInfo)) return false; return true; }, this); }, - getValuesForRunInfo: function(run_info) { - return this.all_values.filter(function(value) { - return value.run_info === run_info; + getValuesForRunInfo: function(runInfo) { + return this.allValues.filter(function(value) { + return value.runInfo === runInfo; }); }, diff --git a/catapult/perf_insights/perf_insights/results/results_test.html b/catapult/perf_insights/perf_insights/results/results_test.html index a056b34d..e65975d1 100644 --- a/catapult/perf_insights/perf_insights/results/results_test.html +++ b/catapult/perf_insights/perf_insights/results/results_test.html @@ -13,13 +13,13 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('resultsAllSuccessful', function() { - var run_info1 = new pi.v.RunInfo('file1.json'); - var run_info2 = new pi.v.RunInfo('file2.json'); + var runInfo1 = new pi.v.RunInfo('file1.json'); + var runInfo2 = new pi.v.RunInfo('file2.json'); var results = new pi.r.Results(); - results.addValue(new pi.v.DictValue(run_info1, 'res', + results.addValue(new pi.v.DictValue(runInfo1, 'res', {my_key: 'my_value'})); - results.addValue(new pi.v.DictValue(run_info2, 'res', + results.addValue(new pi.v.DictValue(runInfo2, 'res', {my_key: 'my_value'})); assert.isFalse(results.hadFailures); assert.equal(results.allValuesFromFailureFreeRuns.length, 2); @@ -27,17 +27,17 @@ tr.b.unittest.testSuite(function() { }); test('oneFailed', function() { - var run_info1 = new pi.v.RunInfo('file1.json'); - var run_info2 = new pi.v.RunInfo('file2.json'); + var runInfo1 = new pi.v.RunInfo('file1.json'); + var runInfo2 = new pi.v.RunInfo('file2.json'); var results = new pi.r.Results(); - results.addValue(new pi.v.DictValue(run_info1, 'res', + results.addValue(new pi.v.DictValue(runInfo1, 'res', {my_key: 'my_value'})); - results.addValue(new pi.v.FailureValue(run_info2, 'res', + results.addValue(new pi.v.FailureValue(runInfo2, 'res', {description: 'blah', stack: 'stack'})); assert.isTrue(results.hadFailures); - assert.isTrue(results.doesRunContainFailure(run_info2)); + assert.isTrue(results.doesRunContainFailure(runInfo2)); assert.equal(results.allValuesFromFailureFreeRuns.length, 1); assert.equal(results.getValuesFromFailureFreeRunsNamed('res').length, 1); }); diff --git a/catapult/perf_insights/perf_insights/ui/caching_column.html b/catapult/perf_insights/perf_insights/ui/caching_column.html new file mode 100644 index 00000000..f90f6159 --- /dev/null +++ b/catapult/perf_insights/perf_insights/ui/caching_column.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/base/base.html"> + +<script> +'use strict'; + +tr.exportTo('pi.ui', function() { + + // Creates a column which computes a value from all the data contained in a + // row and caches that value. This is useful for a grouping table where a + // grouping row can map to a lot of data. + // |title| is used as the caching key and therefore must be unique amongst + // the table columns. + // The |computeValueFn| property should be set to a function that receives an + // array of data and returns the value for the column. + // You can set other properties of the column, like |width|, |colSpan|, + // |cmp| etc. Do not set |value|, as the class provides it. + function CachingColumn(title, opt_computeValueFn) { + this.title = title; + this.computeValueFn = opt_computeValueFn || function(data) { + return data; + }; + }; + + CachingColumn.prototype = { + value: function(row) { + row.cachedValues_ = row.cachedValues_ || {}; + // Using hasOwnProperty to cache false-ish values like undefined. + if (!row.cachedValues_.hasOwnProperty(this.title)) + row.cachedValues_[this.title] = this.computeValueFn(row.data); + return row.cachedValues_[this.title]; + } + }; + + return { + CachingColumn: CachingColumn + }; +}); + +</script> diff --git a/catapult/perf_insights/perf_insights/ui/caching_column_test.html b/catapult/perf_insights/perf_insights/ui/caching_column_test.html new file mode 100644 index 00000000..b9726a27 --- /dev/null +++ b/catapult/perf_insights/perf_insights/ui/caching_column_test.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/perf_insights/ui/caching_column.html"> +<link rel="import" href="/tracing/core/test_utils.html"> + +<script> +'use strict'; + +tr.b.unittest.testSuite(function() { + var CachingColumn = pi.ui.CachingColumn; + + test('default', function() { + var col = new CachingColumn('Title'); + var row = { + data: [] + }; + + assert.equal(col.title, 'Title'); + assert.deepEqual(col.value(row), []); + }); + + test('multipleColumns', function() { + var colA = new CachingColumn('ColA', function(data) { return data[0].a; }); + var colB = new CachingColumn('ColB', function(data) { return data[0].b; }); + var row = { + data: [{a: 'A', b: 'B'}] + }; + + assert.equal(colA.value(row), 'A'); + assert.equal(colB.value(row), 'B'); + }); + + test('cachesUndefined', function() { + var callCount = 0; + var col = new CachingColumn('Col', function(data) { + callCount++; + return undefined; + }); + var row = { + data: [] + }; + + assert.isUndefined(col.value(row)); + col.value(row); // Value should have been cached. + assert.equal(callCount, 1); + }); +}); +</script> + diff --git a/catapult/perf_insights/perf_insights/ui/generic_results_view.html b/catapult/perf_insights/perf_insights/ui/generic_results_view.html index 5f4d357a..9ba58522 100644 --- a/catapult/perf_insights/perf_insights/ui/generic_results_view.html +++ b/catapult/perf_insights/perf_insights/ui/generic_results_view.html @@ -50,18 +50,18 @@ found in the LICENSE file. results = new tr.r.Results(); var rows = []; - results.allRunInfos.forEach(function(run_info) { - var valuesForRun = results.getValuesForRunInfo(run_info); + results.allRunInfos.forEach(function(runInfo) { + var valuesForRun = results.getValuesForRunInfo(runInfo); - var urlSpan = tr.ui.b.createSpan({textContent: run_info.display_name}); + var urlSpan = tr.ui.b.createSpan({textContent: runInfo.displayName}); var row = { url: urlSpan }; - if (results.doesRunContainFailure(run_info)) { + if (results.doesRunContainFailure(runInfo)) { urlSpan.style.backgroundColor = 'red'; - var failureValuesForRun = results.all_values.filter(function(v) { - if (v.run_info !== run_info) + var failureValuesForRun = results.allValues.filter(function(v) { + if (v.runInfo !== runInfo) return false; if (v instanceof pi.v.FailureValue) return true; @@ -99,6 +99,7 @@ found in the LICENSE file. }); rows.push(row); }); + table.rowHighlightEnabled = true; table.importantColumNames = ['url']; table.items = rows; } diff --git a/catapult/perf_insights/perf_insights/ui/generic_results_view_test.html b/catapult/perf_insights/perf_insights/ui/generic_results_view_test.html index 3ad1b934..87f16b14 100644 --- a/catapult/perf_insights/perf_insights/ui/generic_results_view_test.html +++ b/catapult/perf_insights/perf_insights/ui/generic_results_view_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('basic', function() { var run1 = new pi.v.RunInfo('my_test.json'); var run2 = new pi.v.RunInfo('test2.json'); diff --git a/catapult/perf_insights/perf_insights/ui/grouping_table.html b/catapult/perf_insights/perf_insights/ui/grouping_table.html index 75af313b..5f58ab4d 100644 --- a/catapult/perf_insights/perf_insights/ui/grouping_table.html +++ b/catapult/perf_insights/perf_insights/ui/grouping_table.html @@ -25,7 +25,7 @@ found in the LICENSE file. tr.exportTo('pi.ui', function() { - function Row(title, data, groupingKeyFuncs) { + function Row(title, data, groupingKeyFuncs, compareFunc) { this.title = title; this.data_ = data; if (groupingKeyFuncs === undefined) @@ -93,7 +93,7 @@ tr.exportTo('pi.ui', function() { }, get tableColumns() { - return this.$.tableColumns; + return this.$.table.tableColumns; }, set tableColumns(tableColumns) { @@ -101,7 +101,7 @@ tr.exportTo('pi.ui', function() { }, get sortColumnIndex() { - return this.$.sortColumnIndex; + return this.$.table.sortColumnIndex; }, set sortColumnIndex(sortColumnIndex) { @@ -109,13 +109,53 @@ tr.exportTo('pi.ui', function() { }, get sortDescending() { - return this.$.sortDescending; + return this.$.table.sortDescending; }, set sortDescending(sortDescending) { this.$.table.sortDescending = sortDescending; }, + get rowHighlightEnabled() { + return this.$.table.rowHighlightEnabled; + }, + + set rowHighlightEnabled(rowHighlightEnabled) { + this.$.table.rowHighlightEnabled = rowHighlightEnabled; + }, + + get supportsSelection() { + return this.$.table.supportsSelection; + }, + + set supportsSelection(supportsSelection) { + this.$.table.supportsSelection = supportsSelection; + }, + + get cellSelectionMode() { + return this.$.table.cellSelectionMode; + }, + + set cellSelectionMode(cellSelectionMode) { + this.$.table.cellSelectionMode = cellSelectionMode; + }, + + get selectedColumnIndex() { + return this.$.table.selectedColumnIndex; + }, + + set selectedColumnIndex(selectedColumnIndex) { + this.$.table.selectedColumnIndex = selectedColumnIndex; + }, + + get selectedTableRow() { + return this.$.table.selectedTableRow; + }, + + set selectedTableRow(selectedTableRow) { + this.$.table.selectedTableRow = selectedTableRow; + }, + get groupBy() { return this.groupBy_; }, @@ -141,11 +181,11 @@ tr.exportTo('pi.ui', function() { var dataToGroup = this.dataToGroup_ || []; var superRow = new Row('', dataToGroup, groupBy); - this.$.table.tableRows = superRow.subRows; + this.$.table.tableRows = superRow.subRows || []; } }); return { - } + }; }); </script> diff --git a/catapult/perf_insights/perf_insights/ui/map_function_side_panel.html b/catapult/perf_insights/perf_insights/ui/map_function_side_panel.html index 51fa331f..bbe43f07 100644 --- a/catapult/perf_insights/perf_insights/ui/map_function_side_panel.html +++ b/catapult/perf_insights/perf_insights/ui/map_function_side_panel.html @@ -127,10 +127,10 @@ found in the LICENSE file. mapResultEl.appendChild(gov); var results = new pi.r.Results(); - var run_info = new pi.v.RunInfo(document.location.toString()); + var runInfo = new pi.v.RunInfo(document.location.toString()); try { - this.currentMapFunctionTypeInfo.constructor(results, run_info, + this.currentMapFunctionTypeInfo.constructor(results, runInfo, this.model_); } catch (ex) { ex = tr.b.normalizeException(ex); @@ -138,7 +138,7 @@ found in the LICENSE file. return; } - gov.object = results.all_values.map(function(v) { + gov.object = results.allValues.map(function(v) { return v.asDict(); }); }, diff --git a/catapult/perf_insights/perf_insights/ui/map_function_side_panel_test.html b/catapult/perf_insights/perf_insights/ui/map_function_side_panel_test.html index b8f6d056..8008fec5 100644 --- a/catapult/perf_insights/perf_insights/ui/map_function_side_panel_test.html +++ b/catapult/perf_insights/perf_insights/ui/map_function_side_panel_test.html @@ -8,7 +8,7 @@ found in the LICENSE file. <link rel="import" href="/perf_insights/value/value.html"> <link rel="import" href="/perf_insights/value/run_info.html"> <link rel="import" href="/perf_insights/results/results.html"> -<link rel="import" href="/perf_insights/wr/weather_report_map_function.html"> +<link rel="import" href="/perf_insights/mappers/weather_report_map_function.html"> <link rel="import" href="/tracing/core/test_utils.html"> <link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html"> <link rel="import" href="/perf_insights/ui/map_function_side_panel.html"> @@ -19,9 +19,9 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('basicChrome', function() { - var m = tr.e.audits.newChromeModel(function(m) { + var m = tr.e.chrome.ChromeTestUtils.newChromeModel(function(m) { // Browser. m.browserMain.sliceGroup.pushSlice(test_utils.newSliceEx({ name: 'BrowserSlice', diff --git a/catapult/perf_insights/perf_insights/ui/perf_insights_full_config.html b/catapult/perf_insights/perf_insights/ui/perf_insights_full_config.html index a0ebf3a7..4b8c21b3 100644 --- a/catapult/perf_insights/perf_insights/ui/perf_insights_full_config.html +++ b/catapult/perf_insights/perf_insights/ui/perf_insights_full_config.html @@ -5,6 +5,4 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> <link rel="import" href="/perf_insights/perf_insights_full_config.html"> - -<!-- Optional but useful perf_insights UI bits are listed here. --> -<link rel="import" href="/perf_insights/ui/wr/weather_report.html"> +<link rel="import" href="/perf_insights/ui/reports/all_reports.html"> diff --git a/catapult/perf_insights/perf_insights/ui/pi_app_main.html b/catapult/perf_insights/perf_insights/ui/pi_app_main.html index a9cdd3f2..afdde7ac 100644 --- a/catapult/perf_insights/perf_insights/ui/pi_app_main.html +++ b/catapult/perf_insights/perf_insights/ui/pi_app_main.html @@ -7,7 +7,7 @@ found in the LICENSE file. <link rel="import" href="/tracing/base/xhr.html"> <link rel="import" href="/tracing/ui/base/dom_helpers.html"> <link rel="import" href="/tracing/ui/base/polymer_utils.html"> -<link rel="import" href="/perf_insights/ui/pi_report.html"> +<link rel="import" href="/perf_insights/ui/reports/pi_report.html"> <link rel="import" href="/perf_insights/map_function.html"> <link rel="import" href="/perf_insights/ui/generic_results_view.html"> @@ -111,7 +111,7 @@ tr.exportTo('pi.ui', function() { topLeftControls.appendChild(corpusQuerySelector); var piReportPolymerElementNames = tr.ui.b.getPolymerElementsThatSubclass( - 'pi-ui-pi-report'); + 'pi-ui-r-pi-report'); var piReportElementOptions = piReportPolymerElementNames.map( function(peTagName) { return { diff --git a/catapult/perf_insights/perf_insights/ui/pi_app_main_test.html b/catapult/perf_insights/perf_insights/ui/pi_app_main_test.html index d0a85f8d..e9cd869e 100644 --- a/catapult/perf_insights/perf_insights/ui/pi_app_main_test.html +++ b/catapult/perf_insights/perf_insights/ui/pi_app_main_test.html @@ -16,7 +16,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('instantiate', function() { var app = document.createElement('pi-ui-pi-app-main'); @@ -24,7 +24,7 @@ tr.b.unittest.testSuite(function() { var p = Promise.resolve(); p = p.then(function() { var dataString = tr.b.getSync( - '/perf_insights/ui/wr/wr_result_view_test_data.json'); + '/perf_insights/ui/reports/wr_result_view_test_data.json'); return dataString; }); return p; diff --git a/catapult/perf_insights/perf_insights/ui/reports/all_reports.html b/catapult/perf_insights/perf_insights/ui/reports/all_reports.html new file mode 100644 index 00000000..cfeeeb97 --- /dev/null +++ b/catapult/perf_insights/perf_insights/ui/reports/all_reports.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<!-- +Copyright (c) 2013 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<link rel="import" href="/perf_insights/ui/reports/weather_report.html"> +<link rel="import" href="/perf_insights/ui/reports/slice_cost_report.html"> +<link rel="import" href="/perf_insights/ui/reports/rail_score_report.html"> +<link rel="import" href="/perf_insights/ui/reports/coverage_report.html"> +<link rel="import" href="/perf_insights/ui/reports/task_info_report.html"> diff --git a/catapult/perf_insights/perf_insights/ui/reports/coverage_report.html b/catapult/perf_insights/perf_insights/ui/reports/coverage_report.html new file mode 100644 index 00000000..080c43ff --- /dev/null +++ b/catapult/perf_insights/perf_insights/ui/reports/coverage_report.html @@ -0,0 +1,223 @@ +<!DOCTYPE HTML> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<link rel="import" href="/tracing/ui/base/dom_helpers.html"> +<link rel="import" href="/tracing/ui/base/info_bar_group.html"> +<link rel="import" href="/tracing/ui/base/overlay.html"> +<link rel="import" href="/tracing/ui/base/table.html"> +<link rel="import" href="/tracing/ui/units/time_duration_span.html"> +<link rel="import" href="/perf_insights/results/results.html"> +<link rel="import" href="/perf_insights/ui/reports/pi_report.html"> +<link rel="import" href="/perf_insights/ui/generic_results_view.html"> +<link rel="import" href="/perf_insights/mappers/reduce.html"> +<link rel="import" href="/perf_insights/mappers/slice_cost.html"> + +<polymer-element name="pi-ui-wr-coverage-report" + extends="pi-ui-r-pi-report" + map-function-href="/perf_insights/wr/weather_report_map_function.html" + map-function-name="weatherReportMapFunction"> + <template> + <style> + :host { + display: flex; + flex-direction: column; + } + top-controls { + display: flex; + flex: 0 0 auto; + background-color: rgb(236, 236, 236); + border-bottom: 1px solid #8e8e8e; + padding: 4px; + } + #table { + flex: 1 1 auto; + } + </style> + <top-controls> + </top-controls> + <tr-ui-b-info-bar-group id="infobars"></tr-ui-b-info-bar-group> + <tr-ui-b-table id="table"></tr-ui-b-table> + </template> + <script> + 'use strict'; + + Polymer({ + created: function() { + this.mapResults_ = undefined; + }, + + get mapResults() { + return this.mapResults_; + }, + + set mapResults(mapResults) { + this.mapResults_ = mapResults; + this.updateContents_(); + }, + + updateContents_: function() { + var table = this.$.table; + + var results = this.mapResults_; + if (!results) + results = new tr.r.Results(); + + this.$.infobars.clearMessages(); + this.maybeAddFailuresInfoBarMessage_(results); + + var columns = this.createColumns_(); + table.tableColumns = columns; + table.sortColumnIndex = 2; + table.sortDescending = true; + + var allCoverageInfo = []; + results.allValuesFromFailureFreeRuns.forEach(function(result) { + if (result.name != 'wr') + return; + + // TODO(vmpstr): Why is there no irCoverage here? + if (!result.value.irCoverage) { + allCoverageInfo.push({ + title: result.runInfo.displayName + ' (no coverage)', + coverage: { + associatedEventsCount: 'N/A', + unassociatedEventsCount: 'N/A', + coveredEventsCountRatio: 'N/A', + associatedEventsCpuTimeMs: 'N/A', + unassociatedEventsCpuTimeMs: 'N/A', + coveredEventsCpuTimeRatio: 'N/A' + } + }); + return; + } + allCoverageInfo.push({ + title: result.runInfo.displayName, + coverage: result.value.irCoverage + }); + }); + + table.tableRows = allCoverageInfo; + table.rebuild(); + }, + + maybeAddFailuresInfoBarMessage_: function(results) { + if (!results.hadFailures) + return; + + function onTellMeMore() { + var dlg = new tr.ui.b.Overlay(); + dlg.dlg = 'Results summary'; + + var grv = document.createElement('pi-ui-generic-results-view'); + + grv.mapResults = results; + grv.style.minHeight = '500px'; + dlg.appendChild(grv); + dlg.visible = true; + } + + var numFailedRuns = results.failedRunInfos.length; + this.$.infobars.addMessage( + 'There were ' + numFailedRuns + ' traces that did not process.', + [ + { + buttonText: 'Tell me more...', + onClick: onTellMeMore + } + ]); + }, + + createColumns_: function() { + function formatMs(value) { + var floatValue = parseFloat(value); + if (isNaN(floatValue)) + return 'N/A'; + var span = document.createElement('tr-ui-u-time-duration-span'); + span.duration = floatValue; + return span; + } + + function formatPercent(value) { + var floatValue = parseFloat(value); + if (isNaN(floatValue)) + return 'N/A'; + return tr.b.u.Units.normalizedPercentage.format(floatValue); + } + + function formatCount(value) { + var intValue = parseInt(value); + if (isNaN(intValue)) + return 'N/A'; + return intValue.toLocaleString(); + } + + var columns = [ + { + title: 'Title', + value: function(row) { + return row.title; + }, + width: '400px', + cmp: function(a, b) { + return a.title.localeCompare(b.title); + } + }, + { + title: 'Total event count', + value: function(row) { + return formatCount(row.coverage.associatedEventsCount + + row.coverage.unassociatedEventsCount); + }, + cmp: function(a, b) { + var aTotal = a.coverage.associatedEventsCount + + a.coverage.unassociatedEventsCount; + var bTotal = b.coverage.associatedEventsCount + + b.coverage.unassociatedEventsCount; + return tr.b.compareNumericWithNaNs(aTotal, bTotal); + } + }, + { + title: 'Associated event percentage', + value: function(row) { + return formatPercent(row.coverage.coveredEventsCountRatio); + }, + cmp: function(a, b) { + return tr.b.compareNumericWithNaNs( + a.coverage.coveredEventsCountRatio, + b.coverage.coveredEventsCountRatio); + } + }, + { + title: 'Total event CPU time', + value: function(row) { + return formatMs(row.coverage.associatedEventsCpuTimeMs + + row.coverage.unassociatedEventsCpuTimeMs); + }, + cmp: function(a, b) { + var aTotal = a.coverage.associatedEventsCpuTimeMs + + a.coverage.unassociatedEventsCpuTimeMs; + var bTotal = b.coverage.associatedEventsCpuTimeMs + + b.coverage.unassociatedEventsCpuTimeMs; + return tr.b.compareNumericWithNaNs(aTotal, bTotal); + } + }, + { + title: 'Associated time percentage', + value: function(row) { + return formatPercent(row.coverage.coveredEventsCpuTimeRatio); + }, + cmp: function(a, b) { + return tr.b.compareNumericWithNaNs( + a.coverage.coveredEventsCpuTimeRatio, + b.coverage.coveredEventsCpuTimeRatio); + } + } + ]; + return columns; + } + }); + </script> +</polymer-element> diff --git a/catapult/perf_insights/perf_insights/ui/pi_report.html b/catapult/perf_insights/perf_insights/ui/reports/pi_report.html index 02b394bf..1b4de261 100644 --- a/catapult/perf_insights/perf_insights/ui/pi_report.html +++ b/catapult/perf_insights/perf_insights/ui/reports/pi_report.html @@ -8,10 +8,10 @@ found in the LICENSE file. <link rel="import" href="/tracing/ui/base/table.html"> <link rel="import" href="/tracing/ui/units/time_duration_span.html"> <link rel="import" href="/perf_insights/results/results.html"> -<link rel="import" href="/perf_insights/wr/reduce.html"> -<link rel="import" href="/perf_insights/wr/slice_cost.html"> +<link rel="import" href="/perf_insights/mappers/reduce.html"> +<link rel="import" href="/perf_insights/mappers/slice_cost.html"> -<polymer-element name="pi-ui-pi-report"> +<polymer-element name="pi-ui-r-pi-report"> <script> 'use strict'; diff --git a/catapult/perf_insights/perf_insights/ui/reports/rail_score_report.html b/catapult/perf_insights/perf_insights/ui/reports/rail_score_report.html new file mode 100644 index 00000000..22d97db1 --- /dev/null +++ b/catapult/perf_insights/perf_insights/ui/reports/rail_score_report.html @@ -0,0 +1,80 @@ +<!DOCTYPE HTML> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<link rel="import" href="/tracing/base/units/units.html"> +<link rel="import" href="/tracing/base/units/histogram.html"> +<link rel="import" href="/tracing/ui/base/dom_helpers.html"> +<link rel="import" href="/tracing/ui/base/info_bar_group.html"> +<link rel="import" href="/tracing/ui/base/overlay.html"> +<link rel="import" href="/tracing/ui/units/generic_table_view.html"> +<link rel="import" href="/tracing/ui/units/histogram_span.html"> +<link rel="import" href="/perf_insights/results/results.html"> +<link rel="import" href="/perf_insights/ui/reports/pi_report.html"> +<link rel="import" href="/perf_insights/ui/grouping_table.html"> +<link rel="import" href="/perf_insights/ui/generic_results_view.html"> +<link rel="import" href="/perf_insights/mappers/slice_cost.html"> + +<polymer-element name="pi-ui-r-rail-score-report" + extends="pi-ui-r-pi-report" + map-function-href="/perf_insights/mappers/weather_report_map_function.html" + map-function-name="weatherReportMapFunction"> + <template> + <style> + :host { + display: flex; + flex-direction: column; + } + #histogram { + flex: 1 1 auto; + max-width: 400px; + } + </style> + <tr-ui-u-histogram-span id="histogram"></tr-ui-u-histogram-span> + </template> + <script> + 'use strict'; + + Polymer({ + created: function() { + this.mapResults_ = undefined; + }, + + ready: function() { + }, + + get mapResults() { + return this.mapResults_; + }, + + set mapResults(mapResults) { + this.mapResults_ = mapResults; + this.updateContents_(); + }, + + updateContents_: function() { + var table = this.$.table; + + var results = this.mapResults_; + if (!results) + results = new tr.r.Results(); + + var overallScoreHistogram = tr.b.u.Histogram.createLinear( + tr.b.u.Units.normalizedPercentage, + tr.b.Range.fromExplicitRange(0, 1), + 10); + results.allValuesFromFailureFreeRuns.map(function(v) { + if (!v.value.railScore) + return; + var railScore = v.value.railScore; + overallScoreHistogram.add(railScore.overallScore, + v.runInfo.url); + }); + + this.$.histogram.histogram = overallScoreHistogram; + } + }); + </script> +</polymer-element> diff --git a/catapult/perf_insights/perf_insights/ui/wr/weather_report.html b/catapult/perf_insights/perf_insights/ui/reports/slice_cost_report.html index 0bdbdf58..4cad9b44 100644 --- a/catapult/perf_insights/perf_insights/ui/wr/weather_report.html +++ b/catapult/perf_insights/perf_insights/ui/reports/slice_cost_report.html @@ -9,15 +9,14 @@ found in the LICENSE file. <link rel="import" href="/tracing/ui/base/overlay.html"> <link rel="import" href="/tracing/ui/units/time_duration_span.html"> <link rel="import" href="/perf_insights/results/results.html"> -<link rel="import" href="/perf_insights/ui/pi_report.html"> +<link rel="import" href="/perf_insights/ui/reports/pi_report.html"> <link rel="import" href="/perf_insights/ui/grouping_table.html"> <link rel="import" href="/perf_insights/ui/generic_results_view.html"> -<link rel="import" href="/perf_insights/wr/reduce.html"> -<link rel="import" href="/perf_insights/wr/slice_cost.html"> +<link rel="import" href="/perf_insights/mappers/slice_cost.html"> -<polymer-element name="pi-ui-wr-weather-report" - extends="pi-ui-pi-report" - map-function-href="/perf_insights/wr/weather_report_map_function.html" +<polymer-element name="pi-ui-r-slice-cost-report" + extends="pi-ui-r-pi-report" + map-function-href="/perf_insights/mappers/weather_report_map_function.html" map-function-name="weatherReportMapFunction"> <template> <style> @@ -38,7 +37,6 @@ found in the LICENSE file. </style> <top-controls> </top-controls> - <tr-ui-b-info-bar-group id="infobars"></tr-ui-b-info-bar-group> <pi-ui-grouping-table id="table"></pi-ui-grouping-table> </template> <script> @@ -54,21 +52,21 @@ found in the LICENSE file. this.groupByThreadName_ = tr.ui.b.createCheckBox( undefined, undefined, - 'pi.ui.wr.weather_report.gropuByThreadName', true, + 'pi.ui.wr.weather_report.groupByThreadName', true, 'Group by thread name', this.updateContents_.bind(this)); topControls.appendChild(this.groupByThreadName_); this.groupByRAILTypeName_ = tr.ui.b.createCheckBox( undefined, undefined, - 'pi.ui.wr.weather_report.gropuByRAILTypeName', true, + 'pi.ui.wr.weather_report.groupByRAILTypeName', true, 'Group by RAIL Stage', this.updateContents_.bind(this)); topControls.appendChild(this.groupByRAILTypeName_); this.groupByDomain_ = tr.ui.b.createCheckBox( undefined, undefined, - 'pi.ui.wr.weather_report.gropuByDomain', true, + 'pi.ui.wr.weather_report.groupByDomain', true, 'Group by Domain', this.updateContents_.bind(this)); topControls.appendChild(this.groupByDomain_); @@ -90,9 +88,6 @@ found in the LICENSE file. if (!results) results = new tr.r.Results(); - this.$.infobars.clearMessages(); - this.maybeAddFailuresInfoBarMessage_(results); - var columns = this.createColumns_(); table.tableColumns = columns; table.sortColumnIndex = 2; @@ -139,38 +134,12 @@ found in the LICENSE file. }); } + table.supportsSelection = true; table.groupBy = groupBy; table.dataToGroup = allSliceCosts; table.rebuild(); }, - maybeAddFailuresInfoBarMessage_: function(results) { - if (!results.hadFailures) - return; - - function onTellMeMore() { - var dlg = new tr.ui.b.Overlay(); - dlg.dlg = 'Results summary'; - - var grv = document.createElement('pi-ui-generic-results-view'); - - grv.mapResults = results; - grv.style.minHeight = '500px'; - dlg.appendChild(grv); - dlg.visible = true; - } - - var numFailedRuns = results.failedRunInfos.length; - this.$.infobars.addMessage( - 'There were ' + numFailedRuns + ' traces that did not process.', - [ - { - buttonText: 'Tell me more...', - onClick: onTellMeMore - } - ]); - }, - createColumns_: function() { function compareTimestamps(x, y) { @@ -189,8 +158,8 @@ found in the LICENSE file. row.data, function(sliceCostInfo) { return sliceCostInfo.selfTime; - }), - } + }) + }; row.stats_ = stats; } return row.stats_; diff --git a/catapult/perf_insights/perf_insights/ui/reports/task_info_report.html b/catapult/perf_insights/perf_insights/ui/reports/task_info_report.html new file mode 100644 index 00000000..fafd2323 --- /dev/null +++ b/catapult/perf_insights/perf_insights/ui/reports/task_info_report.html @@ -0,0 +1,235 @@ +<!DOCTYPE HTML> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<link rel="import" href="/tracing/base/iteration_helpers.html"> +<link rel="import" href="/tracing/base/units/histogram.html"> +<link rel="import" href="/tracing/ui/base/dom_helpers.html"> +<link rel="import" href="/tracing/ui/base/info_bar_group.html"> +<link rel="import" href="/tracing/ui/base/overlay.html"> +<link rel="import" href="/tracing/ui/base/table.html"> +<link rel="import" href="/tracing/ui/units/histogram_span.html"> +<link rel="import" href="/tracing/ui/units/time_duration_span.html"> +<link rel="import" href="/perf_insights/results/results.html"> +<link rel="import" href="/perf_insights/ui/reports/pi_report.html"> +<link rel="import" href="/perf_insights/ui/generic_results_view.html"> +<link rel="import" href="/perf_insights/ui/caching_column.html"> +<link rel="import" href="/perf_insights/ui/grouping_table.html"> +<link rel="import" href="/perf_insights/mappers/reduce.html"> +<link rel="import" href="/perf_insights/mappers/slice_cost.html"> + +<polymer-element name="pi-ui-r-task-info-report" + extends="pi-ui-r-pi-report" + map-function-href="/perf_insights/mappers/task_info_map_function.html" + map-function-name="taskInfoMapFunction"> + <template> + <style> + :host { + display: flex; + flex-direction: column; + } + top-controls { + display: flex; + flex: 0 0 auto; + background-color: rgb(236, 236, 236); + border-bottom: 1px solid #8e8e8e; + padding: 4px; + } + #table { + flex: 1 1 auto; + } + </style> + <tr-ui-b-info-bar-group id="infobars"></tr-ui-b-info-bar-group> + <pi-ui-grouping-table id="table"></pi-ui-grouping-table> + <h1>Histogram</h1> + <tr-ui-u-histogram-span id="histogram"></tr-ui-u-histogram-span> + </template> + <script> + 'use strict'; + + Polymer({ + created: function() { + this.mapResults_ = undefined; + }, + + ready: function() { + this.$.table.addEventListener('selection-changed', + function(tableEvent) { + tableEvent.stopPropagation(); + this.setHistogramBasedOnSelection_(); + }.bind(this)); + }, + + get mapResults() { + return this.mapResults_; + }, + + set mapResults(mapResults) { + this.mapResults_ = mapResults; + this.updateContents_(); + }, + + updateContents_: function() { + var table = this.$.table; + + var results = this.mapResults_; + if (!results) + results = new tr.r.Results(); + + this.$.infobars.clearMessages(); + this.maybeAddFailuresInfoBarMessage_(results); + + var columns = this.createColumns_(); + table.tableColumns = columns; + table.sortColumnIndex = 3; + table.sortDescending = true; + + var rows = []; + results.allValuesFromFailureFreeRuns.forEach(function(result) { + for (var process in result.value) { + for (var thread in result.value[process]) { + rows.push({ + process: process, + thread: thread, + type: result.name, + histogram: + tr.b.u.Histogram.fromDict(result.value[process][thread]) + }); + } + } + }); + + var groupBy = []; + groupBy.push(function(datum) { + return datum.process; + }); + groupBy.push(function(datum) { + return datum.thread; + }); + table.supportsSelection = true; + table.groupBy = groupBy; + table.groupBy = groupBy; + table.dataToGroup = rows; + table.supportsSelection = true; + table.cellSelectionMode = true; + table.rowHighlightEnabled = true; + table.rebuild(); + }, + + maybeAddFailuresInfoBarMessage_: function(results) { + if (!results.hadFailures) + return; + + function onTellMeMore() { + var dlg = new tr.ui.b.Overlay(); + dlg.dlg = 'Results summary'; + + var grv = document.createElement('pi-ui-generic-results-view'); + + grv.mapResults = results; + grv.style.minHeight = '500px'; + dlg.appendChild(grv); + dlg.visible = true; + } + + var numFailedRuns = results.failedRunInfos.length; + this.$.infobars.addMessage( + 'There were ' + numFailedRuns + ' traces that did not process.', + [ + { + buttonText: 'Tell me more...', + onClick: onTellMeMore + } + ]); + }, + + createColumns_: function() { + + function getStatsForRow(row) { + if (row.stats_ === undefined) { + row.stats_ = {}; + COLUMN_INFOS.forEach(function(info) { + info.statSetter(row.stats_, + averageFromHistograms(info.type, row.data)); + }); + } + return row.stats_; + } + + var columns = [{ + title: 'Title', + value: function(row) { + return row.title; + }, + cmp: function(a, b) { + var sA = a.title; + var sB = b.title; + if (sA < sB) + return -1; + if (sA > sB) + return 1; + return 0; + }, + width: '500px' + }, + this.createCachingColumn_('Avg. Time in queue', 'time_spent_in_queue'), + this.createCachingColumn_('Avg. Self time', + 'time_spent_in_top_level_task'), + this.createCachingColumn_('Avg. CPU time', + 'cpu_time_spent_in_top_level_task') + ]; + + return columns; + }, + + createCachingColumn_(title, type) { + + function averageFromHistograms(data) { + var runningSum = 0; + var numValues = 0; + data.forEach(function(datum) { + if (datum.type !== type) + return; + runningSum += datum.histogram.runningSum; + numValues += datum.histogram.numValues; + }); + var average = 0; + if (numValues !== 0) + average = runningSum / numValues; + return tr.ui.units.createTimeDurationSpan(average); + } + + var column = new pi.ui.CachingColumn(title, averageFromHistograms); + column.type = type; + column.cmp = function(row0, row1) { + return column.value(row0).duration - column.value(row1).duration; + }; + return column; + }, + + setHistogramBasedOnSelection_: function() { + var table = this.$.table; + var selectedColumn = table.selectedColumnIndex; + // Don't display a histogram if the user selects the title. + if (selectedColumn === 0) + return; + + var desiredType = table.tableColumns[selectedColumn].type; + var histogram = undefined; + table.selectedTableRow.data.forEach(function(datum) { + if (datum.type !== desiredType) + return; + if (!histogram) + histogram = datum.histogram.clone(); + else + histogram.addHistogram(datum.histogram); + }); + + this.$.histogram.histogram = histogram; + } + + }); + </script> +</polymer-element> diff --git a/catapult/perf_insights/perf_insights/ui/reports/task_info_report_test.html b/catapult/perf_insights/perf_insights/ui/reports/task_info_report_test.html new file mode 100644 index 00000000..9fdec4dc --- /dev/null +++ b/catapult/perf_insights/perf_insights/ui/reports/task_info_report_test.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<!-- +Copyright (c) 2013 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/perf_insights/value/value.html"> +<link rel="import" href="/perf_insights/value/run_info.html"> +<link rel="import" href="/perf_insights/results/results.html"> +<link rel="import" href="/perf_insights/ui/reports/task_info_report.html"> + +<link rel="import" href="/perf_insights/perf_insights_full_config.html"> +<link rel="import" href="/tracing/base/xhr.html"> + +<script> +'use strict'; + +tr.b.unittest.testSuite(function() { + var test_utils = tr.c.TestUtils; + test('savedData', function() { + // TODO(nduca): #1219, stop reading an actual wr file as our test data and + // use synthetic data. + var dataString = tr.b.getSync( + '/perf_insights/ui/reports/task_info_result_view_test_data.json'); + var results = pi.r.Results.fromDict(JSON.parse(dataString)); + + var view = document.createElement('pi-ui-r-task-info-report'); + view.mapResults = results; + this.addHTMLOutput(view); + }); +}); +</script> + diff --git a/catapult/perf_insights/perf_insights/ui/reports/task_info_result_view_test_data.json b/catapult/perf_insights/perf_insights/ui/reports/task_info_result_view_test_data.json new file mode 100644 index 00000000..844fa0ae --- /dev/null +++ b/catapult/perf_insights/perf_insights/ui/reports/task_info_result_view_test_data.json @@ -0,0 +1,15821 @@ +{ + "runs": { + "4593ca6b-75fb-4823-a7c9-2414d8e045c3": { + "url": "file:///work/trace-viewer/catapult/perf_insights/test_data/googlemaps_ipc_newbinding.html", + "display_name": "googlemaps_ipc_newbinding.html", + "metadata": { + "tags": [] + }, + "type": "perf_insights.value.RunInfo", + "run_id": "4593ca6b-75fb-4823-a7c9-2414d8e045c3" + } + }, + "values": [ + { + "important": false, + "type": "dict", + "name": "time_spent_in_queue", + "value": { + "Renderer": { + "Chrome_ChildIOThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 346.93500077724457, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1387, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 11, + "max": 10, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "HTMLParserThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 3.937000036239624, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 9, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "CrRendererMain": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 41, + "max": 1.7976931348623157e+308, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 250 + }, + "runningSum": 59472.10500061512, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1768, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 266, + "max": 10, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 5 + }, + { + "count": 268, + "max": 15, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 10 + }, + { + "count": 175, + "max": 20, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 15 + }, + { + "count": 110, + "max": 25, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 20 + }, + { + "count": 67, + "max": 30, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 25 + }, + { + "count": 27, + "max": 35, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 30 + }, + { + "count": 12, + "max": 40, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 35 + }, + { + "count": 30, + "max": 45, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 40 + }, + { + "count": 14, + "max": 50, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 45 + }, + { + "count": 31, + "max": 55, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 50 + }, + { + "count": 9, + "max": 60, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 55 + }, + { + "count": 7, + "max": 65, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null + ], + "min": 60 + }, + { + "count": 1, + "max": 70, + "sourceInfos": [ + null + ], + "min": 65 + }, + { + "count": 4, + "max": 75, + "sourceInfos": [ + null, + null, + null, + null + ], + "min": 70 + }, + { + "count": 4, + "max": 80, + "sourceInfos": [ + null, + null, + null, + null + ], + "min": 75 + }, + { + "count": 6, + "max": 85, + "sourceInfos": [ + null, + null, + null, + null, + null, + null + ], + "min": 80 + }, + { + "count": 8, + "max": 90, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 85 + }, + { + "count": 6, + "max": 95, + "sourceInfos": [ + null, + null, + null, + null, + null, + null + ], + "min": 90 + }, + { + "count": 12, + "max": 100, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 95 + }, + { + "count": 21, + "max": 105, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 100 + }, + { + "count": 9, + "max": 110, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 105 + }, + { + "count": 6, + "max": 115, + "sourceInfos": [ + null, + null, + null, + null, + null, + null + ], + "min": 110 + }, + { + "count": 8, + "max": 120, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 115 + }, + { + "count": 2, + "max": 125, + "sourceInfos": [ + null, + null + ], + "min": 120 + }, + { + "count": 6, + "max": 130, + "sourceInfos": [ + null, + null, + null, + null, + null, + null + ], + "min": 125 + }, + { + "count": 4, + "max": 135, + "sourceInfos": [ + null, + null, + null, + null + ], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 2, + "max": 145, + "sourceInfos": [ + null, + null + ], + "min": 140 + }, + { + "count": 1, + "max": 150, + "sourceInfos": [ + null + ], + "min": 145 + }, + { + "count": 7, + "max": 155, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null + ], + "min": 150 + }, + { + "count": 4, + "max": 160, + "sourceInfos": [ + null, + null, + null, + null + ], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 1, + "max": 170, + "sourceInfos": [ + null + ], + "min": 165 + }, + { + "count": 3, + "max": 175, + "sourceInfos": [ + null, + null, + null + ], + "min": 170 + }, + { + "count": 2, + "max": 180, + "sourceInfos": [ + null, + null + ], + "min": 175 + }, + { + "count": 2, + "max": 185, + "sourceInfos": [ + null, + null + ], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 2, + "max": 200, + "sourceInfos": [ + null, + null + ], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 1, + "max": 220, + "sourceInfos": [ + null + ], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 1, + "max": 230, + "sourceInfos": [ + null + ], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "ScriptStreamerThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 29.5450000166893, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 4, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 1, + "max": 15, + "sourceInfos": [ + null + ], + "min": 10 + }, + { + "count": 1, + "max": 20, + "sourceInfos": [ + null + ], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Compositor": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 5226.530001997948, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1862, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 131, + "max": 10, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 5 + }, + { + "count": 154, + "max": 15, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 10 + }, + { + "count": 54, + "max": 20, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 15 + }, + { + "count": 6, + "max": 25, + "sourceInfos": [ + null, + null, + null, + null, + null, + null + ], + "min": 20 + }, + { + "count": 3, + "max": 30, + "sourceInfos": [ + null, + null, + null + ], + "min": 25 + }, + { + "count": 1, + "max": 35, + "sourceInfos": [ + null + ], + "min": 30 + }, + { + "count": 1, + "max": 40, + "sourceInfos": [ + null + ], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + } + }, + "GPU Process": { + "Chrome_ChildIOThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 65.07199990749359, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 459, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "CrGpuMain": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 1538.237999022007, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 707, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 65, + "max": 10, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 5 + }, + { + "count": 20, + "max": 15, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 10 + }, + { + "count": 6, + "max": 20, + "sourceInfos": [ + null, + null, + null, + null, + null, + null + ], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 7, + "max": 45, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null + ], + "min": 40 + }, + { + "count": 1, + "max": 50, + "sourceInfos": [ + null + ], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + } + }, + "Browser": { + "CrBrowserMain": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 3, + "max": 1.7976931348623157e+308, + "sourceInfos": [ + null, + null, + null + ], + "min": 250 + }, + "runningSum": 4609.991001069546, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 886, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 56, + "max": 10, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 5 + }, + { + "count": 20, + "max": 15, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 10 + }, + { + "count": 5, + "max": 20, + "sourceInfos": [ + null, + null, + null, + null, + null + ], + "min": 15 + }, + { + "count": 1, + "max": 25, + "sourceInfos": [ + null + ], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 1, + "max": 35, + "sourceInfos": [ + null + ], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 2, + "max": 105, + "sourceInfos": [ + null, + null + ], + "min": 100 + }, + { + "count": 1, + "max": 110, + "sourceInfos": [ + null + ], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 1, + "max": 185, + "sourceInfos": [ + null + ], + "min": 180 + }, + { + "count": 1, + "max": 190, + "sourceInfos": [ + null + ], + "min": 185 + }, + { + "count": 1, + "max": 195, + "sourceInfos": [ + null + ], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_FileThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0.15200001001358032, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1, + "max": 5, + "sourceInfos": [ + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "BrowserWatchdog": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0.27500003576278687, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1, + "max": 5, + "sourceInfos": [ + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_IOThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 2790.7339997291565, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1482, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 81, + "max": 10, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 5 + }, + { + "count": 20, + "max": 15, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 10 + }, + { + "count": 9, + "max": 20, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 15 + }, + { + "count": 22, + "max": 25, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 20 + }, + { + "count": 8, + "max": 30, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 25 + }, + { + "count": 5, + "max": 35, + "sourceInfos": [ + null, + null, + null, + null, + null + ], + "min": 30 + }, + { + "count": 3, + "max": 40, + "sourceInfos": [ + null, + null, + null + ], + "min": 35 + }, + { + "count": 2, + "max": 45, + "sourceInfos": [ + null, + null + ], + "min": 40 + }, + { + "count": 2, + "max": 50, + "sourceInfos": [ + null, + null + ], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 1, + "max": 70, + "sourceInfos": [ + null + ], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "BrowserBlockingWorker": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 9.61300003528595, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 16, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_HistoryThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 7.388000011444092, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 15, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "SimpleCacheWorker": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 11.991999685764313, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 110, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_FileUserBlockingThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0.21399998664855957, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 3, + "max": 5, + "sourceInfos": [ + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + } + } + }, + "run_id": "4593ca6b-75fb-4823-a7c9-2414d8e045c3" + }, + { + "important": false, + "type": "dict", + "name": "time_spent_in_top_level_task", + "value": { + "Renderer": { + "Chrome_ChildIOThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 129.13300000000186, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1392, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 1, + "max": 10, + "sourceInfos": [ + null + ], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "HTMLParserThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0.366, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 6, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "ScriptStreamerThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0.3659999999999981, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 5, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Compositor": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 91.04900000000123, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 2113, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "CrRendererMain": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 155.82399982834139, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1821, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 2, + "max": 10, + "sourceInfos": [ + null, + null + ], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + } + }, + "GPU Process": { + "Chrome_ChildIOThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 36.75999999999995, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 438, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "CrGpuMain": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 64.20599999999996, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 782, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + } + }, + "Browser": { + "CrBrowserMain": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 73.7190000000003, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 932, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 1, + "max": 10, + "sourceInfos": [ + null + ], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "BrowserWatchdog": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1, + "max": 5, + "sourceInfos": [ + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_FileThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 1.0370000004768372, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1, + "max": 5, + "sourceInfos": [ + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "BrowserBlockingWorker": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 7.4159999999999995, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 16, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_IOThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 380.5269999999984, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1606, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 5, + "max": 10, + "sourceInfos": [ + null, + null, + null, + null, + null + ], + "min": 5 + }, + { + "count": 1, + "max": 15, + "sourceInfos": [ + null + ], + "min": 10 + }, + { + "count": 1, + "max": 20, + "sourceInfos": [ + null + ], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_HistoryThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 7.295, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 15, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "SimpleCacheWorker": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 121.31800000000011, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 104, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 4, + "max": 10, + "sourceInfos": [ + null, + null, + null, + null + ], + "min": 5 + }, + { + "count": 2, + "max": 15, + "sourceInfos": [ + null, + null + ], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_FileUserBlockingThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0.946, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 3, + "max": 5, + "sourceInfos": [ + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + } + } + }, + "run_id": "4593ca6b-75fb-4823-a7c9-2414d8e045c3" + }, + { + "important": false, + "type": "dict", + "name": "cpu_time_spent_in_top_level_task", + "value": { + "Renderer": { + "Chrome_ChildIOThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 102.63100000000148, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1393, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "HTMLParserThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0.33599999999999997, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 6, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "ScriptStreamerThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0.3669999999999993, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 5, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Compositor": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 59.800999999999945, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 2113, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "CrRendererMain": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 106.63600000000078, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 1, + "max": 0, + "sourceInfos": [ + null + ], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1822, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + } + }, + "GPU Process": { + "Chrome_ChildIOThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 32.56099999999997, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 438, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "CrGpuMain": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 51.278999999999925, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 782, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + } + }, + "Browser": { + "CrBrowserMain": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 53.17599999999998, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 933, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "BrowserWatchdog": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1, + "max": 5, + "sourceInfos": [ + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_FileThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1, + "max": 5, + "sourceInfos": [ + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "BrowserBlockingWorker": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 4.732, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 16, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_IOThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 311.174, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 1607, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 5, + "max": 10, + "sourceInfos": [ + null, + null, + null, + null, + null + ], + "min": 5 + }, + { + "count": 1, + "max": 15, + "sourceInfos": [ + null + ], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_HistoryThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 6.501, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 15, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "SimpleCacheWorker": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 46.78199999999995, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 110, + "max": 5, + "sourceInfos": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + }, + "Chrome_FileUserBlockingThread": { + "nanSourceInfos": [], + "min": 0, + "max": 250, + "overflowBin": { + "count": 0, + "max": 1.7976931348623157e+308, + "sourceInfos": [], + "min": 250 + }, + "runningSum": 0.917, + "centralBinWidth": 5, + "numNans": 0, + "underflowBin": { + "count": 0, + "max": 0, + "sourceInfos": [], + "min": -1.7976931348623157e+308 + }, + "centralBins": [ + { + "count": 3, + "max": 5, + "sourceInfos": [ + null, + null, + null + ], + "min": 0 + }, + { + "count": 0, + "max": 10, + "sourceInfos": [], + "min": 5 + }, + { + "count": 0, + "max": 15, + "sourceInfos": [], + "min": 10 + }, + { + "count": 0, + "max": 20, + "sourceInfos": [], + "min": 15 + }, + { + "count": 0, + "max": 25, + "sourceInfos": [], + "min": 20 + }, + { + "count": 0, + "max": 30, + "sourceInfos": [], + "min": 25 + }, + { + "count": 0, + "max": 35, + "sourceInfos": [], + "min": 30 + }, + { + "count": 0, + "max": 40, + "sourceInfos": [], + "min": 35 + }, + { + "count": 0, + "max": 45, + "sourceInfos": [], + "min": 40 + }, + { + "count": 0, + "max": 50, + "sourceInfos": [], + "min": 45 + }, + { + "count": 0, + "max": 55, + "sourceInfos": [], + "min": 50 + }, + { + "count": 0, + "max": 60, + "sourceInfos": [], + "min": 55 + }, + { + "count": 0, + "max": 65, + "sourceInfos": [], + "min": 60 + }, + { + "count": 0, + "max": 70, + "sourceInfos": [], + "min": 65 + }, + { + "count": 0, + "max": 75, + "sourceInfos": [], + "min": 70 + }, + { + "count": 0, + "max": 80, + "sourceInfos": [], + "min": 75 + }, + { + "count": 0, + "max": 85, + "sourceInfos": [], + "min": 80 + }, + { + "count": 0, + "max": 90, + "sourceInfos": [], + "min": 85 + }, + { + "count": 0, + "max": 95, + "sourceInfos": [], + "min": 90 + }, + { + "count": 0, + "max": 100, + "sourceInfos": [], + "min": 95 + }, + { + "count": 0, + "max": 105, + "sourceInfos": [], + "min": 100 + }, + { + "count": 0, + "max": 110, + "sourceInfos": [], + "min": 105 + }, + { + "count": 0, + "max": 115, + "sourceInfos": [], + "min": 110 + }, + { + "count": 0, + "max": 120, + "sourceInfos": [], + "min": 115 + }, + { + "count": 0, + "max": 125, + "sourceInfos": [], + "min": 120 + }, + { + "count": 0, + "max": 130, + "sourceInfos": [], + "min": 125 + }, + { + "count": 0, + "max": 135, + "sourceInfos": [], + "min": 130 + }, + { + "count": 0, + "max": 140, + "sourceInfos": [], + "min": 135 + }, + { + "count": 0, + "max": 145, + "sourceInfos": [], + "min": 140 + }, + { + "count": 0, + "max": 150, + "sourceInfos": [], + "min": 145 + }, + { + "count": 0, + "max": 155, + "sourceInfos": [], + "min": 150 + }, + { + "count": 0, + "max": 160, + "sourceInfos": [], + "min": 155 + }, + { + "count": 0, + "max": 165, + "sourceInfos": [], + "min": 160 + }, + { + "count": 0, + "max": 170, + "sourceInfos": [], + "min": 165 + }, + { + "count": 0, + "max": 175, + "sourceInfos": [], + "min": 170 + }, + { + "count": 0, + "max": 180, + "sourceInfos": [], + "min": 175 + }, + { + "count": 0, + "max": 185, + "sourceInfos": [], + "min": 180 + }, + { + "count": 0, + "max": 190, + "sourceInfos": [], + "min": 185 + }, + { + "count": 0, + "max": 195, + "sourceInfos": [], + "min": 190 + }, + { + "count": 0, + "max": 200, + "sourceInfos": [], + "min": 195 + }, + { + "count": 0, + "max": 205, + "sourceInfos": [], + "min": 200 + }, + { + "count": 0, + "max": 210, + "sourceInfos": [], + "min": 205 + }, + { + "count": 0, + "max": 215, + "sourceInfos": [], + "min": 210 + }, + { + "count": 0, + "max": 220, + "sourceInfos": [], + "min": 215 + }, + { + "count": 0, + "max": 225, + "sourceInfos": [], + "min": 220 + }, + { + "count": 0, + "max": 230, + "sourceInfos": [], + "min": 225 + }, + { + "count": 0, + "max": 235, + "sourceInfos": [], + "min": 230 + }, + { + "count": 0, + "max": 240, + "sourceInfos": [], + "min": 235 + }, + { + "count": 0, + "max": 245, + "sourceInfos": [], + "min": 240 + }, + { + "count": 0, + "max": 250, + "sourceInfos": [], + "min": 245 + } + ], + "unit": "ms" + } + } + }, + "run_id": "4593ca6b-75fb-4823-a7c9-2414d8e045c3" + } + ] +} diff --git a/catapult/perf_insights/perf_insights/ui/reports/weather_report.html b/catapult/perf_insights/perf_insights/ui/reports/weather_report.html new file mode 100644 index 00000000..ebd7a6b4 --- /dev/null +++ b/catapult/perf_insights/perf_insights/ui/reports/weather_report.html @@ -0,0 +1,103 @@ +<!DOCTYPE HTML> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<link rel="import" href="/tracing/base/iteration_helpers.html"> +<link rel="import" href="/tracing/ui/base/dom_helpers.html"> +<link rel="import" href="/tracing/ui/base/info_bar_group.html"> +<link rel="import" href="/tracing/ui/base/overlay.html"> +<link rel="import" href="/perf_insights/results/results.html"> +<link rel="import" href="/perf_insights/ui/reports/pi_report.html"> +<link rel="import" href="/perf_insights/ui/reports/rail_score_report.html"> +<link rel="import" href="/perf_insights/ui/reports/slice_cost_report.html"> +<link rel="import" href="/perf_insights/ui/grouping_table.html"> +<link rel="import" href="/perf_insights/ui/generic_results_view.html"> + +<polymer-element name="pi-ui-r-weather-report" + extends="pi-ui-r-pi-report" + map-function-href="/perf_insights/mappers/weather_report_map_function.html" + map-function-name="weatherReportMapFunction"> + <template> + <style> + :host { + display: flex; + flex-direction: column; + } + h1 { + margin: 20px 0 0px 0; + font-size: 12pt; + } + .sub-report { + margin-left: 10px; + } + </style> + <tr-ui-b-info-bar-group id="infobars"></tr-ui-b-info-bar-group> + <h1>Slice costs</h1> + <pi-ui-r-slice-cost-report class="sub-report"></pi-ui-r-slice-cost-report> + + <h1>RAIL</h1> + <pi-ui-r-rail-score-report class="sub-report"></pi-ui-r-rail-score-report> + </template> + <script> + 'use strict'; + + Polymer({ + created: function() { + this.mapResults_ = undefined; + }, + + get mapResults() { + return this.mapResults_; + }, + + set mapResults(mapResults) { + this.mapResults_ = mapResults; + this.updateContents_(); + }, + + updateContents_: function() { + var results = this.mapResults_; + if (!results) + results = new tr.r.Results(); + + this.$.infobars.clearMessages(); + this.maybeAddFailuresInfoBarMessage_(results); + + var reports = tr.b.asArray( + this.shadowRoot.querySelectorAll('.sub-report')); + reports.forEach(function(report) { + report.mapResults = results; + }); + }, + + maybeAddFailuresInfoBarMessage_: function(results) { + if (!results.hadFailures) + return; + + function onTellMeMore() { + var dlg = new tr.ui.b.Overlay(); + dlg.dlg = 'Results summary'; + + var grv = document.createElement('pi-ui-generic-results-view'); + + grv.mapResults = results; + grv.style.minHeight = '500px'; + dlg.appendChild(grv); + dlg.visible = true; + } + + var numFailedRuns = results.failedRunInfos.length; + this.$.infobars.addMessage( + 'There were ' + numFailedRuns + ' traces that did not process.', + [ + { + buttonText: 'Tell me more...', + onClick: onTellMeMore + } + ]); + } + }); + </script> +</polymer-element> diff --git a/catapult/perf_insights/perf_insights/ui/wr/weather_report_test.html b/catapult/perf_insights/perf_insights/ui/reports/weather_report_test.html index 113f73bc..8eef577a 100644 --- a/catapult/perf_insights/perf_insights/ui/wr/weather_report_test.html +++ b/catapult/perf_insights/perf_insights/ui/reports/weather_report_test.html @@ -8,7 +8,7 @@ found in the LICENSE file. <link rel="import" href="/perf_insights/value/value.html"> <link rel="import" href="/perf_insights/value/run_info.html"> <link rel="import" href="/perf_insights/results/results.html"> -<link rel="import" href="/perf_insights/ui/wr/weather_report.html"> +<link rel="import" href="/perf_insights/ui/reports/weather_report.html"> <link rel="import" href="/perf_insights/perf_insights_full_config.html"> <link rel="import" href="/tracing/base/xhr.html"> @@ -17,15 +17,15 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('savedData', function() { // TODO(nduca): #1219, stop reading an actual wr file as our test data and // use synthetic data. var dataString = tr.b.getSync( - '/perf_insights/ui/wr/wr_result_view_test_data.json'); + '/perf_insights/ui/reports/wr_result_view_test_data.json'); var results = pi.r.Results.fromDict(JSON.parse(dataString)); - var view = document.createElement('pi-ui-wr-weather-report'); + var view = document.createElement('pi-ui-r-weather-report'); view.mapResults = results; this.addHTMLOutput(view); }); diff --git a/catapult/perf_insights/perf_insights/ui/wr/wr_result_view_test_data.json b/catapult/perf_insights/perf_insights/ui/reports/wr_result_view_test_data.json index 289c8a5e..289c8a5e 100644 --- a/catapult/perf_insights/perf_insights/ui/wr/wr_result_view_test_data.json +++ b/catapult/perf_insights/perf_insights/ui/reports/wr_result_view_test_data.json diff --git a/catapult/perf_insights/perf_insights/upload.py b/catapult/perf_insights/perf_insights/upload.py index 1cd601a1..35b0d8e1 100644 --- a/catapult/perf_insights/perf_insights/upload.py +++ b/catapult/perf_insights/perf_insights/upload.py @@ -11,6 +11,8 @@ from perf_insights import trace_info import third_party.cloudstorage as gcs +from google.appengine.api import app_identity + default_retry_params = gcs.RetryParams(initial_delay=0.2, max_delay=5.0, backoff_factor=2, @@ -32,8 +34,12 @@ class UploadPage(webapp2.RequestHandler): def post(self): trace_uuid = str(uuid.uuid4()) - bucket_name = ('/performance-insights/' + trace_uuid) - gcs_file = gcs.open(bucket_name, + if 'GCS_BUCKET_NAME' not in os.environ: + bucket_name = app_identity.get_default_gcs_bucket_name() + else: + bucket_name = os.environ['GCS_BUCKET_NAME'] + gcs_path = ('/' + bucket_name + '/' + trace_uuid + '.gz') + gcs_file = gcs.open(gcs_path, 'w', content_type='application/octet-stream', options={}, diff --git a/catapult/perf_insights/perf_insights/value/run_info.html b/catapult/perf_insights/perf_insights/value/run_info.html index c298829b..ac228950 100644 --- a/catapult/perf_insights/perf_insights/value/run_info.html +++ b/catapult/perf_insights/perf_insights/value/run_info.html @@ -10,20 +10,20 @@ found in the LICENSE file. tr.exportTo('pi.v', function() { // This value must stay sync'd with the constant of the same name - // in run_info.py. + // in runInfo.py. var PI_VALUE_RUN_INFO_ID = 'perf_insights.value.RunInfo'; - function RunInfo(url, opt_display_name, opt_run_id, opt_metadata) { - if (opt_run_id !== undefined) - this.run_id = opt_run_id; + function RunInfo(url, opt_displayName, opt_runId, opt_metadata) { + if (opt_runId !== undefined) + this.runId = opt_runId; else - this.run_id = 'pi.v.RunInfo-' + tr.b.GUID.allocate(); + this.runId = 'pi.v.RunInfo-' + tr.b.GUID.allocate(); this.url = url; - if (opt_display_name !== undefined) - this.display_name = opt_display_name; + if (opt_displayName !== undefined) + this.displayName = opt_displayName; else - this.display_name = this.url; + this.displayName = this.url; if (opt_metadata !== undefined) this.metadata = opt_metadata; @@ -33,7 +33,7 @@ tr.exportTo('pi.v', function() { RunInfo.fromDict = function(d) { if (d.type !== PI_VALUE_RUN_INFO_ID) - throw new Error('Unsupported run_info format: ' + d.type); + throw new Error('Unsupported runInfo format: ' + d.type); if (d.run_id === undefined) throw new Error('Must contain run_id'); if (d.url === undefined) @@ -45,12 +45,12 @@ tr.exportTo('pi.v', function() { asDict: function() { var d = { type: PI_VALUE_RUN_INFO_ID, - run_id: this.run_id, + run_id: this.runId, url: this.url, metadata: this.metadata }; - if (this.display_name !== this.url) - d.display_name = this.display_name; + if (this.displayName !== this.url) + d.display_name = this.displayName; return d; } }; diff --git a/catapult/perf_insights/perf_insights/value/value.html b/catapult/perf_insights/perf_insights/value/value.html index 377e36f2..32c5f346 100644 --- a/catapult/perf_insights/perf_insights/value/value.html +++ b/catapult/perf_insights/perf_insights/value/value.html @@ -11,43 +11,46 @@ found in the LICENSE file. 'use strict'; tr.exportTo('pi.v', function() { - function Value(run_info, name, opt_options) { + function Value(runInfo, name, opt_options) { var options = opt_options || {}; this.guid = tr.b.GUID.allocate(); - this.run_info = run_info; + this.runInfo = runInfo; this.name = name; this.units = options.units; this.description = options.description; this.important = options.important !== undefined ? options.important : false; - this.ir_stable_id = options.ir_stable_id; + this.irStableID = options.irStableID; } - Value.fromDict = function(run_info, d) { - if (d.run_id !== run_info.run_id) + Value.fromDict = function(runInfo, d) { + if (d.run_id !== runInfo.runId) throw new Error('run_ids mismatch'); if (d.type === 'dict') - return DictValue.fromDict(run_info, d); + return DictValue.fromDict(runInfo, d); if (d.type == 'failure') - return FailureValue.fromDict(run_info, d); + return FailureValue.fromDict(runInfo, d); if (d.type === 'skip') - return SkipValue.fromDict(run_info, d); + return SkipValue.fromDict(runInfo, d); throw new Error('Not implemented'); }; Value.prototype = { asDict: function() { + return this.asJSON(); + }, + asJSON: function() { var d = { - 'run_id': this.run_info.run_id, + 'run_id': this.runInfo.runId, 'name': this.name, 'units': this.units, 'description': this.description, 'important': this.important, - 'ir_stable_id': this.ir_stable_id + 'ir_stable_id': this.irStableID }; this._asDictInto(d); if (d.type === undefined) @@ -61,18 +64,18 @@ tr.exportTo('pi.v', function() { }; - function DictValue(run_info, name, value, opt_options) { + function DictValue(runInfo, name, value, opt_options) { var options = opt_options || {}; - Value.call(this, run_info, name, options); + Value.call(this, runInfo, name, options); this.value = value; } - DictValue.fromDict = function(run_info, d) { + DictValue.fromDict = function(runInfo, d) { if (d.units !== undefined) throw new Error('Expected units to be undefined'); if (d.value === undefined) throw new Error('Expected value to be provided'); - return new DictValue(run_info, d.name, d.value, d); + return new DictValue(runInfo, d.name, d.value, d); } DictValue.prototype = { @@ -85,7 +88,7 @@ tr.exportTo('pi.v', function() { }; - function FailureValue(run_info, name, opt_options) { + function FailureValue(runInfo, name, opt_options) { var options = opt_options || {}; var stack; @@ -102,25 +105,25 @@ tr.exportTo('pi.v', function() { if (typeof stack !== 'string') throw new Error('stack must be provided as a string'); - Value.call(this, run_info, name, options); + Value.call(this, runInfo, name, options); this.stack = stack; } - FailureValue.fromError = function(run_info, e) { + FailureValue.fromError = function(runInfo, e) { var ex = tr.b.normalizeException(e); - return new FailureValue(run_info, + return new FailureValue(runInfo, ex.typeName, {description: ex.message, stack: ex.stack}); } - FailureValue.fromDict = function(run_info, d) { + FailureValue.fromDict = function(runInfo, d) { if (d.units !== undefined) throw new Error('Expected units to be undefined'); if (d.name === undefined) throw new Error('Expected stack_str to be provided'); - return new FailureValue(run_info, d.name, d); + return new FailureValue(runInfo, d.name, d); } FailureValue.prototype = { @@ -133,17 +136,17 @@ tr.exportTo('pi.v', function() { }; - function SkipValue(run_info, name, opt_options) { + function SkipValue(runInfo, name, opt_options) { var options = opt_options || {}; - Value.call(this, run_info, name, options); + Value.call(this, runInfo, name, options); } - SkipValue.fromDict = function(run_info, d) { + SkipValue.fromDict = function(runInfo, d) { if (d.units !== undefined) throw new Error('Expected units to be undefined'); if (d.name === undefined) throw new Error('Expected name to be provided'); - return new SkipValue(run_info, d.name, d); + return new SkipValue(runInfo, d.name, d); } SkipValue.prototype = { diff --git a/catapult/perf_insights/perf_insights/value/value_test.html b/catapult/perf_insights/perf_insights/value/value_test.html index dc06ceb4..0c7bc603 100644 --- a/catapult/perf_insights/perf_insights/value/value_test.html +++ b/catapult/perf_insights/perf_insights/value/value_test.html @@ -14,25 +14,25 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('dictValueBasic', function() { - var run_info = new pi.v.RunInfo('my_test.json'); - var v = new pi.v.DictValue(run_info, 'MyFailure', + var runInfo = new pi.v.RunInfo('my_test.json'); + var v = new pi.v.DictValue(runInfo, 'MyFailure', {my_key: 'my_value'}); var d = v.asDict(); - var v2 = pi.v.Value.fromDict(run_info, d); + var v2 = pi.v.Value.fromDict(runInfo, d); assert.instanceOf(v2, pi.v.DictValue); assert.equal(v.name, v2.name); assert.deepEqual(v.value, v2.value); }); test('failureValueBasic', function() { - var run_info = new pi.v.RunInfo('my_test.json'); - var v = new pi.v.FailureValue(run_info, 'MyFailure', + var runInfo = new pi.v.RunInfo('my_test.json'); + var v = new pi.v.FailureValue(runInfo, 'MyFailure', {description: 'Description', stack: tr.b.stackTraceAsString()}); var d = v.asDict(); - var v2 = pi.v.Value.fromDict(run_info, d); + var v2 = pi.v.Value.fromDict(runInfo, d); assert.instanceOf(v2, pi.v.FailureValue); assert.equal(v.name, v2.name); assert.equal(v.description, v2.description); @@ -40,12 +40,12 @@ tr.b.unittest.testSuite(function() { }); test('skipValueBasic', function() { - var run_info = new pi.v.RunInfo('my_test.json'); - var v = new pi.v.SkipValue(run_info, 'MySkip', + var runInfo = new pi.v.RunInfo('my_test.json'); + var v = new pi.v.SkipValue(runInfo, 'MySkip', {description: 'WhySkipped'}); var d = v.asDict(); - var v2 = pi.v.Value.fromDict(run_info, d); + var v2 = pi.v.Value.fromDict(runInfo, d); assert.instanceOf(v2, pi.v.SkipValue); assert.equal(v.name, v2.name); assert.equal(v.description, v2.description); diff --git a/catapult/perf_insights/perf_insights_build/pi_report_to_html.py b/catapult/perf_insights/perf_insights_build/pi_report_to_html.py index 5aaeb98b..a014c968 100644 --- a/catapult/perf_insights/perf_insights_build/pi_report_to_html.py +++ b/catapult/perf_insights/perf_insights_build/pi_report_to_html.py @@ -12,11 +12,12 @@ from perf_insights import corpus_query from perf_insights import local_directory_corpus_driver from perf_insights import map_function_handle as map_function_handle_module from perf_insights import map_runner +from perf_insights import progress_reporter as progress_reporter_module from perf_insights.results import json_output_formatter from tvcm import generate import perf_insights import perf_insights_project -import polymer_soup +import bs4 def Main(argv, pi_report_file=None): @@ -48,34 +49,29 @@ def Main(argv, pi_report_file=None): query = corpus_query.CorpusQuery.FromString( args.query) - return PiReportToHTML(args.output_file, args.trace_directory, + with codecs.open(args.output_file, mode='w', encoding='utf-8') as ofile: + return PiReportToHTML(ofile, args.trace_directory, pi_report_file, query, args.json, args.stop_on_error, args.jobs) -def _GetAttr(n, attr, defaultValue=None): - for pair in n.attrs: - if pair[0] == attr: - return pair[1] - return defaultValue - def _GetMapFunctionHrefFromPiReport(html_contents): - soup = polymer_soup.PolymerSoup(html_contents) + soup = bs4.BeautifulSoup(html_contents) elements = soup.findAll('polymer-element') for element in elements: - if _GetAttr(element, 'extends').lower() == 'pi-ui-pi-report': - map_function_href = _GetAttr(element, 'map-function-href') + if element.attrs.get('extends').lower() == 'pi-ui-r-pi-report': + map_function_href = element.attrs.get('map-function-href', None) if map_function_href is None: raise Exception('Report is missing map-function-href attribute') - pi_report_element_name = _GetAttr(element, 'name', None) + pi_report_element_name = element.attrs.get('name', None) if pi_report_element_name is None: raise Exception('Report is missing name attribute') return map_function_href, pi_report_element_name - raise Exception('No element that extends pi-ui-pi-report was found') + raise Exception('No element that extends pi-ui-r-pi-report was found') -def PiReportToHTML(output_file, trace_directory, pi_report_file, +def PiReportToHTML(ofile, trace_directory, pi_report_file, query, json_output=False, - stop_on_error=False, jobs=1): + stop_on_error=False, jobs=1, quiet=False): project = perf_insights_project.PerfInsightsProject() with open(pi_report_file, 'r') as f: @@ -91,30 +87,34 @@ def PiReportToHTML(output_file, trace_directory, pi_report_file, raise Exception('Could not find %s' % map_function_href) results = _MapTraces(trace_directory, map_function_handle, - query, stop_on_error, jobs) + query, stop_on_error, jobs, quiet) if stop_on_error and results.had_failures: sys.stderr.write('There were mapping errors. Aborting.'); return 255 - with codecs.open(output_file, mode='w', encoding='utf-8') as ofile: - if json_output: - json.dump(results.AsDict(), ofile, indent=2) - else: - WriteResultsToFile(ofile, project, - pi_report_file, pi_report_element_name, - results) + if json_output: + json.dump(results.AsDict(), ofile, indent=2) + else: + WriteResultsToFile(ofile, project, + pi_report_file, pi_report_element_name, + results) return 0 def _MapTraces(trace_directory, map_function_handle, query, stop_on_error=False, - jobs=1): + jobs=1, quiet=False): corpus_driver = local_directory_corpus_driver.LocalDirectoryCorpusDriver( os.path.abspath(os.path.expanduser(trace_directory))) trace_handles = corpus_driver.GetTraceHandlesMatchingQuery(query) + if quiet: + alt_progress_reporter = progress_reporter_module.ProgressReporter() + else: + alt_progress_reporter = None runner = map_runner.MapRunner(trace_handles, map_function_handle, - stop_on_error=stop_on_error) + stop_on_error=stop_on_error, + progress_reporter=alt_progress_reporter) return runner.Run(jobs=jobs) diff --git a/catapult/perf_insights/perf_insights_build/pi_report_to_html_unittest.py b/catapult/perf_insights/perf_insights_build/pi_report_to_html_unittest.py index 97ff9709..fc1a2985 100644 --- a/catapult/perf_insights/perf_insights_build/pi_report_to_html_unittest.py +++ b/catapult/perf_insights/perf_insights_build/pi_report_to_html_unittest.py @@ -7,10 +7,30 @@ import os import tempfile import unittest -from tracing_build import trace2html +from perf_insights import corpus_query +from perf_insights_build import pi_report_to_html +import perf_insights_project -class Trace2HTMLTests(unittest.TestCase): +class PiReportToHTMLTests(unittest.TestCase): - def test_writeHTMLForTracesToFile(self): - pass
\ No newline at end of file + def test_basic(self): + # Note: We can't use "with" when working with tempfile.NamedTemporaryFile as + # that does not work on Windows. We use the longer, more clunky version + # instead. See https://bugs.python.org/issue14243 for detials. + raw_tmpfile = tempfile.NamedTemporaryFile( + mode='w', suffix='.html', delete=False) + raw_tmpfile.close() + try: + project = perf_insights_project.PerfInsightsProject() + with codecs.open(raw_tmpfile.name, 'w', encoding='utf-8') as tmpfile: + res = pi_report_to_html.PiReportToHTML( + tmpfile, + project.perf_insights_test_data_path, + project.GetAbsPathFromHRef( + '/perf_insights/ui/reports/weather_report.html'), + corpus_query.CorpusQuery.FromString('MAX_TRACE_HANDLES=2'), + quiet=True) + self.assertEquals(res, 0) + finally: + os.remove(raw_tmpfile.name)
\ No newline at end of file diff --git a/catapult/perf_insights/perf_insights_examples/map_process_count.html b/catapult/perf_insights/perf_insights_examples/map_process_count.html index 555911b2..2f8c6f2d 100644 --- a/catapult/perf_insights/perf_insights_examples/map_process_count.html +++ b/catapult/perf_insights/perf_insights_examples/map_process_count.html @@ -4,14 +4,15 @@ Copyright (c) 2015 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/perf_insights/value/value.html"> + <link rel="import" href="/perf_insights/map_function.html"> +<link rel="import" href="/perf_insights/value/value.html"> <script> tr.exportTo('pie', function() { - function mapProcessCount(results, run_info, model) { + function mapProcessCount(results, runInfo, model) { results.addValue(new pi.v.DictValue( - run_info, + runInfo, 'load_info', { numProcesses: model.getAllProcesses().length })); @@ -20,7 +21,7 @@ tr.exportTo('pie', function() { pi.MapFunction.register(mapProcessCount); return { - mapProcessCount: mapProcessCount + mapProcessCountForTest: mapProcessCount }; }); </script> diff --git a/catapult/perf_insights/perf_insights_examples/map_process_count_test.html b/catapult/perf_insights/perf_insights_examples/map_process_count_test.html index 0629a775..01d73cc0 100644 --- a/catapult/perf_insights/perf_insights_examples/map_process_count_test.html +++ b/catapult/perf_insights/perf_insights_examples/map_process_count_test.html @@ -1,6 +1,6 @@ <!DOCTYPE html> <!-- -Copyright (c) 2013 The Chromium Authors. All rights reserved. +Copyright (c) 2015 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> @@ -15,7 +15,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('mapperTest', function() { var m = test_utils.newModel(function(m) { var p1 = m.getOrCreateProcess(1); @@ -27,11 +27,11 @@ tr.b.unittest.testSuite(function() { }); var results = new pi.r.Results(); - var run_info = new pi.v.RunInfo('my_test.json'); - pie.mapProcessCount(results, run_info, m); + var runInfo = new pi.v.RunInfo('my_test.json'); + pie.mapProcessCountForTest(results, runInfo, m); - assert.equal(results.all_values.length, 1); - assert.isTrue(results.all_values[0] instanceof pi.v.DictValue); + assert.equal(results.allValues.length, 1); + assert.isTrue(results.allValues[0] instanceof pi.v.DictValue); }); }); diff --git a/catapult/perf_insights/perf_insights_examples/map_startup_info.html b/catapult/perf_insights/perf_insights_examples/map_startup_info.html index 9069d68e..962bc6fc 100644 --- a/catapult/perf_insights/perf_insights_examples/map_startup_info.html +++ b/catapult/perf_insights/perf_insights_examples/map_startup_info.html @@ -4,15 +4,16 @@ Copyright (c) 2015 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/perf_insights/value/value.html"> + <link rel="import" href="/perf_insights/map_function.html"> +<link rel="import" href="/perf_insights/value/value.html"> <link rel="import" href="/tracing/base/range.html"> <link rel="import" href="/tracing/extras/chrome/chrome_browser_helper.html"> <link rel="import" href="/tracing/extras/chrome/chrome_renderer_helper.html"> <script> tr.exportTo('pie', function() { - function mapStartupInfo(results, run_info, model) { + function mapStartupInfo(results, runInfo, model) { var startupIRs = model.interactionRecords.filter(function(ir) { return ir instanceof tr.e.rail.LoadInteractionRecord && ir.name === 'Startup'; @@ -36,10 +37,10 @@ tr.exportTo('pie', function() { }); if (browser_startup.isEmpty && renderer_startup.isEmpty) { - results.addValue(new pi.v.SkipValue(run_info, 'startup_info')); + results.addValue(new pi.v.SkipValue(runInfo, 'startup_info')); } else { results.addValue(new pi.v.DictValue( - run_info, + runInfo, 'startup_info', { 'browserStartup': browser_startup, @@ -52,7 +53,7 @@ tr.exportTo('pie', function() { // Exporting for tests. return { - mapStartupInfo: mapStartupInfo + mapStartupInfoForTest: mapStartupInfo }; }); </script> diff --git a/catapult/perf_insights/perf_insights_examples/map_startup_info_test.html b/catapult/perf_insights/perf_insights_examples/map_startup_info_test.html index a4de79fa..365702ec 100644 --- a/catapult/perf_insights/perf_insights_examples/map_startup_info_test.html +++ b/catapult/perf_insights/perf_insights_examples/map_startup_info_test.html @@ -1,6 +1,6 @@ <!DOCTYPE html> <!-- -Copyright (c) 2013 The Chromium Authors. All rights reserved. +Copyright (c) 2015 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> @@ -17,7 +17,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('mapperTest', function() { var m = test_utils.newModel(function(m) { @@ -46,25 +46,25 @@ tr.b.unittest.testSuite(function() { }); var results = new pi.r.Results(); - var run_info = new pi.v.RunInfo('my_test.json'); - pie.mapStartupInfo(results, run_info, m); + var runInfo = new pi.v.RunInfo('my_test.json'); + pie.mapStartupInfoForTest(results, runInfo, m); - assert.equal(results.all_values.length, 1); - assert.equal(results.all_values[0].value.browserStartup.min, 10); - assert.equal(results.all_values[0].value.browserStartup.max, 80); - assert.isFalse(results.all_values[0].value.browserStartup.isEmpty); - assert.isTrue(results.all_values[0].value.rendererStartup.isEmpty); + assert.equal(results.allValues.length, 1); + assert.equal(results.allValues[0].value.browserStartup.min, 10); + assert.equal(results.allValues[0].value.browserStartup.max, 80); + assert.isFalse(results.allValues[0].value.browserStartup.isEmpty); + assert.isTrue(results.allValues[0].value.rendererStartup.isEmpty); }); test('mapperTestEmptyTrace', function() { var m = test_utils.newModel(); var results = new pi.r.Results(); - var run_info = new pi.v.RunInfo('my_test.json'); - pie.mapStartupInfo(results, run_info, m); + var runInfo = new pi.v.RunInfo('my_test.json'); + pie.mapStartupInfoForTest(results, runInfo, m); - assert.equal(results.all_values.length, 1); - assert.isTrue(results.all_values[0] instanceof pi.v.SkipValue); + assert.equal(results.allValues.length, 1); + assert.isTrue(results.allValues[0] instanceof pi.v.SkipValue); }); }); diff --git a/catapult/systrace/README.md b/catapult/systrace/README.md new file mode 100644 index 00000000..3ca92493 --- /dev/null +++ b/catapult/systrace/README.md @@ -0,0 +1,10 @@ +<!-- Copyright 2015 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> +Systrace +======== + +Systrace provides command-line tools to analyze the performance of your +application. It currently includes +[Android Systrace](http://developer.android.com/tools/help/systrace.html). diff --git a/catapult/systrace/bin/run_tests b/catapult/systrace/bin/run_tests new file mode 100755 index 00000000..6578a8b0 --- /dev/null +++ b/catapult/systrace/bin/run_tests @@ -0,0 +1,27 @@ +#!/usr/bin/env python2.7 + +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Runs the unit test suite for systrace.""" + +import os +import sys +import unittest + +_CATAPULT = os.path.abspath( + os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)) + +def main(): + systrace_package_path = os.path.join(_CATAPULT, 'systrace', 'systrace') + suite = unittest.TestLoader().discover( + systrace_package_path, pattern = '*_unittest.py') + result = unittest.TextTestRunner(verbosity=2).run(suite) + if result.wasSuccessful(): + sys.exit(0) + else: + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/catapult/systrace/systrace/.gitignore b/catapult/systrace/systrace/.gitignore new file mode 100644 index 00000000..8a3c5edf --- /dev/null +++ b/catapult/systrace/systrace/.gitignore @@ -0,0 +1,3 @@ +*.pyc +systrace_trace_viewer.html +trace.html diff --git a/AUTHORS b/catapult/systrace/systrace/AUTHORS index 5a7ed829..5a7ed829 100644 --- a/AUTHORS +++ b/catapult/systrace/systrace/AUTHORS diff --git a/LICENSE b/catapult/systrace/systrace/LICENSE index 8dc35041..8dc35041 100644 --- a/LICENSE +++ b/catapult/systrace/systrace/LICENSE diff --git a/catapult/systrace/systrace/OWNERS b/catapult/systrace/systrace/OWNERS new file mode 100644 index 00000000..a007f0a3 --- /dev/null +++ b/catapult/systrace/systrace/OWNERS @@ -0,0 +1 @@ +ccraik@google.com diff --git a/catapult/systrace/systrace/README.md b/catapult/systrace/systrace/README.md new file mode 100644 index 00000000..0e103a52 --- /dev/null +++ b/catapult/systrace/systrace/README.md @@ -0,0 +1,16 @@ +<!-- Copyright 2015 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> +Systrace +======== + +Systrace relies on +[Trace-Viewer](https://github.com/catapult-project/catapult/blob/master/tracing/README.md) +to visualize the traces. The development of Trace-Viewer and Systrace is +decoupled by the systrace_trace_viewer.html file. +* The update_systrace_trace_viewer.py script generates +systrace_trace_viewer.html based on the Trace-Viewer code. +* Systrace visualizes the trace result based on systrace_trace_viewer.html. +* Systrace will auto update systrace_trace_viewer.html if +update_systrace_trace_viewer.py exists. diff --git a/catapult/systrace/systrace/agents/__init__.py b/catapult/systrace/systrace/agents/__init__.py new file mode 100644 index 00000000..047b03ca --- /dev/null +++ b/catapult/systrace/systrace/agents/__init__.py @@ -0,0 +1,3 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. diff --git a/agents/atrace_agent.py b/catapult/systrace/systrace/agents/atrace_agent.py index 897059d2..8b7c779b 100644 --- a/agents/atrace_agent.py +++ b/catapult/systrace/systrace/agents/atrace_agent.py @@ -78,13 +78,14 @@ class AtraceAgent(systrace_agent.SystraceAgent): self._expect_trace = False self._adb = None self._trace_data = None + self._tracer_args = None if not self._categories: self._categories = get_default_categories(self._options.device_serial) def start(self): - tracer_args = self._construct_trace_command() + self._tracer_args = self._construct_trace_command() - self._adb = do_popen(tracer_args) + self._adb = do_popen(self._tracer_args) def collect_result(self): trace_data = self._collect_trace_data() @@ -266,7 +267,7 @@ class AtraceAgent(systrace_agent.SystraceAgent): if self._adb.returncode != 0: print >> sys.stderr, ('The command "%s" returned error code %d.' % - (' '.join(tracer_args), self._adb.returncode)) + (' '.join(self._tracer_args), self._adb.returncode)) sys.exit(1) return trace_data @@ -324,18 +325,25 @@ class AtraceLegacyAgent(AtraceAgent): super(AtraceLegacyAgent, self).start() if self.expect_trace(): SHELL_ARGS = ['getprop', 'debug.atrace.tags.enableflags'] - output, return_code = util.run_adb_shell(SHELL_ARGS, self._options.device_serial) + output, return_code = util.run_adb_shell(SHELL_ARGS, + self._options.device_serial) + if return_code != 0: + print >> sys.stderr, ( + '\nThe command "%s" failed with the following message:' + % ' '.join(SHELL_ARGS)) + print >> sys.stderr, str(output) + sys.exit(1) + flags = 0 - if return_code == 0: - try: - if output.startswith('0x'): - flags = int(output, 16) - elif output.startswith('0'): - flags = int(output, 8) - else: - flags = int(output) - except ValueError, e: - pass + try: + if output.startswith('0x'): + flags = int(output, 16) + elif output.startswith('0'): + flags = int(output, 8) + else: + flags = int(output) + except ValueError: + pass if flags: tags = [] diff --git a/run_unittest.py b/catapult/systrace/systrace/agents/atrace_agent_unittest.py index 862dbb2f..46a5ed2b 100755..100644 --- a/run_unittest.py +++ b/catapult/systrace/systrace/agents/atrace_agent_unittest.py @@ -3,7 +3,9 @@ # Copyright (c) 2015 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. + import contextlib +import os import unittest import agents.atrace_agent as atrace_agent @@ -11,7 +13,6 @@ import systrace import util DEVICE_SERIAL = 'AG8404EC0444AGC' -LIST_TMP_ARGS = ['ls', '/data/local/tmp'] ATRACE_ARGS = ['atrace', '-z', '-t', '10', '-b', '4096'] CATEGORIES = ['sched', 'gfx', 'view', 'wm'] ADB_SHELL = ['adb', '-s', DEVICE_SERIAL, 'shell'] @@ -36,37 +37,24 @@ TRACE_BOOT_CMD = (ADB_SHELL + 'persist.debug.atrace.boottrace', '0', '&&', 'rm', '/data/misc/boottrace/categories']) -TEST_DIR = 'test_data/' -ATRACE_DATA = TEST_DIR + 'atrace_data' -ATRACE_DATA_RAW = TEST_DIR + 'atrace_data_raw' -ATRACE_DATA_RAW_FROM_FILE = TEST_DIR + 'atrace_data_raw_from_file' -ATRACE_DATA_STRIPPED = TEST_DIR + 'atrace_data_stripped' -ATRACE_DATA_THREAD_FIXED = TEST_DIR + 'atrace_data_thread_fixed' -ATRACE_DATA_WITH_THREAD_LIST = TEST_DIR + 'atrace_data_with_thread_list' -ATRACE_THREAD_NAMES = TEST_DIR + 'atrace_thread_names' -ATRACE_THREAD_LIST = TEST_DIR + 'atrace_ps_dump' -ATRACE_EXTRACTED_THREADS = TEST_DIR + 'atrace_extracted_threads' -ATRACE_PROCFS_DUMP = TEST_DIR + 'atrace_procfs_dump' -ATRACE_EXTRACTED_TGIDS = TEST_DIR + 'atrace_extracted_tgids' -ATRACE_MISSING_TGIDS = TEST_DIR + 'atrace_missing_tgids' -ATRACE_FIXED_TGIDS = TEST_DIR + 'atrace_fixed_tgids' - - -class UtilUnitTest(unittest.TestCase): - def test_construct_adb_shell_command(self): - command = util.construct_adb_shell_command(LIST_TMP_ARGS, None) - self.assertEqual(' '.join(command), 'adb shell ls /data/local/tmp') - - command = util.construct_adb_shell_command(LIST_TMP_ARGS, DEVICE_SERIAL) - self.assertEqual(' '.join(command), - 'adb -s AG8404EC0444AGC shell ls /data/local/tmp') - - command = util.construct_adb_shell_command(ATRACE_ARGS, DEVICE_SERIAL) - self.assertEqual(' '.join(command), - 'adb -s AG8404EC0444AGC shell atrace -z -t 10 -b 4096') - - -class AtraceAgentUnitTest(unittest.TestCase): +TEST_DIR = os.path.join(os.path.dirname(__file__), os.pardir, 'test_data') +ATRACE_DATA = os.path.join(TEST_DIR, 'atrace_data') +ATRACE_DATA_RAW = os.path.join(TEST_DIR, 'atrace_data_raw') +ATRACE_DATA_RAW_FROM_FILE = os.path.join(TEST_DIR, 'atrace_data_raw_from_file') +ATRACE_DATA_STRIPPED = os.path.join(TEST_DIR, 'atrace_data_stripped') +ATRACE_DATA_THREAD_FIXED = os.path.join(TEST_DIR, 'atrace_data_thread_fixed') +ATRACE_DATA_WITH_THREAD_LIST = os.path.join(TEST_DIR, + 'atrace_data_with_thread_list') +ATRACE_THREAD_NAMES = os.path.join(TEST_DIR, 'atrace_thread_names') +ATRACE_THREAD_LIST = os.path.join(TEST_DIR, 'atrace_ps_dump') +ATRACE_EXTRACTED_THREADS = os.path.join(TEST_DIR, 'atrace_extracted_threads') +ATRACE_PROCFS_DUMP = os.path.join(TEST_DIR, 'atrace_procfs_dump') +ATRACE_EXTRACTED_TGIDS = os.path.join(TEST_DIR, 'atrace_extracted_tgids') +ATRACE_MISSING_TGIDS = os.path.join(TEST_DIR, 'atrace_missing_tgids') +ATRACE_FIXED_TGIDS = os.path.join(TEST_DIR, 'atrace_fixed_tgids') + + +class AtraceAgentTest(unittest.TestCase): def test_construct_trace_command(self): options, categories = systrace.parse_options(SYSTRACE_CMD) agent = atrace_agent.AtraceAgent(options, categories) @@ -161,7 +149,7 @@ class AtraceAgentUnitTest(unittest.TestCase): self.assertEqual(res, fixed) -class AtraceLegacyAgentUnitTest(unittest.TestCase): +class AtraceLegacyAgentTest(unittest.TestCase): def test_construct_trace_command(self): options, categories = systrace.parse_options(SYSTRACE_CMD) agent = atrace_agent.AtraceLegacyAgent(options, categories) @@ -170,14 +158,10 @@ class AtraceLegacyAgentUnitTest(unittest.TestCase): self.assertEqual(True, agent.expect_trace()) -class BootAgentUnitTest(unittest.TestCase): +class BootAgentTest(unittest.TestCase): def test_boot(self): options, categories = systrace.parse_options(SYSTRACE_BOOT_CMD) agent = atrace_agent.BootAgent(options, categories) tracer_args = agent._construct_trace_command() self.assertEqual(' '.join(TRACE_BOOT_CMD), ' '.join(tracer_args)) self.assertEqual(True, agent.expect_trace()) - - -if __name__ == '__main__': - unittest.main() diff --git a/prefix.html b/catapult/systrace/systrace/prefix.html index 7749d886..7749d886 100644 --- a/prefix.html +++ b/catapult/systrace/systrace/prefix.html diff --git a/suffix.html b/catapult/systrace/systrace/suffix.html index 308b1d01..308b1d01 100644 --- a/suffix.html +++ b/catapult/systrace/systrace/suffix.html diff --git a/systrace-legacy.py b/catapult/systrace/systrace/systrace-legacy.py index 4e29572e..859a4164 100755 --- a/systrace-legacy.py +++ b/catapult/systrace/systrace/systrace-legacy.py @@ -49,9 +49,9 @@ def main(): action='store_true', help='trace CPU idle events') parser.add_option('-l', '--cpu-load', dest='trace_cpu_load', default=False, action='store_true', help='trace CPU load') - parser.add_option('-s', '--no-cpu-sched', dest='trace_cpu_sched', default=True, - action='store_false', help='inhibit tracing CPU ' + - 'scheduler (allows longer trace times by reducing data ' + + parser.add_option('-s', '--no-cpu-sched', dest='trace_cpu_sched', + default=True, action='store_false', help='inhibit tracing ' + 'CPU scheduler (allows longer trace times by reducing data ' 'rate into buffer)') parser.add_option('-u', '--bus-utilization', dest='trace_bus_utilization', default=False, action='store_true', @@ -64,15 +64,16 @@ def main(): 'comma separated list of: ' + ', '.join(trace_tag_bits.iterkeys())) parser.add_option('--link-assets', dest='link_assets', default=False, - action='store_true', help='link to original CSS or JS resources ' - 'instead of embedding them') + action='store_true', help='link to original CSS or JS ' + 'resources instead of embedding them') parser.add_option('--from-file', dest='from_file', action='store', - help='read the trace from a file rather than running a live trace') + help='read the trace from a file rather than running a live' + ' trace') parser.add_option('--asset-dir', dest='asset_dir', default='trace-viewer', type='string', help='') parser.add_option('-e', '--serial', dest='device_serial', type='string', help='adb device serial number') - options, args = parser.parse_args() + options, unused_args = parser.parse_args() # pylint: disable=unused-variable if options.link_assets or options.asset_dir != 'trace-viewer': parser.error('--link-assets and --asset-dir is deprecated.') @@ -86,16 +87,16 @@ def main(): except KeyError: parser.error('unrecognized tag: %s\nknown tags are: %s' % (tag, ', '.join(trace_tag_bits.iterkeys()))) - atrace_args = ['adb', 'shell', 'setprop', 'debug.atrace.tags.enableflags', hex(flags)] + atrace_args = ['adb', 'shell', 'setprop', 'debug.atrace.tags.enableflags', + hex(flags)] add_adb_serial(atrace_args, options.device_serial) try: subprocess.check_call(atrace_args) except subprocess.CalledProcessError, e: print >> sys.stderr, 'unable to set tags: %s' % e print '\nSet enabled tags to: %s\n' % ', '.join(tags) - print ('You will likely need to restart the Android framework for this to ' + - 'take effect:\n\n adb shell stop\n adb shell ' + - 'start\n') + print ('You will likely need to restart the Android framework for this to ' + 'take effect:\n\n adb shell stop\n adb shell start\n') return atrace_args = ['adb', 'shell', 'atrace', '-z'] @@ -142,7 +143,8 @@ def main(): stderr=subprocess.PIPE) dec = zlib.decompressobj() while True: - ready = select.select([adb.stdout, adb.stderr], [], [adb.stdout, adb.stderr]) + ready = select.select([adb.stdout, adb.stderr], [], + [adb.stdout, adb.stderr]) if adb.stderr in ready[0]: err = os.read(adb.stderr.fileno(), 4096) sys.stderr.write(err) @@ -196,10 +198,11 @@ def main(): html_suffix = read_asset(script_dir, 'suffix.html') html_file.write(html_suffix) html_file.close() - print " done\n\n wrote file://%s\n" % (os.path.abspath(options.output_file)) + print " done\n\n wrote file://%s\n" % ( + os.path.abspath(options.output_file)) else: - print >> sys.stderr, ('An error occured while capturing the trace. Output ' + - 'file was not written.') + print >> sys.stderr, ('An error occured while capturing the trace. Output ' + 'file was not written.') def read_asset(src_dir, filename): return open(os.path.join(src_dir, filename)).read() diff --git a/catapult/systrace/systrace/systrace.py b/catapult/systrace/systrace/systrace.py new file mode 100755 index 00000000..9a6a05a3 --- /dev/null +++ b/catapult/systrace/systrace/systrace.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python + +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Android system-wide tracing utility. + +This is a tool for capturing a trace that includes data from both userland and +the kernel. It creates an HTML file for visualizing the trace. +""" + +import sys + +# Make sure we're using a new enough version of Python. +# The flags= parameter of re.sub() is new in Python 2.7. And Systrace does not +# support Python 3 yet. +version = sys.version_info[:2] +if version != (2, 7): + sys.stderr.write('This script does not support Python %d.%d. ' + 'Please use Python 2.7.\n' % version) + sys.exit(1) + +import imp +import optparse +import os + +import util + + +# The default agent directory. +DEFAULT_AGENT_DIR = 'agents' + + +def parse_options(argv): + """Parses and checks the command-line options. + + Returns: + A tuple containing the options structure and a list of categories to + be traced. + """ + usage = 'Usage: %prog [options] [category1 [category2 ...]]' + desc = 'Example: %prog -b 32768 -t 15 gfx input view sched freq' + parser = optparse.OptionParser(usage=usage, description=desc) + parser.add_option('-o', dest='output_file', help='write HTML to FILE', + default='trace.html', metavar='FILE') + parser.add_option('-t', '--time', dest='trace_time', type='int', + help='trace for N seconds', metavar='N') + parser.add_option('-b', '--buf-size', dest='trace_buf_size', type='int', + help='use a trace buffer size of N KB', metavar='N') + parser.add_option('-k', '--ktrace', dest='kfuncs', action='store', + help='specify a comma-separated list of kernel functions ' + 'to trace') + parser.add_option('-l', '--list-categories', dest='list_categories', + default=False, action='store_true', + help='list the available categories and exit') + parser.add_option('-a', '--app', dest='app_name', default=None, type='string', + action='store', + help='enable application-level tracing for comma-separated ' + 'list of app cmdlines') + parser.add_option('--no-fix-threads', dest='fix_threads', default=True, + action='store_false', + help='don\'t fix missing or truncated thread names') + parser.add_option('--no-fix-tgids', dest='fix_tgids', default=True, + action='store_false', + help='Do not run extra commands to restore missing thread ' + 'to thread group id mappings.') + parser.add_option('--no-fix-circular', dest='fix_circular', default=True, + action='store_false', + help='don\'t fix truncated circular traces') + parser.add_option('--no-compress', dest='compress_trace_data', + default=True, action='store_false', + help='Tell the device not to send the trace data in ' + 'compressed form.') + parser.add_option('--link-assets', dest='link_assets', default=False, + action='store_true', + help='(deprecated)') + parser.add_option('--boot', dest='boot', default=False, action='store_true', + help='reboot the device with tracing during boot enabled. ' + 'The report is created by hitting Ctrl+C after the device ' + 'has booted up.') + parser.add_option('--from-file', dest='from_file', action='store', + help='read the trace from a file (compressed) rather than ' + 'running a live trace') + parser.add_option('--asset-dir', dest='asset_dir', default='trace-viewer', + type='string', help='(deprecated)') + parser.add_option('-e', '--serial', dest='device_serial', type='string', + help='adb device serial number') + parser.add_option('--agent-dirs', dest='agent_dirs', type='string', + help='the directories of additional systrace agent modules.' + ' The directories should be comma separated, e.g., ' + '--agent-dirs=dir1,dir2,dir3. Directory |%s| is the default' + ' agent directory and will always be checked.' + % DEFAULT_AGENT_DIR) + + options, categories = parser.parse_args(argv[1:]) + + if options.link_assets or options.asset_dir != 'trace-viewer': + parser.error('--link-assets and --asset-dir are deprecated.') + + if (options.trace_time is not None) and (options.trace_time <= 0): + parser.error('the trace time must be a positive number') + + if (options.trace_buf_size is not None) and (options.trace_buf_size <= 0): + parser.error('the trace buffer size must be a positive number') + + return (options, categories) + + +def write_trace_html(html_filename, script_dir, agents): + """Writes out a trace html file. + + Args: + html_filename: The name of the file to write. + script_dir: The directory containing this script. + agents: The systrace agents. + """ + systrace_dir = os.path.abspath(os.path.dirname(__file__)) + html_prefix = read_asset(systrace_dir, 'prefix.html') + html_suffix = read_asset(systrace_dir, 'suffix.html') + trace_viewer_html = read_asset(script_dir, 'systrace_trace_viewer.html') + + # Open the file in binary mode to prevent python from changing the + # line endings. + html_file = open(html_filename, 'wb') + html_file.write(html_prefix.replace('{{SYSTRACE_TRACE_VIEWER_HTML}}', + trace_viewer_html)) + + html_file.write('<!-- BEGIN TRACE -->\n') + for a in agents: + html_file.write(' <script class="') + html_file.write(a.get_class_name()) + html_file.write('" type="application/text">\n') + html_file.write(a.get_trace_data()) + html_file.write(' </script>\n') + html_file.write('<!-- END TRACE -->\n') + + html_file.write(html_suffix) + html_file.close() + print('\n wrote file://%s\n' % os.path.abspath(html_filename)) + + +def create_agents(options, categories): + """Create systrace agents. + + This function will search systrace agent modules in agent directories and + create the corresponding systrace agents. + Args: + options: The command-line options. + categories: The trace categories to capture. + Returns: + The list of systrace agents. + """ + agent_dirs = [os.path.join(os.path.dirname(__file__), DEFAULT_AGENT_DIR)] + if options.agent_dirs: + agent_dirs.extend(options.agent_dirs.split(',')) + + agents = [] + for agent_dir in agent_dirs: + if not agent_dir: + continue + for filename in os.listdir(agent_dir): + (module_name, ext) = os.path.splitext(filename) + if (ext != '.py' or module_name == '__init__' + or module_name.endswith('_unittest')): + continue + (f, pathname, data) = imp.find_module(module_name, [agent_dir]) + try: + module = imp.load_module(module_name, f, pathname, data) + finally: + if f: + f.close() + if module: + agent = module.try_create_agent(options, categories) + if not agent: + continue + agents.append(agent) + return agents + + +def main(): + options, categories = parse_options(sys.argv) + agents = create_agents(options, categories) + + if not agents: + dirs = DEFAULT_AGENT_DIR + if options.agent_dirs: + dirs += ',' + options.agent_dirs + sys.stderr.write('No systrace agent is available in directories |%s|.\n' % + dirs) + sys.exit(1) + + try: + update_systrace_trace_viewer = __import__('update_systrace_trace_viewer') + except ImportError: + pass + else: + update_systrace_trace_viewer.update() + + for a in agents: + a.start() + + for a in agents: + a.collect_result() + if not a.expect_trace(): + # Nothing more to do. + return + + script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) + write_trace_html(options.output_file, script_dir, agents) + + +def read_asset(src_dir, filename): + return open(os.path.join(src_dir, filename)).read() + + +if __name__ == '__main__': + main() diff --git a/systrace_agent.py b/catapult/systrace/systrace/systrace_agent.py index 376d4f25..376d4f25 100644 --- a/systrace_agent.py +++ b/catapult/systrace/systrace/systrace_agent.py diff --git a/test_data/atrace_data b/catapult/systrace/systrace/test_data/atrace_data index 2aceb181..2aceb181 100644 --- a/test_data/atrace_data +++ b/catapult/systrace/systrace/test_data/atrace_data diff --git a/test_data/atrace_data_raw b/catapult/systrace/systrace/test_data/atrace_data_raw index 6500ec05..1c8e0860 100644 --- a/test_data/atrace_data_raw +++ b/catapult/systrace/systrace/test_data/atrace_data_raw @@ -1,128 +1,128 @@ -
-# tracer: nop
-#
-# entries-in-buffer/entries-written: 116/116 #P:1
-#
-# _-----=> irqs-off
-# / _----=> need-resched
-# | / _---=> hardirq/softirq
-# || / _--=> preempt-depth
-# ||| / delay
-# TASK-PID CPU# |||| TIMESTAMP FUNCTION
-# | | | |||| | |
- atrace-14446 [000] ...2 1212.465062: sched_switch: prev_comm=atrace prev_pid=14446 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.465074: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.465082: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.465092: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.465102: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.465126: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.465132: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.465139: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.465145: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.465227: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h5 1212.465297: sched_wakeup: comm=adbd pid=212 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.465306: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=adbd next_pid=212 next_prio=120
- adbd-212 [000] d..4 1212.465329: sched_wakeup: comm=adbd pid=209 prio=120 success=1 target_cpu=000
- adbd-212 [000] ...2 1212.465348: sched_switch: prev_comm=adbd prev_pid=212 prev_prio=120 prev_state=S ==> next_comm=adbd next_pid=209 next_prio=120
- adbd-209 [000] d..4 1212.465395: sched_wakeup: comm=adbd pid=211 prio=120 success=1 target_cpu=000
- adbd-209 [000] ...2 1212.465441: sched_switch: prev_comm=adbd prev_pid=209 prev_prio=120 prev_state=S ==> next_comm=adbd next_pid=211 next_prio=120
- adbd-211 [000] ...2 1212.465448: sched_switch: prev_comm=adbd prev_pid=211 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h5 1212.574554: sched_wakeup: comm=sensors.qcom pid=292 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.574566: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=sensors.qcom next_pid=292 next_prio=120
- sensors.qcom-292 [000] ...2 1212.574665: sched_switch: prev_comm=sensors.qcom prev_pid=292 prev_prio=120 prev_state=S ==> next_comm=sensors.qcom next_pid=14447 next_prio=120
- sensors.qcom-14447 [000] d..4 1212.574797: sched_wakeup: comm=sensors.qcom pid=1593 prio=120 success=1 target_cpu=000
- sensors.qcom-14447 [000] ...2 1212.574802: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=R+ ==> next_comm=sensors.qcom next_pid=1593 next_prio=120
- sensors.qcom-1593 [000] ...2 1212.574819: sched_switch: prev_comm=sensors.qcom prev_pid=1593 prev_prio=120 prev_state=D ==> next_comm=sensors.qcom next_pid=14447 next_prio=120
- sensors.qcom-14447 [000] d..3 1212.574823: sched_wakeup: comm=sensors.qcom pid=1593 prio=120 success=1 target_cpu=000
- sensors.qcom-14447 [000] ...2 1212.574827: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=R+ ==> next_comm=sensors.qcom next_pid=1593 next_prio=120
- sensors.qcom-1593 [000] d..4 1212.574865: sched_wakeup: comm=sensors.qcom pid=760 prio=120 success=1 target_cpu=000
- sensors.qcom-1593 [000] ...2 1212.574876: sched_switch: prev_comm=sensors.qcom prev_pid=1593 prev_prio=120 prev_state=S ==> next_comm=sensors.qcom next_pid=760 next_prio=120
- sensors.qcom-760 [000] d..4 1212.574905: sched_wakeup: comm=system_server pid=782 prio=118 success=1 target_cpu=000
- sensors.qcom-760 [000] ...2 1212.574917: sched_switch: prev_comm=sensors.qcom prev_pid=760 prev_prio=120 prev_state=S ==> next_comm=system_server next_pid=782 next_prio=118
- system_server-782 [000] d..4 1212.574981: sched_wakeup: comm=system_server pid=785 prio=118 success=1 target_cpu=000
- system_server-782 [000] ...2 1212.575009: sched_switch: prev_comm=system_server prev_pid=782 prev_prio=118 prev_state=S ==> next_comm=system_server next_pid=785 next_prio=118
- system_server-785 [000] ...2 1212.575045: sched_switch: prev_comm=system_server prev_pid=785 prev_prio=118 prev_state=S ==> next_comm=sensors.qcom next_pid=14447 next_prio=120
- sensors.qcom-14447 [000] ...3 1212.575143: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=x ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.575153: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.575159: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.575167: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.575175: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.575181: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.575188: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.575195: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.575201: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.575211: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h4 1212.649601: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.649614: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120
- MMHandlerThread-7231 [000] ...2 1212.649630: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h6 1212.729539: sched_wakeup: comm=kworker/u:1 pid=21 prio=120 success=1 target_cpu=000
- <idle>-0 [000] dNs6 1212.729550: sched_wakeup: comm=kworker/0:2H pid=557 prio=100 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.729563: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:1 next_pid=21 next_prio=120
- kworker/u:1-21 [000] d..5 1212.729571: sched_wakeup: comm=mpdecision pid=2046 prio=113 success=1 target_cpu=000
- kworker/u:1-21 [000] ...2 1212.729578: sched_switch: prev_comm=kworker/u:1 prev_pid=21 prev_prio=120 prev_state=S ==> next_comm=kworker/0:2H next_pid=557 next_prio=100
- kworker/0:2H-557 [000] d..4 1212.729597: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000
- kworker/0:2H-557 [000] ...2 1212.729600: sched_switch: prev_comm=kworker/0:2H prev_pid=557 prev_prio=100 prev_state=D ==> next_comm=mpdecision next_pid=2046 next_prio=113
- mpdecision-2046 [000] ...2 1212.729801: sched_switch: prev_comm=mpdecision prev_pid=2046 prev_prio=113 prev_state=S ==> next_comm=kworker/0:1H next_pid=17 next_prio=100
- kworker/0:1H-17 [000] ...2 1212.730104: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.730134: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.730154: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.730176: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.730201: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.730220: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.730241: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.730262: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.730280: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.730303: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h6 1212.730638: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.730669: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100
- kworker/u:0H-7 [000] d..6 1212.730707: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000
- kworker/u:0H-7 [000] ...2 1212.730728: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100
- kworker/0:1H-17 [000] ...2 1212.730916: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h6 1212.731632: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.731661: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100
- kworker/u:0H-7 [000] d..6 1212.731702: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000
- kworker/u:0H-7 [000] ...2 1212.731722: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100
- kworker/0:1H-17 [000] ...2 1212.731832: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h6 1212.732685: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.732714: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100
- kworker/u:0H-7 [000] d..6 1212.732747: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000
- kworker/u:0H-7 [000] ...2 1212.732767: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100
- kworker/0:1H-17 [000] d..4 1212.732810: sched_wakeup: comm=kworker/0:2H pid=557 prio=100 success=1 target_cpu=000
- kworker/0:1H-17 [000] ...2 1212.732829: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=S ==> next_comm=kworker/0:2H next_pid=557 next_prio=100
- kworker/0:2H-557 [000] ...2 1212.732854: sched_switch: prev_comm=kworker/0:2H prev_pid=557 prev_prio=100 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h4 1212.876266: sched_wakeup: comm=RILSender0 pid=1365 prio=120 success=1 target_cpu=000
- <idle>-0 [000] dNh4 1212.876284: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.876316: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=RILSender0 next_pid=1365 next_prio=120
- RILSender0-1365 [000] ...2 1212.876415: sched_switch: prev_comm=RILSender0 prev_pid=1365 prev_prio=120 prev_state=S ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120
- MMHandlerThread-7231 [000] ...2 1212.876454: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h4 1213.089569: sched_wakeup: comm=Thread-625 pid=5750 prio=120 success=1 target_cpu=000
- <idle>-0 [000] dNh4 1213.089587: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.089622: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=Thread-625 next_pid=5750 next_prio=120
- Thread-625-5750 [000] ...2 1213.089842: sched_switch: prev_comm=Thread-625 prev_pid=5750 prev_prio=120 prev_state=S ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120
- MMHandlerThread-7231 [000] ...2 1213.089879: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h4 1213.327439: sched_wakeup: comm=pandora.android pid=5395 prio=120 success=1 target_cpu=000
- <idle>-0 [000] dNh4 1213.327455: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.327487: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120
- MMHandlerThread-7231 [000] ...2 1213.327518: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=pandora.android next_pid=5395 next_prio=120
- pandora.android-5395 [000] d..4 1213.327718: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000
- pandora.android-5395 [000] ...2 1213.327739: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=780 next_prio=120
- Binder_1-780 [000] ...2 1213.327763: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=D ==> next_comm=pandora.android next_pid=5395 next_prio=120
- pandora.android-5395 [000] d..3 1213.327781: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000
- pandora.android-5395 [000] ...2 1213.327795: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=780 next_prio=120
- Binder_1-780 [000] d..4 1213.328056: sched_wakeup: comm=Binder_1 pid=878 prio=120 success=1 target_cpu=000
- Binder_1-780 [000] ...2 1213.328095: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=S ==> next_comm=Binder_1 next_pid=878 next_prio=120
- Binder_1-878 [000] d..4 1213.328263: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000
- Binder_1-878 [000] ...2 1213.328345: sched_switch: prev_comm=Binder_1 prev_pid=878 prev_prio=120 prev_state=S ==> next_comm=Binder_1 next_pid=780 next_prio=120
- Binder_1-780 [000] ...2 1213.328558: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=S ==> next_comm=pandora.android next_pid=5395 next_prio=120
- pandora.android-5395 [000] ...2 1213.328743: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1213.328773: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.328793: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1213.328821: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1213.328846: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.328866: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1213.328891: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1213.328913: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.328931: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1213.328964: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h4 1213.465138: sched_wakeup: comm=atrace pid=14446 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.465171: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=atrace next_pid=14446 next_prio=120
+ +# tracer: nop +# +# entries-in-buffer/entries-written: 116/116 #P:1 +# +# _-----=> irqs-off +# / _----=> need-resched +# | / _---=> hardirq/softirq +# || / _--=> preempt-depth +# ||| / delay +# TASK-PID CPU# |||| TIMESTAMP FUNCTION +# | | | |||| | | + atrace-14446 [000] ...2 1212.465062: sched_switch: prev_comm=atrace prev_pid=14446 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.465074: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.465082: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.465092: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.465102: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.465126: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.465132: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.465139: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.465145: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.465227: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h5 1212.465297: sched_wakeup: comm=adbd pid=212 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.465306: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=adbd next_pid=212 next_prio=120 + adbd-212 [000] d..4 1212.465329: sched_wakeup: comm=adbd pid=209 prio=120 success=1 target_cpu=000 + adbd-212 [000] ...2 1212.465348: sched_switch: prev_comm=adbd prev_pid=212 prev_prio=120 prev_state=S ==> next_comm=adbd next_pid=209 next_prio=120 + adbd-209 [000] d..4 1212.465395: sched_wakeup: comm=adbd pid=211 prio=120 success=1 target_cpu=000 + adbd-209 [000] ...2 1212.465441: sched_switch: prev_comm=adbd prev_pid=209 prev_prio=120 prev_state=S ==> next_comm=adbd next_pid=211 next_prio=120 + adbd-211 [000] ...2 1212.465448: sched_switch: prev_comm=adbd prev_pid=211 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h5 1212.574554: sched_wakeup: comm=sensors.qcom pid=292 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.574566: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=sensors.qcom next_pid=292 next_prio=120 + sensors.qcom-292 [000] ...2 1212.574665: sched_switch: prev_comm=sensors.qcom prev_pid=292 prev_prio=120 prev_state=S ==> next_comm=sensors.qcom next_pid=14447 next_prio=120 + sensors.qcom-14447 [000] d..4 1212.574797: sched_wakeup: comm=sensors.qcom pid=1593 prio=120 success=1 target_cpu=000 + sensors.qcom-14447 [000] ...2 1212.574802: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=R+ ==> next_comm=sensors.qcom next_pid=1593 next_prio=120 + sensors.qcom-1593 [000] ...2 1212.574819: sched_switch: prev_comm=sensors.qcom prev_pid=1593 prev_prio=120 prev_state=D ==> next_comm=sensors.qcom next_pid=14447 next_prio=120 + sensors.qcom-14447 [000] d..3 1212.574823: sched_wakeup: comm=sensors.qcom pid=1593 prio=120 success=1 target_cpu=000 + sensors.qcom-14447 [000] ...2 1212.574827: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=R+ ==> next_comm=sensors.qcom next_pid=1593 next_prio=120 + sensors.qcom-1593 [000] d..4 1212.574865: sched_wakeup: comm=sensors.qcom pid=760 prio=120 success=1 target_cpu=000 + sensors.qcom-1593 [000] ...2 1212.574876: sched_switch: prev_comm=sensors.qcom prev_pid=1593 prev_prio=120 prev_state=S ==> next_comm=sensors.qcom next_pid=760 next_prio=120 + sensors.qcom-760 [000] d..4 1212.574905: sched_wakeup: comm=system_server pid=782 prio=118 success=1 target_cpu=000 + sensors.qcom-760 [000] ...2 1212.574917: sched_switch: prev_comm=sensors.qcom prev_pid=760 prev_prio=120 prev_state=S ==> next_comm=system_server next_pid=782 next_prio=118 + system_server-782 [000] d..4 1212.574981: sched_wakeup: comm=system_server pid=785 prio=118 success=1 target_cpu=000 + system_server-782 [000] ...2 1212.575009: sched_switch: prev_comm=system_server prev_pid=782 prev_prio=118 prev_state=S ==> next_comm=system_server next_pid=785 next_prio=118 + system_server-785 [000] ...2 1212.575045: sched_switch: prev_comm=system_server prev_pid=785 prev_prio=118 prev_state=S ==> next_comm=sensors.qcom next_pid=14447 next_prio=120 + sensors.qcom-14447 [000] ...3 1212.575143: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=x ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.575153: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.575159: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.575167: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.575175: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.575181: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.575188: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.575195: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.575201: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.575211: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h4 1212.649601: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.649614: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120 + MMHandlerThread-7231 [000] ...2 1212.649630: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h6 1212.729539: sched_wakeup: comm=kworker/u:1 pid=21 prio=120 success=1 target_cpu=000 + <idle>-0 [000] dNs6 1212.729550: sched_wakeup: comm=kworker/0:2H pid=557 prio=100 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.729563: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:1 next_pid=21 next_prio=120 + kworker/u:1-21 [000] d..5 1212.729571: sched_wakeup: comm=mpdecision pid=2046 prio=113 success=1 target_cpu=000 + kworker/u:1-21 [000] ...2 1212.729578: sched_switch: prev_comm=kworker/u:1 prev_pid=21 prev_prio=120 prev_state=S ==> next_comm=kworker/0:2H next_pid=557 next_prio=100 + kworker/0:2H-557 [000] d..4 1212.729597: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000 + kworker/0:2H-557 [000] ...2 1212.729600: sched_switch: prev_comm=kworker/0:2H prev_pid=557 prev_prio=100 prev_state=D ==> next_comm=mpdecision next_pid=2046 next_prio=113 + mpdecision-2046 [000] ...2 1212.729801: sched_switch: prev_comm=mpdecision prev_pid=2046 prev_prio=113 prev_state=S ==> next_comm=kworker/0:1H next_pid=17 next_prio=100 + kworker/0:1H-17 [000] ...2 1212.730104: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.730134: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.730154: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.730176: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.730201: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.730220: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.730241: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.730262: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.730280: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.730303: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h6 1212.730638: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.730669: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100 + kworker/u:0H-7 [000] d..6 1212.730707: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000 + kworker/u:0H-7 [000] ...2 1212.730728: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100 + kworker/0:1H-17 [000] ...2 1212.730916: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h6 1212.731632: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.731661: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100 + kworker/u:0H-7 [000] d..6 1212.731702: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000 + kworker/u:0H-7 [000] ...2 1212.731722: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100 + kworker/0:1H-17 [000] ...2 1212.731832: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h6 1212.732685: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.732714: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100 + kworker/u:0H-7 [000] d..6 1212.732747: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000 + kworker/u:0H-7 [000] ...2 1212.732767: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100 + kworker/0:1H-17 [000] d..4 1212.732810: sched_wakeup: comm=kworker/0:2H pid=557 prio=100 success=1 target_cpu=000 + kworker/0:1H-17 [000] ...2 1212.732829: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=S ==> next_comm=kworker/0:2H next_pid=557 next_prio=100 + kworker/0:2H-557 [000] ...2 1212.732854: sched_switch: prev_comm=kworker/0:2H prev_pid=557 prev_prio=100 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h4 1212.876266: sched_wakeup: comm=RILSender0 pid=1365 prio=120 success=1 target_cpu=000 + <idle>-0 [000] dNh4 1212.876284: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.876316: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=RILSender0 next_pid=1365 next_prio=120 + RILSender0-1365 [000] ...2 1212.876415: sched_switch: prev_comm=RILSender0 prev_pid=1365 prev_prio=120 prev_state=S ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120 + MMHandlerThread-7231 [000] ...2 1212.876454: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h4 1213.089569: sched_wakeup: comm=Thread-625 pid=5750 prio=120 success=1 target_cpu=000 + <idle>-0 [000] dNh4 1213.089587: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.089622: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=Thread-625 next_pid=5750 next_prio=120 + Thread-625-5750 [000] ...2 1213.089842: sched_switch: prev_comm=Thread-625 prev_pid=5750 prev_prio=120 prev_state=S ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120 + MMHandlerThread-7231 [000] ...2 1213.089879: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h4 1213.327439: sched_wakeup: comm=pandora.android pid=5395 prio=120 success=1 target_cpu=000 + <idle>-0 [000] dNh4 1213.327455: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.327487: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120 + MMHandlerThread-7231 [000] ...2 1213.327518: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=pandora.android next_pid=5395 next_prio=120 + pandora.android-5395 [000] d..4 1213.327718: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000 + pandora.android-5395 [000] ...2 1213.327739: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=780 next_prio=120 + Binder_1-780 [000] ...2 1213.327763: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=D ==> next_comm=pandora.android next_pid=5395 next_prio=120 + pandora.android-5395 [000] d..3 1213.327781: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000 + pandora.android-5395 [000] ...2 1213.327795: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=780 next_prio=120 + Binder_1-780 [000] d..4 1213.328056: sched_wakeup: comm=Binder_1 pid=878 prio=120 success=1 target_cpu=000 + Binder_1-780 [000] ...2 1213.328095: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=S ==> next_comm=Binder_1 next_pid=878 next_prio=120 + Binder_1-878 [000] d..4 1213.328263: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000 + Binder_1-878 [000] ...2 1213.328345: sched_switch: prev_comm=Binder_1 prev_pid=878 prev_prio=120 prev_state=S ==> next_comm=Binder_1 next_pid=780 next_prio=120 + Binder_1-780 [000] ...2 1213.328558: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=S ==> next_comm=pandora.android next_pid=5395 next_prio=120 + pandora.android-5395 [000] ...2 1213.328743: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1213.328773: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.328793: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1213.328821: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1213.328846: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.328866: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1213.328891: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1213.328913: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.328931: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1213.328964: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h4 1213.465138: sched_wakeup: comm=atrace pid=14446 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.465171: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=atrace next_pid=14446 next_prio=120 diff --git a/test_data/atrace_data_stripped b/catapult/systrace/systrace/test_data/atrace_data_stripped index 3261ebf9..3261ebf9 100644 --- a/test_data/atrace_data_stripped +++ b/catapult/systrace/systrace/test_data/atrace_data_stripped diff --git a/test_data/atrace_data_thread_fixed b/catapult/systrace/systrace/test_data/atrace_data_thread_fixed index 7b423e76..7b423e76 100644 --- a/test_data/atrace_data_thread_fixed +++ b/catapult/systrace/systrace/test_data/atrace_data_thread_fixed diff --git a/test_data/atrace_data_with_thread_list b/catapult/systrace/systrace/test_data/atrace_data_with_thread_list index 860d73fe..32091c9f 100644 --- a/test_data/atrace_data_with_thread_list +++ b/catapult/systrace/systrace/test_data/atrace_data_with_thread_list @@ -1,1660 +1,1660 @@ -
-# tracer: nop
-#
-# entries-in-buffer/entries-written: 116/116 #P:1
-#
-# _-----=> irqs-off
-# / _----=> need-resched
-# | / _---=> hardirq/softirq
-# || / _--=> preempt-depth
-# ||| / delay
-# TASK-PID CPU# |||| TIMESTAMP FUNCTION
-# | | | |||| | |
- atrace-14446 [000] ...2 1212.465062: sched_switch: prev_comm=atrace prev_pid=14446 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.465074: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.465082: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.465092: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.465102: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.465126: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.465132: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.465139: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.465145: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.465227: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h5 1212.465297: sched_wakeup: comm=adbd pid=212 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.465306: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=adbd next_pid=212 next_prio=120
- adbd-212 [000] d..4 1212.465329: sched_wakeup: comm=adbd pid=209 prio=120 success=1 target_cpu=000
- adbd-212 [000] ...2 1212.465348: sched_switch: prev_comm=adbd prev_pid=212 prev_prio=120 prev_state=S ==> next_comm=adbd next_pid=209 next_prio=120
- adbd-209 [000] d..4 1212.465395: sched_wakeup: comm=adbd pid=211 prio=120 success=1 target_cpu=000
- adbd-209 [000] ...2 1212.465441: sched_switch: prev_comm=adbd prev_pid=209 prev_prio=120 prev_state=S ==> next_comm=adbd next_pid=211 next_prio=120
- adbd-211 [000] ...2 1212.465448: sched_switch: prev_comm=adbd prev_pid=211 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h5 1212.574554: sched_wakeup: comm=sensors.qcom pid=292 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.574566: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=sensors.qcom next_pid=292 next_prio=120
- sensors.qcom-292 [000] ...2 1212.574665: sched_switch: prev_comm=sensors.qcom prev_pid=292 prev_prio=120 prev_state=S ==> next_comm=sensors.qcom next_pid=14447 next_prio=120
- sensors.qcom-14447 [000] d..4 1212.574797: sched_wakeup: comm=sensors.qcom pid=1593 prio=120 success=1 target_cpu=000
- sensors.qcom-14447 [000] ...2 1212.574802: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=R+ ==> next_comm=sensors.qcom next_pid=1593 next_prio=120
- sensors.qcom-1593 [000] ...2 1212.574819: sched_switch: prev_comm=sensors.qcom prev_pid=1593 prev_prio=120 prev_state=D ==> next_comm=sensors.qcom next_pid=14447 next_prio=120
- sensors.qcom-14447 [000] d..3 1212.574823: sched_wakeup: comm=sensors.qcom pid=1593 prio=120 success=1 target_cpu=000
- sensors.qcom-14447 [000] ...2 1212.574827: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=R+ ==> next_comm=sensors.qcom next_pid=1593 next_prio=120
- sensors.qcom-1593 [000] d..4 1212.574865: sched_wakeup: comm=sensors.qcom pid=760 prio=120 success=1 target_cpu=000
- sensors.qcom-1593 [000] ...2 1212.574876: sched_switch: prev_comm=sensors.qcom prev_pid=1593 prev_prio=120 prev_state=S ==> next_comm=sensors.qcom next_pid=760 next_prio=120
- sensors.qcom-760 [000] d..4 1212.574905: sched_wakeup: comm=system_server pid=782 prio=118 success=1 target_cpu=000
- sensors.qcom-760 [000] ...2 1212.574917: sched_switch: prev_comm=sensors.qcom prev_pid=760 prev_prio=120 prev_state=S ==> next_comm=system_server next_pid=782 next_prio=118
- system_server-782 [000] d..4 1212.574981: sched_wakeup: comm=system_server pid=785 prio=118 success=1 target_cpu=000
- system_server-782 [000] ...2 1212.575009: sched_switch: prev_comm=system_server prev_pid=782 prev_prio=118 prev_state=S ==> next_comm=system_server next_pid=785 next_prio=118
- system_server-785 [000] ...2 1212.575045: sched_switch: prev_comm=system_server prev_pid=785 prev_prio=118 prev_state=S ==> next_comm=sensors.qcom next_pid=14447 next_prio=120
- sensors.qcom-14447 [000] ...3 1212.575143: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=x ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.575153: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.575159: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.575167: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.575175: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.575181: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.575188: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.575195: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.575201: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.575211: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h4 1212.649601: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.649614: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120
- MMHandlerThread-7231 [000] ...2 1212.649630: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h6 1212.729539: sched_wakeup: comm=kworker/u:1 pid=21 prio=120 success=1 target_cpu=000
- <idle>-0 [000] dNs6 1212.729550: sched_wakeup: comm=kworker/0:2H pid=557 prio=100 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.729563: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:1 next_pid=21 next_prio=120
- kworker/u:1-21 [000] d..5 1212.729571: sched_wakeup: comm=mpdecision pid=2046 prio=113 success=1 target_cpu=000
- kworker/u:1-21 [000] ...2 1212.729578: sched_switch: prev_comm=kworker/u:1 prev_pid=21 prev_prio=120 prev_state=S ==> next_comm=kworker/0:2H next_pid=557 next_prio=100
- kworker/0:2H-557 [000] d..4 1212.729597: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000
- kworker/0:2H-557 [000] ...2 1212.729600: sched_switch: prev_comm=kworker/0:2H prev_pid=557 prev_prio=100 prev_state=D ==> next_comm=mpdecision next_pid=2046 next_prio=113
- mpdecision-2046 [000] ...2 1212.729801: sched_switch: prev_comm=mpdecision prev_pid=2046 prev_prio=113 prev_state=S ==> next_comm=kworker/0:1H next_pid=17 next_prio=100
- kworker/0:1H-17 [000] ...2 1212.730104: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.730134: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.730154: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.730176: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.730201: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.730220: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.730241: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1212.730262: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.730280: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1212.730303: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h6 1212.730638: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.730669: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100
- kworker/u:0H-7 [000] d..6 1212.730707: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000
- kworker/u:0H-7 [000] ...2 1212.730728: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100
- kworker/0:1H-17 [000] ...2 1212.730916: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h6 1212.731632: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.731661: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100
- kworker/u:0H-7 [000] d..6 1212.731702: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000
- kworker/u:0H-7 [000] ...2 1212.731722: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100
- kworker/0:1H-17 [000] ...2 1212.731832: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h6 1212.732685: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.732714: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100
- kworker/u:0H-7 [000] d..6 1212.732747: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000
- kworker/u:0H-7 [000] ...2 1212.732767: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100
- kworker/0:1H-17 [000] d..4 1212.732810: sched_wakeup: comm=kworker/0:2H pid=557 prio=100 success=1 target_cpu=000
- kworker/0:1H-17 [000] ...2 1212.732829: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=S ==> next_comm=kworker/0:2H next_pid=557 next_prio=100
- kworker/0:2H-557 [000] ...2 1212.732854: sched_switch: prev_comm=kworker/0:2H prev_pid=557 prev_prio=100 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h4 1212.876266: sched_wakeup: comm=RILSender0 pid=1365 prio=120 success=1 target_cpu=000
- <idle>-0 [000] dNh4 1212.876284: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1212.876316: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=RILSender0 next_pid=1365 next_prio=120
- RILSender0-1365 [000] ...2 1212.876415: sched_switch: prev_comm=RILSender0 prev_pid=1365 prev_prio=120 prev_state=S ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120
- MMHandlerThread-7231 [000] ...2 1212.876454: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h4 1213.089569: sched_wakeup: comm=Thread-625 pid=5750 prio=120 success=1 target_cpu=000
- <idle>-0 [000] dNh4 1213.089587: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.089622: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=Thread-625 next_pid=5750 next_prio=120
- Thread-625-5750 [000] ...2 1213.089842: sched_switch: prev_comm=Thread-625 prev_pid=5750 prev_prio=120 prev_state=S ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120
- MMHandlerThread-7231 [000] ...2 1213.089879: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h4 1213.327439: sched_wakeup: comm=pandora.android pid=5395 prio=120 success=1 target_cpu=000
- <idle>-0 [000] dNh4 1213.327455: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.327487: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120
- MMHandlerThread-7231 [000] ...2 1213.327518: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=pandora.android next_pid=5395 next_prio=120
- pandora.android-5395 [000] d..4 1213.327718: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000
- pandora.android-5395 [000] ...2 1213.327739: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=780 next_prio=120
- Binder_1-780 [000] ...2 1213.327763: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=D ==> next_comm=pandora.android next_pid=5395 next_prio=120
- pandora.android-5395 [000] d..3 1213.327781: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000
- pandora.android-5395 [000] ...2 1213.327795: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=780 next_prio=120
- Binder_1-780 [000] d..4 1213.328056: sched_wakeup: comm=Binder_1 pid=878 prio=120 success=1 target_cpu=000
- Binder_1-780 [000] ...2 1213.328095: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=S ==> next_comm=Binder_1 next_pid=878 next_prio=120
- Binder_1-878 [000] d..4 1213.328263: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000
- Binder_1-878 [000] ...2 1213.328345: sched_switch: prev_comm=Binder_1 prev_pid=878 prev_prio=120 prev_state=S ==> next_comm=Binder_1 next_pid=780 next_prio=120
- Binder_1-780 [000] ...2 1213.328558: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=S ==> next_comm=pandora.android next_pid=5395 next_prio=120
- pandora.android-5395 [000] ...2 1213.328743: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1213.328773: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.328793: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1213.328821: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1213.328846: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.328866: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1213.328891: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d..4 1213.328913: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.328931: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120
- ksoftirqd/0-3 [000] ...2 1213.328964: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <idle>-0 [000] d.h4 1213.465138: sched_wakeup: comm=atrace pid=14446 prio=120 success=1 target_cpu=000
- <idle>-0 [000] ...2 1213.465171: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=atrace next_pid=14446 next_prio=120
-USER PID PPID VSIZE RSS WCHAN PC NAME
-root 1 0 8784 712 ffffffff 00000000 S /init
-root 2 0 0 0 ffffffff 00000000 S kthreadd
-root 3 2 0 0 ffffffff 00000000 S ksoftirqd/0
-root 7 2 0 0 ffffffff 00000000 D kworker/u:0H
-root 8 2 0 0 ffffffff 00000000 S migration/0
-root 13 2 0 0 ffffffff 00000000 S khelper
-root 14 2 0 0 ffffffff 00000000 S netns
-root 17 2 0 0 ffffffff 00000000 S kworker/0:1H
-root 18 2 0 0 ffffffff 00000000 S modem_notifier
-root 19 2 0 0 ffffffff 00000000 S smd_channel_clo
-root 20 2 0 0 ffffffff 00000000 S smsm_cb_wq
-root 21 2 0 0 ffffffff 00000000 S kworker/u:1
-root 22 2 0 0 ffffffff 00000000 S rpm-smd
-root 23 2 0 0 ffffffff 00000000 S kworker/u:1H
-root 24 2 0 0 ffffffff 00000000 S irq/317-earjack
-root 25 2 0 0 ffffffff 00000000 S sync_supers
-root 26 2 0 0 ffffffff 00000000 S bdi-default
-root 27 2 0 0 ffffffff 00000000 S kblockd
-root 28 2 0 0 ffffffff 00000000 S vmalloc
-root 29 2 0 0 ffffffff 00000000 S khubd
-root 30 2 0 0 ffffffff 00000000 S irq/102-msm_iom
-root 31 2 0 0 ffffffff 00000000 S irq/102-msm_iom
-root 32 2 0 0 ffffffff 00000000 S irq/102-msm_iom
-root 33 2 0 0 ffffffff 00000000 S irq/79-msm_iomm
-root 34 2 0 0 ffffffff 00000000 S irq/78-msm_iomm
-root 35 2 0 0 ffffffff 00000000 S irq/78-msm_iomm
-root 36 2 0 0 ffffffff 00000000 S irq/74-msm_iomm
-root 37 2 0 0 ffffffff 00000000 S irq/75-msm_iomm
-root 38 2 0 0 ffffffff 00000000 S irq/75-msm_iomm
-root 39 2 0 0 ffffffff 00000000 S irq/75-msm_iomm
-root 40 2 0 0 ffffffff 00000000 S irq/75-msm_iomm
-root 41 2 0 0 ffffffff 00000000 S irq/273-msm_iom
-root 42 2 0 0 ffffffff 00000000 S irq/273-msm_iom
-root 43 2 0 0 ffffffff 00000000 S irq/97-msm_iomm
-root 44 2 0 0 ffffffff 00000000 S irq/97-msm_iomm
-root 45 2 0 0 ffffffff 00000000 S irq/97-msm_iomm
-root 46 2 0 0 ffffffff 00000000 S l2cap
-root 47 2 0 0 ffffffff 00000000 S a2mp
-root 48 2 0 0 ffffffff 00000000 S cfg80211
-root 49 2 0 0 ffffffff 00000000 S qmi
-root 50 2 0 0 ffffffff 00000000 S nmea
-root 51 2 0 0 ffffffff 00000000 S msm_ipc_router
-root 52 2 0 0 ffffffff 00000000 S apr_driver
-root 54 2 0 0 ffffffff 00000000 S kswapd0
-root 55 2 0 0 ffffffff 00000000 S fsnotify_mark
-root 56 2 0 0 ffffffff 00000000 S cifsiod
-root 57 2 0 0 ffffffff 00000000 S crypto
-root 75 2 0 0 ffffffff 00000000 S ad_calc_wq
-root 76 2 0 0 ffffffff 00000000 S hdmi_tx_workq
-root 77 2 0 0 ffffffff 00000000 S anx7808_work
-root 78 2 0 0 ffffffff 00000000 S k_hsuart
-root 79 2 0 0 ffffffff 00000000 S diag_wq
-root 80 2 0 0 ffffffff 00000000 S diag_cntl_wq
-root 81 2 0 0 ffffffff 00000000 S diag_dci_wq
-root 82 2 0 0 ffffffff 00000000 S kgsl-3d0
-root 84 2 0 0 ffffffff 00000000 S f9966000.spi
-root 88 2 0 0 ffffffff 00000000 S usbnet
-root 89 2 0 0 ffffffff 00000000 S irq/329-anx7808
-root 90 2 0 0 ffffffff 00000000 S k_rmnet_mux_wor
-root 91 2 0 0 ffffffff 00000000 S f_mtp
-root 92 2 0 0 ffffffff 00000000 S file-storage
-root 93 2 0 0 ffffffff 00000000 S uether
-root 94 2 0 0 ffffffff 00000000 S synaptics_wq
-root 95 2 0 0 ffffffff 00000000 S irq/362-s3350
-root 96 2 0 0 ffffffff 00000000 S kworker/0:2
-root 97 2 0 0 ffffffff 00000000 S msm_vidc_worker
-root 98 2 0 0 ffffffff 00000000 S msm_vidc_worker
-root 99 2 0 0 ffffffff 00000000 S msm_cpp_workque
-root 100 2 0 0 ffffffff 00000000 S irq/350-bq51013
-root 102 2 0 0 ffffffff 00000000 S dm_bufio_cache
-root 103 2 0 0 ffffffff 00000000 D dbs_sync/0
-root 104 2 0 0 ffffffff 00000000 D dbs_sync/1
-root 105 2 0 0 ffffffff 00000000 D dbs_sync/2
-root 106 2 0 0 ffffffff 00000000 D dbs_sync/3
-root 107 2 0 0 ffffffff 00000000 S cfinteractive
-root 108 2 0 0 ffffffff 00000000 S irq/170-msm_sdc
-root 109 2 0 0 ffffffff 00000000 S binder
-root 110 2 0 0 ffffffff 00000000 S usb_bam_wq
-root 111 2 0 0 ffffffff 00000000 S krfcommd
-root 112 2 0 0 ffffffff 00000000 S bam_dmux_rx
-root 113 2 0 0 ffffffff 00000000 S bam_dmux_tx
-root 114 2 0 0 ffffffff 00000000 S rq_stats
-root 115 2 0 0 ffffffff 00000000 S deferwq
-root 117 2 0 0 ffffffff 00000000 S irq/361-MAX1704
-root 119 2 0 0 ffffffff 00000000 S mmcqd/1
-root 120 2 0 0 ffffffff 00000000 S mmcqd/1rpmb
-root 121 2 0 0 ffffffff 00000000 S wl_event_handle
-root 122 2 0 0 ffffffff 00000000 S dhd_watchdog_th
-root 123 2 0 0 ffffffff 00000000 S dhd_dpc
-root 124 2 0 0 ffffffff 00000000 S dhd_rxf
-root 125 2 0 0 ffffffff 00000000 S dhd_sysioc
-root 126 2 0 0 ffffffff 00000000 S vibrator
-root 127 2 0 0 ffffffff 00000000 S max1462x
-root 128 2 0 0 ffffffff 00000000 S irq/310-maxim_m
-root 129 2 0 0 ffffffff 00000000 S irq/311-maxim_m
-root 130 1 8780 576 ffffffff 00000000 S /sbin/ueventd
-root 132 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p25
-root 133 2 0 0 ffffffff 00000000 S ext4-dio-unwrit
-root 136 2 0 0 ffffffff 00000000 S flush-179:0
-root 138 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p28
-root 139 2 0 0 ffffffff 00000000 S ext4-dio-unwrit
-root 143 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p27
-root 144 2 0 0 ffffffff 00000000 S ext4-dio-unwrit
-root 145 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p16
-root 146 2 0 0 ffffffff 00000000 S ext4-dio-unwrit
-logd 169 1 18632 2740 ffffffff 00000000 S /system/bin/logd
-logd 216 169 18632 2740 ffffffff 00000000 S logd.reader
-logd 217 169 18632 2740 ffffffff 00000000 S logd.writer
-logd 218 169 18632 2740 ffffffff 00000000 S logd
-logd 244 169 18632 2740 ffffffff 00000000 S logd.auditd
-root 170 1 9832 304 ffffffff 00000000 S /sbin/healthd
-root 171 1 10620 1240 ffffffff 00000000 S /system/bin/lmkd
-system 172 1 9452 676 ffffffff 00000000 S /system/bin/servicemanager
-root 173 1 18028 1652 ffffffff 00000000 S /system/bin/vold
-root 223 173 18028 1652 ffffffff 00000000 S vold
-root 226 173 18028 1652 ffffffff 00000000 S vold
-root 174 2 0 0 ffffffff 00000000 S IPCRTR
-root 175 2 0 0 ffffffff 00000000 S sb-1
-root 177 2 0 0 ffffffff 00000000 S ipc_rtr_q6_ipcr
-root 179 2 0 0 ffffffff 00000000 S ngd_msm_ctrl_ng
-system 180 1 146792 9724 ffffffff 00000000 S /system/bin/surfaceflinger
-system 240 180 146792 9724 ffffffff 00000000 S Binder_1
-system 242 180 146792 9724 ffffffff 00000000 S DispSync
-system 243 180 146792 9724 ffffffff 00000000 S Binder_2
-system 361 180 146792 9724 ffffffff 00000000 S hwcUeventThread
-system 362 180 146792 9724 ffffffff 00000000 S hwcVsyncThread
-system 396 180 146792 9724 ffffffff 00000000 S GL updater
-system 397 180 146792 9724 ffffffff 00000000 S surfaceflinger
-system 398 180 146792 9724 ffffffff 00000000 S EventThread
-system 399 180 146792 9724 ffffffff 00000000 S surfaceflinger
-system 400 180 146792 9724 ffffffff 00000000 S EventThread
-system 401 180 146792 9724 ffffffff 00000000 S EventControl
-system 575 180 146792 9724 ffffffff 00000000 S Binder_3
-system 1501 180 146792 9724 ffffffff 00000000 S Binder_4
-system 5633 180 146792 9724 ffffffff 00000000 S Binder_5
-nobody 181 1 19792 1112 ffffffff 00000000 S /system/bin/rmt_storage
-nobody 571 181 19792 1112 ffffffff 00000000 S rmt_storage
-nobody 572 181 19792 1112 ffffffff 00000000 S rmt_storage
-nobody 573 181 19792 1112 ffffffff 00000000 S rmt_storage
-nobody 574 181 19792 1112 ffffffff 00000000 S rmt_storage
-system 182 1 11100 992 ffffffff 00000000 S /system/bin/qseecomd
-root 183 2 0 0 ffffffff 00000000 S msm_slim_qmi_cl
-root 184 2 0 0 ffffffff 00000000 S msm_qmi_rtx_q
-shell 185 1 9316 716 c047451c b6f58da8 S /system/bin/sh
-root 187 1 9200 368 ffffffff 00000000 S /system/bin/subsystem_ramdump
-root 188 1 22828 1404 ffffffff 00000000 S /system/bin/netd
-root 548 188 22828 1404 ffffffff 00000000 S netd
-root 549 188 22828 1404 ffffffff 00000000 S netd
-root 550 188 22828 1404 ffffffff 00000000 S netd
-root 551 188 22828 1404 ffffffff 00000000 S netd
-root 552 188 22828 1404 ffffffff 00000000 S netd
-root 553 188 22828 1404 ffffffff 00000000 S netd
-root 554 188 22828 1404 ffffffff 00000000 S netd
-root 555 188 22828 1404 ffffffff 00000000 S netd
-root 189 1 10048 848 ffffffff 00000000 S /system/bin/debuggerd
-radio 191 1 35988 4712 ffffffff 00000000 S /system/bin/rild
-radio 335 191 35988 4712 ffffffff 00000000 S rild
-radio 343 191 35988 4712 ffffffff 00000000 S rild
-radio 346 191 35988 4712 ffffffff 00000000 S rild
-radio 584 191 35988 4712 ffffffff 00000000 S rild
-radio 585 191 35988 4712 ffffffff 00000000 S rild
-radio 587 191 35988 4712 ffffffff 00000000 S rild
-radio 588 191 35988 4712 ffffffff 00000000 S rild
-radio 589 191 35988 4712 ffffffff 00000000 S rild
-radio 591 191 35988 4712 ffffffff 00000000 S rild
-radio 592 191 35988 4712 ffffffff 00000000 S rild
-radio 593 191 35988 4712 ffffffff 00000000 S rild
-radio 594 191 35988 4712 ffffffff 00000000 S rild
-drm 192 1 26084 3832 ffffffff 00000000 S /system/bin/drmserver
-drm 419 192 26084 3832 ffffffff 00000000 S Binder_1
-media 194 1 106516 8584 ffffffff 00000000 S /system/bin/mediaserver
-media 755 194 106516 8584 ffffffff 00000000 S ApmTone
-media 756 194 106516 8584 ffffffff 00000000 S ApmAudio
-media 757 194 106516 8584 ffffffff 00000000 S ApmOutput
-media 758 194 106516 8584 ffffffff 00000000 S mediaserver
-media 759 194 106516 8584 ffffffff 00000000 S FastMixer
-media 871 194 106516 8584 ffffffff 00000000 S AudioOut_2
-media 872 194 106516 8584 ffffffff 00000000 S AudioOut_4
-media 873 194 106516 8584 ffffffff 00000000 S FastMixer
-media 874 194 106516 8584 ffffffff 00000000 S AudioOut_6
-media 878 194 106516 8584 ffffffff 00000000 S Binder_1
-media 879 194 106516 8584 ffffffff 00000000 S Binder_2
-media 1133 194 106516 8584 ffffffff 00000000 S Binder_3
-install 195 1 9408 704 ffffffff 00000000 S /system/bin/installd
-keystore 197 1 12536 1848 ffffffff 00000000 S /system/bin/keystore
-radio 198 1 18856 636 ffffffff 00000000 S /system/bin/bridgemgrd
-radio 288 198 18856 636 ffffffff 00000000 S bridgemgrd
-radio 602 198 18856 636 ffffffff 00000000 S bridgemgrd
-radio 603 198 18856 636 ffffffff 00000000 S bridgemgrd
-radio 841 198 18856 636 ffffffff 00000000 S bridgemgrd
-radio 199 1 24060 732 ffffffff 00000000 S /system/bin/qmuxd
-radio 293 199 24060 732 ffffffff 00000000 S qmuxd
-radio 576 199 24060 732 ffffffff 00000000 S qmuxd
-radio 577 199 24060 732 ffffffff 00000000 S qmuxd
-radio 578 199 24060 732 ffffffff 00000000 S qmuxd
-radio 579 199 24060 732 ffffffff 00000000 S qmuxd
-radio 580 199 24060 732 ffffffff 00000000 S qmuxd
-radio 581 199 24060 732 ffffffff 00000000 S qmuxd
-radio 582 199 24060 732 ffffffff 00000000 S qmuxd
-radio 583 199 24060 732 ffffffff 00000000 S qmuxd
-radio 200 1 20036 996 ffffffff 00000000 S /system/bin/netmgrd
-radio 289 200 20036 996 ffffffff 00000000 S netmgrd
-radio 736 200 20036 996 ffffffff 00000000 S netmgrd
-radio 746 200 20036 996 ffffffff 00000000 S netmgrd
-radio 747 200 20036 996 ffffffff 00000000 S netmgrd
-radio 748 200 20036 996 ffffffff 00000000 S netmgrd
-nobody 201 1 59912 1748 ffffffff 00000000 S /system/bin/sensors.qcom
-nobody 290 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 292 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 560 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 563 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 564 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 605 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 614 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 621 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 622 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 623 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 624 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 625 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 626 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 627 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 628 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 629 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 633 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 643 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 650 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 651 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 760 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 763 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 784 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 790 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 792 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 794 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 796 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 798 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 800 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 802 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 804 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 806 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 808 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 810 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 812 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 814 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 816 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 818 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 820 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 822 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 824 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 1593 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 1600 201 59912 1748 ffffffff 00000000 S sensors.qcom
-root 204 1 58772 1524 ffffffff 00000000 S /system/bin/thermal-engine-hh
-root 247 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 250 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 252 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 253 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 254 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 255 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 257 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 258 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 259 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 260 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 261 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 262 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 263 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 264 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 265 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 266 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 267 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 268 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 269 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 270 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 272 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 273 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 275 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 276 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 277 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 278 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 280 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 281 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 282 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 283 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 284 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 286 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 287 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 295 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 297 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 299 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 300 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 301 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 559 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 596 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 600 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 601 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 205 1 1482684 53160 ffffffff 00000000 S zygote
-root 14357 205 1482684 53160 ffffffff 00000000 S ReferenceQueueD
-root 14358 205 1482684 53160 ffffffff 00000000 S FinalizerDaemon
-root 14359 205 1482684 53160 ffffffff 00000000 S FinalizerWatchd
-root 14360 205 1482684 53160 ffffffff 00000000 S HeapTrimmerDaem
-root 14361 205 1482684 53160 ffffffff 00000000 S GCDaemon
-media_rw 206 1 15400 5240 ffffffff 00000000 S /system/bin/sdcard
-media_rw 227 206 15400 5240 ffffffff 00000000 S sdcard
-media_rw 228 206 15400 5240 ffffffff 00000000 S sdcard
-camera 207 1 16300 4440 ffffffff 00000000 S /system/bin/mm-qcamera-daemon
-system 208 1 20500 1236 ffffffff 00000000 S /system/bin/time_daemon
-system 308 208 20500 1236 ffffffff 00000000 S time_daemon
-system 561 208 20500 1236 ffffffff 00000000 S time_daemon
-system 597 208 20500 1236 ffffffff 00000000 S time_daemon
-system 598 208 20500 1236 ffffffff 00000000 S time_daemon
-system 599 208 20500 1236 ffffffff 00000000 S time_daemon
-shell 209 1 16984 312 ffffffff 00000000 S /sbin/adbd
-shell 210 209 16984 312 ffffffff 00000000 S adbd
-shell 211 209 16984 312 ffffffff 00000000 S adbd
-shell 212 209 16984 308 ffffffff 00000000 S adbd
-shell 14445 209 16984 308 ffffffff 00000000 S adbd
-root 214 2 0 0 ffffffff 00000000 S irq/288-wcd9xxx
-root 219 2 0 0 ffffffff 00000000 S kauditd
-root 311 2 0 0 ffffffff 00000000 D msm_thermal:hot
-root 312 2 0 0 ffffffff 00000000 D msm_thermal:fre
-system 348 182 15288 564 ffffffff 00000000 S /system/bin/qseecomd
-system 349 348 15288 564 ffffffff 00000000 S qseecomd
-system 351 348 15288 564 ffffffff 00000000 S qseecomd
-system 386 348 15288 564 ffffffff 00000000 S qseecomd
-system 387 348 15288 564 ffffffff 00000000 S qseecomd
-root 360 2 0 0 ffffffff 00000000 D mdss_fb0
-root 557 2 0 0 ffffffff 00000000 S kworker/0:2H
-root 558 2 0 0 ffffffff 00000000 S IPCRTR
-root 562 2 0 0 ffffffff 00000000 S ipc_rtr_smd_ipc
-system 764 205 1701620 103200 ffffffff 00000000 S system_server
-system 767 764 1701620 103200 ffffffff 00000000 S Heap thread poo
-system 768 764 1701620 103200 ffffffff 00000000 S Heap thread poo
-system 770 764 1701620 103200 ffffffff 00000000 S Heap thread poo
-system 773 764 1701620 103200 ffffffff 00000000 S Signal Catcher
-system 774 764 1701620 103200 ffffffff 00000000 S JDWP
-system 775 764 1701620 103200 ffffffff 00000000 S ReferenceQueueD
-system 776 764 1701620 103200 ffffffff 00000000 S FinalizerDaemon
-system 777 764 1701620 103200 ffffffff 00000000 S FinalizerWatchd
-system 778 764 1701620 103200 ffffffff 00000000 S HeapTrimmerDaem
-system 779 764 1701620 103200 ffffffff 00000000 S GCDaemon
-system 780 764 1701620 103200 ffffffff 00000000 S Binder_1
-system 781 764 1701620 103200 ffffffff 00000000 S Binder_2
-system 782 764 1701620 103200 ffffffff 00000000 S system_server
-system 783 764 1701620 103200 ffffffff 00000000 S system_server
-system 785 764 1701620 103200 ffffffff 00000000 S system_server
-system 786 764 1701620 103200 ffffffff 00000000 S system_server
-system 788 764 1701620 103200 ffffffff 00000000 S system_server
-system 789 764 1701620 103200 ffffffff 00000000 S system_server
-system 791 764 1701620 103200 ffffffff 00000000 S system_server
-system 793 764 1701620 103200 ffffffff 00000000 S system_server
-system 795 764 1701620 103200 ffffffff 00000000 S system_server
-system 797 764 1701620 103200 ffffffff 00000000 S system_server
-system 799 764 1701620 103200 ffffffff 00000000 S system_server
-system 801 764 1701620 103200 ffffffff 00000000 S system_server
-system 803 764 1701620 103200 ffffffff 00000000 S system_server
-system 805 764 1701620 103200 ffffffff 00000000 S system_server
-system 807 764 1701620 103200 ffffffff 00000000 S system_server
-system 809 764 1701620 103200 ffffffff 00000000 S system_server
-system 811 764 1701620 103200 ffffffff 00000000 S system_server
-system 813 764 1701620 103200 ffffffff 00000000 S system_server
-system 815 764 1701620 103200 ffffffff 00000000 S system_server
-system 817 764 1701620 103200 ffffffff 00000000 S system_server
-system 819 764 1701620 103200 ffffffff 00000000 S system_server
-system 821 764 1701620 103200 ffffffff 00000000 S system_server
-system 823 764 1701620 103200 ffffffff 00000000 S system_server
-system 826 764 1701620 103200 ffffffff 00000000 S SensorEventAckR
-system 827 764 1701620 103200 ffffffff 00000000 S SensorService
-system 828 764 1701620 103200 ffffffff 00000000 S android.bg
-system 829 764 1701620 103200 ffffffff 00000000 S ActivityManager
-system 830 764 1701620 103200 ffffffff 00000000 S FileObserver
-system 831 764 1701620 103200 ffffffff 00000000 S android.fg
-system 832 764 1701620 103200 ffffffff 00000000 S android.ui
-system 833 764 1701620 103200 ffffffff 00000000 S android.io
-system 834 764 1701620 103200 ffffffff 00000000 S android.display
-system 835 764 1701620 103200 ffffffff 00000000 S CpuTracker
-system 836 764 1701620 103200 ffffffff 00000000 S PowerManagerSer
-system 837 764 1701620 103200 ffffffff 00000000 S system_server
-system 838 764 1701620 103200 ffffffff 00000000 S system_server
-system 839 764 1701620 103200 ffffffff 00000000 S BatteryStats_wa
-system 840 764 1701620 103200 ffffffff 00000000 S PackageManager
-system 842 764 1701620 103200 ffffffff 00000000 S PackageInstalle
-system 844 764 1701620 103200 ffffffff 00000000 S AlarmManager
-system 845 764 1701620 103200 ffffffff 00000000 S UEventObserver
-system 853 764 1701620 103200 ffffffff 00000000 S InputDispatcher
-system 854 764 1701620 103200 ffffffff 00000000 S InputReader
-system 857 764 1701620 103200 ffffffff 00000000 S MountService
-system 858 764 1701620 103200 ffffffff 00000000 S VoldConnector
-system 860 764 1701620 103200 ffffffff 00000000 S NetdConnector
-system 861 764 1701620 103200 ffffffff 00000000 S NetworkStats
-system 862 764 1701620 103200 ffffffff 00000000 S NetworkPolicy
-system 863 764 1701620 103200 ffffffff 00000000 S WifiP2pService
-system 864 764 1701620 103200 ffffffff 00000000 S WifiStateMachin
-system 865 764 1701620 103200 ffffffff 00000000 S WifiService
-system 866 764 1701620 103200 ffffffff 00000000 S ConnectivitySer
-system 867 764 1701620 103200 ffffffff 00000000 S NsdService
-system 868 764 1701620 103200 ffffffff 00000000 S mDnsConnector
-system 869 764 1701620 103200 ffffffff 00000000 S ranker
-system 870 764 1701620 103200 ffffffff 00000000 S AudioService
-system 882 764 1701620 103200 ffffffff 00000000 S WifiWatchdogSta
-system 883 764 1701620 103200 ffffffff 00000000 S WifiManager
-system 884 764 1701620 103200 ffffffff 00000000 S WifiScanningSer
-system 885 764 1701620 103200 ffffffff 00000000 S WifiRttService
-system 886 764 1701620 103200 ffffffff 00000000 S EthernetService
-system 887 764 1701620 103200 ffffffff 00000000 S backup
-system 889 764 1701620 103200 ffffffff 00000000 S Thread-69
-system 892 764 1701620 103200 ffffffff 00000000 S LazyTaskWriterT
-system 893 764 1701620 103200 ffffffff 00000000 S UsbService host
-system 894 764 1701620 103200 ffffffff 00000000 S Thread-73
-system 942 764 1701620 103200 ffffffff 00000000 S Binder_3
-system 1079 764 1701620 103200 ffffffff 00000000 S watchdog
-system 1094 764 1701620 103200 ffffffff 00000000 S SoundPool
-system 1095 764 1701620 103200 ffffffff 00000000 S SoundPoolThread
-system 1108 764 1701620 103200 ffffffff 00000000 S Binder_4
-system 1109 764 1701620 103200 ffffffff 00000000 S Binder_5
-system 1186 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1188 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1191 764 1701620 103200 ffffffff 00000000 S NetworkTimeUpda
-system 1192 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1226 764 1701620 103200 ffffffff 00000000 S Binder_6
-system 1233 764 1701620 103200 ffffffff 00000000 S Binder_7
-system 1247 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1256 764 1701620 103200 ffffffff 00000000 S Binder_8
-system 1260 764 1701620 103200 ffffffff 00000000 S WifiMonitor
-system 1271 764 1701620 103200 ffffffff 00000000 S Binder_9
-system 1288 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1289 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1319 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1320 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1367 764 1701620 103200 ffffffff 00000000 S Thread-89
-system 1391 764 1701620 103200 ffffffff 00000000 S AsyncQueryWorke
-system 1654 764 1701620 103200 ffffffff 00000000 S Binder_A
-system 1693 764 1701620 103200 ffffffff 00000000 S NetworkMonitorN
-system 1695 764 1701620 103200 ffffffff 00000000 S DhcpStateMachin
-system 1781 764 1701620 103200 ffffffff 00000000 S AsyncTask #1
-system 1782 764 1701620 103200 ffffffff 00000000 S AsyncTask #2
-system 2097 764 1701620 103200 ffffffff 00000000 S AsyncTask #3
-system 2124 764 1701620 103200 ffffffff 00000000 S SyncHandler-0
-system 2905 764 1701620 103200 ffffffff 00000000 S PowerManagerSer
-system 4226 764 1701620 103200 ffffffff 00000000 S AsyncTask #4
-system 4265 764 1701620 103200 ffffffff 00000000 S UsbDebuggingMan
-system 5717 764 1701620 103200 ffffffff 00000000 S GL updater
-system 6709 764 1701620 103200 ffffffff 00000000 S Binder_B
-wifi 888 1 12568 2672 ffffffff 00000000 S /system/bin/wpa_supplicant
-u0_a20 915 205 1616624 108684 ffffffff 00000000 S com.android.systemui
-u0_a20 919 915 1616624 108684 ffffffff 00000000 S Heap thread poo
-u0_a20 920 915 1616624 108684 ffffffff 00000000 S Heap thread poo
-u0_a20 921 915 1616624 108684 ffffffff 00000000 S Heap thread poo
-u0_a20 925 915 1616624 108684 ffffffff 00000000 S Signal Catcher
-u0_a20 926 915 1616624 108684 ffffffff 00000000 S JDWP
-u0_a20 927 915 1616624 108684 ffffffff 00000000 S ReferenceQueueD
-u0_a20 928 915 1616624 108684 ffffffff 00000000 S FinalizerDaemon
-u0_a20 929 915 1616624 108684 ffffffff 00000000 S FinalizerWatchd
-u0_a20 930 915 1616624 108684 ffffffff 00000000 S HeapTrimmerDaem
-u0_a20 931 915 1616624 108684 ffffffff 00000000 S GCDaemon
-u0_a20 933 915 1616624 108684 ffffffff 00000000 S Binder_1
-u0_a20 934 915 1616624 108684 ffffffff 00000000 S Binder_2
-u0_a20 964 915 1616624 108684 ffffffff 00000000 S SoundPool
-u0_a20 965 915 1616624 108684 ffffffff 00000000 S SoundPoolThread
-u0_a20 970 915 1616624 108684 ffffffff 00000000 S Recents-TaskRes
-u0_a20 1078 915 1616624 108684 ffffffff 00000000 S SystemUI Storag
-u0_a20 1378 915 1616624 108684 ffffffff 00000000 S PhoneStatusBar
-u0_a20 1381 915 1616624 108684 ffffffff 00000000 S WifiManager
-u0_a20 1416 915 1616624 108684 ffffffff 00000000 S ConnectivityMan
-u0_a20 1428 915 1616624 108684 ffffffff 00000000 S Binder_3
-u0_a20 1431 915 1616624 108684 ffffffff 00000000 S FlashlightContr
-u0_a20 1434 915 1616624 108684 ffffffff 00000000 S AsyncTask #1
-u0_a20 1435 915 1616624 108684 ffffffff 00000000 S QSTileHost
-u0_a20 1438 915 1616624 108684 ffffffff 00000000 S AsyncTask #2
-u0_a20 1441 915 1616624 108684 ffffffff 00000000 S RenderThread
-u0_a20 1442 915 1616624 108684 ffffffff 00000000 S AsyncTask #3
-u0_a20 1565 915 1616624 108684 ffffffff 00000000 S hwuiTask1
-u0_a20 1566 915 1616624 108684 ffffffff 00000000 S hwuiTask2
-u0_a20 1637 915 1616624 108684 ffffffff 00000000 S AsyncTask #4
-u0_a20 1692 915 1616624 108684 ffffffff 00000000 S GL updater
-u0_a20 1807 915 1616624 108684 ffffffff 00000000 S RenderThread
-u0_a20 4480 915 1616624 108684 ffffffff 00000000 S Binder_4
-u0_a6 936 205 1506908 56892 ffffffff 00000000 S android.process.media
-u0_a6 943 936 1506908 56892 ffffffff 00000000 S Heap thread poo
-u0_a6 944 936 1506908 56892 ffffffff 00000000 S Heap thread poo
-u0_a6 945 936 1506908 56892 ffffffff 00000000 S Heap thread poo
-u0_a6 947 936 1506908 56892 ffffffff 00000000 S Signal Catcher
-u0_a6 949 936 1506908 56892 ffffffff 00000000 S JDWP
-u0_a6 950 936 1506908 56892 ffffffff 00000000 S ReferenceQueueD
-u0_a6 951 936 1506908 56892 ffffffff 00000000 S FinalizerDaemon
-u0_a6 952 936 1506908 56892 ffffffff 00000000 S FinalizerWatchd
-u0_a6 953 936 1506908 56892 ffffffff 00000000 S HeapTrimmerDaem
-u0_a6 954 936 1506908 56892 ffffffff 00000000 S GCDaemon
-u0_a6 956 936 1506908 56892 ffffffff 00000000 S Binder_1
-u0_a6 957 936 1506908 56892 ffffffff 00000000 S Binder_2
-u0_a6 1007 936 1506908 56892 ffffffff 00000000 S thumbs thread
-u0_a6 1020 936 1506908 56892 ffffffff 00000000 S MtpServer
-u0_a6 2810 936 1506908 56892 ffffffff 00000000 S DownloadReceive
-u0_a6 4917 936 1506908 56892 ffffffff 00000000 S Binder_3
-u0_a6 5816 936 1506908 56892 ffffffff 00000000 S Binder_4
-u0_a6 8575 936 1506908 56892 ffffffff 00000000 S Binder_5
-u0_a22 1111 205 1526156 42532 ffffffff 00000000 S com.google.android.googlequicksearchbox:interactor
-u0_a22 1113 1111 1526156 42532 ffffffff 00000000 S Heap thread poo
-u0_a22 1114 1111 1526156 42532 ffffffff 00000000 S Heap thread poo
-u0_a22 1116 1111 1526156 42532 ffffffff 00000000 S Heap thread poo
-u0_a22 1121 1111 1526156 42532 ffffffff 00000000 S Signal Catcher
-u0_a22 1124 1111 1526156 42532 ffffffff 00000000 S JDWP
-u0_a22 1125 1111 1526156 42532 ffffffff 00000000 S ReferenceQueueD
-u0_a22 1126 1111 1526156 42532 ffffffff 00000000 S FinalizerDaemon
-u0_a22 1127 1111 1526156 42532 ffffffff 00000000 S FinalizerWatchd
-u0_a22 1128 1111 1526156 42532 ffffffff 00000000 S HeapTrimmerDaem
-u0_a22 1129 1111 1526156 42532 ffffffff 00000000 S GCDaemon
-u0_a22 1131 1111 1526156 42532 ffffffff 00000000 S Binder_1
-u0_a22 1132 1111 1526156 42532 ffffffff 00000000 S Binder_2
-u0_a22 1561 1111 1526156 42532 ffffffff 00000000 S AsyncTask #1
-u0_a51 1136 205 1515064 46788 ffffffff 00000000 S com.google.android.inputmethod.pinyin
-u0_a51 1142 1136 1515064 46788 ffffffff 00000000 S Heap thread poo
-u0_a51 1143 1136 1515064 46788 ffffffff 00000000 S Heap thread poo
-u0_a51 1144 1136 1515064 46788 ffffffff 00000000 S Heap thread poo
-u0_a51 1145 1136 1515064 46788 ffffffff 00000000 S Signal Catcher
-u0_a51 1146 1136 1515064 46788 ffffffff 00000000 S JDWP
-u0_a51 1147 1136 1515064 46788 ffffffff 00000000 S ReferenceQueueD
-u0_a51 1148 1136 1515064 46788 ffffffff 00000000 S FinalizerDaemon
-u0_a51 1149 1136 1515064 46788 ffffffff 00000000 S FinalizerWatchd
-u0_a51 1151 1136 1515064 46788 ffffffff 00000000 S HeapTrimmerDaem
-u0_a51 1152 1136 1515064 46788 ffffffff 00000000 S GCDaemon
-u0_a51 1153 1136 1515064 46788 ffffffff 00000000 S Binder_1
-u0_a51 1154 1136 1515064 46788 ffffffff 00000000 S Binder_2
-u0_a51 1330 1136 1515064 46788 ffffffff 00000000 S GAThread
-u0_a51 1331 1136 1515064 46788 ffffffff 00000000 S measurement-1
-u0_a51 1336 1136 1515064 46788 ffffffff 00000000 S pool-1-thread-1
-u0_a51 1503 1136 1515064 46788 ffffffff 00000000 S AsyncTask #1
-u0_a51 1622 1136 1515064 46788 ffffffff 00000000 S AsyncTask #2
-nfc 1199 205 1511808 46336 ffffffff 00000000 S com.android.nfc
-nfc 1208 1199 1511808 46336 ffffffff 00000000 S Heap thread poo
-nfc 1209 1199 1511808 46336 ffffffff 00000000 S Heap thread poo
-nfc 1210 1199 1511808 46336 ffffffff 00000000 S Heap thread poo
-nfc 1211 1199 1511808 46336 ffffffff 00000000 S Signal Catcher
-nfc 1212 1199 1511808 46336 ffffffff 00000000 S JDWP
-nfc 1213 1199 1511808 46336 ffffffff 00000000 S ReferenceQueueD
-nfc 1214 1199 1511808 46336 ffffffff 00000000 S FinalizerDaemon
-nfc 1215 1199 1511808 46336 ffffffff 00000000 S FinalizerWatchd
-nfc 1216 1199 1511808 46336 ffffffff 00000000 S HeapTrimmerDaem
-nfc 1219 1199 1511808 46336 ffffffff 00000000 S GCDaemon
-nfc 1220 1199 1511808 46336 ffffffff 00000000 S Binder_1
-nfc 1221 1199 1511808 46336 ffffffff 00000000 S Binder_2
-nfc 1385 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1388 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1393 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1408 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1409 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1425 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1573 1199 1511808 46336 ffffffff 00000000 S Thread-55
-nfc 1574 1199 1511808 46336 ffffffff 00000000 S Thread-56
-nfc 1575 1199 1511808 46336 ffffffff 00000000 S Thread-57
-nfc 1577 1199 1511808 46336 ffffffff 00000000 S SoundPool
-nfc 1578 1199 1511808 46336 ffffffff 00000000 S SoundPoolThread
-nfc 2906 1199 1511808 46336 ffffffff 00000000 S AsyncTask #2
-nfc 2915 1199 1511808 46336 ffffffff 00000000 S AsyncTask #3
-nfc 5610 1199 1511808 46336 ffffffff 00000000 S AsyncTask #4
-nfc 5719 1199 1511808 46336 ffffffff 00000000 S AsyncTask #5
-radio 1234 205 1493064 38832 ffffffff 00000000 S com.redbend.vdmc
-radio 1236 1234 1493064 38832 ffffffff 00000000 S Heap thread poo
-radio 1237 1234 1493064 38832 ffffffff 00000000 S Heap thread poo
-radio 1238 1234 1493064 38832 ffffffff 00000000 S Heap thread poo
-radio 1244 1234 1493064 38832 ffffffff 00000000 S Signal Catcher
-radio 1245 1234 1493064 38832 ffffffff 00000000 S JDWP
-radio 1246 1234 1493064 38832 ffffffff 00000000 S ReferenceQueueD
-radio 1248 1234 1493064 38832 ffffffff 00000000 S FinalizerDaemon
-radio 1249 1234 1493064 38832 ffffffff 00000000 S FinalizerWatchd
-radio 1250 1234 1493064 38832 ffffffff 00000000 S HeapTrimmerDaem
-radio 1251 1234 1493064 38832 ffffffff 00000000 S GCDaemon
-radio 1252 1234 1493064 38832 ffffffff 00000000 S Binder_1
-radio 1257 1234 1493064 38832 ffffffff 00000000 S Binder_2
-radio 1274 205 1525408 58916 ffffffff 00000000 S com.android.phone
-radio 1282 1274 1525408 58916 ffffffff 00000000 S Heap thread poo
-radio 1283 1274 1525408 58916 ffffffff 00000000 S Heap thread poo
-radio 1284 1274 1525408 58916 ffffffff 00000000 S Heap thread poo
-radio 1285 1274 1525408 58916 ffffffff 00000000 S Signal Catcher
-radio 1286 1274 1525408 58916 ffffffff 00000000 S JDWP
-radio 1287 1274 1525408 58916 ffffffff 00000000 S ReferenceQueueD
-radio 1290 1274 1525408 58916 ffffffff 00000000 S FinalizerDaemon
-radio 1291 1274 1525408 58916 ffffffff 00000000 S FinalizerWatchd
-radio 1292 1274 1525408 58916 ffffffff 00000000 S HeapTrimmerDaem
-radio 1293 1274 1525408 58916 ffffffff 00000000 S GCDaemon
-radio 1299 1274 1525408 58916 ffffffff 00000000 S Binder_1
-radio 1315 1274 1525408 58916 ffffffff 00000000 S Binder_2
-radio 1365 1274 1525408 58916 ffffffff 00000000 S RILSender0
-radio 1366 1274 1525408 58916 ffffffff 00000000 S RILReceiver0
-radio 1380 1274 1525408 58916 ffffffff 00000000 S DcHandlerThread
-radio 1392 1274 1525408 58916 ffffffff 00000000 S GsmCellBroadcas
-radio 1394 1274 1525408 58916 ffffffff 00000000 S GsmInboundSmsHa
-radio 1397 1274 1525408 58916 ffffffff 00000000 S CellBroadcastHa
-radio 1417 1274 1525408 58916 ffffffff 00000000 S CdmaInboundSmsH
-radio 1418 1274 1525408 58916 ffffffff 00000000 S CdmaServiceCate
-radio 1427 1274 1525408 58916 ffffffff 00000000 S DcSwitchStateMa
-radio 1429 1274 1525408 58916 ffffffff 00000000 S SyncHandler-0
-radio 1443 1274 1525408 58916 ffffffff 00000000 S AsyncTask #1
-radio 1473 1274 1525408 58916 ffffffff 00000000 S Binder_3
-radio 1517 1274 1525408 58916 ffffffff 00000000 S ervice.Executor
-radio 1518 1274 1525408 58916 ffffffff 00000000 S WifiManager
-radio 1563 1274 1525408 58916 ffffffff 00000000 S Cat Telephony s
-radio 1564 1274 1525408 58916 ffffffff 00000000 S RilMessageDecod
-radio 1567 1274 1525408 58916 ffffffff 00000000 S Cat Icon Loader
-radio 1690 1274 1525408 58916 ffffffff 00000000 S Binder_4
-radio 4571 1274 1525408 58916 ffffffff 00000000 S Stk App Service
-u0_a22 1305 205 1674592 127012 ffffffff 00000000 S com.google.android.googlequicksearchbox
-u0_a22 1306 1305 1674592 127012 ffffffff 00000000 S Heap thread poo
-u0_a22 1307 1305 1674592 127012 ffffffff 00000000 S Heap thread poo
-u0_a22 1308 1305 1674592 127012 ffffffff 00000000 S Heap thread poo
-u0_a22 1317 1305 1674592 127012 ffffffff 00000000 S Signal Catcher
-u0_a22 1318 1305 1674592 127012 ffffffff 00000000 S JDWP
-u0_a22 1322 1305 1674592 127012 ffffffff 00000000 S ReferenceQueueD
-u0_a22 1323 1305 1674592 127012 ffffffff 00000000 S FinalizerDaemon
-u0_a22 1324 1305 1674592 127012 ffffffff 00000000 S FinalizerWatchd
-u0_a22 1332 1305 1674592 127012 ffffffff 00000000 S HeapTrimmerDaem
-u0_a22 1333 1305 1674592 127012 ffffffff 00000000 S GCDaemon
-u0_a22 1334 1305 1674592 127012 ffffffff 00000000 S Binder_1
-u0_a22 1335 1305 1674592 127012 ffffffff 00000000 S Binder_2
-u0_a22 1386 1305 1674592 127012 ffffffff 00000000 S launcher-loader
-u0_a22 1395 1305 1674592 127012 ffffffff 00000000 S AsyncTask #1
-u0_a22 1432 1305 1674592 127012 ffffffff 00000000 S AsyncTask #2
-u0_a22 1484 1305 1674592 127012 ffffffff 00000000 S GELServices-0
-u0_a22 1514 1305 1674592 127012 ffffffff 00000000 S RenderThread
-u0_a22 1540 1305 1674592 127012 ffffffff 00000000 S AsyncTask #3
-u0_a22 1618 1305 1674592 127012 ffffffff 00000000 S GELServices-1
-u0_a22 1621 1305 1674592 127012 ffffffff 00000000 S GELServices-2
-u0_a22 1629 1305 1674592 127012 ffffffff 00000000 S GELServices-3
-u0_a22 1632 1305 1674592 127012 ffffffff 00000000 S AsyncTask #4
-u0_a22 1633 1305 1674592 127012 ffffffff 00000000 S AsyncTask #5
-u0_a22 1636 1305 1674592 127012 ffffffff 00000000 S GELServices-4
-u0_a22 1644 1305 1674592 127012 ffffffff 00000000 S GL updater
-u0_a22 1647 1305 1674592 127012 ffffffff 00000000 S GELServices-5
-u0_a22 1664 1305 1674592 127012 ffffffff 00000000 S GELServices-6
-u0_a22 1764 1305 1674592 127012 ffffffff 00000000 S Binder_3
-u0_a22 1766 1305 1674592 127012 ffffffff 00000000 S GELServices-7
-u0_a22 1772 1305 1674592 127012 ffffffff 00000000 S RenderThread
-u0_a22 1773 1305 1674592 127012 ffffffff 00000000 S RenderThread
-u0_a22 1774 1305 1674592 127012 ffffffff 00000000 S RenderThread
-u0_a22 1775 1305 1674592 127012 ffffffff 00000000 S RenderThread
-u0_a22 1998 1305 1674592 127012 ffffffff 00000000 S GELServices-8
-u0_a22 2320 1305 1674592 127012 ffffffff 00000000 S RemoteViewsCach
-u0_a22 2321 1305 1674592 127012 ffffffff 00000000 S RemoteViewsAdap
-u0_a22 2902 1305 1674592 127012 ffffffff 00000000 S GELServices-9
-u0_a22 1451 205 1584512 87716 ffffffff 00000000 S com.google.android.googlequicksearchbox:search
-u0_a22 1457 1451 1584512 87716 ffffffff 00000000 S Heap thread poo
-u0_a22 1458 1451 1584512 87716 ffffffff 00000000 S Heap thread poo
-u0_a22 1459 1451 1584512 87716 ffffffff 00000000 S Heap thread poo
-u0_a22 1460 1451 1584512 87716 ffffffff 00000000 S Signal Catcher
-u0_a22 1461 1451 1584512 87716 ffffffff 00000000 S JDWP
-u0_a22 1462 1451 1584512 87716 ffffffff 00000000 S ReferenceQueueD
-u0_a22 1463 1451 1584512 87716 ffffffff 00000000 S FinalizerDaemon
-u0_a22 1464 1451 1584512 87716 ffffffff 00000000 S FinalizerWatchd
-u0_a22 1466 1451 1584512 87716 ffffffff 00000000 S HeapTrimmerDaem
-u0_a22 1468 1451 1584512 87716 ffffffff 00000000 S GCDaemon
-u0_a22 1474 1451 1584512 87716 ffffffff 00000000 S Binder_1
-u0_a22 1475 1451 1584512 87716 ffffffff 00000000 S Binder_2
-u0_a22 1515 1451 1584512 87716 ffffffff 00000000 S User-Facing Non
-u0_a22 1516 1451 1584512 87716 ffffffff 00000000 S User-Facing Non
-u0_a22 1535 1451 1584512 87716 ffffffff 00000000 S User-Facing Non
-u0_a22 1538 1451 1584512 87716 ffffffff 00000000 S User-Facing Non
-u0_a22 1553 1451 1584512 87716 ffffffff 00000000 S User-Facing Non
-u0_a22 1560 1451 1584512 87716 ffffffff 00000000 S IcingConnection
-u0_a22 1580 1451 1584512 87716 ffffffff 00000000 S AudioRouter-0
-u0_a22 1626 1451 1584512 87716 ffffffff 00000000 S AsyncFileStorag
-u0_a22 1635 1451 1584512 87716 ffffffff 00000000 S WifiManager
-u0_a22 1643 1451 1584512 87716 ffffffff 00000000 S LocationOracleI
-u0_a22 1646 1451 1584512 87716 ffffffff 00000000 S GoogleApiClient
-u0_a22 1769 1451 1584512 87716 ffffffff 00000000 S Binder_3
-u0_a22 1770 1451 1584512 87716 ffffffff 00000000 S Gservices
-u0_a22 1810 1451 1584512 87716 ffffffff 00000000 S ChromiumNet
-u0_a22 1811 1451 1584512 87716 ffffffff 00000000 S DnsConfigServic
-u0_a22 1812 1451 1584512 87716 ffffffff 00000000 S inotify_reader
-u0_a22 1815 1451 1584512 87716 ffffffff 00000000 S Network File Th
-u0_a22 1816 1451 1584512 87716 ffffffff 00000000 S SimpleCacheWork
-u0_a22 1817 1451 1584512 87716 ffffffff 00000000 S SimpleCacheWork
-u0_a22 1823 1451 1584512 87716 ffffffff 00000000 S Binder_4
-u0_a22 1824 1451 1584512 87716 ffffffff 00000000 S Binder_5
-u0_a22 12193 1451 1584512 87716 ffffffff 00000000 S Background Bloc
-u0_a22 12207 1451 1584512 87716 ffffffff 00000000 S User-Facing Blo
-u0_a22 12211 1451 1584512 87716 ffffffff 00000000 S WorkerPool/1221
-u0_a22 12232 1451 1584512 87716 ffffffff 00000000 S Background Non-
-u0_a22 12235 1451 1584512 87716 ffffffff 00000000 S Background Bloc
-u0_a22 12236 1451 1584512 87716 ffffffff 00000000 S Background Bloc
-u0_a22 12237 1451 1584512 87716 ffffffff 00000000 S Background Non-
-u0_a8 1478 205 1613496 72932 ffffffff 00000000 S com.google.process.gapps
-u0_a8 1485 1478 1613496 72932 ffffffff 00000000 S Heap thread poo
-u0_a8 1486 1478 1613496 72932 ffffffff 00000000 S Heap thread poo
-u0_a8 1487 1478 1613496 72932 ffffffff 00000000 S Heap thread poo
-u0_a8 1488 1478 1613496 72932 ffffffff 00000000 S Signal Catcher
-u0_a8 1489 1478 1613496 72932 ffffffff 00000000 S JDWP
-u0_a8 1490 1478 1613496 72932 ffffffff 00000000 S ReferenceQueueD
-u0_a8 1491 1478 1613496 72932 ffffffff 00000000 S FinalizerDaemon
-u0_a8 1492 1478 1613496 72932 ffffffff 00000000 S FinalizerWatchd
-u0_a8 1493 1478 1613496 72932 ffffffff 00000000 S HeapTrimmerDaem
-u0_a8 1494 1478 1613496 72932 ffffffff 00000000 S GCDaemon
-u0_a8 1495 1478 1613496 72932 ffffffff 00000000 S Binder_1
-u0_a8 1496 1478 1613496 72932 ffffffff 00000000 S Binder_2
-u0_a8 1497 1478 1613496 72932 ffffffff 00000000 S Binder_3
-u0_a8 1613 1478 1613496 72932 ffffffff 00000000 S Gservices
-u0_a8 1614 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@
-u0_a8 1615 1478 1613496 72932 ffffffff 00000000 S Gservices
-u0_a8 1616 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@
-u0_a8 1620 1478 1613496 72932 ffffffff 00000000 S Gservices
-u0_a8 1996 1478 1613496 72932 ffffffff 00000000 S Binder_4
-u0_a8 1997 1478 1613496 72932 ffffffff 00000000 S Binder_5
-u0_a8 2510 1478 1613496 72932 ffffffff 00000000 S GCMWriter
-u0_a8 2512 1478 1613496 72932 ffffffff 00000000 S AsyncTask #1
-u0_a8 2536 1478 1613496 72932 ffffffff 00000000 S GCMReader
-u0_a8 2547 1478 1613496 72932 ffffffff 00000000 S pool-2-thread-1
-u0_a8 3680 1478 1613496 72932 ffffffff 00000000 S WifiManager
-u0_a8 4135 1478 1613496 72932 ffffffff 00000000 S AsyncTask #2
-u0_a8 4159 1478 1613496 72932 ffffffff 00000000 S AsyncTask #3
-u0_a8 4184 1478 1613496 72932 ffffffff 00000000 S AsyncTask #4
-u0_a8 4210 1478 1613496 72932 ffffffff 00000000 S AsyncTask #5
-u0_a8 4541 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@
-u0_a8 4735 1478 1613496 72932 ffffffff 00000000 S pool-8-thread-1
-u0_a8 4770 1478 1613496 72932 ffffffff 00000000 S Binder_6
-u0_a8 12448 1478 1613496 72932 ffffffff 00000000 S OkHttp Connecti
-u0_a8 14401 1478 1613496 72932 ffffffff 00000000 S Thread-233
-u0_a8 14409 1478 1613496 72932 ffffffff 00000000 S OkHttp Connecti
-dhcp 1700 1 9344 756 ffffffff 00000000 S /system/bin/dhcpcd
-u0_a8 1873 205 1756828 84724 ffffffff 00000000 S com.google.android.gms
-u0_a8 1878 1873 1756828 84724 ffffffff 00000000 S Heap thread poo
-u0_a8 1880 1873 1756828 84724 ffffffff 00000000 S Heap thread poo
-u0_a8 1881 1873 1756828 84724 ffffffff 00000000 S Heap thread poo
-u0_a8 1882 1873 1756828 84724 ffffffff 00000000 S Signal Catcher
-u0_a8 1883 1873 1756828 84724 ffffffff 00000000 S JDWP
-u0_a8 1884 1873 1756828 84724 ffffffff 00000000 S ReferenceQueueD
-u0_a8 1885 1873 1756828 84724 ffffffff 00000000 S FinalizerDaemon
-u0_a8 1886 1873 1756828 84724 ffffffff 00000000 S FinalizerWatchd
-u0_a8 1887 1873 1756828 84724 ffffffff 00000000 S HeapTrimmerDaem
-u0_a8 1888 1873 1756828 84724 ffffffff 00000000 S GCDaemon
-u0_a8 1889 1873 1756828 84724 ffffffff 00000000 S Binder_1
-u0_a8 1890 1873 1756828 84724 ffffffff 00000000 S Binder_2
-u0_a8 1895 1873 1756828 84724 ffffffff 00000000 S Gservices
-u0_a8 1898 1873 1756828 84724 ffffffff 00000000 S measurement-1
-u0_a8 1900 1873 1756828 84724 ffffffff 00000000 S AsyncTask #1
-u0_a8 1904 1873 1756828 84724 ffffffff 00000000 S AsyncTask #2
-u0_a8 2001 1873 1756828 84724 ffffffff 00000000 S Binder_3
-u0_a8 2497 1873 1756828 84724 ffffffff 00000000 S WifiManager
-u0_a8 2509 1873 1756828 84724 ffffffff 00000000 S picasa-uploads-
-u0_a8 2946 1873 1756828 84724 ffffffff 00000000 S pool-7-thread-1
-u0_a8 4390 1873 1756828 84724 ffffffff 00000000 S pool-13-thread-
-u0_a8 4391 1873 1756828 84724 ffffffff 00000000 S pool-18-thread-
-u0_a8 4392 1873 1756828 84724 ffffffff 00000000 S pool-11-thread-
-u0_a8 4394 1873 1756828 84724 ffffffff 00000000 S pool-25-thread-
-u0_a8 4395 1873 1756828 84724 ffffffff 00000000 S pool-25-thread-
-u0_a8 4396 1873 1756828 84724 ffffffff 00000000 S pool-25-thread-
-u0_a8 4397 1873 1756828 84724 ffffffff 00000000 S pool-25-thread-
-u0_a8 4398 1873 1756828 84724 ffffffff 00000000 S pool-14-thread-
-u0_a8 4521 1873 1756828 84724 ffffffff 00000000 S MediaTracker bu
-u0_a8 4766 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-0
-u0_a8 4771 1873 1756828 84724 ffffffff 00000000 S Icing-Worker-0
-u0_a8 4796 1873 1756828 84724 ffffffff 00000000 S Thread-200
-u0_a8 4797 1873 1756828 84724 ffffffff 00000000 S Thread-201
-u0_a8 4798 1873 1756828 84724 ffffffff 00000000 S Thread-202
-u0_a8 4799 1873 1756828 84724 ffffffff 00000000 S Thread-203
-u0_a8 4800 1873 1756828 84724 ffffffff 00000000 S Thread-204
-u0_a8 5793 1873 1756828 84724 ffffffff 00000000 S Binder_4
-u0_a8 6257 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-1
-u0_a8 6258 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-2
-u0_a8 6259 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-3
-u0_a8 6673 1873 1756828 84724 ffffffff 00000000 S pool-22-thread-
-u0_a8 8581 1873 1756828 84724 ffffffff 00000000 S Binder_5
-u0_a8 9001 1873 1756828 84724 ffffffff 00000000 S Gservices
-u0_a8 9024 1873 1756828 84724 ffffffff 00000000 S GamesProviderWo
-u0_a8 11865 1873 1756828 84724 ffffffff 00000000 S pool-37-thread-
-u0_a8 1949 205 1614008 81544 ffffffff 00000000 S com.google.android.gms.persistent
-u0_a8 1954 1949 1614008 81544 ffffffff 00000000 S Heap thread poo
-u0_a8 1955 1949 1614008 81544 ffffffff 00000000 S Heap thread poo
-u0_a8 1956 1949 1614008 81544 ffffffff 00000000 S Heap thread poo
-u0_a8 1959 1949 1614008 81544 ffffffff 00000000 S Signal Catcher
-u0_a8 1960 1949 1614008 81544 ffffffff 00000000 S JDWP
-u0_a8 1961 1949 1614008 81544 ffffffff 00000000 S ReferenceQueueD
-u0_a8 1962 1949 1614008 81544 ffffffff 00000000 S FinalizerDaemon
-u0_a8 1963 1949 1614008 81544 ffffffff 00000000 S FinalizerWatchd
-u0_a8 1964 1949 1614008 81544 ffffffff 00000000 S HeapTrimmerDaem
-u0_a8 1965 1949 1614008 81544 ffffffff 00000000 S GCDaemon
-u0_a8 1966 1949 1614008 81544 ffffffff 00000000 S Binder_1
-u0_a8 1967 1949 1614008 81544 ffffffff 00000000 S Binder_2
-u0_a8 1968 1949 1614008 81544 ffffffff 00000000 S Gservices
-u0_a8 1973 1949 1614008 81544 ffffffff 00000000 S IntentService[G
-u0_a8 1976 1949 1614008 81544 ffffffff 00000000 S FlpThread
-u0_a8 1977 1949 1614008 81544 ffffffff 00000000 S Binder_3
-u0_a8 1978 1949 1614008 81544 ffffffff 00000000 S WifiManager
-u0_a8 1979 1949 1614008 81544 ffffffff 00000000 S GeofencerStateM
-u0_a8 1980 1949 1614008 81544 ffffffff 00000000 S LocationService
-u0_a8 1984 1949 1614008 81544 ffffffff 00000000 S Binder_4
-u0_a8 1986 1949 1614008 81544 ffffffff 00000000 S Binder_5
-u0_a8 1990 1949 1614008 81544 ffffffff 00000000 S pool-4-thread-1
-u0_a8 1992 1949 1614008 81544 ffffffff 00000000 S GmsCoreStatsSer
-u0_a8 1995 1949 1614008 81544 ffffffff 00000000 S GoogleLocationS
-u0_a8 2004 1949 1614008 81544 ffffffff 00000000 S Thread-139
-u0_a8 2005 1949 1614008 81544 ffffffff 00000000 S Thread-140
-u0_a8 2006 1949 1614008 81544 ffffffff 00000000 S Thread-141
-u0_a8 2007 1949 1614008 81544 ffffffff 00000000 S Thread-142
-u0_a8 2021 1949 1614008 81544 ffffffff 00000000 S NetworkLocation
-u0_a8 2029 1949 1614008 81544 ffffffff 00000000 S UlrDispatchingS
-u0_a8 2030 1949 1614008 81544 ffffffff 00000000 S nlp-async-worke
-u0_a8 2521 1949 1614008 81544 ffffffff 00000000 S FitnessServiceF
-u0_a8 2522 1949 1614008 81544 ffffffff 00000000 S FitRecordingBro
-u0_a8 2526 1949 1614008 81544 ffffffff 00000000 S AsyncTask #1
-u0_a8 2530 1949 1614008 81544 ffffffff 00000000 S NearbyMessagesB
-u0_a8 4180 1949 1614008 81544 ffffffff 00000000 S AsyncTask #2
-u0_a8 4221 1949 1614008 81544 ffffffff 00000000 S AsyncTask #3
-u0_a8 4223 1949 1614008 81544 ffffffff 00000000 S AsyncTask #4
-u0_a8 4749 1949 1614008 81544 ffffffff 00000000 S CopresenceEvent
-u0_a8 6326 1949 1614008 81544 ffffffff 00000000 S AsyncTask #5
-u0_a8 6917 1949 1614008 81544 ffffffff 00000000 S Binder_6
-u0_a8 7196 1949 1614008 81544 ffffffff 00000000 S UlrDispatchingS
-u0_a8 7260 1949 1614008 81544 ffffffff 00000000 S Thread-174
-u0_a8 7261 1949 1614008 81544 ffffffff 00000000 S Thread-175
-u0_a8 7262 1949 1614008 81544 ffffffff 00000000 S Thread-176
-u0_a8 7263 1949 1614008 81544 ffffffff 00000000 S Thread-177
-u0_a8 7264 1949 1614008 81544 ffffffff 00000000 S Thread-178
-u0_a8 12449 1949 1614008 81544 ffffffff 00000000 S OkHttp Connecti
-root 2031 1 20256 880 ffffffff 00000000 S /system/bin/mpdecision
-root 2032 2031 20256 880 ffffffff 00000000 S mpdecision
-root 2033 2031 20256 880 ffffffff 00000000 S mpdecision
-root 2034 2031 20256 880 ffffffff 00000000 S mpdecision
-root 2035 2031 20256 880 ffffffff 00000000 S mpdecision
-root 2036 2031 20256 880 ffffffff 00000000 S mpdecision
-root 2046 2031 20256 880 ffffffff 00000000 S mpdecision
-u0_a193 2647 205 1541760 60840 ffffffff 00000000 S com.qiyi.video.market
-u0_a193 2653 2647 1541760 60840 ffffffff 00000000 S Heap thread poo
-u0_a193 2654 2647 1541760 60840 ffffffff 00000000 S Heap thread poo
-u0_a193 2655 2647 1541760 60840 ffffffff 00000000 S Heap thread poo
-u0_a193 2656 2647 1541760 60840 ffffffff 00000000 S Signal Catcher
-u0_a193 2657 2647 1541760 60840 ffffffff 00000000 S JDWP
-u0_a193 2658 2647 1541760 60840 ffffffff 00000000 S ReferenceQueueD
-u0_a193 2659 2647 1541760 60840 ffffffff 00000000 S FinalizerDaemon
-u0_a193 2660 2647 1541760 60840 ffffffff 00000000 S FinalizerWatchd
-u0_a193 2661 2647 1541760 60840 ffffffff 00000000 S HeapTrimmerDaem
-u0_a193 2662 2647 1541760 60840 ffffffff 00000000 S GCDaemon
-u0_a193 2663 2647 1541760 60840 ffffffff 00000000 S Binder_1
-u0_a193 2664 2647 1541760 60840 ffffffff 00000000 S Binder_2
-u0_a193 2671 2647 1541760 60840 ffffffff 00000000 S RefQueueWorker@
-u0_a193 2673 2647 1541760 60840 ffffffff 00000000 S .ProcessManager
-u0_a193 2675 2647 1541760 60840 ffffffff 00000000 S Binder_3
-u0_a193 2677 2647 1541760 60840 ffffffff 00000000 S Thread-208
-u0_a193 2679 2647 1541760 60840 ffffffff 00000000 S pool-2-thread-1
-u0_a193 2680 2647 1541760 60840 ffffffff 00000000 S WifiManager
-u0_a193 2682 2647 1541760 60840 ffffffff 00000000 S Timer-0
-u0_a193 2683 2647 1541760 60840 ffffffff 00000000 S Timer-1
-u0_a193 2710 2647 1541760 60840 ffffffff 00000000 S AsyncTask #1
-u0_a193 2718 2647 1541760 60840 ffffffff 00000000 S pool-3-thread-1
-u0_a193 3103 2647 1541760 60840 ffffffff 00000000 S pool-4-thread-1
-u0_a193 6672 2647 1541760 60840 ffffffff 00000000 S AsyncTask #2
-u0_a193 6752 2647 1541760 60840 ffffffff 00000000 S AsyncTask #3
-u0_a193 12484 2647 1541760 60840 ffffffff 00000000 S AsyncTask #4
-u0_a193 12576 2647 1541760 60840 ffffffff 00000000 S AsyncTask #5
-u0_a193 3104 205 1523132 46892 ffffffff 00000000 S com.qiyi.video.market:pluginDownloadService
-u0_a193 3110 3104 1523132 46892 ffffffff 00000000 S Heap thread poo
-u0_a193 3111 3104 1523132 46892 ffffffff 00000000 S Heap thread poo
-u0_a193 3112 3104 1523132 46892 ffffffff 00000000 S Heap thread poo
-u0_a193 3113 3104 1523132 46892 ffffffff 00000000 S Signal Catcher
-u0_a193 3114 3104 1523132 46892 ffffffff 00000000 S JDWP
-u0_a193 3115 3104 1523132 46892 ffffffff 00000000 S ReferenceQueueD
-u0_a193 3116 3104 1523132 46892 ffffffff 00000000 S FinalizerDaemon
-u0_a193 3117 3104 1523132 46892 ffffffff 00000000 S FinalizerWatchd
-u0_a193 3118 3104 1523132 46892 ffffffff 00000000 S HeapTrimmerDaem
-u0_a193 3119 3104 1523132 46892 ffffffff 00000000 S GCDaemon
-u0_a193 3120 3104 1523132 46892 ffffffff 00000000 S Binder_1
-u0_a193 3121 3104 1523132 46892 ffffffff 00000000 S Binder_2
-u0_a193 3141 3104 1523132 46892 ffffffff 00000000 S RefQueueWorker@
-u0_a193 3257 3104 1523132 46892 ffffffff 00000000 S pool-3-thread-1
-u0_a193 7173 3104 1523132 46892 ffffffff 00000000 S Binder_3
-u0_a193 3122 205 1538224 61140 ffffffff 00000000 S com.qiyi.video.market:bdservice_v1
-u0_a193 3128 3122 1538224 61140 ffffffff 00000000 S Heap thread poo
-u0_a193 3129 3122 1538224 61140 ffffffff 00000000 S Heap thread poo
-u0_a193 3130 3122 1538224 61140 ffffffff 00000000 S Heap thread poo
-u0_a193 3131 3122 1538224 61140 ffffffff 00000000 S Signal Catcher
-u0_a193 3132 3122 1538224 61140 ffffffff 00000000 S JDWP
-u0_a193 3133 3122 1538224 61140 ffffffff 00000000 S ReferenceQueueD
-u0_a193 3134 3122 1538224 61140 ffffffff 00000000 S FinalizerDaemon
-u0_a193 3135 3122 1538224 61140 ffffffff 00000000 S FinalizerWatchd
-u0_a193 3136 3122 1538224 61140 ffffffff 00000000 S HeapTrimmerDaem
-u0_a193 3137 3122 1538224 61140 ffffffff 00000000 S GCDaemon
-u0_a193 3138 3122 1538224 61140 ffffffff 00000000 S Binder_1
-u0_a193 3139 3122 1538224 61140 ffffffff 00000000 S Binder_2
-u0_a193 3145 3122 1538224 61140 ffffffff 00000000 S RefQueueWorker@
-u0_a193 3206 3122 1538224 61140 ffffffff 00000000 S WifiManager
-u0_a193 3208 3122 1538224 61140 ffffffff 00000000 S NanoHttpd Main
-u0_a193 7586 3122 1538224 61140 ffffffff 00000000 S pool-4-thread-1
-u0_a193 10584 3122 1538224 61140 ffffffff 00000000 S pool-2-thread-1
-u0_a193 3154 205 1522116 53536 ffffffff 00000000 S com.qiyi.video.market:baiduLocation
-u0_a193 3163 3154 1522116 53536 ffffffff 00000000 S Heap thread poo
-u0_a193 3164 3154 1522116 53536 ffffffff 00000000 S Heap thread poo
-u0_a193 3165 3154 1522116 53536 ffffffff 00000000 S Heap thread poo
-u0_a193 3166 3154 1522116 53536 ffffffff 00000000 S Signal Catcher
-u0_a193 3167 3154 1522116 53536 ffffffff 00000000 S JDWP
-u0_a193 3168 3154 1522116 53536 ffffffff 00000000 S ReferenceQueueD
-u0_a193 3169 3154 1522116 53536 ffffffff 00000000 S FinalizerDaemon
-u0_a193 3170 3154 1522116 53536 ffffffff 00000000 S FinalizerWatchd
-u0_a193 3171 3154 1522116 53536 ffffffff 00000000 S HeapTrimmerDaem
-u0_a193 3172 3154 1522116 53536 ffffffff 00000000 S GCDaemon
-u0_a193 3173 3154 1522116 53536 ffffffff 00000000 S Binder_1
-u0_a193 3174 3154 1522116 53536 ffffffff 00000000 S Binder_2
-u0_a193 3177 3154 1522116 53536 ffffffff 00000000 S RefQueueWorker@
-u0_a193 3199 3154 1522116 53536 ffffffff 00000000 S WifiManager
-u0_a86 3179 205 1561816 58376 ffffffff 00000000 S com.tencent.mm:push
-u0_a86 3183 3179 1561816 58376 ffffffff 00000000 S Heap thread poo
-u0_a86 3184 3179 1561816 58376 ffffffff 00000000 S Heap thread poo
-u0_a86 3185 3179 1561816 58376 ffffffff 00000000 S Heap thread poo
-u0_a86 3187 3179 1561816 58376 ffffffff 00000000 S Signal Catcher
-u0_a86 3189 3179 1561816 58376 ffffffff 00000000 S JDWP
-u0_a86 3190 3179 1561816 58376 ffffffff 00000000 S ReferenceQueueD
-u0_a86 3191 3179 1561816 58376 ffffffff 00000000 S FinalizerDaemon
-u0_a86 3192 3179 1561816 58376 ffffffff 00000000 S FinalizerWatchd
-u0_a86 3193 3179 1561816 58376 ffffffff 00000000 S HeapTrimmerDaem
-u0_a86 3194 3179 1561816 58376 ffffffff 00000000 S GCDaemon
-u0_a86 3195 3179 1561816 58376 ffffffff 00000000 S Binder_1
-u0_a86 3196 3179 1561816 58376 ffffffff 00000000 S Binder_2
-u0_a86 3210 3179 1561816 58376 ffffffff 00000000 S THREAD_POOL_HAN
-u0_a86 3212 3179 1561816 58376 ffffffff 00000000 S tencent.mm:push
-u0_a86 3216 3179 1561816 58376 ffffffff 00000000 S FileObserver
-u0_a86 3238 3179 1561816 58376 ffffffff 00000000 S tencent.mm:push
-u0_a86 3239 3179 1561816 58376 ffffffff 00000000 S default
-u0_a86 3240 3179 1561816 58376 ffffffff 00000000 S WifiManager
-u0_a86 5627 3179 1561816 58376 ffffffff 00000000 S Binder_3
-u0_a86 7150 3179 1561816 58376 ffffffff 00000000 S default
-u0_a170 3217 205 1531688 52204 ffffffff 00000000 S com.baidu.searchbox:bdservice_v1
-u0_a170 3220 3217 1531688 52204 ffffffff 00000000 S Heap thread poo
-u0_a170 3221 3217 1531688 52204 ffffffff 00000000 S Heap thread poo
-u0_a170 3223 3217 1531688 52204 ffffffff 00000000 S Heap thread poo
-u0_a170 3226 3217 1531688 52204 ffffffff 00000000 S Signal Catcher
-u0_a170 3228 3217 1531688 52204 ffffffff 00000000 S JDWP
-u0_a170 3229 3217 1531688 52204 ffffffff 00000000 S ReferenceQueueD
-u0_a170 3230 3217 1531688 52204 ffffffff 00000000 S FinalizerDaemon
-u0_a170 3231 3217 1531688 52204 ffffffff 00000000 S FinalizerWatchd
-u0_a170 3233 3217 1531688 52204 ffffffff 00000000 S HeapTrimmerDaem
-u0_a170 3234 3217 1531688 52204 ffffffff 00000000 S GCDaemon
-u0_a170 3235 3217 1531688 52204 ffffffff 00000000 S Binder_1
-u0_a170 3236 3217 1531688 52204 ffffffff 00000000 S Binder_2
-u0_a170 3303 3217 1531688 52204 ffffffff 00000000 S AsyncTask #1
-u0_a170 3304 3217 1531688 52204 ffffffff 00000000 S AsyncTask #2
-u0_a170 3518 3217 1531688 52204 ffffffff 00000000 S PushService-Pus
-u0_a170 3519 3217 1531688 52204 ffffffff 00000000 S PushService-Pus
-u0_a170 6201 3217 1531688 52204 ffffffff 00000000 S pool-1-thread-1
-u0_a170 10591 3217 1531688 52204 ffffffff 00000000 S RefQueueWorker@
-u0_a170 3260 205 1533384 53212 ffffffff 00000000 S com.baidu.searchbox:bdmoservice
-u0_a170 3264 3260 1533384 53212 ffffffff 00000000 S Heap thread poo
-u0_a170 3265 3260 1533384 53212 ffffffff 00000000 S Heap thread poo
-u0_a170 3266 3260 1533384 53212 ffffffff 00000000 S Heap thread poo
-u0_a170 3269 3260 1533384 53212 ffffffff 00000000 S Signal Catcher
-u0_a170 3270 3260 1533384 53212 ffffffff 00000000 S JDWP
-u0_a170 3271 3260 1533384 53212 ffffffff 00000000 S ReferenceQueueD
-u0_a170 3272 3260 1533384 53212 ffffffff 00000000 S FinalizerDaemon
-u0_a170 3273 3260 1533384 53212 ffffffff 00000000 S FinalizerWatchd
-u0_a170 3274 3260 1533384 53212 ffffffff 00000000 S HeapTrimmerDaem
-u0_a170 3275 3260 1533384 53212 ffffffff 00000000 S GCDaemon
-u0_a170 3276 3260 1533384 53212 ffffffff 00000000 S Binder_1
-u0_a170 3277 3260 1533384 53212 ffffffff 00000000 S Binder_2
-u0_a170 3738 3260 1533384 53212 ffffffff 00000000 S NanoHttpd Main
-u0_a170 5783 3260 1533384 53212 ffffffff 00000000 S WifiManager
-u0_a126 3633 205 1515740 46080 ffffffff 00000000 S com.tencent.portfolio:push
-u0_a126 3636 3633 1515740 46080 ffffffff 00000000 S Heap thread poo
-u0_a126 3638 3633 1515740 46080 ffffffff 00000000 S Heap thread poo
-u0_a126 3639 3633 1515740 46080 ffffffff 00000000 S Heap thread poo
-u0_a126 3642 3633 1515740 46080 ffffffff 00000000 S Signal Catcher
-u0_a126 3643 3633 1515740 46080 ffffffff 00000000 S JDWP
-u0_a126 3645 3633 1515740 46080 ffffffff 00000000 S ReferenceQueueD
-u0_a126 3646 3633 1515740 46080 ffffffff 00000000 S FinalizerDaemon
-u0_a126 3647 3633 1515740 46080 ffffffff 00000000 S FinalizerWatchd
-u0_a126 3648 3633 1515740 46080 ffffffff 00000000 S HeapTrimmerDaem
-u0_a126 3649 3633 1515740 46080 ffffffff 00000000 S GCDaemon
-u0_a126 3650 3633 1515740 46080 ffffffff 00000000 S Binder_1
-u0_a126 3651 3633 1515740 46080 ffffffff 00000000 S Binder_2
-u0_a126 3661 3633 1515740 46080 ffffffff 00000000 S TPPluginCenter
-u0_a126 3663 3633 1515740 46080 ffffffff 00000000 S pool-1-thread-1
-u0_a126 3665 3633 1515740 46080 ffffffff 00000000 S MidService
-u0_a126 3667 3633 1515740 46080 ffffffff 00000000 S pool-2-thread-1
-u0_a126 3668 3633 1515740 46080 ffffffff 00000000 S push core threa
-u0_a126 3670 3633 1515740 46080 ffffffff 00000000 S .ProcessManager
-u0_a126 3672 3633 1515740 46080 ffffffff 00000000 S Binder_3
-u0_a126 3674 3633 1515740 46080 ffffffff 00000000 S pool-4-thread-1
-u0_a126 3675 3633 1515740 46080 ffffffff 00000000 S pool-3-thread-1
-u0_a126 5638 3633 1515740 46080 ffffffff 00000000 S Timer-0
-bluetooth 4227 205 1527652 48088 ffffffff 00000000 S com.android.bluetooth
-bluetooth 4231 4227 1527652 48088 ffffffff 00000000 S Heap thread poo
-bluetooth 4233 4227 1527652 48088 ffffffff 00000000 S Heap thread poo
-bluetooth 4235 4227 1527652 48088 ffffffff 00000000 S Heap thread poo
-bluetooth 4236 4227 1527652 48088 ffffffff 00000000 S Signal Catcher
-bluetooth 4237 4227 1527652 48088 ffffffff 00000000 S JDWP
-bluetooth 4238 4227 1527652 48088 ffffffff 00000000 S ReferenceQueueD
-bluetooth 4239 4227 1527652 48088 ffffffff 00000000 S FinalizerDaemon
-bluetooth 4240 4227 1527652 48088 ffffffff 00000000 S FinalizerWatchd
-bluetooth 4241 4227 1527652 48088 ffffffff 00000000 S HeapTrimmerDaem
-bluetooth 4242 4227 1527652 48088 ffffffff 00000000 S GCDaemon
-bluetooth 4243 4227 1527652 48088 ffffffff 00000000 S Binder_1
-bluetooth 4244 4227 1527652 48088 ffffffff 00000000 S Binder_2
-bluetooth 4308 4227 1527652 48088 ffffffff 00000000 S BluetoothAdapte
-bluetooth 4309 4227 1527652 48088 ffffffff 00000000 S droid.bluetooth
-bluetooth 4311 4227 1527652 48088 ffffffff 00000000 S bluedroid wake/
-bluetooth 4312 4227 1527652 48088 ffffffff 00000000 S BT Service Call
-bluetooth 4315 4227 1527652 48088 ffffffff 00000000 S BondStateMachin
-bluetooth 4316 4227 1527652 48088 ffffffff 00000000 S Binder_3
-bluetooth 4317 4227 1527652 48088 ffffffff 00000000 S Binder_4
-bluetooth 4318 4227 1527652 48088 ffffffff 00000000 S HeadsetStateMac
-bluetooth 4320 4227 1527652 48088 ffffffff 00000000 S BluetoothAvrcpH
-bluetooth 4321 4227 1527652 48088 ffffffff 00000000 S A2dpStateMachin
-bluetooth 4322 4227 1527652 48088 ffffffff 00000000 S A2DP-MEDIA
-bluetooth 4323 4227 1527652 48088 ffffffff 00000000 S uipc-main
-bluetooth 4324 4227 1527652 48088 ffffffff 00000000 S BluetoothHdpHan
-bluetooth 4325 4227 1527652 48088 ffffffff 00000000 S droid.bluetooth
-bluetooth 4326 4227 1527652 48088 ffffffff 00000000 S BluetoothAdvert
-bluetooth 4327 4227 1527652 48088 ffffffff 00000000 S BluetoothScanMa
-bluetooth 4331 4227 1527652 48088 ffffffff 00000000 S bluedroid wake/
-bluetooth 4333 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker
-bluetooth 4338 4227 1527652 48088 ffffffff 00000000 S userial_read
-bluetooth 4478 4227 1527652 48088 ffffffff 00000000 S BT Service Call
-bluetooth 4479 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker
-bluetooth 4481 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker
-bluetooth 4482 4227 1527652 48088 ffffffff 00000000 S BluetoothMapAcc
-bluetooth 6459 4227 1527652 48088 ffffffff 00000000 S BluetoothPbapAc
-bluetooth 6473 4227 1527652 48088 ffffffff 00000000 S pool-1-thread-1
-bluetooth 6477 4227 1527652 48088 ffffffff 00000000 S BtOppRfcommList
-radio 4597 205 1493160 37460 ffffffff 00000000 S com.qualcomm.qcrilmsgtunnel
-radio 4603 4597 1493160 37460 ffffffff 00000000 S Heap thread poo
-radio 4604 4597 1493160 37460 ffffffff 00000000 S Heap thread poo
-radio 4605 4597 1493160 37460 ffffffff 00000000 S Heap thread poo
-radio 4606 4597 1493160 37460 ffffffff 00000000 S Signal Catcher
-radio 4607 4597 1493160 37460 ffffffff 00000000 S JDWP
-radio 4608 4597 1493160 37460 ffffffff 00000000 S ReferenceQueueD
-radio 4609 4597 1493160 37460 ffffffff 00000000 S FinalizerDaemon
-radio 4610 4597 1493160 37460 ffffffff 00000000 S FinalizerWatchd
-radio 4611 4597 1493160 37460 ffffffff 00000000 S HeapTrimmerDaem
-radio 4612 4597 1493160 37460 ffffffff 00000000 S GCDaemon
-radio 4613 4597 1493160 37460 ffffffff 00000000 S Binder_1
-radio 4614 4597 1493160 37460 ffffffff 00000000 S Binder_2
-radio 4615 4597 1493160 37460 ffffffff 00000000 S QcRilReceiver
-radio 4616 4597 1493160 37460 ffffffff 00000000 S QcRilSender
-u0_a193 5239 205 1528424 47860 ffffffff 00000000 S .iqiyipushserviceGlobal
-u0_a193 5242 5239 1528424 47860 ffffffff 00000000 S Heap thread poo
-u0_a193 5244 5239 1528424 47860 ffffffff 00000000 S Heap thread poo
-u0_a193 5245 5239 1528424 47860 ffffffff 00000000 S Heap thread poo
-u0_a193 5248 5239 1528424 47860 ffffffff 00000000 S Signal Catcher
-u0_a193 5249 5239 1528424 47860 ffffffff 00000000 S JDWP
-u0_a193 5250 5239 1528424 47860 ffffffff 00000000 S ReferenceQueueD
-u0_a193 5251 5239 1528424 47860 ffffffff 00000000 S FinalizerDaemon
-u0_a193 5252 5239 1528424 47860 ffffffff 00000000 S FinalizerWatchd
-u0_a193 5253 5239 1528424 47860 ffffffff 00000000 S HeapTrimmerDaem
-u0_a193 5254 5239 1528424 47860 ffffffff 00000000 S GCDaemon
-u0_a193 5255 5239 1528424 47860 ffffffff 00000000 S Binder_1
-u0_a193 5257 5239 1528424 47860 ffffffff 00000000 S Binder_2
-u0_a193 5280 5239 1528424 47860 ffffffff 00000000 S RefQueueWorker@
-u0_a193 5281 5239 1528424 47860 ffffffff 00000000 S Binder_3
-u0_a193 5361 5239 1528424 47860 ffffffff 00000000 S Micro Client Co
-u0_a193 5362 5239 1528424 47860 ffffffff 00000000 S Micro Client Co
-u0_a193 5363 5239 1528424 47860 ffffffff 00000000 S Micro Client Ca
-u0_a193 6740 5239 1528424 47860 ffffffff 00000000 S Binder_4
-u0_a193 7091 5239 1528424 47860 ffffffff 00000000 S Binder_5
-u0_a193 7557 5239 1528424 47860 ffffffff 00000000 S Binder_6
-u0_a193 5285 5239 1521088 34196 ffffffff 00000000 S .iqiyipushserviceGlobal
-u0_a90 5323 205 1557268 59988 ffffffff 00000000 S com.strava
-u0_a90 5327 5323 1557268 59988 ffffffff 00000000 S Heap thread poo
-u0_a90 5328 5323 1557268 59988 ffffffff 00000000 S Heap thread poo
-u0_a90 5329 5323 1557268 59988 ffffffff 00000000 S Heap thread poo
-u0_a90 5332 5323 1557268 59988 ffffffff 00000000 S Signal Catcher
-u0_a90 5333 5323 1557268 59988 ffffffff 00000000 S JDWP
-u0_a90 5334 5323 1557268 59988 ffffffff 00000000 S ReferenceQueueD
-u0_a90 5335 5323 1557268 59988 ffffffff 00000000 S FinalizerDaemon
-u0_a90 5336 5323 1557268 59988 ffffffff 00000000 S FinalizerWatchd
-u0_a90 5337 5323 1557268 59988 ffffffff 00000000 S HeapTrimmerDaem
-u0_a90 5338 5323 1557268 59988 ffffffff 00000000 S GCDaemon
-u0_a90 5339 5323 1557268 59988 ffffffff 00000000 S Binder_1
-u0_a90 5340 5323 1557268 59988 ffffffff 00000000 S Binder_2
-u0_a90 5345 5323 1557268 59988 ffffffff 00000000 S Queue
-u0_a90 5346 5323 1557268 59988 ffffffff 00000000 S Queue
-u0_a90 5347 5323 1557268 59988 ffffffff 00000000 S Queue
-u0_a90 5348 5323 1557268 59988 ffffffff 00000000 S Queue
-u0_a90 5349 5323 1557268 59988 ffffffff 00000000 S Queue
-u0_a90 5352 5323 1557268 59988 ffffffff 00000000 S Crashlytics Exc
-u0_a90 5354 5323 1557268 59988 ffffffff 00000000 S pool-3-thread-1
-u0_a90 5364 5323 1557268 59988 ffffffff 00000000 S Thread-584
-u0_a90 5365 5323 1557268 59988 ffffffff 00000000 S Thread-585
-u0_a90 5366 5323 1557268 59988 ffffffff 00000000 S Thread-586
-u0_a90 5367 5323 1557268 59988 ffffffff 00000000 S pool-4-thread-1
-u0_a90 5369 5323 1557268 59988 ffffffff 00000000 S Crashlytics Tra
-u0_a90 5372 5323 1557268 59988 ffffffff 00000000 S Thread-593
-u0_a90 5373 5323 1557268 59988 ffffffff 00000000 S Thread-594
-u0_a90 5374 5323 1557268 59988 ffffffff 00000000 S Thread-595
-u0_a90 5375 5323 1557268 59988 ffffffff 00000000 S Thread-596
-u0_a90 5376 5323 1557268 59988 ffffffff 00000000 S pool-6-thread-1
-u0_a90 5377 5323 1557268 59988 ffffffff 00000000 S Thread-598
-u0_a90 5378 5323 1557268 59988 ffffffff 00000000 S Thread-599
-u0_a90 5379 5323 1557268 59988 ffffffff 00000000 S Thread-600
-u0_a90 5381 5323 1557268 59988 ffffffff 00000000 S Thread-602
-u0_a90 5383 5323 1557268 59988 ffffffff 00000000 S Thread #1
-u0_a90 5384 5323 1557268 59988 ffffffff 00000000 S AsyncTask #1
-u0_a90 5387 5323 1557268 59988 ffffffff 00000000 S Thread-605
-u0_a90 5388 5323 1557268 59988 ffffffff 00000000 S Thread-606
-u0_a90 5389 5323 1557268 59988 ffffffff 00000000 S Thread-607
-u0_a90 5390 5323 1557268 59988 ffffffff 00000000 S Thread-608
-u0_a90 5391 5323 1557268 59988 ffffffff 00000000 S Thread-609
-u0_a90 5393 5323 1557268 59988 ffffffff 00000000 S eNowAuthService
-u0_a90 5394 5323 1557268 59988 ffffffff 00000000 S Thread #2
-u0_a90 5468 5323 1557268 59988 ffffffff 00000000 S Okio Watchdog
-u0_a90 5498 5323 1557268 59988 ffffffff 00000000 S Thread #3
-u0_a109 5395 205 1524968 53976 ffffffff 00000000 S com.pandora.android
-u0_a109 5397 5395 1524968 53976 ffffffff 00000000 S Heap thread poo
-u0_a109 5398 5395 1524968 53976 ffffffff 00000000 S Heap thread poo
-u0_a109 5399 5395 1524968 53976 ffffffff 00000000 S Heap thread poo
-u0_a109 5401 5395 1524968 53976 ffffffff 00000000 S Signal Catcher
-u0_a109 5403 5395 1524968 53976 ffffffff 00000000 S JDWP
-u0_a109 5407 5395 1524968 53976 ffffffff 00000000 S ReferenceQueueD
-u0_a109 5408 5395 1524968 53976 ffffffff 00000000 S FinalizerDaemon
-u0_a109 5409 5395 1524968 53976 ffffffff 00000000 S FinalizerWatchd
-u0_a109 5410 5395 1524968 53976 ffffffff 00000000 S HeapTrimmerDaem
-u0_a109 5411 5395 1524968 53976 ffffffff 00000000 S GCDaemon
-u0_a109 5414 5395 1524968 53976 ffffffff 00000000 S Binder_1
-u0_a109 5416 5395 1524968 53976 ffffffff 00000000 S Binder_2
-u0_a109 5422 5395 1524968 53976 ffffffff 00000000 S Crashlytics Exc
-u0_a109 5429 5395 1524968 53976 ffffffff 00000000 S pool-2-thread-1
-u0_a109 5430 5395 1524968 53976 ffffffff 00000000 S AsyncTask #1
-u0_a109 5437 5395 1524968 53976 ffffffff 00000000 S Crashlytics Tra
-u0_a109 5439 5395 1524968 53976 ffffffff 00000000 S AsyncTask #2
-u0_a109 5440 5395 1524968 53976 ffffffff 00000000 S pool-4-thread-1
-u0_a109 5443 5395 1524968 53976 ffffffff 00000000 S PurchasingManag
-u0_a109 5444 5395 1524968 53976 ffffffff 00000000 S BluetoothServer
-u0_a109 5445 5395 1524968 53976 ffffffff 00000000 S AsyncTask #3
-u0_a109 5446 5395 1524968 53976 ffffffff 00000000 S AsyncTask #4
-u0_a109 5590 5395 1524968 53976 ffffffff 00000000 S Binder_3
-u0_a109 6481 5395 1524968 53976 ffffffff 00000000 S AsyncTask #5
-u0_a110 5474 205 1525556 49828 ffffffff 00000000 S tunein.player
-u0_a110 5479 5474 1525556 49828 ffffffff 00000000 S Heap thread poo
-u0_a110 5480 5474 1525556 49828 ffffffff 00000000 S Heap thread poo
-u0_a110 5481 5474 1525556 49828 ffffffff 00000000 S Heap thread poo
-u0_a110 5483 5474 1525556 49828 ffffffff 00000000 S Signal Catcher
-u0_a110 5484 5474 1525556 49828 ffffffff 00000000 S JDWP
-u0_a110 5485 5474 1525556 49828 ffffffff 00000000 S ReferenceQueueD
-u0_a110 5486 5474 1525556 49828 ffffffff 00000000 S FinalizerDaemon
-u0_a110 5487 5474 1525556 49828 ffffffff 00000000 S FinalizerWatchd
-u0_a110 5488 5474 1525556 49828 ffffffff 00000000 S HeapTrimmerDaem
-u0_a110 5489 5474 1525556 49828 ffffffff 00000000 S GCDaemon
-u0_a110 5490 5474 1525556 49828 ffffffff 00000000 S Binder_1
-u0_a110 5492 5474 1525556 49828 ffffffff 00000000 S Binder_2
-u0_a110 5503 5474 1525556 49828 ffffffff 00000000 S geHandlerThread
-u0_a110 5504 5474 1525556 49828 ffffffff 00000000 S GAThread
-u0_a110 5507 5474 1525556 49828 ffffffff 00000000 S Crashlytics Exc
-u0_a110 5510 5474 1525556 49828 ffffffff 00000000 S AsyncTask #1
-u0_a110 5515 5474 1525556 49828 ffffffff 00000000 S Crashlytics Tra
-u0_a110 5518 5474 1525556 49828 ffffffff 00000000 S AsyncTask #2
-u0_a110 5587 5474 1525556 49828 ffffffff 00000000 S AcceptThreadSec
-u0_a88 5519 205 1556696 65876 ffffffff 00000000 S com.dropbox.android
-u0_a88 5525 5519 1556696 65876 ffffffff 00000000 S Heap thread poo
-u0_a88 5526 5519 1556696 65876 ffffffff 00000000 S Heap thread poo
-u0_a88 5527 5519 1556696 65876 ffffffff 00000000 S Heap thread poo
-u0_a88 5528 5519 1556696 65876 ffffffff 00000000 S Signal Catcher
-u0_a88 5529 5519 1556696 65876 ffffffff 00000000 S JDWP
-u0_a88 5530 5519 1556696 65876 ffffffff 00000000 S ReferenceQueueD
-u0_a88 5531 5519 1556696 65876 ffffffff 00000000 S FinalizerDaemon
-u0_a88 5532 5519 1556696 65876 ffffffff 00000000 S FinalizerWatchd
-u0_a88 5533 5519 1556696 65876 ffffffff 00000000 S HeapTrimmerDaem
-u0_a88 5534 5519 1556696 65876 ffffffff 00000000 S GCDaemon
-u0_a88 5535 5519 1556696 65876 ffffffff 00000000 S Binder_1
-u0_a88 5536 5519 1556696 65876 ffffffff 00000000 S Binder_2
-u0_a88 5562 5519 1556696 65876 ffffffff 00000000 S Dropbox log upl
-u0_a88 5563 5519 1556696 65876 ffffffff 00000000 S gandalf updater
-u0_a88 5568 5519 1556696 65876 ffffffff 00000000 S pool-10-thread-
-u0_a88 5569 5519 1556696 65876 ffffffff 00000000 S DbxFileObserver
-u0_a88 5570 5519 1556696 65876 ffffffff 00000000 S LocalThumbManag
-u0_a88 5574 5519 1556696 65876 ffffffff 00000000 S local AsyncTask
-u0_a88 5575 5519 1556696 65876 ffffffff 00000000 S remote AsyncTas
-u0_a88 5576 5519 1556696 65876 ffffffff 00000000 S local AsyncTask
-u0_a88 5577 5519 1556696 65876 ffffffff 00000000 S remote AsyncTas
-u0_a88 5578 5519 1556696 65876 ffffffff 00000000 S Dropbox notif o
-u0_a88 5579 5519 1556696 65876 ffffffff 00000000 S Dropbox notif s
-u0_a88 5580 5519 1556696 65876 ffffffff 00000000 S Picasso-Stats
-u0_a88 5581 5519 1556696 65876 ffffffff 00000000 S Picasso-Dispatc
-u0_a88 5582 5519 1556696 65876 ffffffff 00000000 S Picasso-refQueu
-u0_a88 5583 5519 1556696 65876 ffffffff 00000000 S gandalf updater
-u0_a88 5592 5519 1556696 65876 ffffffff 00000000 S DbxFileObserver
-u0_a88 5593 5519 1556696 65876 ffffffff 00000000 S dbxpool-34:r-th
-u0_a88 5594 5519 1556696 65876 ffffffff 00000000 S dbxpool-32:au-t
-u0_a88 5595 5519 1556696 65876 ffffffff 00000000 S dbxpool-38:a-th
-u0_a88 5596 5519 1556696 65876 ffffffff 00000000 S Timer-0
-u0_a88 5597 5519 1556696 65876 ffffffff 00000000 S dbxpool-6:a-thr
-u0_a88 5599 5519 1556696 65876 ffffffff 00000000 S Timer-1
-u0_a88 5718 5519 1556696 65876 ffffffff 00000000 S RefQueueWorker@
-u0_a88 5750 5519 1556696 65876 ffffffff 00000000 S Thread-625
-u0_a88 5818 5519 1556696 65876 ffffffff 00000000 S Binder_3
-u0_a88 8569 5519 1556696 65876 ffffffff 00000000 S Binder_4
-u0_a88 8572 5519 1556696 65876 ffffffff 00000000 S Binder_5
-u0_a88 8580 5519 1556696 65876 ffffffff 00000000 S Binder_6
-u0_a93 5688 205 1496212 39724 ffffffff 00000000 S com.devuni.flashlight:remote
-u0_a93 5693 5688 1496212 39724 ffffffff 00000000 S Heap thread poo
-u0_a93 5694 5688 1496212 39724 ffffffff 00000000 S Heap thread poo
-u0_a93 5695 5688 1496212 39724 ffffffff 00000000 S Heap thread poo
-u0_a93 5697 5688 1496212 39724 ffffffff 00000000 S Signal Catcher
-u0_a93 5698 5688 1496212 39724 ffffffff 00000000 S JDWP
-u0_a93 5699 5688 1496212 39724 ffffffff 00000000 S ReferenceQueueD
-u0_a93 5700 5688 1496212 39724 ffffffff 00000000 S FinalizerDaemon
-u0_a93 5701 5688 1496212 39724 ffffffff 00000000 S FinalizerWatchd
-u0_a93 5702 5688 1496212 39724 ffffffff 00000000 S HeapTrimmerDaem
-u0_a93 5703 5688 1496212 39724 ffffffff 00000000 S GCDaemon
-u0_a93 5704 5688 1496212 39724 ffffffff 00000000 S Binder_1
-u0_a93 5705 5688 1496212 39724 ffffffff 00000000 S Binder_2
-u0_a93 12039 5688 1496212 39724 ffffffff 00000000 S pool-1-thread-1
-u0_a86 6202 205 1809096 86876 ffffffff 00000000 S com.tencent.mm
-u0_a86 6206 6202 1809096 86876 ffffffff 00000000 S Heap thread poo
-u0_a86 6207 6202 1809096 86876 ffffffff 00000000 S Heap thread poo
-u0_a86 6208 6202 1809096 86876 ffffffff 00000000 S Heap thread poo
-u0_a86 6211 6202 1809096 86876 ffffffff 00000000 S Signal Catcher
-u0_a86 6212 6202 1809096 86876 ffffffff 00000000 S JDWP
-u0_a86 6213 6202 1809096 86876 ffffffff 00000000 S ReferenceQueueD
-u0_a86 6214 6202 1809096 86876 ffffffff 00000000 S FinalizerDaemon
-u0_a86 6215 6202 1809096 86876 ffffffff 00000000 S FinalizerWatchd
-u0_a86 6217 6202 1809096 86876 ffffffff 00000000 S HeapTrimmerDaem
-u0_a86 6218 6202 1809096 86876 ffffffff 00000000 S GCDaemon
-u0_a86 6220 6202 1809096 86876 ffffffff 00000000 S Binder_1
-u0_a86 6221 6202 1809096 86876 ffffffff 00000000 S Binder_2
-u0_a86 6236 6202 1809096 86876 ffffffff 00000000 S THREAD_POOL_HAN
-u0_a86 6237 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm
-u0_a86 6239 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm
-u0_a86 6240 6202 1809096 86876 ffffffff 00000000 S MonitorHandlerT
-u0_a86 6241 6202 1809096 86876 ffffffff 00000000 S .ProcessManager
-u0_a86 6243 6202 1809096 86876 ffffffff 00000000 S Binder_3
-u0_a86 6245 6202 1809096 86876 ffffffff 00000000 S default
-u0_a86 6246 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm
-u0_a86 6247 6202 1809096 86876 ffffffff 00000000 S MMHandlerThread
-u0_a86 6269 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6270 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6271 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6272 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6273 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6274 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6276 6202 1809096 86876 ffffffff 00000000 S ExdeviceHandler
-u0_a86 6277 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6279 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout
-u0_a86 6280 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout
-u0_a86 6282 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6284 6202 1809096 86876 ffffffff 00000000 S downloadStateCh
-u0_a86 6288 6202 1809096 86876 ffffffff 00000000 S WifiManager
-u0_a86 6289 6202 1809096 86876 ffffffff 00000000 S refresh Notific
-u0_a86 6292 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6293 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6294 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6295 6202 1809096 86876 ffffffff 00000000 S SearchDaemon
-u0_a86 6303 6202 1809096 86876 ffffffff 00000000 S Binder_4
-u0_a86 6313 6202 1809096 86876 ffffffff 00000000 S pool-2-thread-1
-u0_a86 6373 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout
-u0_a86 6408 6202 1809096 86876 ffffffff 00000000 S h
-u0_a86 7230 6202 1809096 86876 ffffffff 00000000 S default
-u0_a86 7231 6202 1809096 86876 ffffffff 00000000 S MMHandlerThread
-u0_a191 8839 205 1510312 57352 ffffffff 00000000 S com.ushaqi.zhuishushenqi:pushservice
-u0_a191 8845 8839 1510312 57352 ffffffff 00000000 S Heap thread poo
-u0_a191 8846 8839 1510312 57352 ffffffff 00000000 S Heap thread poo
-u0_a191 8847 8839 1510312 57352 ffffffff 00000000 S Heap thread poo
-u0_a191 8849 8839 1510312 57352 ffffffff 00000000 S Signal Catcher
-u0_a191 8850 8839 1510312 57352 ffffffff 00000000 S JDWP
-u0_a191 8851 8839 1510312 57352 ffffffff 00000000 S ReferenceQueueD
-u0_a191 8852 8839 1510312 57352 ffffffff 00000000 S FinalizerDaemon
-u0_a191 8853 8839 1510312 57352 ffffffff 00000000 S FinalizerWatchd
-u0_a191 8854 8839 1510312 57352 ffffffff 00000000 S HeapTrimmerDaem
-u0_a191 8855 8839 1510312 57352 ffffffff 00000000 S GCDaemon
-u0_a191 8856 8839 1510312 57352 ffffffff 00000000 S Binder_1
-u0_a191 8857 8839 1510312 57352 ffffffff 00000000 S Binder_2
-u0_a191 8867 8839 1510312 57352 ffffffff 00000000 S local_job_dispa
-u0_a191 8869 8839 1510312 57352 ffffffff 00000000 S remote_job_disp
-u0_a191 8887 8839 1510312 57352 ffffffff 00000000 S Upload Http Rec
-u0_a191 8890 8839 1510312 57352 ffffffff 00000000 S Connection Cont
-u0_a191 8963 8839 1510312 57352 ffffffff 00000000 S Smack Packet Re
-root 11634 2 0 0 ffffffff 00000000 S kworker/u:0
-root 11779 2 0 0 ffffffff 00000000 S kworker/0:3H
-root 11928 2 0 0 ffffffff 00000000 S kworker/0:1
-root 12431 2 0 0 ffffffff 00000000 S kworker/u:2
-u0_a85 12971 205 1595348 59000 ffffffff 00000000 S com.life360.android.safetymapd:service
-u0_a85 12977 12971 1595348 59000 ffffffff 00000000 S Heap thread poo
-u0_a85 12978 12971 1595348 59000 ffffffff 00000000 S Heap thread poo
-u0_a85 12979 12971 1595348 59000 ffffffff 00000000 S Heap thread poo
-u0_a85 12980 12971 1595348 59000 ffffffff 00000000 S Signal Catcher
-u0_a85 12981 12971 1595348 59000 ffffffff 00000000 S JDWP
-u0_a85 12982 12971 1595348 59000 ffffffff 00000000 S ReferenceQueueD
-u0_a85 12983 12971 1595348 59000 ffffffff 00000000 S FinalizerDaemon
-u0_a85 12984 12971 1595348 59000 ffffffff 00000000 S FinalizerWatchd
-u0_a85 12985 12971 1595348 59000 ffffffff 00000000 S HeapTrimmerDaem
-u0_a85 12986 12971 1595348 59000 ffffffff 00000000 S GCDaemon
-u0_a85 12987 12971 1595348 59000 ffffffff 00000000 S Binder_1
-u0_a85 12988 12971 1595348 59000 ffffffff 00000000 S Binder_2
-u0_a85 13099 12971 1595348 59000 ffffffff 00000000 S WifiManager
-u0_a106 13071 205 1523392 47680 ffffffff 00000000 S com.xianguo.tingguo
-u0_a106 13075 13071 1523392 47680 ffffffff 00000000 S Heap thread poo
-u0_a106 13076 13071 1523392 47680 ffffffff 00000000 S Heap thread poo
-u0_a106 13077 13071 1523392 47680 ffffffff 00000000 S Heap thread poo
-u0_a106 13080 13071 1523392 47680 ffffffff 00000000 S Signal Catcher
-u0_a106 13081 13071 1523392 47680 ffffffff 00000000 S JDWP
-u0_a106 13082 13071 1523392 47680 ffffffff 00000000 S ReferenceQueueD
-u0_a106 13083 13071 1523392 47680 ffffffff 00000000 S FinalizerDaemon
-u0_a106 13084 13071 1523392 47680 ffffffff 00000000 S FinalizerWatchd
-u0_a106 13085 13071 1523392 47680 ffffffff 00000000 S HeapTrimmerDaem
-u0_a106 13086 13071 1523392 47680 ffffffff 00000000 S GCDaemon
-u0_a106 13087 13071 1523392 47680 ffffffff 00000000 S Binder_1
-u0_a106 13088 13071 1523392 47680 ffffffff 00000000 S Binder_2
-u0_a106 13090 13071 1523392 47680 ffffffff 00000000 S SoundPool
-u0_a106 13091 13071 1523392 47680 ffffffff 00000000 S SoundPoolThread
-u0_a106 13276 13071 1523392 47680 ffffffff 00000000 S WifiManager
-u0_a65 13345 205 1526244 52680 ffffffff 00000000 S com.google.android.apps.photos
-u0_a65 13351 13345 1526244 52680 ffffffff 00000000 S Heap thread poo
-u0_a65 13352 13345 1526244 52680 ffffffff 00000000 S Heap thread poo
-u0_a65 13353 13345 1526244 52680 ffffffff 00000000 S Heap thread poo
-u0_a65 13354 13345 1526244 52680 ffffffff 00000000 S Signal Catcher
-u0_a65 13355 13345 1526244 52680 ffffffff 00000000 S JDWP
-u0_a65 13356 13345 1526244 52680 ffffffff 00000000 S ReferenceQueueD
-u0_a65 13357 13345 1526244 52680 ffffffff 00000000 S FinalizerDaemon
-u0_a65 13358 13345 1526244 52680 ffffffff 00000000 S FinalizerWatchd
-u0_a65 13359 13345 1526244 52680 ffffffff 00000000 S HeapTrimmerDaem
-u0_a65 13360 13345 1526244 52680 ffffffff 00000000 S GCDaemon
-u0_a65 13361 13345 1526244 52680 ffffffff 00000000 S Binder_1
-u0_a65 13362 13345 1526244 52680 ffffffff 00000000 S Binder_2
-u0_a65 13783 13345 1526244 52680 ffffffff 00000000 S pool-1-thread-1
-u0_a65 13796 13345 1526244 52680 ffffffff 00000000 S rotating_file-t
-u0_a65 13904 13345 1526244 52680 ffffffff 00000000 S Binder_3
-u0_a67 13491 205 1567688 56576 ffffffff 00000000 S com.google.android.apps.plus
-u0_a67 13493 13491 1567688 56576 ffffffff 00000000 S Heap thread poo
-u0_a67 13494 13491 1567688 56576 ffffffff 00000000 S Heap thread poo
-u0_a67 13495 13491 1567688 56576 ffffffff 00000000 S Heap thread poo
-u0_a67 13497 13491 1567688 56576 ffffffff 00000000 S Signal Catcher
-u0_a67 13499 13491 1567688 56576 ffffffff 00000000 S JDWP
-u0_a67 13502 13491 1567688 56576 ffffffff 00000000 S ReferenceQueueD
-u0_a67 13503 13491 1567688 56576 ffffffff 00000000 S FinalizerDaemon
-u0_a67 13504 13491 1567688 56576 ffffffff 00000000 S FinalizerWatchd
-u0_a67 13505 13491 1567688 56576 ffffffff 00000000 S HeapTrimmerDaem
-u0_a67 13506 13491 1567688 56576 ffffffff 00000000 S GCDaemon
-u0_a67 13507 13491 1567688 56576 ffffffff 00000000 S Binder_1
-u0_a67 13508 13491 1567688 56576 ffffffff 00000000 S Binder_2
-u0_a67 13512 13491 1567688 56576 ffffffff 00000000 S picasa-photo-pr
-u0_a67 13528 13491 1567688 56576 ffffffff 00000000 S iu-sync-manager
-u0_a67 13538 13491 1567688 56576 ffffffff 00000000 S pool-2-thread-1
-u0_a67 13881 13491 1567688 56576 ffffffff 00000000 S Gservices
-u0_a4 13516 205 1503264 48612 ffffffff 00000000 S android.process.acore
-u0_a4 13520 13516 1503264 48612 ffffffff 00000000 S Heap thread poo
-u0_a4 13521 13516 1503264 48612 ffffffff 00000000 S Heap thread poo
-u0_a4 13522 13516 1503264 48612 ffffffff 00000000 S Heap thread poo
-u0_a4 13525 13516 1503264 48612 ffffffff 00000000 S Signal Catcher
-u0_a4 13526 13516 1503264 48612 ffffffff 00000000 S JDWP
-u0_a4 13527 13516 1503264 48612 ffffffff 00000000 S ReferenceQueueD
-u0_a4 13529 13516 1503264 48612 ffffffff 00000000 S FinalizerDaemon
-u0_a4 13530 13516 1503264 48612 ffffffff 00000000 S FinalizerWatchd
-u0_a4 13531 13516 1503264 48612 ffffffff 00000000 S HeapTrimmerDaem
-u0_a4 13532 13516 1503264 48612 ffffffff 00000000 S GCDaemon
-u0_a4 13533 13516 1503264 48612 ffffffff 00000000 S Binder_1
-u0_a4 13534 13516 1503264 48612 ffffffff 00000000 S Binder_2
-u0_a4 13536 13516 1503264 48612 ffffffff 00000000 S ContactsProvide
-u0_a4 13537 13516 1503264 48612 ffffffff 00000000 S CallLogProvider
-u0_a102 13613 205 1521420 45204 ffffffff 00000000 S com.sohu.inputmethod.sogou:classic
-u0_a102 13616 13613 1521420 45204 ffffffff 00000000 S Heap thread poo
-u0_a102 13617 13613 1521420 45204 ffffffff 00000000 S Heap thread poo
-u0_a102 13618 13613 1521420 45204 ffffffff 00000000 S Heap thread poo
-u0_a102 13620 13613 1521420 45204 ffffffff 00000000 S Signal Catcher
-u0_a102 13623 13613 1521420 45204 ffffffff 00000000 S JDWP
-u0_a102 13624 13613 1521420 45204 ffffffff 00000000 S ReferenceQueueD
-u0_a102 13625 13613 1521420 45204 ffffffff 00000000 S FinalizerDaemon
-u0_a102 13626 13613 1521420 45204 ffffffff 00000000 S FinalizerWatchd
-u0_a102 13627 13613 1521420 45204 ffffffff 00000000 S HeapTrimmerDaem
-u0_a102 13628 13613 1521420 45204 ffffffff 00000000 S GCDaemon
-u0_a102 13629 13613 1521420 45204 ffffffff 00000000 S Binder_1
-u0_a102 13630 13613 1521420 45204 ffffffff 00000000 S Binder_2
-u0_a102 13635 13613 1521420 45204 ffffffff 00000000 S Thread-1443
-u0_a102 13636 13613 1521420 45204 ffffffff 00000000 S Thread-1444
-u0_a102 13637 13613 1521420 45204 ffffffff 00000000 S Thread-1445
-u0_a102 13638 13613 1521420 45204 ffffffff 00000000 S Thread-1446
-u0_a102 13639 13613 1521420 45204 ffffffff 00000000 S Thread-1447
-u0_a102 13641 13613 1521420 45204 ffffffff 00000000 S WifiManager
-u0_a102 13905 13613 1521420 45204 ffffffff 00000000 S Binder_3
-u0_a102 13647 205 1514052 44264 ffffffff 00000000 S com.sohu.inputmethod.sogou
-u0_a102 13651 13647 1514052 44264 ffffffff 00000000 S Heap thread poo
-u0_a102 13652 13647 1514052 44264 ffffffff 00000000 S Heap thread poo
-u0_a102 13653 13647 1514052 44264 ffffffff 00000000 S Heap thread poo
-u0_a102 13656 13647 1514052 44264 ffffffff 00000000 S Signal Catcher
-u0_a102 13657 13647 1514052 44264 ffffffff 00000000 S JDWP
-u0_a102 13658 13647 1514052 44264 ffffffff 00000000 S ReferenceQueueD
-u0_a102 13659 13647 1514052 44264 ffffffff 00000000 S FinalizerDaemon
-u0_a102 13660 13647 1514052 44264 ffffffff 00000000 S FinalizerWatchd
-u0_a102 13661 13647 1514052 44264 ffffffff 00000000 S HeapTrimmerDaem
-u0_a102 13662 13647 1514052 44264 ffffffff 00000000 S GCDaemon
-u0_a102 13663 13647 1514052 44264 ffffffff 00000000 S Binder_1
-u0_a102 13664 13647 1514052 44264 ffffffff 00000000 S Binder_2
-u0_a102 13671 205 1519416 43248 ffffffff 00000000 S sogou.mobile.explorer.hotwords
-u0_a102 13677 13671 1519416 43248 ffffffff 00000000 S Heap thread poo
-u0_a102 13678 13671 1519416 43248 ffffffff 00000000 S Heap thread poo
-u0_a102 13679 13671 1519416 43248 ffffffff 00000000 S Heap thread poo
-u0_a102 13680 13671 1519416 43248 ffffffff 00000000 S Signal Catcher
-u0_a102 13681 13671 1519416 43248 ffffffff 00000000 S JDWP
-u0_a102 13682 13671 1519416 43248 ffffffff 00000000 S ReferenceQueueD
-u0_a102 13683 13671 1519416 43248 ffffffff 00000000 S FinalizerDaemon
-u0_a102 13684 13671 1519416 43248 ffffffff 00000000 S FinalizerWatchd
-u0_a102 13685 13671 1519416 43248 ffffffff 00000000 S HeapTrimmerDaem
-u0_a102 13686 13671 1519416 43248 ffffffff 00000000 S GCDaemon
-u0_a102 13687 13671 1519416 43248 ffffffff 00000000 S Binder_1
-u0_a102 13688 13671 1519416 43248 ffffffff 00000000 S Binder_2
-u0_a102 13690 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-1
-u0_a102 13691 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-2
-u0_a102 13692 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-3
-u0_a102 13694 13671 1519416 43248 ffffffff 00000000 S Timer-0
-u0_a198 13695 205 1506040 40332 ffffffff 00000000 S org.chromium.chrome.shell
-u0_a198 13701 13695 1506040 40332 ffffffff 00000000 S Heap thread poo
-u0_a198 13702 13695 1506040 40332 ffffffff 00000000 S Heap thread poo
-u0_a198 13703 13695 1506040 40332 ffffffff 00000000 S Heap thread poo
-u0_a198 13704 13695 1506040 40332 ffffffff 00000000 S Signal Catcher
-u0_a198 13705 13695 1506040 40332 ffffffff 00000000 S JDWP
-u0_a198 13706 13695 1506040 40332 ffffffff 00000000 S ReferenceQueueD
-u0_a198 13707 13695 1506040 40332 ffffffff 00000000 S FinalizerDaemon
-u0_a198 13708 13695 1506040 40332 ffffffff 00000000 S FinalizerWatchd
-u0_a198 13709 13695 1506040 40332 ffffffff 00000000 S HeapTrimmerDaem
-u0_a198 13710 13695 1506040 40332 ffffffff 00000000 S GCDaemon
-u0_a198 13711 13695 1506040 40332 ffffffff 00000000 S Binder_1
-u0_a198 13712 13695 1506040 40332 ffffffff 00000000 S Binder_2
-u0_a198 13713 13695 1506040 40332 ffffffff 00000000 S Binder_3
-u0_a200 13715 205 1511344 38748 ffffffff 00000000 S com.rolocule.motiontennis
-u0_a200 13721 13715 1511344 38748 ffffffff 00000000 S Heap thread poo
-u0_a200 13722 13715 1511344 38748 ffffffff 00000000 S Heap thread poo
-u0_a200 13723 13715 1511344 38748 ffffffff 00000000 S Heap thread poo
-u0_a200 13724 13715 1511344 38748 ffffffff 00000000 S Signal Catcher
-u0_a200 13725 13715 1511344 38748 ffffffff 00000000 S JDWP
-u0_a200 13731 13715 1511344 38748 ffffffff 00000000 S ReferenceQueueD
-u0_a200 13732 13715 1511344 38748 ffffffff 00000000 S FinalizerDaemon
-u0_a200 13733 13715 1511344 38748 ffffffff 00000000 S FinalizerWatchd
-u0_a200 13734 13715 1511344 38748 ffffffff 00000000 S HeapTrimmerDaem
-u0_a200 13735 13715 1511344 38748 ffffffff 00000000 S GCDaemon
-u0_a200 13736 13715 1511344 38748 ffffffff 00000000 S Binder_1
-u0_a200 13737 13715 1511344 38748 ffffffff 00000000 S Binder_2
-u0_a175 13747 205 1510096 43460 ffffffff 00000000 S com.google.android.apps.chrome
-u0_a175 13751 13747 1510096 43460 ffffffff 00000000 S Heap thread poo
-u0_a175 13752 13747 1510096 43460 ffffffff 00000000 S Heap thread poo
-u0_a175 13754 13747 1510096 43460 ffffffff 00000000 S Heap thread poo
-u0_a175 13756 13747 1510096 43460 ffffffff 00000000 S Signal Catcher
-u0_a175 13757 13747 1510096 43460 ffffffff 00000000 S JDWP
-u0_a175 13758 13747 1510096 43460 ffffffff 00000000 S ReferenceQueueD
-u0_a175 13759 13747 1510096 43460 ffffffff 00000000 S FinalizerDaemon
-u0_a175 13760 13747 1510096 43460 ffffffff 00000000 S FinalizerWatchd
-u0_a175 13761 13747 1510096 43460 ffffffff 00000000 S HeapTrimmerDaem
-u0_a175 13762 13747 1510096 43460 ffffffff 00000000 S GCDaemon
-u0_a175 13763 13747 1510096 43460 ffffffff 00000000 S Binder_1
-u0_a175 13764 13747 1510096 43460 ffffffff 00000000 S Binder_2
-u0_a85 13774 205 1594212 50972 ffffffff 00000000 S com.life360.android.safetymapd
-u0_a85 13780 13774 1594212 50972 ffffffff 00000000 S Heap thread poo
-u0_a85 13781 13774 1594212 50972 ffffffff 00000000 S Heap thread poo
-u0_a85 13782 13774 1594212 50972 ffffffff 00000000 S Heap thread poo
-u0_a85 13784 13774 1594212 50972 ffffffff 00000000 S Signal Catcher
-u0_a85 13785 13774 1594212 50972 ffffffff 00000000 S JDWP
-u0_a85 13786 13774 1594212 50972 ffffffff 00000000 S ReferenceQueueD
-u0_a85 13787 13774 1594212 50972 ffffffff 00000000 S FinalizerDaemon
-u0_a85 13788 13774 1594212 50972 ffffffff 00000000 S FinalizerWatchd
-u0_a85 13789 13774 1594212 50972 ffffffff 00000000 S HeapTrimmerDaem
-u0_a85 13790 13774 1594212 50972 ffffffff 00000000 S GCDaemon
-u0_a85 13791 13774 1594212 50972 ffffffff 00000000 S Binder_1
-u0_a85 13792 13774 1594212 50972 ffffffff 00000000 S Binder_2
-u0_a16 13801 205 1538004 50644 ffffffff 00000000 S com.android.vending
-u0_a16 13807 13801 1538004 50644 ffffffff 00000000 S Heap thread poo
-u0_a16 13808 13801 1538004 50644 ffffffff 00000000 S Heap thread poo
-u0_a16 13809 13801 1538004 50644 ffffffff 00000000 S Heap thread poo
-u0_a16 13811 13801 1538004 50644 ffffffff 00000000 S Signal Catcher
-u0_a16 13812 13801 1538004 50644 ffffffff 00000000 S JDWP
-u0_a16 13813 13801 1538004 50644 ffffffff 00000000 S ReferenceQueueD
-u0_a16 13814 13801 1538004 50644 ffffffff 00000000 S FinalizerDaemon
-u0_a16 13815 13801 1538004 50644 ffffffff 00000000 S FinalizerWatchd
-u0_a16 13816 13801 1538004 50644 ffffffff 00000000 S HeapTrimmerDaem
-u0_a16 13817 13801 1538004 50644 ffffffff 00000000 S GCDaemon
-u0_a16 13818 13801 1538004 50644 ffffffff 00000000 S Binder_1
-u0_a16 13819 13801 1538004 50644 ffffffff 00000000 S Binder_2
-u0_a16 13828 13801 1538004 50644 ffffffff 00000000 S Gservices
-u0_a16 13833 13801 1538004 50644 ffffffff 00000000 S pool-1-thread-1
-u0_a16 13834 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@
-u0_a16 13837 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@
-u0_a16 13838 13801 1538004 50644 ffffffff 00000000 S Thread-1482
-u0_a16 13839 13801 1538004 50644 ffffffff 00000000 S Thread-1483
-u0_a16 13840 13801 1538004 50644 ffffffff 00000000 S Thread-1484
-u0_a16 13843 13801 1538004 50644 ffffffff 00000000 S download-manage
-u0_a16 13844 13801 1538004 50644 ffffffff 00000000 S NetworkQualityQ
-u0_a16 13845 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@
-u0_a16 13846 13801 1538004 50644 ffffffff 00000000 S Thread-1489
-u0_a16 13847 13801 1538004 50644 ffffffff 00000000 S Thread-1490
-u0_a16 13848 13801 1538004 50644 ffffffff 00000000 S Thread-1491
-u0_a16 13849 13801 1538004 50644 ffffffff 00000000 S Thread-1492
-u0_a16 13850 13801 1538004 50644 ffffffff 00000000 S Thread-1493
-u0_a16 13851 13801 1538004 50644 ffffffff 00000000 S PlayEventLogger
-u0_a16 13852 13801 1538004 50644 ffffffff 00000000 S tentative-gc-ru
-u0_a16 13862 13801 1538004 50644 ffffffff 00000000 S libraries-threa
-u0_a16 13872 13801 1538004 50644 ffffffff 00000000 S AsyncTask #1
-u0_a16 13876 13801 1538004 50644 ffffffff 00000000 S AsyncTask #2
-u0_a16 13877 13801 1538004 50644 ffffffff 00000000 S AsyncTask #3
-u0_a16 13878 13801 1538004 50644 ffffffff 00000000 S PlayEventLogger
-u0_a16 13880 13801 1538004 50644 ffffffff 00000000 S Thread-1501
-u0_a16 14407 13801 1538004 50644 ffffffff 00000000 S Binder_3
-u0_a8 13853 205 1573700 51720 ffffffff 00000000 S com.google.android.gms:car
-u0_a8 13856 13853 1573700 51720 ffffffff 00000000 S Heap thread poo
-u0_a8 13857 13853 1573700 51720 ffffffff 00000000 S Heap thread poo
-u0_a8 13858 13853 1573700 51720 ffffffff 00000000 S Heap thread poo
-u0_a8 13863 13853 1573700 51720 ffffffff 00000000 S Signal Catcher
-u0_a8 13864 13853 1573700 51720 ffffffff 00000000 S JDWP
-u0_a8 13865 13853 1573700 51720 ffffffff 00000000 S ReferenceQueueD
-u0_a8 13866 13853 1573700 51720 ffffffff 00000000 S FinalizerDaemon
-u0_a8 13867 13853 1573700 51720 ffffffff 00000000 S FinalizerWatchd
-u0_a8 13868 13853 1573700 51720 ffffffff 00000000 S HeapTrimmerDaem
-u0_a8 13869 13853 1573700 51720 ffffffff 00000000 S GCDaemon
-u0_a8 13870 13853 1573700 51720 ffffffff 00000000 S Binder_1
-u0_a8 13871 13853 1573700 51720 ffffffff 00000000 S Binder_2
-u0_a8 13873 13853 1573700 51720 ffffffff 00000000 S Gservices
-u0_a8 13913 13853 1573700 51720 ffffffff 00000000 S Binder_3
-u0_a8 13885 205 1572668 47460 ffffffff 00000000 S com.google.android.gms.wearable
-u0_a8 13890 13885 1572668 47460 ffffffff 00000000 S Heap thread poo
-u0_a8 13891 13885 1572668 47460 ffffffff 00000000 S Heap thread poo
-u0_a8 13892 13885 1572668 47460 ffffffff 00000000 S Heap thread poo
-u0_a8 13894 13885 1572668 47460 ffffffff 00000000 S Signal Catcher
-u0_a8 13895 13885 1572668 47460 ffffffff 00000000 S JDWP
-u0_a8 13896 13885 1572668 47460 ffffffff 00000000 S ReferenceQueueD
-u0_a8 13897 13885 1572668 47460 ffffffff 00000000 S FinalizerDaemon
-u0_a8 13898 13885 1572668 47460 ffffffff 00000000 S FinalizerWatchd
-u0_a8 13899 13885 1572668 47460 ffffffff 00000000 S HeapTrimmerDaem
-u0_a8 13900 13885 1572668 47460 ffffffff 00000000 S GCDaemon
-u0_a8 13901 13885 1572668 47460 ffffffff 00000000 S Binder_1
-u0_a8 13902 13885 1572668 47460 ffffffff 00000000 S Binder_2
-u0_a8 13903 13885 1572668 47460 ffffffff 00000000 S Gservices
-root 14061 2 0 0 ffffffff 00000000 S kworker/u:3
-root 14136 2 0 0 ffffffff 00000000 S kworker/0:0H
-u0_a101 14356 205 1503136 44308 ffffffff 00000000 S com.google.android.apps.gcs
-u0_a101 14362 14356 1503136 44308 ffffffff 00000000 S Heap thread poo
-u0_a101 14363 14356 1503136 44308 ffffffff 00000000 S Heap thread poo
-u0_a101 14364 14356 1503136 44308 ffffffff 00000000 S Heap thread poo
-u0_a101 14365 14356 1503136 44308 ffffffff 00000000 S Signal Catcher
-u0_a101 14366 14356 1503136 44308 ffffffff 00000000 S JDWP
-u0_a101 14367 14356 1503136 44308 ffffffff 00000000 S ReferenceQueueD
-u0_a101 14368 14356 1503136 44308 ffffffff 00000000 S FinalizerDaemon
-u0_a101 14369 14356 1503136 44308 ffffffff 00000000 S FinalizerWatchd
-u0_a101 14370 14356 1503136 44308 ffffffff 00000000 S HeapTrimmerDaem
-u0_a101 14371 14356 1503136 44308 ffffffff 00000000 S GCDaemon
-u0_a101 14372 14356 1503136 44308 ffffffff 00000000 S Binder_1
-u0_a101 14373 14356 1503136 44308 ffffffff 00000000 S Binder_2
-u0_a101 14375 14356 1503136 44308 ffffffff 00000000 S Gservices
-u0_a101 14376 14356 1503136 44308 ffffffff 00000000 S RefQueueWorker@
-u0_a101 14377 14356 1503136 44308 ffffffff 00000000 S Thread-1495
-u0_a101 14378 14356 1503136 44308 ffffffff 00000000 S Thread-1496
-u0_a101 14379 14356 1503136 44308 ffffffff 00000000 S Thread-1497
-u0_a101 14380 14356 1503136 44308 ffffffff 00000000 S Thread-1498
-u0_a101 14381 14356 1503136 44308 ffffffff 00000000 S Thread-1499
-shell 14444 209 9316 612 c01a863c b6eeee44 S /system/bin/sh
-shell 14448 14444 10672 768 00000000 b6ef0da8 R ps
+ +# tracer: nop +# +# entries-in-buffer/entries-written: 116/116 #P:1 +# +# _-----=> irqs-off +# / _----=> need-resched +# | / _---=> hardirq/softirq +# || / _--=> preempt-depth +# ||| / delay +# TASK-PID CPU# |||| TIMESTAMP FUNCTION +# | | | |||| | | + atrace-14446 [000] ...2 1212.465062: sched_switch: prev_comm=atrace prev_pid=14446 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.465074: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.465082: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.465092: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.465102: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.465126: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.465132: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.465139: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.465145: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.465227: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h5 1212.465297: sched_wakeup: comm=adbd pid=212 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.465306: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=adbd next_pid=212 next_prio=120 + adbd-212 [000] d..4 1212.465329: sched_wakeup: comm=adbd pid=209 prio=120 success=1 target_cpu=000 + adbd-212 [000] ...2 1212.465348: sched_switch: prev_comm=adbd prev_pid=212 prev_prio=120 prev_state=S ==> next_comm=adbd next_pid=209 next_prio=120 + adbd-209 [000] d..4 1212.465395: sched_wakeup: comm=adbd pid=211 prio=120 success=1 target_cpu=000 + adbd-209 [000] ...2 1212.465441: sched_switch: prev_comm=adbd prev_pid=209 prev_prio=120 prev_state=S ==> next_comm=adbd next_pid=211 next_prio=120 + adbd-211 [000] ...2 1212.465448: sched_switch: prev_comm=adbd prev_pid=211 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h5 1212.574554: sched_wakeup: comm=sensors.qcom pid=292 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.574566: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=sensors.qcom next_pid=292 next_prio=120 + sensors.qcom-292 [000] ...2 1212.574665: sched_switch: prev_comm=sensors.qcom prev_pid=292 prev_prio=120 prev_state=S ==> next_comm=sensors.qcom next_pid=14447 next_prio=120 + sensors.qcom-14447 [000] d..4 1212.574797: sched_wakeup: comm=sensors.qcom pid=1593 prio=120 success=1 target_cpu=000 + sensors.qcom-14447 [000] ...2 1212.574802: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=R+ ==> next_comm=sensors.qcom next_pid=1593 next_prio=120 + sensors.qcom-1593 [000] ...2 1212.574819: sched_switch: prev_comm=sensors.qcom prev_pid=1593 prev_prio=120 prev_state=D ==> next_comm=sensors.qcom next_pid=14447 next_prio=120 + sensors.qcom-14447 [000] d..3 1212.574823: sched_wakeup: comm=sensors.qcom pid=1593 prio=120 success=1 target_cpu=000 + sensors.qcom-14447 [000] ...2 1212.574827: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=R+ ==> next_comm=sensors.qcom next_pid=1593 next_prio=120 + sensors.qcom-1593 [000] d..4 1212.574865: sched_wakeup: comm=sensors.qcom pid=760 prio=120 success=1 target_cpu=000 + sensors.qcom-1593 [000] ...2 1212.574876: sched_switch: prev_comm=sensors.qcom prev_pid=1593 prev_prio=120 prev_state=S ==> next_comm=sensors.qcom next_pid=760 next_prio=120 + sensors.qcom-760 [000] d..4 1212.574905: sched_wakeup: comm=system_server pid=782 prio=118 success=1 target_cpu=000 + sensors.qcom-760 [000] ...2 1212.574917: sched_switch: prev_comm=sensors.qcom prev_pid=760 prev_prio=120 prev_state=S ==> next_comm=system_server next_pid=782 next_prio=118 + system_server-782 [000] d..4 1212.574981: sched_wakeup: comm=system_server pid=785 prio=118 success=1 target_cpu=000 + system_server-782 [000] ...2 1212.575009: sched_switch: prev_comm=system_server prev_pid=782 prev_prio=118 prev_state=S ==> next_comm=system_server next_pid=785 next_prio=118 + system_server-785 [000] ...2 1212.575045: sched_switch: prev_comm=system_server prev_pid=785 prev_prio=118 prev_state=S ==> next_comm=sensors.qcom next_pid=14447 next_prio=120 + sensors.qcom-14447 [000] ...3 1212.575143: sched_switch: prev_comm=sensors.qcom prev_pid=14447 prev_prio=120 prev_state=x ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.575153: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.575159: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.575167: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.575175: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.575181: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.575188: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.575195: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.575201: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.575211: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h4 1212.649601: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.649614: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120 + MMHandlerThread-7231 [000] ...2 1212.649630: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h6 1212.729539: sched_wakeup: comm=kworker/u:1 pid=21 prio=120 success=1 target_cpu=000 + <idle>-0 [000] dNs6 1212.729550: sched_wakeup: comm=kworker/0:2H pid=557 prio=100 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.729563: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:1 next_pid=21 next_prio=120 + kworker/u:1-21 [000] d..5 1212.729571: sched_wakeup: comm=mpdecision pid=2046 prio=113 success=1 target_cpu=000 + kworker/u:1-21 [000] ...2 1212.729578: sched_switch: prev_comm=kworker/u:1 prev_pid=21 prev_prio=120 prev_state=S ==> next_comm=kworker/0:2H next_pid=557 next_prio=100 + kworker/0:2H-557 [000] d..4 1212.729597: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000 + kworker/0:2H-557 [000] ...2 1212.729600: sched_switch: prev_comm=kworker/0:2H prev_pid=557 prev_prio=100 prev_state=D ==> next_comm=mpdecision next_pid=2046 next_prio=113 + mpdecision-2046 [000] ...2 1212.729801: sched_switch: prev_comm=mpdecision prev_pid=2046 prev_prio=113 prev_state=S ==> next_comm=kworker/0:1H next_pid=17 next_prio=100 + kworker/0:1H-17 [000] ...2 1212.730104: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.730134: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.730154: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.730176: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.730201: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.730220: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.730241: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1212.730262: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.730280: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1212.730303: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h6 1212.730638: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.730669: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100 + kworker/u:0H-7 [000] d..6 1212.730707: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000 + kworker/u:0H-7 [000] ...2 1212.730728: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100 + kworker/0:1H-17 [000] ...2 1212.730916: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h6 1212.731632: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.731661: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100 + kworker/u:0H-7 [000] d..6 1212.731702: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000 + kworker/u:0H-7 [000] ...2 1212.731722: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100 + kworker/0:1H-17 [000] ...2 1212.731832: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h6 1212.732685: sched_wakeup: comm=kworker/u:0H pid=7 prio=100 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.732714: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u:0H next_pid=7 next_prio=100 + kworker/u:0H-7 [000] d..6 1212.732747: sched_wakeup: comm=kworker/0:1H pid=17 prio=100 success=1 target_cpu=000 + kworker/u:0H-7 [000] ...2 1212.732767: sched_switch: prev_comm=kworker/u:0H prev_pid=7 prev_prio=100 prev_state=D ==> next_comm=kworker/0:1H next_pid=17 next_prio=100 + kworker/0:1H-17 [000] d..4 1212.732810: sched_wakeup: comm=kworker/0:2H pid=557 prio=100 success=1 target_cpu=000 + kworker/0:1H-17 [000] ...2 1212.732829: sched_switch: prev_comm=kworker/0:1H prev_pid=17 prev_prio=100 prev_state=S ==> next_comm=kworker/0:2H next_pid=557 next_prio=100 + kworker/0:2H-557 [000] ...2 1212.732854: sched_switch: prev_comm=kworker/0:2H prev_pid=557 prev_prio=100 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h4 1212.876266: sched_wakeup: comm=RILSender0 pid=1365 prio=120 success=1 target_cpu=000 + <idle>-0 [000] dNh4 1212.876284: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1212.876316: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=RILSender0 next_pid=1365 next_prio=120 + RILSender0-1365 [000] ...2 1212.876415: sched_switch: prev_comm=RILSender0 prev_pid=1365 prev_prio=120 prev_state=S ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120 + MMHandlerThread-7231 [000] ...2 1212.876454: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h4 1213.089569: sched_wakeup: comm=Thread-625 pid=5750 prio=120 success=1 target_cpu=000 + <idle>-0 [000] dNh4 1213.089587: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.089622: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=Thread-625 next_pid=5750 next_prio=120 + Thread-625-5750 [000] ...2 1213.089842: sched_switch: prev_comm=Thread-625 prev_pid=5750 prev_prio=120 prev_state=S ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120 + MMHandlerThread-7231 [000] ...2 1213.089879: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h4 1213.327439: sched_wakeup: comm=pandora.android pid=5395 prio=120 success=1 target_cpu=000 + <idle>-0 [000] dNh4 1213.327455: sched_wakeup: comm=MMHandlerThread pid=7231 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.327487: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=MMHandlerThread next_pid=7231 next_prio=120 + MMHandlerThread-7231 [000] ...2 1213.327518: sched_switch: prev_comm=MMHandlerThread prev_pid=7231 prev_prio=120 prev_state=S ==> next_comm=pandora.android next_pid=5395 next_prio=120 + pandora.android-5395 [000] d..4 1213.327718: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000 + pandora.android-5395 [000] ...2 1213.327739: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=780 next_prio=120 + Binder_1-780 [000] ...2 1213.327763: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=D ==> next_comm=pandora.android next_pid=5395 next_prio=120 + pandora.android-5395 [000] d..3 1213.327781: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000 + pandora.android-5395 [000] ...2 1213.327795: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=780 next_prio=120 + Binder_1-780 [000] d..4 1213.328056: sched_wakeup: comm=Binder_1 pid=878 prio=120 success=1 target_cpu=000 + Binder_1-780 [000] ...2 1213.328095: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=S ==> next_comm=Binder_1 next_pid=878 next_prio=120 + Binder_1-878 [000] d..4 1213.328263: sched_wakeup: comm=Binder_1 pid=780 prio=120 success=1 target_cpu=000 + Binder_1-878 [000] ...2 1213.328345: sched_switch: prev_comm=Binder_1 prev_pid=878 prev_prio=120 prev_state=S ==> next_comm=Binder_1 next_pid=780 next_prio=120 + Binder_1-780 [000] ...2 1213.328558: sched_switch: prev_comm=Binder_1 prev_pid=780 prev_prio=120 prev_state=S ==> next_comm=pandora.android next_pid=5395 next_prio=120 + pandora.android-5395 [000] ...2 1213.328743: sched_switch: prev_comm=pandora.android prev_pid=5395 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1213.328773: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.328793: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1213.328821: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1213.328846: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.328866: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1213.328891: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d..4 1213.328913: sched_wakeup: comm=ksoftirqd/0 pid=3 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.328931: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/0 next_pid=3 next_prio=120 + ksoftirqd/0-3 [000] ...2 1213.328964: sched_switch: prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + <idle>-0 [000] d.h4 1213.465138: sched_wakeup: comm=atrace pid=14446 prio=120 success=1 target_cpu=000 + <idle>-0 [000] ...2 1213.465171: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=atrace next_pid=14446 next_prio=120 +USER PID PPID VSIZE RSS WCHAN PC NAME +root 1 0 8784 712 ffffffff 00000000 S /init +root 2 0 0 0 ffffffff 00000000 S kthreadd +root 3 2 0 0 ffffffff 00000000 S ksoftirqd/0 +root 7 2 0 0 ffffffff 00000000 D kworker/u:0H +root 8 2 0 0 ffffffff 00000000 S migration/0 +root 13 2 0 0 ffffffff 00000000 S khelper +root 14 2 0 0 ffffffff 00000000 S netns +root 17 2 0 0 ffffffff 00000000 S kworker/0:1H +root 18 2 0 0 ffffffff 00000000 S modem_notifier +root 19 2 0 0 ffffffff 00000000 S smd_channel_clo +root 20 2 0 0 ffffffff 00000000 S smsm_cb_wq +root 21 2 0 0 ffffffff 00000000 S kworker/u:1 +root 22 2 0 0 ffffffff 00000000 S rpm-smd +root 23 2 0 0 ffffffff 00000000 S kworker/u:1H +root 24 2 0 0 ffffffff 00000000 S irq/317-earjack +root 25 2 0 0 ffffffff 00000000 S sync_supers +root 26 2 0 0 ffffffff 00000000 S bdi-default +root 27 2 0 0 ffffffff 00000000 S kblockd +root 28 2 0 0 ffffffff 00000000 S vmalloc +root 29 2 0 0 ffffffff 00000000 S khubd +root 30 2 0 0 ffffffff 00000000 S irq/102-msm_iom +root 31 2 0 0 ffffffff 00000000 S irq/102-msm_iom +root 32 2 0 0 ffffffff 00000000 S irq/102-msm_iom +root 33 2 0 0 ffffffff 00000000 S irq/79-msm_iomm +root 34 2 0 0 ffffffff 00000000 S irq/78-msm_iomm +root 35 2 0 0 ffffffff 00000000 S irq/78-msm_iomm +root 36 2 0 0 ffffffff 00000000 S irq/74-msm_iomm +root 37 2 0 0 ffffffff 00000000 S irq/75-msm_iomm +root 38 2 0 0 ffffffff 00000000 S irq/75-msm_iomm +root 39 2 0 0 ffffffff 00000000 S irq/75-msm_iomm +root 40 2 0 0 ffffffff 00000000 S irq/75-msm_iomm +root 41 2 0 0 ffffffff 00000000 S irq/273-msm_iom +root 42 2 0 0 ffffffff 00000000 S irq/273-msm_iom +root 43 2 0 0 ffffffff 00000000 S irq/97-msm_iomm +root 44 2 0 0 ffffffff 00000000 S irq/97-msm_iomm +root 45 2 0 0 ffffffff 00000000 S irq/97-msm_iomm +root 46 2 0 0 ffffffff 00000000 S l2cap +root 47 2 0 0 ffffffff 00000000 S a2mp +root 48 2 0 0 ffffffff 00000000 S cfg80211 +root 49 2 0 0 ffffffff 00000000 S qmi +root 50 2 0 0 ffffffff 00000000 S nmea +root 51 2 0 0 ffffffff 00000000 S msm_ipc_router +root 52 2 0 0 ffffffff 00000000 S apr_driver +root 54 2 0 0 ffffffff 00000000 S kswapd0 +root 55 2 0 0 ffffffff 00000000 S fsnotify_mark +root 56 2 0 0 ffffffff 00000000 S cifsiod +root 57 2 0 0 ffffffff 00000000 S crypto +root 75 2 0 0 ffffffff 00000000 S ad_calc_wq +root 76 2 0 0 ffffffff 00000000 S hdmi_tx_workq +root 77 2 0 0 ffffffff 00000000 S anx7808_work +root 78 2 0 0 ffffffff 00000000 S k_hsuart +root 79 2 0 0 ffffffff 00000000 S diag_wq +root 80 2 0 0 ffffffff 00000000 S diag_cntl_wq +root 81 2 0 0 ffffffff 00000000 S diag_dci_wq +root 82 2 0 0 ffffffff 00000000 S kgsl-3d0 +root 84 2 0 0 ffffffff 00000000 S f9966000.spi +root 88 2 0 0 ffffffff 00000000 S usbnet +root 89 2 0 0 ffffffff 00000000 S irq/329-anx7808 +root 90 2 0 0 ffffffff 00000000 S k_rmnet_mux_wor +root 91 2 0 0 ffffffff 00000000 S f_mtp +root 92 2 0 0 ffffffff 00000000 S file-storage +root 93 2 0 0 ffffffff 00000000 S uether +root 94 2 0 0 ffffffff 00000000 S synaptics_wq +root 95 2 0 0 ffffffff 00000000 S irq/362-s3350 +root 96 2 0 0 ffffffff 00000000 S kworker/0:2 +root 97 2 0 0 ffffffff 00000000 S msm_vidc_worker +root 98 2 0 0 ffffffff 00000000 S msm_vidc_worker +root 99 2 0 0 ffffffff 00000000 S msm_cpp_workque +root 100 2 0 0 ffffffff 00000000 S irq/350-bq51013 +root 102 2 0 0 ffffffff 00000000 S dm_bufio_cache +root 103 2 0 0 ffffffff 00000000 D dbs_sync/0 +root 104 2 0 0 ffffffff 00000000 D dbs_sync/1 +root 105 2 0 0 ffffffff 00000000 D dbs_sync/2 +root 106 2 0 0 ffffffff 00000000 D dbs_sync/3 +root 107 2 0 0 ffffffff 00000000 S cfinteractive +root 108 2 0 0 ffffffff 00000000 S irq/170-msm_sdc +root 109 2 0 0 ffffffff 00000000 S binder +root 110 2 0 0 ffffffff 00000000 S usb_bam_wq +root 111 2 0 0 ffffffff 00000000 S krfcommd +root 112 2 0 0 ffffffff 00000000 S bam_dmux_rx +root 113 2 0 0 ffffffff 00000000 S bam_dmux_tx +root 114 2 0 0 ffffffff 00000000 S rq_stats +root 115 2 0 0 ffffffff 00000000 S deferwq +root 117 2 0 0 ffffffff 00000000 S irq/361-MAX1704 +root 119 2 0 0 ffffffff 00000000 S mmcqd/1 +root 120 2 0 0 ffffffff 00000000 S mmcqd/1rpmb +root 121 2 0 0 ffffffff 00000000 S wl_event_handle +root 122 2 0 0 ffffffff 00000000 S dhd_watchdog_th +root 123 2 0 0 ffffffff 00000000 S dhd_dpc +root 124 2 0 0 ffffffff 00000000 S dhd_rxf +root 125 2 0 0 ffffffff 00000000 S dhd_sysioc +root 126 2 0 0 ffffffff 00000000 S vibrator +root 127 2 0 0 ffffffff 00000000 S max1462x +root 128 2 0 0 ffffffff 00000000 S irq/310-maxim_m +root 129 2 0 0 ffffffff 00000000 S irq/311-maxim_m +root 130 1 8780 576 ffffffff 00000000 S /sbin/ueventd +root 132 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p25 +root 133 2 0 0 ffffffff 00000000 S ext4-dio-unwrit +root 136 2 0 0 ffffffff 00000000 S flush-179:0 +root 138 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p28 +root 139 2 0 0 ffffffff 00000000 S ext4-dio-unwrit +root 143 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p27 +root 144 2 0 0 ffffffff 00000000 S ext4-dio-unwrit +root 145 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p16 +root 146 2 0 0 ffffffff 00000000 S ext4-dio-unwrit +logd 169 1 18632 2740 ffffffff 00000000 S /system/bin/logd +logd 216 169 18632 2740 ffffffff 00000000 S logd.reader +logd 217 169 18632 2740 ffffffff 00000000 S logd.writer +logd 218 169 18632 2740 ffffffff 00000000 S logd +logd 244 169 18632 2740 ffffffff 00000000 S logd.auditd +root 170 1 9832 304 ffffffff 00000000 S /sbin/healthd +root 171 1 10620 1240 ffffffff 00000000 S /system/bin/lmkd +system 172 1 9452 676 ffffffff 00000000 S /system/bin/servicemanager +root 173 1 18028 1652 ffffffff 00000000 S /system/bin/vold +root 223 173 18028 1652 ffffffff 00000000 S vold +root 226 173 18028 1652 ffffffff 00000000 S vold +root 174 2 0 0 ffffffff 00000000 S IPCRTR +root 175 2 0 0 ffffffff 00000000 S sb-1 +root 177 2 0 0 ffffffff 00000000 S ipc_rtr_q6_ipcr +root 179 2 0 0 ffffffff 00000000 S ngd_msm_ctrl_ng +system 180 1 146792 9724 ffffffff 00000000 S /system/bin/surfaceflinger +system 240 180 146792 9724 ffffffff 00000000 S Binder_1 +system 242 180 146792 9724 ffffffff 00000000 S DispSync +system 243 180 146792 9724 ffffffff 00000000 S Binder_2 +system 361 180 146792 9724 ffffffff 00000000 S hwcUeventThread +system 362 180 146792 9724 ffffffff 00000000 S hwcVsyncThread +system 396 180 146792 9724 ffffffff 00000000 S GL updater +system 397 180 146792 9724 ffffffff 00000000 S surfaceflinger +system 398 180 146792 9724 ffffffff 00000000 S EventThread +system 399 180 146792 9724 ffffffff 00000000 S surfaceflinger +system 400 180 146792 9724 ffffffff 00000000 S EventThread +system 401 180 146792 9724 ffffffff 00000000 S EventControl +system 575 180 146792 9724 ffffffff 00000000 S Binder_3 +system 1501 180 146792 9724 ffffffff 00000000 S Binder_4 +system 5633 180 146792 9724 ffffffff 00000000 S Binder_5 +nobody 181 1 19792 1112 ffffffff 00000000 S /system/bin/rmt_storage +nobody 571 181 19792 1112 ffffffff 00000000 S rmt_storage +nobody 572 181 19792 1112 ffffffff 00000000 S rmt_storage +nobody 573 181 19792 1112 ffffffff 00000000 S rmt_storage +nobody 574 181 19792 1112 ffffffff 00000000 S rmt_storage +system 182 1 11100 992 ffffffff 00000000 S /system/bin/qseecomd +root 183 2 0 0 ffffffff 00000000 S msm_slim_qmi_cl +root 184 2 0 0 ffffffff 00000000 S msm_qmi_rtx_q +shell 185 1 9316 716 c047451c b6f58da8 S /system/bin/sh +root 187 1 9200 368 ffffffff 00000000 S /system/bin/subsystem_ramdump +root 188 1 22828 1404 ffffffff 00000000 S /system/bin/netd +root 548 188 22828 1404 ffffffff 00000000 S netd +root 549 188 22828 1404 ffffffff 00000000 S netd +root 550 188 22828 1404 ffffffff 00000000 S netd +root 551 188 22828 1404 ffffffff 00000000 S netd +root 552 188 22828 1404 ffffffff 00000000 S netd +root 553 188 22828 1404 ffffffff 00000000 S netd +root 554 188 22828 1404 ffffffff 00000000 S netd +root 555 188 22828 1404 ffffffff 00000000 S netd +root 189 1 10048 848 ffffffff 00000000 S /system/bin/debuggerd +radio 191 1 35988 4712 ffffffff 00000000 S /system/bin/rild +radio 335 191 35988 4712 ffffffff 00000000 S rild +radio 343 191 35988 4712 ffffffff 00000000 S rild +radio 346 191 35988 4712 ffffffff 00000000 S rild +radio 584 191 35988 4712 ffffffff 00000000 S rild +radio 585 191 35988 4712 ffffffff 00000000 S rild +radio 587 191 35988 4712 ffffffff 00000000 S rild +radio 588 191 35988 4712 ffffffff 00000000 S rild +radio 589 191 35988 4712 ffffffff 00000000 S rild +radio 591 191 35988 4712 ffffffff 00000000 S rild +radio 592 191 35988 4712 ffffffff 00000000 S rild +radio 593 191 35988 4712 ffffffff 00000000 S rild +radio 594 191 35988 4712 ffffffff 00000000 S rild +drm 192 1 26084 3832 ffffffff 00000000 S /system/bin/drmserver +drm 419 192 26084 3832 ffffffff 00000000 S Binder_1 +media 194 1 106516 8584 ffffffff 00000000 S /system/bin/mediaserver +media 755 194 106516 8584 ffffffff 00000000 S ApmTone +media 756 194 106516 8584 ffffffff 00000000 S ApmAudio +media 757 194 106516 8584 ffffffff 00000000 S ApmOutput +media 758 194 106516 8584 ffffffff 00000000 S mediaserver +media 759 194 106516 8584 ffffffff 00000000 S FastMixer +media 871 194 106516 8584 ffffffff 00000000 S AudioOut_2 +media 872 194 106516 8584 ffffffff 00000000 S AudioOut_4 +media 873 194 106516 8584 ffffffff 00000000 S FastMixer +media 874 194 106516 8584 ffffffff 00000000 S AudioOut_6 +media 878 194 106516 8584 ffffffff 00000000 S Binder_1 +media 879 194 106516 8584 ffffffff 00000000 S Binder_2 +media 1133 194 106516 8584 ffffffff 00000000 S Binder_3 +install 195 1 9408 704 ffffffff 00000000 S /system/bin/installd +keystore 197 1 12536 1848 ffffffff 00000000 S /system/bin/keystore +radio 198 1 18856 636 ffffffff 00000000 S /system/bin/bridgemgrd +radio 288 198 18856 636 ffffffff 00000000 S bridgemgrd +radio 602 198 18856 636 ffffffff 00000000 S bridgemgrd +radio 603 198 18856 636 ffffffff 00000000 S bridgemgrd +radio 841 198 18856 636 ffffffff 00000000 S bridgemgrd +radio 199 1 24060 732 ffffffff 00000000 S /system/bin/qmuxd +radio 293 199 24060 732 ffffffff 00000000 S qmuxd +radio 576 199 24060 732 ffffffff 00000000 S qmuxd +radio 577 199 24060 732 ffffffff 00000000 S qmuxd +radio 578 199 24060 732 ffffffff 00000000 S qmuxd +radio 579 199 24060 732 ffffffff 00000000 S qmuxd +radio 580 199 24060 732 ffffffff 00000000 S qmuxd +radio 581 199 24060 732 ffffffff 00000000 S qmuxd +radio 582 199 24060 732 ffffffff 00000000 S qmuxd +radio 583 199 24060 732 ffffffff 00000000 S qmuxd +radio 200 1 20036 996 ffffffff 00000000 S /system/bin/netmgrd +radio 289 200 20036 996 ffffffff 00000000 S netmgrd +radio 736 200 20036 996 ffffffff 00000000 S netmgrd +radio 746 200 20036 996 ffffffff 00000000 S netmgrd +radio 747 200 20036 996 ffffffff 00000000 S netmgrd +radio 748 200 20036 996 ffffffff 00000000 S netmgrd +nobody 201 1 59912 1748 ffffffff 00000000 S /system/bin/sensors.qcom +nobody 290 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 292 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 560 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 563 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 564 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 605 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 614 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 621 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 622 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 623 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 624 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 625 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 626 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 627 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 628 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 629 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 633 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 643 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 650 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 651 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 760 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 763 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 784 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 790 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 792 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 794 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 796 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 798 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 800 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 802 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 804 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 806 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 808 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 810 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 812 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 814 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 816 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 818 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 820 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 822 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 824 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 1593 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 1600 201 59912 1748 ffffffff 00000000 S sensors.qcom +root 204 1 58772 1524 ffffffff 00000000 S /system/bin/thermal-engine-hh +root 247 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 250 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 252 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 253 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 254 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 255 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 257 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 258 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 259 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 260 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 261 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 262 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 263 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 264 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 265 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 266 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 267 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 268 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 269 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 270 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 272 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 273 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 275 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 276 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 277 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 278 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 280 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 281 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 282 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 283 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 284 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 286 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 287 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 295 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 297 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 299 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 300 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 301 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 559 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 596 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 600 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 601 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 205 1 1482684 53160 ffffffff 00000000 S zygote +root 14357 205 1482684 53160 ffffffff 00000000 S ReferenceQueueD +root 14358 205 1482684 53160 ffffffff 00000000 S FinalizerDaemon +root 14359 205 1482684 53160 ffffffff 00000000 S FinalizerWatchd +root 14360 205 1482684 53160 ffffffff 00000000 S HeapTrimmerDaem +root 14361 205 1482684 53160 ffffffff 00000000 S GCDaemon +media_rw 206 1 15400 5240 ffffffff 00000000 S /system/bin/sdcard +media_rw 227 206 15400 5240 ffffffff 00000000 S sdcard +media_rw 228 206 15400 5240 ffffffff 00000000 S sdcard +camera 207 1 16300 4440 ffffffff 00000000 S /system/bin/mm-qcamera-daemon +system 208 1 20500 1236 ffffffff 00000000 S /system/bin/time_daemon +system 308 208 20500 1236 ffffffff 00000000 S time_daemon +system 561 208 20500 1236 ffffffff 00000000 S time_daemon +system 597 208 20500 1236 ffffffff 00000000 S time_daemon +system 598 208 20500 1236 ffffffff 00000000 S time_daemon +system 599 208 20500 1236 ffffffff 00000000 S time_daemon +shell 209 1 16984 312 ffffffff 00000000 S /sbin/adbd +shell 210 209 16984 312 ffffffff 00000000 S adbd +shell 211 209 16984 312 ffffffff 00000000 S adbd +shell 212 209 16984 308 ffffffff 00000000 S adbd +shell 14445 209 16984 308 ffffffff 00000000 S adbd +root 214 2 0 0 ffffffff 00000000 S irq/288-wcd9xxx +root 219 2 0 0 ffffffff 00000000 S kauditd +root 311 2 0 0 ffffffff 00000000 D msm_thermal:hot +root 312 2 0 0 ffffffff 00000000 D msm_thermal:fre +system 348 182 15288 564 ffffffff 00000000 S /system/bin/qseecomd +system 349 348 15288 564 ffffffff 00000000 S qseecomd +system 351 348 15288 564 ffffffff 00000000 S qseecomd +system 386 348 15288 564 ffffffff 00000000 S qseecomd +system 387 348 15288 564 ffffffff 00000000 S qseecomd +root 360 2 0 0 ffffffff 00000000 D mdss_fb0 +root 557 2 0 0 ffffffff 00000000 S kworker/0:2H +root 558 2 0 0 ffffffff 00000000 S IPCRTR +root 562 2 0 0 ffffffff 00000000 S ipc_rtr_smd_ipc +system 764 205 1701620 103200 ffffffff 00000000 S system_server +system 767 764 1701620 103200 ffffffff 00000000 S Heap thread poo +system 768 764 1701620 103200 ffffffff 00000000 S Heap thread poo +system 770 764 1701620 103200 ffffffff 00000000 S Heap thread poo +system 773 764 1701620 103200 ffffffff 00000000 S Signal Catcher +system 774 764 1701620 103200 ffffffff 00000000 S JDWP +system 775 764 1701620 103200 ffffffff 00000000 S ReferenceQueueD +system 776 764 1701620 103200 ffffffff 00000000 S FinalizerDaemon +system 777 764 1701620 103200 ffffffff 00000000 S FinalizerWatchd +system 778 764 1701620 103200 ffffffff 00000000 S HeapTrimmerDaem +system 779 764 1701620 103200 ffffffff 00000000 S GCDaemon +system 780 764 1701620 103200 ffffffff 00000000 S Binder_1 +system 781 764 1701620 103200 ffffffff 00000000 S Binder_2 +system 782 764 1701620 103200 ffffffff 00000000 S system_server +system 783 764 1701620 103200 ffffffff 00000000 S system_server +system 785 764 1701620 103200 ffffffff 00000000 S system_server +system 786 764 1701620 103200 ffffffff 00000000 S system_server +system 788 764 1701620 103200 ffffffff 00000000 S system_server +system 789 764 1701620 103200 ffffffff 00000000 S system_server +system 791 764 1701620 103200 ffffffff 00000000 S system_server +system 793 764 1701620 103200 ffffffff 00000000 S system_server +system 795 764 1701620 103200 ffffffff 00000000 S system_server +system 797 764 1701620 103200 ffffffff 00000000 S system_server +system 799 764 1701620 103200 ffffffff 00000000 S system_server +system 801 764 1701620 103200 ffffffff 00000000 S system_server +system 803 764 1701620 103200 ffffffff 00000000 S system_server +system 805 764 1701620 103200 ffffffff 00000000 S system_server +system 807 764 1701620 103200 ffffffff 00000000 S system_server +system 809 764 1701620 103200 ffffffff 00000000 S system_server +system 811 764 1701620 103200 ffffffff 00000000 S system_server +system 813 764 1701620 103200 ffffffff 00000000 S system_server +system 815 764 1701620 103200 ffffffff 00000000 S system_server +system 817 764 1701620 103200 ffffffff 00000000 S system_server +system 819 764 1701620 103200 ffffffff 00000000 S system_server +system 821 764 1701620 103200 ffffffff 00000000 S system_server +system 823 764 1701620 103200 ffffffff 00000000 S system_server +system 826 764 1701620 103200 ffffffff 00000000 S SensorEventAckR +system 827 764 1701620 103200 ffffffff 00000000 S SensorService +system 828 764 1701620 103200 ffffffff 00000000 S android.bg +system 829 764 1701620 103200 ffffffff 00000000 S ActivityManager +system 830 764 1701620 103200 ffffffff 00000000 S FileObserver +system 831 764 1701620 103200 ffffffff 00000000 S android.fg +system 832 764 1701620 103200 ffffffff 00000000 S android.ui +system 833 764 1701620 103200 ffffffff 00000000 S android.io +system 834 764 1701620 103200 ffffffff 00000000 S android.display +system 835 764 1701620 103200 ffffffff 00000000 S CpuTracker +system 836 764 1701620 103200 ffffffff 00000000 S PowerManagerSer +system 837 764 1701620 103200 ffffffff 00000000 S system_server +system 838 764 1701620 103200 ffffffff 00000000 S system_server +system 839 764 1701620 103200 ffffffff 00000000 S BatteryStats_wa +system 840 764 1701620 103200 ffffffff 00000000 S PackageManager +system 842 764 1701620 103200 ffffffff 00000000 S PackageInstalle +system 844 764 1701620 103200 ffffffff 00000000 S AlarmManager +system 845 764 1701620 103200 ffffffff 00000000 S UEventObserver +system 853 764 1701620 103200 ffffffff 00000000 S InputDispatcher +system 854 764 1701620 103200 ffffffff 00000000 S InputReader +system 857 764 1701620 103200 ffffffff 00000000 S MountService +system 858 764 1701620 103200 ffffffff 00000000 S VoldConnector +system 860 764 1701620 103200 ffffffff 00000000 S NetdConnector +system 861 764 1701620 103200 ffffffff 00000000 S NetworkStats +system 862 764 1701620 103200 ffffffff 00000000 S NetworkPolicy +system 863 764 1701620 103200 ffffffff 00000000 S WifiP2pService +system 864 764 1701620 103200 ffffffff 00000000 S WifiStateMachin +system 865 764 1701620 103200 ffffffff 00000000 S WifiService +system 866 764 1701620 103200 ffffffff 00000000 S ConnectivitySer +system 867 764 1701620 103200 ffffffff 00000000 S NsdService +system 868 764 1701620 103200 ffffffff 00000000 S mDnsConnector +system 869 764 1701620 103200 ffffffff 00000000 S ranker +system 870 764 1701620 103200 ffffffff 00000000 S AudioService +system 882 764 1701620 103200 ffffffff 00000000 S WifiWatchdogSta +system 883 764 1701620 103200 ffffffff 00000000 S WifiManager +system 884 764 1701620 103200 ffffffff 00000000 S WifiScanningSer +system 885 764 1701620 103200 ffffffff 00000000 S WifiRttService +system 886 764 1701620 103200 ffffffff 00000000 S EthernetService +system 887 764 1701620 103200 ffffffff 00000000 S backup +system 889 764 1701620 103200 ffffffff 00000000 S Thread-69 +system 892 764 1701620 103200 ffffffff 00000000 S LazyTaskWriterT +system 893 764 1701620 103200 ffffffff 00000000 S UsbService host +system 894 764 1701620 103200 ffffffff 00000000 S Thread-73 +system 942 764 1701620 103200 ffffffff 00000000 S Binder_3 +system 1079 764 1701620 103200 ffffffff 00000000 S watchdog +system 1094 764 1701620 103200 ffffffff 00000000 S SoundPool +system 1095 764 1701620 103200 ffffffff 00000000 S SoundPoolThread +system 1108 764 1701620 103200 ffffffff 00000000 S Binder_4 +system 1109 764 1701620 103200 ffffffff 00000000 S Binder_5 +system 1186 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1188 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1191 764 1701620 103200 ffffffff 00000000 S NetworkTimeUpda +system 1192 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1226 764 1701620 103200 ffffffff 00000000 S Binder_6 +system 1233 764 1701620 103200 ffffffff 00000000 S Binder_7 +system 1247 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1256 764 1701620 103200 ffffffff 00000000 S Binder_8 +system 1260 764 1701620 103200 ffffffff 00000000 S WifiMonitor +system 1271 764 1701620 103200 ffffffff 00000000 S Binder_9 +system 1288 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1289 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1319 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1320 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1367 764 1701620 103200 ffffffff 00000000 S Thread-89 +system 1391 764 1701620 103200 ffffffff 00000000 S AsyncQueryWorke +system 1654 764 1701620 103200 ffffffff 00000000 S Binder_A +system 1693 764 1701620 103200 ffffffff 00000000 S NetworkMonitorN +system 1695 764 1701620 103200 ffffffff 00000000 S DhcpStateMachin +system 1781 764 1701620 103200 ffffffff 00000000 S AsyncTask #1 +system 1782 764 1701620 103200 ffffffff 00000000 S AsyncTask #2 +system 2097 764 1701620 103200 ffffffff 00000000 S AsyncTask #3 +system 2124 764 1701620 103200 ffffffff 00000000 S SyncHandler-0 +system 2905 764 1701620 103200 ffffffff 00000000 S PowerManagerSer +system 4226 764 1701620 103200 ffffffff 00000000 S AsyncTask #4 +system 4265 764 1701620 103200 ffffffff 00000000 S UsbDebuggingMan +system 5717 764 1701620 103200 ffffffff 00000000 S GL updater +system 6709 764 1701620 103200 ffffffff 00000000 S Binder_B +wifi 888 1 12568 2672 ffffffff 00000000 S /system/bin/wpa_supplicant +u0_a20 915 205 1616624 108684 ffffffff 00000000 S com.android.systemui +u0_a20 919 915 1616624 108684 ffffffff 00000000 S Heap thread poo +u0_a20 920 915 1616624 108684 ffffffff 00000000 S Heap thread poo +u0_a20 921 915 1616624 108684 ffffffff 00000000 S Heap thread poo +u0_a20 925 915 1616624 108684 ffffffff 00000000 S Signal Catcher +u0_a20 926 915 1616624 108684 ffffffff 00000000 S JDWP +u0_a20 927 915 1616624 108684 ffffffff 00000000 S ReferenceQueueD +u0_a20 928 915 1616624 108684 ffffffff 00000000 S FinalizerDaemon +u0_a20 929 915 1616624 108684 ffffffff 00000000 S FinalizerWatchd +u0_a20 930 915 1616624 108684 ffffffff 00000000 S HeapTrimmerDaem +u0_a20 931 915 1616624 108684 ffffffff 00000000 S GCDaemon +u0_a20 933 915 1616624 108684 ffffffff 00000000 S Binder_1 +u0_a20 934 915 1616624 108684 ffffffff 00000000 S Binder_2 +u0_a20 964 915 1616624 108684 ffffffff 00000000 S SoundPool +u0_a20 965 915 1616624 108684 ffffffff 00000000 S SoundPoolThread +u0_a20 970 915 1616624 108684 ffffffff 00000000 S Recents-TaskRes +u0_a20 1078 915 1616624 108684 ffffffff 00000000 S SystemUI Storag +u0_a20 1378 915 1616624 108684 ffffffff 00000000 S PhoneStatusBar +u0_a20 1381 915 1616624 108684 ffffffff 00000000 S WifiManager +u0_a20 1416 915 1616624 108684 ffffffff 00000000 S ConnectivityMan +u0_a20 1428 915 1616624 108684 ffffffff 00000000 S Binder_3 +u0_a20 1431 915 1616624 108684 ffffffff 00000000 S FlashlightContr +u0_a20 1434 915 1616624 108684 ffffffff 00000000 S AsyncTask #1 +u0_a20 1435 915 1616624 108684 ffffffff 00000000 S QSTileHost +u0_a20 1438 915 1616624 108684 ffffffff 00000000 S AsyncTask #2 +u0_a20 1441 915 1616624 108684 ffffffff 00000000 S RenderThread +u0_a20 1442 915 1616624 108684 ffffffff 00000000 S AsyncTask #3 +u0_a20 1565 915 1616624 108684 ffffffff 00000000 S hwuiTask1 +u0_a20 1566 915 1616624 108684 ffffffff 00000000 S hwuiTask2 +u0_a20 1637 915 1616624 108684 ffffffff 00000000 S AsyncTask #4 +u0_a20 1692 915 1616624 108684 ffffffff 00000000 S GL updater +u0_a20 1807 915 1616624 108684 ffffffff 00000000 S RenderThread +u0_a20 4480 915 1616624 108684 ffffffff 00000000 S Binder_4 +u0_a6 936 205 1506908 56892 ffffffff 00000000 S android.process.media +u0_a6 943 936 1506908 56892 ffffffff 00000000 S Heap thread poo +u0_a6 944 936 1506908 56892 ffffffff 00000000 S Heap thread poo +u0_a6 945 936 1506908 56892 ffffffff 00000000 S Heap thread poo +u0_a6 947 936 1506908 56892 ffffffff 00000000 S Signal Catcher +u0_a6 949 936 1506908 56892 ffffffff 00000000 S JDWP +u0_a6 950 936 1506908 56892 ffffffff 00000000 S ReferenceQueueD +u0_a6 951 936 1506908 56892 ffffffff 00000000 S FinalizerDaemon +u0_a6 952 936 1506908 56892 ffffffff 00000000 S FinalizerWatchd +u0_a6 953 936 1506908 56892 ffffffff 00000000 S HeapTrimmerDaem +u0_a6 954 936 1506908 56892 ffffffff 00000000 S GCDaemon +u0_a6 956 936 1506908 56892 ffffffff 00000000 S Binder_1 +u0_a6 957 936 1506908 56892 ffffffff 00000000 S Binder_2 +u0_a6 1007 936 1506908 56892 ffffffff 00000000 S thumbs thread +u0_a6 1020 936 1506908 56892 ffffffff 00000000 S MtpServer +u0_a6 2810 936 1506908 56892 ffffffff 00000000 S DownloadReceive +u0_a6 4917 936 1506908 56892 ffffffff 00000000 S Binder_3 +u0_a6 5816 936 1506908 56892 ffffffff 00000000 S Binder_4 +u0_a6 8575 936 1506908 56892 ffffffff 00000000 S Binder_5 +u0_a22 1111 205 1526156 42532 ffffffff 00000000 S com.google.android.googlequicksearchbox:interactor +u0_a22 1113 1111 1526156 42532 ffffffff 00000000 S Heap thread poo +u0_a22 1114 1111 1526156 42532 ffffffff 00000000 S Heap thread poo +u0_a22 1116 1111 1526156 42532 ffffffff 00000000 S Heap thread poo +u0_a22 1121 1111 1526156 42532 ffffffff 00000000 S Signal Catcher +u0_a22 1124 1111 1526156 42532 ffffffff 00000000 S JDWP +u0_a22 1125 1111 1526156 42532 ffffffff 00000000 S ReferenceQueueD +u0_a22 1126 1111 1526156 42532 ffffffff 00000000 S FinalizerDaemon +u0_a22 1127 1111 1526156 42532 ffffffff 00000000 S FinalizerWatchd +u0_a22 1128 1111 1526156 42532 ffffffff 00000000 S HeapTrimmerDaem +u0_a22 1129 1111 1526156 42532 ffffffff 00000000 S GCDaemon +u0_a22 1131 1111 1526156 42532 ffffffff 00000000 S Binder_1 +u0_a22 1132 1111 1526156 42532 ffffffff 00000000 S Binder_2 +u0_a22 1561 1111 1526156 42532 ffffffff 00000000 S AsyncTask #1 +u0_a51 1136 205 1515064 46788 ffffffff 00000000 S com.google.android.inputmethod.pinyin +u0_a51 1142 1136 1515064 46788 ffffffff 00000000 S Heap thread poo +u0_a51 1143 1136 1515064 46788 ffffffff 00000000 S Heap thread poo +u0_a51 1144 1136 1515064 46788 ffffffff 00000000 S Heap thread poo +u0_a51 1145 1136 1515064 46788 ffffffff 00000000 S Signal Catcher +u0_a51 1146 1136 1515064 46788 ffffffff 00000000 S JDWP +u0_a51 1147 1136 1515064 46788 ffffffff 00000000 S ReferenceQueueD +u0_a51 1148 1136 1515064 46788 ffffffff 00000000 S FinalizerDaemon +u0_a51 1149 1136 1515064 46788 ffffffff 00000000 S FinalizerWatchd +u0_a51 1151 1136 1515064 46788 ffffffff 00000000 S HeapTrimmerDaem +u0_a51 1152 1136 1515064 46788 ffffffff 00000000 S GCDaemon +u0_a51 1153 1136 1515064 46788 ffffffff 00000000 S Binder_1 +u0_a51 1154 1136 1515064 46788 ffffffff 00000000 S Binder_2 +u0_a51 1330 1136 1515064 46788 ffffffff 00000000 S GAThread +u0_a51 1331 1136 1515064 46788 ffffffff 00000000 S measurement-1 +u0_a51 1336 1136 1515064 46788 ffffffff 00000000 S pool-1-thread-1 +u0_a51 1503 1136 1515064 46788 ffffffff 00000000 S AsyncTask #1 +u0_a51 1622 1136 1515064 46788 ffffffff 00000000 S AsyncTask #2 +nfc 1199 205 1511808 46336 ffffffff 00000000 S com.android.nfc +nfc 1208 1199 1511808 46336 ffffffff 00000000 S Heap thread poo +nfc 1209 1199 1511808 46336 ffffffff 00000000 S Heap thread poo +nfc 1210 1199 1511808 46336 ffffffff 00000000 S Heap thread poo +nfc 1211 1199 1511808 46336 ffffffff 00000000 S Signal Catcher +nfc 1212 1199 1511808 46336 ffffffff 00000000 S JDWP +nfc 1213 1199 1511808 46336 ffffffff 00000000 S ReferenceQueueD +nfc 1214 1199 1511808 46336 ffffffff 00000000 S FinalizerDaemon +nfc 1215 1199 1511808 46336 ffffffff 00000000 S FinalizerWatchd +nfc 1216 1199 1511808 46336 ffffffff 00000000 S HeapTrimmerDaem +nfc 1219 1199 1511808 46336 ffffffff 00000000 S GCDaemon +nfc 1220 1199 1511808 46336 ffffffff 00000000 S Binder_1 +nfc 1221 1199 1511808 46336 ffffffff 00000000 S Binder_2 +nfc 1385 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1388 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1393 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1408 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1409 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1425 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1573 1199 1511808 46336 ffffffff 00000000 S Thread-55 +nfc 1574 1199 1511808 46336 ffffffff 00000000 S Thread-56 +nfc 1575 1199 1511808 46336 ffffffff 00000000 S Thread-57 +nfc 1577 1199 1511808 46336 ffffffff 00000000 S SoundPool +nfc 1578 1199 1511808 46336 ffffffff 00000000 S SoundPoolThread +nfc 2906 1199 1511808 46336 ffffffff 00000000 S AsyncTask #2 +nfc 2915 1199 1511808 46336 ffffffff 00000000 S AsyncTask #3 +nfc 5610 1199 1511808 46336 ffffffff 00000000 S AsyncTask #4 +nfc 5719 1199 1511808 46336 ffffffff 00000000 S AsyncTask #5 +radio 1234 205 1493064 38832 ffffffff 00000000 S com.redbend.vdmc +radio 1236 1234 1493064 38832 ffffffff 00000000 S Heap thread poo +radio 1237 1234 1493064 38832 ffffffff 00000000 S Heap thread poo +radio 1238 1234 1493064 38832 ffffffff 00000000 S Heap thread poo +radio 1244 1234 1493064 38832 ffffffff 00000000 S Signal Catcher +radio 1245 1234 1493064 38832 ffffffff 00000000 S JDWP +radio 1246 1234 1493064 38832 ffffffff 00000000 S ReferenceQueueD +radio 1248 1234 1493064 38832 ffffffff 00000000 S FinalizerDaemon +radio 1249 1234 1493064 38832 ffffffff 00000000 S FinalizerWatchd +radio 1250 1234 1493064 38832 ffffffff 00000000 S HeapTrimmerDaem +radio 1251 1234 1493064 38832 ffffffff 00000000 S GCDaemon +radio 1252 1234 1493064 38832 ffffffff 00000000 S Binder_1 +radio 1257 1234 1493064 38832 ffffffff 00000000 S Binder_2 +radio 1274 205 1525408 58916 ffffffff 00000000 S com.android.phone +radio 1282 1274 1525408 58916 ffffffff 00000000 S Heap thread poo +radio 1283 1274 1525408 58916 ffffffff 00000000 S Heap thread poo +radio 1284 1274 1525408 58916 ffffffff 00000000 S Heap thread poo +radio 1285 1274 1525408 58916 ffffffff 00000000 S Signal Catcher +radio 1286 1274 1525408 58916 ffffffff 00000000 S JDWP +radio 1287 1274 1525408 58916 ffffffff 00000000 S ReferenceQueueD +radio 1290 1274 1525408 58916 ffffffff 00000000 S FinalizerDaemon +radio 1291 1274 1525408 58916 ffffffff 00000000 S FinalizerWatchd +radio 1292 1274 1525408 58916 ffffffff 00000000 S HeapTrimmerDaem +radio 1293 1274 1525408 58916 ffffffff 00000000 S GCDaemon +radio 1299 1274 1525408 58916 ffffffff 00000000 S Binder_1 +radio 1315 1274 1525408 58916 ffffffff 00000000 S Binder_2 +radio 1365 1274 1525408 58916 ffffffff 00000000 S RILSender0 +radio 1366 1274 1525408 58916 ffffffff 00000000 S RILReceiver0 +radio 1380 1274 1525408 58916 ffffffff 00000000 S DcHandlerThread +radio 1392 1274 1525408 58916 ffffffff 00000000 S GsmCellBroadcas +radio 1394 1274 1525408 58916 ffffffff 00000000 S GsmInboundSmsHa +radio 1397 1274 1525408 58916 ffffffff 00000000 S CellBroadcastHa +radio 1417 1274 1525408 58916 ffffffff 00000000 S CdmaInboundSmsH +radio 1418 1274 1525408 58916 ffffffff 00000000 S CdmaServiceCate +radio 1427 1274 1525408 58916 ffffffff 00000000 S DcSwitchStateMa +radio 1429 1274 1525408 58916 ffffffff 00000000 S SyncHandler-0 +radio 1443 1274 1525408 58916 ffffffff 00000000 S AsyncTask #1 +radio 1473 1274 1525408 58916 ffffffff 00000000 S Binder_3 +radio 1517 1274 1525408 58916 ffffffff 00000000 S ervice.Executor +radio 1518 1274 1525408 58916 ffffffff 00000000 S WifiManager +radio 1563 1274 1525408 58916 ffffffff 00000000 S Cat Telephony s +radio 1564 1274 1525408 58916 ffffffff 00000000 S RilMessageDecod +radio 1567 1274 1525408 58916 ffffffff 00000000 S Cat Icon Loader +radio 1690 1274 1525408 58916 ffffffff 00000000 S Binder_4 +radio 4571 1274 1525408 58916 ffffffff 00000000 S Stk App Service +u0_a22 1305 205 1674592 127012 ffffffff 00000000 S com.google.android.googlequicksearchbox +u0_a22 1306 1305 1674592 127012 ffffffff 00000000 S Heap thread poo +u0_a22 1307 1305 1674592 127012 ffffffff 00000000 S Heap thread poo +u0_a22 1308 1305 1674592 127012 ffffffff 00000000 S Heap thread poo +u0_a22 1317 1305 1674592 127012 ffffffff 00000000 S Signal Catcher +u0_a22 1318 1305 1674592 127012 ffffffff 00000000 S JDWP +u0_a22 1322 1305 1674592 127012 ffffffff 00000000 S ReferenceQueueD +u0_a22 1323 1305 1674592 127012 ffffffff 00000000 S FinalizerDaemon +u0_a22 1324 1305 1674592 127012 ffffffff 00000000 S FinalizerWatchd +u0_a22 1332 1305 1674592 127012 ffffffff 00000000 S HeapTrimmerDaem +u0_a22 1333 1305 1674592 127012 ffffffff 00000000 S GCDaemon +u0_a22 1334 1305 1674592 127012 ffffffff 00000000 S Binder_1 +u0_a22 1335 1305 1674592 127012 ffffffff 00000000 S Binder_2 +u0_a22 1386 1305 1674592 127012 ffffffff 00000000 S launcher-loader +u0_a22 1395 1305 1674592 127012 ffffffff 00000000 S AsyncTask #1 +u0_a22 1432 1305 1674592 127012 ffffffff 00000000 S AsyncTask #2 +u0_a22 1484 1305 1674592 127012 ffffffff 00000000 S GELServices-0 +u0_a22 1514 1305 1674592 127012 ffffffff 00000000 S RenderThread +u0_a22 1540 1305 1674592 127012 ffffffff 00000000 S AsyncTask #3 +u0_a22 1618 1305 1674592 127012 ffffffff 00000000 S GELServices-1 +u0_a22 1621 1305 1674592 127012 ffffffff 00000000 S GELServices-2 +u0_a22 1629 1305 1674592 127012 ffffffff 00000000 S GELServices-3 +u0_a22 1632 1305 1674592 127012 ffffffff 00000000 S AsyncTask #4 +u0_a22 1633 1305 1674592 127012 ffffffff 00000000 S AsyncTask #5 +u0_a22 1636 1305 1674592 127012 ffffffff 00000000 S GELServices-4 +u0_a22 1644 1305 1674592 127012 ffffffff 00000000 S GL updater +u0_a22 1647 1305 1674592 127012 ffffffff 00000000 S GELServices-5 +u0_a22 1664 1305 1674592 127012 ffffffff 00000000 S GELServices-6 +u0_a22 1764 1305 1674592 127012 ffffffff 00000000 S Binder_3 +u0_a22 1766 1305 1674592 127012 ffffffff 00000000 S GELServices-7 +u0_a22 1772 1305 1674592 127012 ffffffff 00000000 S RenderThread +u0_a22 1773 1305 1674592 127012 ffffffff 00000000 S RenderThread +u0_a22 1774 1305 1674592 127012 ffffffff 00000000 S RenderThread +u0_a22 1775 1305 1674592 127012 ffffffff 00000000 S RenderThread +u0_a22 1998 1305 1674592 127012 ffffffff 00000000 S GELServices-8 +u0_a22 2320 1305 1674592 127012 ffffffff 00000000 S RemoteViewsCach +u0_a22 2321 1305 1674592 127012 ffffffff 00000000 S RemoteViewsAdap +u0_a22 2902 1305 1674592 127012 ffffffff 00000000 S GELServices-9 +u0_a22 1451 205 1584512 87716 ffffffff 00000000 S com.google.android.googlequicksearchbox:search +u0_a22 1457 1451 1584512 87716 ffffffff 00000000 S Heap thread poo +u0_a22 1458 1451 1584512 87716 ffffffff 00000000 S Heap thread poo +u0_a22 1459 1451 1584512 87716 ffffffff 00000000 S Heap thread poo +u0_a22 1460 1451 1584512 87716 ffffffff 00000000 S Signal Catcher +u0_a22 1461 1451 1584512 87716 ffffffff 00000000 S JDWP +u0_a22 1462 1451 1584512 87716 ffffffff 00000000 S ReferenceQueueD +u0_a22 1463 1451 1584512 87716 ffffffff 00000000 S FinalizerDaemon +u0_a22 1464 1451 1584512 87716 ffffffff 00000000 S FinalizerWatchd +u0_a22 1466 1451 1584512 87716 ffffffff 00000000 S HeapTrimmerDaem +u0_a22 1468 1451 1584512 87716 ffffffff 00000000 S GCDaemon +u0_a22 1474 1451 1584512 87716 ffffffff 00000000 S Binder_1 +u0_a22 1475 1451 1584512 87716 ffffffff 00000000 S Binder_2 +u0_a22 1515 1451 1584512 87716 ffffffff 00000000 S User-Facing Non +u0_a22 1516 1451 1584512 87716 ffffffff 00000000 S User-Facing Non +u0_a22 1535 1451 1584512 87716 ffffffff 00000000 S User-Facing Non +u0_a22 1538 1451 1584512 87716 ffffffff 00000000 S User-Facing Non +u0_a22 1553 1451 1584512 87716 ffffffff 00000000 S User-Facing Non +u0_a22 1560 1451 1584512 87716 ffffffff 00000000 S IcingConnection +u0_a22 1580 1451 1584512 87716 ffffffff 00000000 S AudioRouter-0 +u0_a22 1626 1451 1584512 87716 ffffffff 00000000 S AsyncFileStorag +u0_a22 1635 1451 1584512 87716 ffffffff 00000000 S WifiManager +u0_a22 1643 1451 1584512 87716 ffffffff 00000000 S LocationOracleI +u0_a22 1646 1451 1584512 87716 ffffffff 00000000 S GoogleApiClient +u0_a22 1769 1451 1584512 87716 ffffffff 00000000 S Binder_3 +u0_a22 1770 1451 1584512 87716 ffffffff 00000000 S Gservices +u0_a22 1810 1451 1584512 87716 ffffffff 00000000 S ChromiumNet +u0_a22 1811 1451 1584512 87716 ffffffff 00000000 S DnsConfigServic +u0_a22 1812 1451 1584512 87716 ffffffff 00000000 S inotify_reader +u0_a22 1815 1451 1584512 87716 ffffffff 00000000 S Network File Th +u0_a22 1816 1451 1584512 87716 ffffffff 00000000 S SimpleCacheWork +u0_a22 1817 1451 1584512 87716 ffffffff 00000000 S SimpleCacheWork +u0_a22 1823 1451 1584512 87716 ffffffff 00000000 S Binder_4 +u0_a22 1824 1451 1584512 87716 ffffffff 00000000 S Binder_5 +u0_a22 12193 1451 1584512 87716 ffffffff 00000000 S Background Bloc +u0_a22 12207 1451 1584512 87716 ffffffff 00000000 S User-Facing Blo +u0_a22 12211 1451 1584512 87716 ffffffff 00000000 S WorkerPool/1221 +u0_a22 12232 1451 1584512 87716 ffffffff 00000000 S Background Non- +u0_a22 12235 1451 1584512 87716 ffffffff 00000000 S Background Bloc +u0_a22 12236 1451 1584512 87716 ffffffff 00000000 S Background Bloc +u0_a22 12237 1451 1584512 87716 ffffffff 00000000 S Background Non- +u0_a8 1478 205 1613496 72932 ffffffff 00000000 S com.google.process.gapps +u0_a8 1485 1478 1613496 72932 ffffffff 00000000 S Heap thread poo +u0_a8 1486 1478 1613496 72932 ffffffff 00000000 S Heap thread poo +u0_a8 1487 1478 1613496 72932 ffffffff 00000000 S Heap thread poo +u0_a8 1488 1478 1613496 72932 ffffffff 00000000 S Signal Catcher +u0_a8 1489 1478 1613496 72932 ffffffff 00000000 S JDWP +u0_a8 1490 1478 1613496 72932 ffffffff 00000000 S ReferenceQueueD +u0_a8 1491 1478 1613496 72932 ffffffff 00000000 S FinalizerDaemon +u0_a8 1492 1478 1613496 72932 ffffffff 00000000 S FinalizerWatchd +u0_a8 1493 1478 1613496 72932 ffffffff 00000000 S HeapTrimmerDaem +u0_a8 1494 1478 1613496 72932 ffffffff 00000000 S GCDaemon +u0_a8 1495 1478 1613496 72932 ffffffff 00000000 S Binder_1 +u0_a8 1496 1478 1613496 72932 ffffffff 00000000 S Binder_2 +u0_a8 1497 1478 1613496 72932 ffffffff 00000000 S Binder_3 +u0_a8 1613 1478 1613496 72932 ffffffff 00000000 S Gservices +u0_a8 1614 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@ +u0_a8 1615 1478 1613496 72932 ffffffff 00000000 S Gservices +u0_a8 1616 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@ +u0_a8 1620 1478 1613496 72932 ffffffff 00000000 S Gservices +u0_a8 1996 1478 1613496 72932 ffffffff 00000000 S Binder_4 +u0_a8 1997 1478 1613496 72932 ffffffff 00000000 S Binder_5 +u0_a8 2510 1478 1613496 72932 ffffffff 00000000 S GCMWriter +u0_a8 2512 1478 1613496 72932 ffffffff 00000000 S AsyncTask #1 +u0_a8 2536 1478 1613496 72932 ffffffff 00000000 S GCMReader +u0_a8 2547 1478 1613496 72932 ffffffff 00000000 S pool-2-thread-1 +u0_a8 3680 1478 1613496 72932 ffffffff 00000000 S WifiManager +u0_a8 4135 1478 1613496 72932 ffffffff 00000000 S AsyncTask #2 +u0_a8 4159 1478 1613496 72932 ffffffff 00000000 S AsyncTask #3 +u0_a8 4184 1478 1613496 72932 ffffffff 00000000 S AsyncTask #4 +u0_a8 4210 1478 1613496 72932 ffffffff 00000000 S AsyncTask #5 +u0_a8 4541 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@ +u0_a8 4735 1478 1613496 72932 ffffffff 00000000 S pool-8-thread-1 +u0_a8 4770 1478 1613496 72932 ffffffff 00000000 S Binder_6 +u0_a8 12448 1478 1613496 72932 ffffffff 00000000 S OkHttp Connecti +u0_a8 14401 1478 1613496 72932 ffffffff 00000000 S Thread-233 +u0_a8 14409 1478 1613496 72932 ffffffff 00000000 S OkHttp Connecti +dhcp 1700 1 9344 756 ffffffff 00000000 S /system/bin/dhcpcd +u0_a8 1873 205 1756828 84724 ffffffff 00000000 S com.google.android.gms +u0_a8 1878 1873 1756828 84724 ffffffff 00000000 S Heap thread poo +u0_a8 1880 1873 1756828 84724 ffffffff 00000000 S Heap thread poo +u0_a8 1881 1873 1756828 84724 ffffffff 00000000 S Heap thread poo +u0_a8 1882 1873 1756828 84724 ffffffff 00000000 S Signal Catcher +u0_a8 1883 1873 1756828 84724 ffffffff 00000000 S JDWP +u0_a8 1884 1873 1756828 84724 ffffffff 00000000 S ReferenceQueueD +u0_a8 1885 1873 1756828 84724 ffffffff 00000000 S FinalizerDaemon +u0_a8 1886 1873 1756828 84724 ffffffff 00000000 S FinalizerWatchd +u0_a8 1887 1873 1756828 84724 ffffffff 00000000 S HeapTrimmerDaem +u0_a8 1888 1873 1756828 84724 ffffffff 00000000 S GCDaemon +u0_a8 1889 1873 1756828 84724 ffffffff 00000000 S Binder_1 +u0_a8 1890 1873 1756828 84724 ffffffff 00000000 S Binder_2 +u0_a8 1895 1873 1756828 84724 ffffffff 00000000 S Gservices +u0_a8 1898 1873 1756828 84724 ffffffff 00000000 S measurement-1 +u0_a8 1900 1873 1756828 84724 ffffffff 00000000 S AsyncTask #1 +u0_a8 1904 1873 1756828 84724 ffffffff 00000000 S AsyncTask #2 +u0_a8 2001 1873 1756828 84724 ffffffff 00000000 S Binder_3 +u0_a8 2497 1873 1756828 84724 ffffffff 00000000 S WifiManager +u0_a8 2509 1873 1756828 84724 ffffffff 00000000 S picasa-uploads- +u0_a8 2946 1873 1756828 84724 ffffffff 00000000 S pool-7-thread-1 +u0_a8 4390 1873 1756828 84724 ffffffff 00000000 S pool-13-thread- +u0_a8 4391 1873 1756828 84724 ffffffff 00000000 S pool-18-thread- +u0_a8 4392 1873 1756828 84724 ffffffff 00000000 S pool-11-thread- +u0_a8 4394 1873 1756828 84724 ffffffff 00000000 S pool-25-thread- +u0_a8 4395 1873 1756828 84724 ffffffff 00000000 S pool-25-thread- +u0_a8 4396 1873 1756828 84724 ffffffff 00000000 S pool-25-thread- +u0_a8 4397 1873 1756828 84724 ffffffff 00000000 S pool-25-thread- +u0_a8 4398 1873 1756828 84724 ffffffff 00000000 S pool-14-thread- +u0_a8 4521 1873 1756828 84724 ffffffff 00000000 S MediaTracker bu +u0_a8 4766 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-0 +u0_a8 4771 1873 1756828 84724 ffffffff 00000000 S Icing-Worker-0 +u0_a8 4796 1873 1756828 84724 ffffffff 00000000 S Thread-200 +u0_a8 4797 1873 1756828 84724 ffffffff 00000000 S Thread-201 +u0_a8 4798 1873 1756828 84724 ffffffff 00000000 S Thread-202 +u0_a8 4799 1873 1756828 84724 ffffffff 00000000 S Thread-203 +u0_a8 4800 1873 1756828 84724 ffffffff 00000000 S Thread-204 +u0_a8 5793 1873 1756828 84724 ffffffff 00000000 S Binder_4 +u0_a8 6257 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-1 +u0_a8 6258 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-2 +u0_a8 6259 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-3 +u0_a8 6673 1873 1756828 84724 ffffffff 00000000 S pool-22-thread- +u0_a8 8581 1873 1756828 84724 ffffffff 00000000 S Binder_5 +u0_a8 9001 1873 1756828 84724 ffffffff 00000000 S Gservices +u0_a8 9024 1873 1756828 84724 ffffffff 00000000 S GamesProviderWo +u0_a8 11865 1873 1756828 84724 ffffffff 00000000 S pool-37-thread- +u0_a8 1949 205 1614008 81544 ffffffff 00000000 S com.google.android.gms.persistent +u0_a8 1954 1949 1614008 81544 ffffffff 00000000 S Heap thread poo +u0_a8 1955 1949 1614008 81544 ffffffff 00000000 S Heap thread poo +u0_a8 1956 1949 1614008 81544 ffffffff 00000000 S Heap thread poo +u0_a8 1959 1949 1614008 81544 ffffffff 00000000 S Signal Catcher +u0_a8 1960 1949 1614008 81544 ffffffff 00000000 S JDWP +u0_a8 1961 1949 1614008 81544 ffffffff 00000000 S ReferenceQueueD +u0_a8 1962 1949 1614008 81544 ffffffff 00000000 S FinalizerDaemon +u0_a8 1963 1949 1614008 81544 ffffffff 00000000 S FinalizerWatchd +u0_a8 1964 1949 1614008 81544 ffffffff 00000000 S HeapTrimmerDaem +u0_a8 1965 1949 1614008 81544 ffffffff 00000000 S GCDaemon +u0_a8 1966 1949 1614008 81544 ffffffff 00000000 S Binder_1 +u0_a8 1967 1949 1614008 81544 ffffffff 00000000 S Binder_2 +u0_a8 1968 1949 1614008 81544 ffffffff 00000000 S Gservices +u0_a8 1973 1949 1614008 81544 ffffffff 00000000 S IntentService[G +u0_a8 1976 1949 1614008 81544 ffffffff 00000000 S FlpThread +u0_a8 1977 1949 1614008 81544 ffffffff 00000000 S Binder_3 +u0_a8 1978 1949 1614008 81544 ffffffff 00000000 S WifiManager +u0_a8 1979 1949 1614008 81544 ffffffff 00000000 S GeofencerStateM +u0_a8 1980 1949 1614008 81544 ffffffff 00000000 S LocationService +u0_a8 1984 1949 1614008 81544 ffffffff 00000000 S Binder_4 +u0_a8 1986 1949 1614008 81544 ffffffff 00000000 S Binder_5 +u0_a8 1990 1949 1614008 81544 ffffffff 00000000 S pool-4-thread-1 +u0_a8 1992 1949 1614008 81544 ffffffff 00000000 S GmsCoreStatsSer +u0_a8 1995 1949 1614008 81544 ffffffff 00000000 S GoogleLocationS +u0_a8 2004 1949 1614008 81544 ffffffff 00000000 S Thread-139 +u0_a8 2005 1949 1614008 81544 ffffffff 00000000 S Thread-140 +u0_a8 2006 1949 1614008 81544 ffffffff 00000000 S Thread-141 +u0_a8 2007 1949 1614008 81544 ffffffff 00000000 S Thread-142 +u0_a8 2021 1949 1614008 81544 ffffffff 00000000 S NetworkLocation +u0_a8 2029 1949 1614008 81544 ffffffff 00000000 S UlrDispatchingS +u0_a8 2030 1949 1614008 81544 ffffffff 00000000 S nlp-async-worke +u0_a8 2521 1949 1614008 81544 ffffffff 00000000 S FitnessServiceF +u0_a8 2522 1949 1614008 81544 ffffffff 00000000 S FitRecordingBro +u0_a8 2526 1949 1614008 81544 ffffffff 00000000 S AsyncTask #1 +u0_a8 2530 1949 1614008 81544 ffffffff 00000000 S NearbyMessagesB +u0_a8 4180 1949 1614008 81544 ffffffff 00000000 S AsyncTask #2 +u0_a8 4221 1949 1614008 81544 ffffffff 00000000 S AsyncTask #3 +u0_a8 4223 1949 1614008 81544 ffffffff 00000000 S AsyncTask #4 +u0_a8 4749 1949 1614008 81544 ffffffff 00000000 S CopresenceEvent +u0_a8 6326 1949 1614008 81544 ffffffff 00000000 S AsyncTask #5 +u0_a8 6917 1949 1614008 81544 ffffffff 00000000 S Binder_6 +u0_a8 7196 1949 1614008 81544 ffffffff 00000000 S UlrDispatchingS +u0_a8 7260 1949 1614008 81544 ffffffff 00000000 S Thread-174 +u0_a8 7261 1949 1614008 81544 ffffffff 00000000 S Thread-175 +u0_a8 7262 1949 1614008 81544 ffffffff 00000000 S Thread-176 +u0_a8 7263 1949 1614008 81544 ffffffff 00000000 S Thread-177 +u0_a8 7264 1949 1614008 81544 ffffffff 00000000 S Thread-178 +u0_a8 12449 1949 1614008 81544 ffffffff 00000000 S OkHttp Connecti +root 2031 1 20256 880 ffffffff 00000000 S /system/bin/mpdecision +root 2032 2031 20256 880 ffffffff 00000000 S mpdecision +root 2033 2031 20256 880 ffffffff 00000000 S mpdecision +root 2034 2031 20256 880 ffffffff 00000000 S mpdecision +root 2035 2031 20256 880 ffffffff 00000000 S mpdecision +root 2036 2031 20256 880 ffffffff 00000000 S mpdecision +root 2046 2031 20256 880 ffffffff 00000000 S mpdecision +u0_a193 2647 205 1541760 60840 ffffffff 00000000 S com.qiyi.video.market +u0_a193 2653 2647 1541760 60840 ffffffff 00000000 S Heap thread poo +u0_a193 2654 2647 1541760 60840 ffffffff 00000000 S Heap thread poo +u0_a193 2655 2647 1541760 60840 ffffffff 00000000 S Heap thread poo +u0_a193 2656 2647 1541760 60840 ffffffff 00000000 S Signal Catcher +u0_a193 2657 2647 1541760 60840 ffffffff 00000000 S JDWP +u0_a193 2658 2647 1541760 60840 ffffffff 00000000 S ReferenceQueueD +u0_a193 2659 2647 1541760 60840 ffffffff 00000000 S FinalizerDaemon +u0_a193 2660 2647 1541760 60840 ffffffff 00000000 S FinalizerWatchd +u0_a193 2661 2647 1541760 60840 ffffffff 00000000 S HeapTrimmerDaem +u0_a193 2662 2647 1541760 60840 ffffffff 00000000 S GCDaemon +u0_a193 2663 2647 1541760 60840 ffffffff 00000000 S Binder_1 +u0_a193 2664 2647 1541760 60840 ffffffff 00000000 S Binder_2 +u0_a193 2671 2647 1541760 60840 ffffffff 00000000 S RefQueueWorker@ +u0_a193 2673 2647 1541760 60840 ffffffff 00000000 S .ProcessManager +u0_a193 2675 2647 1541760 60840 ffffffff 00000000 S Binder_3 +u0_a193 2677 2647 1541760 60840 ffffffff 00000000 S Thread-208 +u0_a193 2679 2647 1541760 60840 ffffffff 00000000 S pool-2-thread-1 +u0_a193 2680 2647 1541760 60840 ffffffff 00000000 S WifiManager +u0_a193 2682 2647 1541760 60840 ffffffff 00000000 S Timer-0 +u0_a193 2683 2647 1541760 60840 ffffffff 00000000 S Timer-1 +u0_a193 2710 2647 1541760 60840 ffffffff 00000000 S AsyncTask #1 +u0_a193 2718 2647 1541760 60840 ffffffff 00000000 S pool-3-thread-1 +u0_a193 3103 2647 1541760 60840 ffffffff 00000000 S pool-4-thread-1 +u0_a193 6672 2647 1541760 60840 ffffffff 00000000 S AsyncTask #2 +u0_a193 6752 2647 1541760 60840 ffffffff 00000000 S AsyncTask #3 +u0_a193 12484 2647 1541760 60840 ffffffff 00000000 S AsyncTask #4 +u0_a193 12576 2647 1541760 60840 ffffffff 00000000 S AsyncTask #5 +u0_a193 3104 205 1523132 46892 ffffffff 00000000 S com.qiyi.video.market:pluginDownloadService +u0_a193 3110 3104 1523132 46892 ffffffff 00000000 S Heap thread poo +u0_a193 3111 3104 1523132 46892 ffffffff 00000000 S Heap thread poo +u0_a193 3112 3104 1523132 46892 ffffffff 00000000 S Heap thread poo +u0_a193 3113 3104 1523132 46892 ffffffff 00000000 S Signal Catcher +u0_a193 3114 3104 1523132 46892 ffffffff 00000000 S JDWP +u0_a193 3115 3104 1523132 46892 ffffffff 00000000 S ReferenceQueueD +u0_a193 3116 3104 1523132 46892 ffffffff 00000000 S FinalizerDaemon +u0_a193 3117 3104 1523132 46892 ffffffff 00000000 S FinalizerWatchd +u0_a193 3118 3104 1523132 46892 ffffffff 00000000 S HeapTrimmerDaem +u0_a193 3119 3104 1523132 46892 ffffffff 00000000 S GCDaemon +u0_a193 3120 3104 1523132 46892 ffffffff 00000000 S Binder_1 +u0_a193 3121 3104 1523132 46892 ffffffff 00000000 S Binder_2 +u0_a193 3141 3104 1523132 46892 ffffffff 00000000 S RefQueueWorker@ +u0_a193 3257 3104 1523132 46892 ffffffff 00000000 S pool-3-thread-1 +u0_a193 7173 3104 1523132 46892 ffffffff 00000000 S Binder_3 +u0_a193 3122 205 1538224 61140 ffffffff 00000000 S com.qiyi.video.market:bdservice_v1 +u0_a193 3128 3122 1538224 61140 ffffffff 00000000 S Heap thread poo +u0_a193 3129 3122 1538224 61140 ffffffff 00000000 S Heap thread poo +u0_a193 3130 3122 1538224 61140 ffffffff 00000000 S Heap thread poo +u0_a193 3131 3122 1538224 61140 ffffffff 00000000 S Signal Catcher +u0_a193 3132 3122 1538224 61140 ffffffff 00000000 S JDWP +u0_a193 3133 3122 1538224 61140 ffffffff 00000000 S ReferenceQueueD +u0_a193 3134 3122 1538224 61140 ffffffff 00000000 S FinalizerDaemon +u0_a193 3135 3122 1538224 61140 ffffffff 00000000 S FinalizerWatchd +u0_a193 3136 3122 1538224 61140 ffffffff 00000000 S HeapTrimmerDaem +u0_a193 3137 3122 1538224 61140 ffffffff 00000000 S GCDaemon +u0_a193 3138 3122 1538224 61140 ffffffff 00000000 S Binder_1 +u0_a193 3139 3122 1538224 61140 ffffffff 00000000 S Binder_2 +u0_a193 3145 3122 1538224 61140 ffffffff 00000000 S RefQueueWorker@ +u0_a193 3206 3122 1538224 61140 ffffffff 00000000 S WifiManager +u0_a193 3208 3122 1538224 61140 ffffffff 00000000 S NanoHttpd Main +u0_a193 7586 3122 1538224 61140 ffffffff 00000000 S pool-4-thread-1 +u0_a193 10584 3122 1538224 61140 ffffffff 00000000 S pool-2-thread-1 +u0_a193 3154 205 1522116 53536 ffffffff 00000000 S com.qiyi.video.market:baiduLocation +u0_a193 3163 3154 1522116 53536 ffffffff 00000000 S Heap thread poo +u0_a193 3164 3154 1522116 53536 ffffffff 00000000 S Heap thread poo +u0_a193 3165 3154 1522116 53536 ffffffff 00000000 S Heap thread poo +u0_a193 3166 3154 1522116 53536 ffffffff 00000000 S Signal Catcher +u0_a193 3167 3154 1522116 53536 ffffffff 00000000 S JDWP +u0_a193 3168 3154 1522116 53536 ffffffff 00000000 S ReferenceQueueD +u0_a193 3169 3154 1522116 53536 ffffffff 00000000 S FinalizerDaemon +u0_a193 3170 3154 1522116 53536 ffffffff 00000000 S FinalizerWatchd +u0_a193 3171 3154 1522116 53536 ffffffff 00000000 S HeapTrimmerDaem +u0_a193 3172 3154 1522116 53536 ffffffff 00000000 S GCDaemon +u0_a193 3173 3154 1522116 53536 ffffffff 00000000 S Binder_1 +u0_a193 3174 3154 1522116 53536 ffffffff 00000000 S Binder_2 +u0_a193 3177 3154 1522116 53536 ffffffff 00000000 S RefQueueWorker@ +u0_a193 3199 3154 1522116 53536 ffffffff 00000000 S WifiManager +u0_a86 3179 205 1561816 58376 ffffffff 00000000 S com.tencent.mm:push +u0_a86 3183 3179 1561816 58376 ffffffff 00000000 S Heap thread poo +u0_a86 3184 3179 1561816 58376 ffffffff 00000000 S Heap thread poo +u0_a86 3185 3179 1561816 58376 ffffffff 00000000 S Heap thread poo +u0_a86 3187 3179 1561816 58376 ffffffff 00000000 S Signal Catcher +u0_a86 3189 3179 1561816 58376 ffffffff 00000000 S JDWP +u0_a86 3190 3179 1561816 58376 ffffffff 00000000 S ReferenceQueueD +u0_a86 3191 3179 1561816 58376 ffffffff 00000000 S FinalizerDaemon +u0_a86 3192 3179 1561816 58376 ffffffff 00000000 S FinalizerWatchd +u0_a86 3193 3179 1561816 58376 ffffffff 00000000 S HeapTrimmerDaem +u0_a86 3194 3179 1561816 58376 ffffffff 00000000 S GCDaemon +u0_a86 3195 3179 1561816 58376 ffffffff 00000000 S Binder_1 +u0_a86 3196 3179 1561816 58376 ffffffff 00000000 S Binder_2 +u0_a86 3210 3179 1561816 58376 ffffffff 00000000 S THREAD_POOL_HAN +u0_a86 3212 3179 1561816 58376 ffffffff 00000000 S tencent.mm:push +u0_a86 3216 3179 1561816 58376 ffffffff 00000000 S FileObserver +u0_a86 3238 3179 1561816 58376 ffffffff 00000000 S tencent.mm:push +u0_a86 3239 3179 1561816 58376 ffffffff 00000000 S default +u0_a86 3240 3179 1561816 58376 ffffffff 00000000 S WifiManager +u0_a86 5627 3179 1561816 58376 ffffffff 00000000 S Binder_3 +u0_a86 7150 3179 1561816 58376 ffffffff 00000000 S default +u0_a170 3217 205 1531688 52204 ffffffff 00000000 S com.baidu.searchbox:bdservice_v1 +u0_a170 3220 3217 1531688 52204 ffffffff 00000000 S Heap thread poo +u0_a170 3221 3217 1531688 52204 ffffffff 00000000 S Heap thread poo +u0_a170 3223 3217 1531688 52204 ffffffff 00000000 S Heap thread poo +u0_a170 3226 3217 1531688 52204 ffffffff 00000000 S Signal Catcher +u0_a170 3228 3217 1531688 52204 ffffffff 00000000 S JDWP +u0_a170 3229 3217 1531688 52204 ffffffff 00000000 S ReferenceQueueD +u0_a170 3230 3217 1531688 52204 ffffffff 00000000 S FinalizerDaemon +u0_a170 3231 3217 1531688 52204 ffffffff 00000000 S FinalizerWatchd +u0_a170 3233 3217 1531688 52204 ffffffff 00000000 S HeapTrimmerDaem +u0_a170 3234 3217 1531688 52204 ffffffff 00000000 S GCDaemon +u0_a170 3235 3217 1531688 52204 ffffffff 00000000 S Binder_1 +u0_a170 3236 3217 1531688 52204 ffffffff 00000000 S Binder_2 +u0_a170 3303 3217 1531688 52204 ffffffff 00000000 S AsyncTask #1 +u0_a170 3304 3217 1531688 52204 ffffffff 00000000 S AsyncTask #2 +u0_a170 3518 3217 1531688 52204 ffffffff 00000000 S PushService-Pus +u0_a170 3519 3217 1531688 52204 ffffffff 00000000 S PushService-Pus +u0_a170 6201 3217 1531688 52204 ffffffff 00000000 S pool-1-thread-1 +u0_a170 10591 3217 1531688 52204 ffffffff 00000000 S RefQueueWorker@ +u0_a170 3260 205 1533384 53212 ffffffff 00000000 S com.baidu.searchbox:bdmoservice +u0_a170 3264 3260 1533384 53212 ffffffff 00000000 S Heap thread poo +u0_a170 3265 3260 1533384 53212 ffffffff 00000000 S Heap thread poo +u0_a170 3266 3260 1533384 53212 ffffffff 00000000 S Heap thread poo +u0_a170 3269 3260 1533384 53212 ffffffff 00000000 S Signal Catcher +u0_a170 3270 3260 1533384 53212 ffffffff 00000000 S JDWP +u0_a170 3271 3260 1533384 53212 ffffffff 00000000 S ReferenceQueueD +u0_a170 3272 3260 1533384 53212 ffffffff 00000000 S FinalizerDaemon +u0_a170 3273 3260 1533384 53212 ffffffff 00000000 S FinalizerWatchd +u0_a170 3274 3260 1533384 53212 ffffffff 00000000 S HeapTrimmerDaem +u0_a170 3275 3260 1533384 53212 ffffffff 00000000 S GCDaemon +u0_a170 3276 3260 1533384 53212 ffffffff 00000000 S Binder_1 +u0_a170 3277 3260 1533384 53212 ffffffff 00000000 S Binder_2 +u0_a170 3738 3260 1533384 53212 ffffffff 00000000 S NanoHttpd Main +u0_a170 5783 3260 1533384 53212 ffffffff 00000000 S WifiManager +u0_a126 3633 205 1515740 46080 ffffffff 00000000 S com.tencent.portfolio:push +u0_a126 3636 3633 1515740 46080 ffffffff 00000000 S Heap thread poo +u0_a126 3638 3633 1515740 46080 ffffffff 00000000 S Heap thread poo +u0_a126 3639 3633 1515740 46080 ffffffff 00000000 S Heap thread poo +u0_a126 3642 3633 1515740 46080 ffffffff 00000000 S Signal Catcher +u0_a126 3643 3633 1515740 46080 ffffffff 00000000 S JDWP +u0_a126 3645 3633 1515740 46080 ffffffff 00000000 S ReferenceQueueD +u0_a126 3646 3633 1515740 46080 ffffffff 00000000 S FinalizerDaemon +u0_a126 3647 3633 1515740 46080 ffffffff 00000000 S FinalizerWatchd +u0_a126 3648 3633 1515740 46080 ffffffff 00000000 S HeapTrimmerDaem +u0_a126 3649 3633 1515740 46080 ffffffff 00000000 S GCDaemon +u0_a126 3650 3633 1515740 46080 ffffffff 00000000 S Binder_1 +u0_a126 3651 3633 1515740 46080 ffffffff 00000000 S Binder_2 +u0_a126 3661 3633 1515740 46080 ffffffff 00000000 S TPPluginCenter +u0_a126 3663 3633 1515740 46080 ffffffff 00000000 S pool-1-thread-1 +u0_a126 3665 3633 1515740 46080 ffffffff 00000000 S MidService +u0_a126 3667 3633 1515740 46080 ffffffff 00000000 S pool-2-thread-1 +u0_a126 3668 3633 1515740 46080 ffffffff 00000000 S push core threa +u0_a126 3670 3633 1515740 46080 ffffffff 00000000 S .ProcessManager +u0_a126 3672 3633 1515740 46080 ffffffff 00000000 S Binder_3 +u0_a126 3674 3633 1515740 46080 ffffffff 00000000 S pool-4-thread-1 +u0_a126 3675 3633 1515740 46080 ffffffff 00000000 S pool-3-thread-1 +u0_a126 5638 3633 1515740 46080 ffffffff 00000000 S Timer-0 +bluetooth 4227 205 1527652 48088 ffffffff 00000000 S com.android.bluetooth +bluetooth 4231 4227 1527652 48088 ffffffff 00000000 S Heap thread poo +bluetooth 4233 4227 1527652 48088 ffffffff 00000000 S Heap thread poo +bluetooth 4235 4227 1527652 48088 ffffffff 00000000 S Heap thread poo +bluetooth 4236 4227 1527652 48088 ffffffff 00000000 S Signal Catcher +bluetooth 4237 4227 1527652 48088 ffffffff 00000000 S JDWP +bluetooth 4238 4227 1527652 48088 ffffffff 00000000 S ReferenceQueueD +bluetooth 4239 4227 1527652 48088 ffffffff 00000000 S FinalizerDaemon +bluetooth 4240 4227 1527652 48088 ffffffff 00000000 S FinalizerWatchd +bluetooth 4241 4227 1527652 48088 ffffffff 00000000 S HeapTrimmerDaem +bluetooth 4242 4227 1527652 48088 ffffffff 00000000 S GCDaemon +bluetooth 4243 4227 1527652 48088 ffffffff 00000000 S Binder_1 +bluetooth 4244 4227 1527652 48088 ffffffff 00000000 S Binder_2 +bluetooth 4308 4227 1527652 48088 ffffffff 00000000 S BluetoothAdapte +bluetooth 4309 4227 1527652 48088 ffffffff 00000000 S droid.bluetooth +bluetooth 4311 4227 1527652 48088 ffffffff 00000000 S bluedroid wake/ +bluetooth 4312 4227 1527652 48088 ffffffff 00000000 S BT Service Call +bluetooth 4315 4227 1527652 48088 ffffffff 00000000 S BondStateMachin +bluetooth 4316 4227 1527652 48088 ffffffff 00000000 S Binder_3 +bluetooth 4317 4227 1527652 48088 ffffffff 00000000 S Binder_4 +bluetooth 4318 4227 1527652 48088 ffffffff 00000000 S HeadsetStateMac +bluetooth 4320 4227 1527652 48088 ffffffff 00000000 S BluetoothAvrcpH +bluetooth 4321 4227 1527652 48088 ffffffff 00000000 S A2dpStateMachin +bluetooth 4322 4227 1527652 48088 ffffffff 00000000 S A2DP-MEDIA +bluetooth 4323 4227 1527652 48088 ffffffff 00000000 S uipc-main +bluetooth 4324 4227 1527652 48088 ffffffff 00000000 S BluetoothHdpHan +bluetooth 4325 4227 1527652 48088 ffffffff 00000000 S droid.bluetooth +bluetooth 4326 4227 1527652 48088 ffffffff 00000000 S BluetoothAdvert +bluetooth 4327 4227 1527652 48088 ffffffff 00000000 S BluetoothScanMa +bluetooth 4331 4227 1527652 48088 ffffffff 00000000 S bluedroid wake/ +bluetooth 4333 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker +bluetooth 4338 4227 1527652 48088 ffffffff 00000000 S userial_read +bluetooth 4478 4227 1527652 48088 ffffffff 00000000 S BT Service Call +bluetooth 4479 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker +bluetooth 4481 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker +bluetooth 4482 4227 1527652 48088 ffffffff 00000000 S BluetoothMapAcc +bluetooth 6459 4227 1527652 48088 ffffffff 00000000 S BluetoothPbapAc +bluetooth 6473 4227 1527652 48088 ffffffff 00000000 S pool-1-thread-1 +bluetooth 6477 4227 1527652 48088 ffffffff 00000000 S BtOppRfcommList +radio 4597 205 1493160 37460 ffffffff 00000000 S com.qualcomm.qcrilmsgtunnel +radio 4603 4597 1493160 37460 ffffffff 00000000 S Heap thread poo +radio 4604 4597 1493160 37460 ffffffff 00000000 S Heap thread poo +radio 4605 4597 1493160 37460 ffffffff 00000000 S Heap thread poo +radio 4606 4597 1493160 37460 ffffffff 00000000 S Signal Catcher +radio 4607 4597 1493160 37460 ffffffff 00000000 S JDWP +radio 4608 4597 1493160 37460 ffffffff 00000000 S ReferenceQueueD +radio 4609 4597 1493160 37460 ffffffff 00000000 S FinalizerDaemon +radio 4610 4597 1493160 37460 ffffffff 00000000 S FinalizerWatchd +radio 4611 4597 1493160 37460 ffffffff 00000000 S HeapTrimmerDaem +radio 4612 4597 1493160 37460 ffffffff 00000000 S GCDaemon +radio 4613 4597 1493160 37460 ffffffff 00000000 S Binder_1 +radio 4614 4597 1493160 37460 ffffffff 00000000 S Binder_2 +radio 4615 4597 1493160 37460 ffffffff 00000000 S QcRilReceiver +radio 4616 4597 1493160 37460 ffffffff 00000000 S QcRilSender +u0_a193 5239 205 1528424 47860 ffffffff 00000000 S .iqiyipushserviceGlobal +u0_a193 5242 5239 1528424 47860 ffffffff 00000000 S Heap thread poo +u0_a193 5244 5239 1528424 47860 ffffffff 00000000 S Heap thread poo +u0_a193 5245 5239 1528424 47860 ffffffff 00000000 S Heap thread poo +u0_a193 5248 5239 1528424 47860 ffffffff 00000000 S Signal Catcher +u0_a193 5249 5239 1528424 47860 ffffffff 00000000 S JDWP +u0_a193 5250 5239 1528424 47860 ffffffff 00000000 S ReferenceQueueD +u0_a193 5251 5239 1528424 47860 ffffffff 00000000 S FinalizerDaemon +u0_a193 5252 5239 1528424 47860 ffffffff 00000000 S FinalizerWatchd +u0_a193 5253 5239 1528424 47860 ffffffff 00000000 S HeapTrimmerDaem +u0_a193 5254 5239 1528424 47860 ffffffff 00000000 S GCDaemon +u0_a193 5255 5239 1528424 47860 ffffffff 00000000 S Binder_1 +u0_a193 5257 5239 1528424 47860 ffffffff 00000000 S Binder_2 +u0_a193 5280 5239 1528424 47860 ffffffff 00000000 S RefQueueWorker@ +u0_a193 5281 5239 1528424 47860 ffffffff 00000000 S Binder_3 +u0_a193 5361 5239 1528424 47860 ffffffff 00000000 S Micro Client Co +u0_a193 5362 5239 1528424 47860 ffffffff 00000000 S Micro Client Co +u0_a193 5363 5239 1528424 47860 ffffffff 00000000 S Micro Client Ca +u0_a193 6740 5239 1528424 47860 ffffffff 00000000 S Binder_4 +u0_a193 7091 5239 1528424 47860 ffffffff 00000000 S Binder_5 +u0_a193 7557 5239 1528424 47860 ffffffff 00000000 S Binder_6 +u0_a193 5285 5239 1521088 34196 ffffffff 00000000 S .iqiyipushserviceGlobal +u0_a90 5323 205 1557268 59988 ffffffff 00000000 S com.strava +u0_a90 5327 5323 1557268 59988 ffffffff 00000000 S Heap thread poo +u0_a90 5328 5323 1557268 59988 ffffffff 00000000 S Heap thread poo +u0_a90 5329 5323 1557268 59988 ffffffff 00000000 S Heap thread poo +u0_a90 5332 5323 1557268 59988 ffffffff 00000000 S Signal Catcher +u0_a90 5333 5323 1557268 59988 ffffffff 00000000 S JDWP +u0_a90 5334 5323 1557268 59988 ffffffff 00000000 S ReferenceQueueD +u0_a90 5335 5323 1557268 59988 ffffffff 00000000 S FinalizerDaemon +u0_a90 5336 5323 1557268 59988 ffffffff 00000000 S FinalizerWatchd +u0_a90 5337 5323 1557268 59988 ffffffff 00000000 S HeapTrimmerDaem +u0_a90 5338 5323 1557268 59988 ffffffff 00000000 S GCDaemon +u0_a90 5339 5323 1557268 59988 ffffffff 00000000 S Binder_1 +u0_a90 5340 5323 1557268 59988 ffffffff 00000000 S Binder_2 +u0_a90 5345 5323 1557268 59988 ffffffff 00000000 S Queue +u0_a90 5346 5323 1557268 59988 ffffffff 00000000 S Queue +u0_a90 5347 5323 1557268 59988 ffffffff 00000000 S Queue +u0_a90 5348 5323 1557268 59988 ffffffff 00000000 S Queue +u0_a90 5349 5323 1557268 59988 ffffffff 00000000 S Queue +u0_a90 5352 5323 1557268 59988 ffffffff 00000000 S Crashlytics Exc +u0_a90 5354 5323 1557268 59988 ffffffff 00000000 S pool-3-thread-1 +u0_a90 5364 5323 1557268 59988 ffffffff 00000000 S Thread-584 +u0_a90 5365 5323 1557268 59988 ffffffff 00000000 S Thread-585 +u0_a90 5366 5323 1557268 59988 ffffffff 00000000 S Thread-586 +u0_a90 5367 5323 1557268 59988 ffffffff 00000000 S pool-4-thread-1 +u0_a90 5369 5323 1557268 59988 ffffffff 00000000 S Crashlytics Tra +u0_a90 5372 5323 1557268 59988 ffffffff 00000000 S Thread-593 +u0_a90 5373 5323 1557268 59988 ffffffff 00000000 S Thread-594 +u0_a90 5374 5323 1557268 59988 ffffffff 00000000 S Thread-595 +u0_a90 5375 5323 1557268 59988 ffffffff 00000000 S Thread-596 +u0_a90 5376 5323 1557268 59988 ffffffff 00000000 S pool-6-thread-1 +u0_a90 5377 5323 1557268 59988 ffffffff 00000000 S Thread-598 +u0_a90 5378 5323 1557268 59988 ffffffff 00000000 S Thread-599 +u0_a90 5379 5323 1557268 59988 ffffffff 00000000 S Thread-600 +u0_a90 5381 5323 1557268 59988 ffffffff 00000000 S Thread-602 +u0_a90 5383 5323 1557268 59988 ffffffff 00000000 S Thread #1 +u0_a90 5384 5323 1557268 59988 ffffffff 00000000 S AsyncTask #1 +u0_a90 5387 5323 1557268 59988 ffffffff 00000000 S Thread-605 +u0_a90 5388 5323 1557268 59988 ffffffff 00000000 S Thread-606 +u0_a90 5389 5323 1557268 59988 ffffffff 00000000 S Thread-607 +u0_a90 5390 5323 1557268 59988 ffffffff 00000000 S Thread-608 +u0_a90 5391 5323 1557268 59988 ffffffff 00000000 S Thread-609 +u0_a90 5393 5323 1557268 59988 ffffffff 00000000 S eNowAuthService +u0_a90 5394 5323 1557268 59988 ffffffff 00000000 S Thread #2 +u0_a90 5468 5323 1557268 59988 ffffffff 00000000 S Okio Watchdog +u0_a90 5498 5323 1557268 59988 ffffffff 00000000 S Thread #3 +u0_a109 5395 205 1524968 53976 ffffffff 00000000 S com.pandora.android +u0_a109 5397 5395 1524968 53976 ffffffff 00000000 S Heap thread poo +u0_a109 5398 5395 1524968 53976 ffffffff 00000000 S Heap thread poo +u0_a109 5399 5395 1524968 53976 ffffffff 00000000 S Heap thread poo +u0_a109 5401 5395 1524968 53976 ffffffff 00000000 S Signal Catcher +u0_a109 5403 5395 1524968 53976 ffffffff 00000000 S JDWP +u0_a109 5407 5395 1524968 53976 ffffffff 00000000 S ReferenceQueueD +u0_a109 5408 5395 1524968 53976 ffffffff 00000000 S FinalizerDaemon +u0_a109 5409 5395 1524968 53976 ffffffff 00000000 S FinalizerWatchd +u0_a109 5410 5395 1524968 53976 ffffffff 00000000 S HeapTrimmerDaem +u0_a109 5411 5395 1524968 53976 ffffffff 00000000 S GCDaemon +u0_a109 5414 5395 1524968 53976 ffffffff 00000000 S Binder_1 +u0_a109 5416 5395 1524968 53976 ffffffff 00000000 S Binder_2 +u0_a109 5422 5395 1524968 53976 ffffffff 00000000 S Crashlytics Exc +u0_a109 5429 5395 1524968 53976 ffffffff 00000000 S pool-2-thread-1 +u0_a109 5430 5395 1524968 53976 ffffffff 00000000 S AsyncTask #1 +u0_a109 5437 5395 1524968 53976 ffffffff 00000000 S Crashlytics Tra +u0_a109 5439 5395 1524968 53976 ffffffff 00000000 S AsyncTask #2 +u0_a109 5440 5395 1524968 53976 ffffffff 00000000 S pool-4-thread-1 +u0_a109 5443 5395 1524968 53976 ffffffff 00000000 S PurchasingManag +u0_a109 5444 5395 1524968 53976 ffffffff 00000000 S BluetoothServer +u0_a109 5445 5395 1524968 53976 ffffffff 00000000 S AsyncTask #3 +u0_a109 5446 5395 1524968 53976 ffffffff 00000000 S AsyncTask #4 +u0_a109 5590 5395 1524968 53976 ffffffff 00000000 S Binder_3 +u0_a109 6481 5395 1524968 53976 ffffffff 00000000 S AsyncTask #5 +u0_a110 5474 205 1525556 49828 ffffffff 00000000 S tunein.player +u0_a110 5479 5474 1525556 49828 ffffffff 00000000 S Heap thread poo +u0_a110 5480 5474 1525556 49828 ffffffff 00000000 S Heap thread poo +u0_a110 5481 5474 1525556 49828 ffffffff 00000000 S Heap thread poo +u0_a110 5483 5474 1525556 49828 ffffffff 00000000 S Signal Catcher +u0_a110 5484 5474 1525556 49828 ffffffff 00000000 S JDWP +u0_a110 5485 5474 1525556 49828 ffffffff 00000000 S ReferenceQueueD +u0_a110 5486 5474 1525556 49828 ffffffff 00000000 S FinalizerDaemon +u0_a110 5487 5474 1525556 49828 ffffffff 00000000 S FinalizerWatchd +u0_a110 5488 5474 1525556 49828 ffffffff 00000000 S HeapTrimmerDaem +u0_a110 5489 5474 1525556 49828 ffffffff 00000000 S GCDaemon +u0_a110 5490 5474 1525556 49828 ffffffff 00000000 S Binder_1 +u0_a110 5492 5474 1525556 49828 ffffffff 00000000 S Binder_2 +u0_a110 5503 5474 1525556 49828 ffffffff 00000000 S geHandlerThread +u0_a110 5504 5474 1525556 49828 ffffffff 00000000 S GAThread +u0_a110 5507 5474 1525556 49828 ffffffff 00000000 S Crashlytics Exc +u0_a110 5510 5474 1525556 49828 ffffffff 00000000 S AsyncTask #1 +u0_a110 5515 5474 1525556 49828 ffffffff 00000000 S Crashlytics Tra +u0_a110 5518 5474 1525556 49828 ffffffff 00000000 S AsyncTask #2 +u0_a110 5587 5474 1525556 49828 ffffffff 00000000 S AcceptThreadSec +u0_a88 5519 205 1556696 65876 ffffffff 00000000 S com.dropbox.android +u0_a88 5525 5519 1556696 65876 ffffffff 00000000 S Heap thread poo +u0_a88 5526 5519 1556696 65876 ffffffff 00000000 S Heap thread poo +u0_a88 5527 5519 1556696 65876 ffffffff 00000000 S Heap thread poo +u0_a88 5528 5519 1556696 65876 ffffffff 00000000 S Signal Catcher +u0_a88 5529 5519 1556696 65876 ffffffff 00000000 S JDWP +u0_a88 5530 5519 1556696 65876 ffffffff 00000000 S ReferenceQueueD +u0_a88 5531 5519 1556696 65876 ffffffff 00000000 S FinalizerDaemon +u0_a88 5532 5519 1556696 65876 ffffffff 00000000 S FinalizerWatchd +u0_a88 5533 5519 1556696 65876 ffffffff 00000000 S HeapTrimmerDaem +u0_a88 5534 5519 1556696 65876 ffffffff 00000000 S GCDaemon +u0_a88 5535 5519 1556696 65876 ffffffff 00000000 S Binder_1 +u0_a88 5536 5519 1556696 65876 ffffffff 00000000 S Binder_2 +u0_a88 5562 5519 1556696 65876 ffffffff 00000000 S Dropbox log upl +u0_a88 5563 5519 1556696 65876 ffffffff 00000000 S gandalf updater +u0_a88 5568 5519 1556696 65876 ffffffff 00000000 S pool-10-thread- +u0_a88 5569 5519 1556696 65876 ffffffff 00000000 S DbxFileObserver +u0_a88 5570 5519 1556696 65876 ffffffff 00000000 S LocalThumbManag +u0_a88 5574 5519 1556696 65876 ffffffff 00000000 S local AsyncTask +u0_a88 5575 5519 1556696 65876 ffffffff 00000000 S remote AsyncTas +u0_a88 5576 5519 1556696 65876 ffffffff 00000000 S local AsyncTask +u0_a88 5577 5519 1556696 65876 ffffffff 00000000 S remote AsyncTas +u0_a88 5578 5519 1556696 65876 ffffffff 00000000 S Dropbox notif o +u0_a88 5579 5519 1556696 65876 ffffffff 00000000 S Dropbox notif s +u0_a88 5580 5519 1556696 65876 ffffffff 00000000 S Picasso-Stats +u0_a88 5581 5519 1556696 65876 ffffffff 00000000 S Picasso-Dispatc +u0_a88 5582 5519 1556696 65876 ffffffff 00000000 S Picasso-refQueu +u0_a88 5583 5519 1556696 65876 ffffffff 00000000 S gandalf updater +u0_a88 5592 5519 1556696 65876 ffffffff 00000000 S DbxFileObserver +u0_a88 5593 5519 1556696 65876 ffffffff 00000000 S dbxpool-34:r-th +u0_a88 5594 5519 1556696 65876 ffffffff 00000000 S dbxpool-32:au-t +u0_a88 5595 5519 1556696 65876 ffffffff 00000000 S dbxpool-38:a-th +u0_a88 5596 5519 1556696 65876 ffffffff 00000000 S Timer-0 +u0_a88 5597 5519 1556696 65876 ffffffff 00000000 S dbxpool-6:a-thr +u0_a88 5599 5519 1556696 65876 ffffffff 00000000 S Timer-1 +u0_a88 5718 5519 1556696 65876 ffffffff 00000000 S RefQueueWorker@ +u0_a88 5750 5519 1556696 65876 ffffffff 00000000 S Thread-625 +u0_a88 5818 5519 1556696 65876 ffffffff 00000000 S Binder_3 +u0_a88 8569 5519 1556696 65876 ffffffff 00000000 S Binder_4 +u0_a88 8572 5519 1556696 65876 ffffffff 00000000 S Binder_5 +u0_a88 8580 5519 1556696 65876 ffffffff 00000000 S Binder_6 +u0_a93 5688 205 1496212 39724 ffffffff 00000000 S com.devuni.flashlight:remote +u0_a93 5693 5688 1496212 39724 ffffffff 00000000 S Heap thread poo +u0_a93 5694 5688 1496212 39724 ffffffff 00000000 S Heap thread poo +u0_a93 5695 5688 1496212 39724 ffffffff 00000000 S Heap thread poo +u0_a93 5697 5688 1496212 39724 ffffffff 00000000 S Signal Catcher +u0_a93 5698 5688 1496212 39724 ffffffff 00000000 S JDWP +u0_a93 5699 5688 1496212 39724 ffffffff 00000000 S ReferenceQueueD +u0_a93 5700 5688 1496212 39724 ffffffff 00000000 S FinalizerDaemon +u0_a93 5701 5688 1496212 39724 ffffffff 00000000 S FinalizerWatchd +u0_a93 5702 5688 1496212 39724 ffffffff 00000000 S HeapTrimmerDaem +u0_a93 5703 5688 1496212 39724 ffffffff 00000000 S GCDaemon +u0_a93 5704 5688 1496212 39724 ffffffff 00000000 S Binder_1 +u0_a93 5705 5688 1496212 39724 ffffffff 00000000 S Binder_2 +u0_a93 12039 5688 1496212 39724 ffffffff 00000000 S pool-1-thread-1 +u0_a86 6202 205 1809096 86876 ffffffff 00000000 S com.tencent.mm +u0_a86 6206 6202 1809096 86876 ffffffff 00000000 S Heap thread poo +u0_a86 6207 6202 1809096 86876 ffffffff 00000000 S Heap thread poo +u0_a86 6208 6202 1809096 86876 ffffffff 00000000 S Heap thread poo +u0_a86 6211 6202 1809096 86876 ffffffff 00000000 S Signal Catcher +u0_a86 6212 6202 1809096 86876 ffffffff 00000000 S JDWP +u0_a86 6213 6202 1809096 86876 ffffffff 00000000 S ReferenceQueueD +u0_a86 6214 6202 1809096 86876 ffffffff 00000000 S FinalizerDaemon +u0_a86 6215 6202 1809096 86876 ffffffff 00000000 S FinalizerWatchd +u0_a86 6217 6202 1809096 86876 ffffffff 00000000 S HeapTrimmerDaem +u0_a86 6218 6202 1809096 86876 ffffffff 00000000 S GCDaemon +u0_a86 6220 6202 1809096 86876 ffffffff 00000000 S Binder_1 +u0_a86 6221 6202 1809096 86876 ffffffff 00000000 S Binder_2 +u0_a86 6236 6202 1809096 86876 ffffffff 00000000 S THREAD_POOL_HAN +u0_a86 6237 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm +u0_a86 6239 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm +u0_a86 6240 6202 1809096 86876 ffffffff 00000000 S MonitorHandlerT +u0_a86 6241 6202 1809096 86876 ffffffff 00000000 S .ProcessManager +u0_a86 6243 6202 1809096 86876 ffffffff 00000000 S Binder_3 +u0_a86 6245 6202 1809096 86876 ffffffff 00000000 S default +u0_a86 6246 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm +u0_a86 6247 6202 1809096 86876 ffffffff 00000000 S MMHandlerThread +u0_a86 6269 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6270 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6271 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6272 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6273 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6274 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6276 6202 1809096 86876 ffffffff 00000000 S ExdeviceHandler +u0_a86 6277 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6279 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout +u0_a86 6280 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout +u0_a86 6282 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6284 6202 1809096 86876 ffffffff 00000000 S downloadStateCh +u0_a86 6288 6202 1809096 86876 ffffffff 00000000 S WifiManager +u0_a86 6289 6202 1809096 86876 ffffffff 00000000 S refresh Notific +u0_a86 6292 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6293 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6294 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6295 6202 1809096 86876 ffffffff 00000000 S SearchDaemon +u0_a86 6303 6202 1809096 86876 ffffffff 00000000 S Binder_4 +u0_a86 6313 6202 1809096 86876 ffffffff 00000000 S pool-2-thread-1 +u0_a86 6373 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout +u0_a86 6408 6202 1809096 86876 ffffffff 00000000 S h +u0_a86 7230 6202 1809096 86876 ffffffff 00000000 S default +u0_a86 7231 6202 1809096 86876 ffffffff 00000000 S MMHandlerThread +u0_a191 8839 205 1510312 57352 ffffffff 00000000 S com.ushaqi.zhuishushenqi:pushservice +u0_a191 8845 8839 1510312 57352 ffffffff 00000000 S Heap thread poo +u0_a191 8846 8839 1510312 57352 ffffffff 00000000 S Heap thread poo +u0_a191 8847 8839 1510312 57352 ffffffff 00000000 S Heap thread poo +u0_a191 8849 8839 1510312 57352 ffffffff 00000000 S Signal Catcher +u0_a191 8850 8839 1510312 57352 ffffffff 00000000 S JDWP +u0_a191 8851 8839 1510312 57352 ffffffff 00000000 S ReferenceQueueD +u0_a191 8852 8839 1510312 57352 ffffffff 00000000 S FinalizerDaemon +u0_a191 8853 8839 1510312 57352 ffffffff 00000000 S FinalizerWatchd +u0_a191 8854 8839 1510312 57352 ffffffff 00000000 S HeapTrimmerDaem +u0_a191 8855 8839 1510312 57352 ffffffff 00000000 S GCDaemon +u0_a191 8856 8839 1510312 57352 ffffffff 00000000 S Binder_1 +u0_a191 8857 8839 1510312 57352 ffffffff 00000000 S Binder_2 +u0_a191 8867 8839 1510312 57352 ffffffff 00000000 S local_job_dispa +u0_a191 8869 8839 1510312 57352 ffffffff 00000000 S remote_job_disp +u0_a191 8887 8839 1510312 57352 ffffffff 00000000 S Upload Http Rec +u0_a191 8890 8839 1510312 57352 ffffffff 00000000 S Connection Cont +u0_a191 8963 8839 1510312 57352 ffffffff 00000000 S Smack Packet Re +root 11634 2 0 0 ffffffff 00000000 S kworker/u:0 +root 11779 2 0 0 ffffffff 00000000 S kworker/0:3H +root 11928 2 0 0 ffffffff 00000000 S kworker/0:1 +root 12431 2 0 0 ffffffff 00000000 S kworker/u:2 +u0_a85 12971 205 1595348 59000 ffffffff 00000000 S com.life360.android.safetymapd:service +u0_a85 12977 12971 1595348 59000 ffffffff 00000000 S Heap thread poo +u0_a85 12978 12971 1595348 59000 ffffffff 00000000 S Heap thread poo +u0_a85 12979 12971 1595348 59000 ffffffff 00000000 S Heap thread poo +u0_a85 12980 12971 1595348 59000 ffffffff 00000000 S Signal Catcher +u0_a85 12981 12971 1595348 59000 ffffffff 00000000 S JDWP +u0_a85 12982 12971 1595348 59000 ffffffff 00000000 S ReferenceQueueD +u0_a85 12983 12971 1595348 59000 ffffffff 00000000 S FinalizerDaemon +u0_a85 12984 12971 1595348 59000 ffffffff 00000000 S FinalizerWatchd +u0_a85 12985 12971 1595348 59000 ffffffff 00000000 S HeapTrimmerDaem +u0_a85 12986 12971 1595348 59000 ffffffff 00000000 S GCDaemon +u0_a85 12987 12971 1595348 59000 ffffffff 00000000 S Binder_1 +u0_a85 12988 12971 1595348 59000 ffffffff 00000000 S Binder_2 +u0_a85 13099 12971 1595348 59000 ffffffff 00000000 S WifiManager +u0_a106 13071 205 1523392 47680 ffffffff 00000000 S com.xianguo.tingguo +u0_a106 13075 13071 1523392 47680 ffffffff 00000000 S Heap thread poo +u0_a106 13076 13071 1523392 47680 ffffffff 00000000 S Heap thread poo +u0_a106 13077 13071 1523392 47680 ffffffff 00000000 S Heap thread poo +u0_a106 13080 13071 1523392 47680 ffffffff 00000000 S Signal Catcher +u0_a106 13081 13071 1523392 47680 ffffffff 00000000 S JDWP +u0_a106 13082 13071 1523392 47680 ffffffff 00000000 S ReferenceQueueD +u0_a106 13083 13071 1523392 47680 ffffffff 00000000 S FinalizerDaemon +u0_a106 13084 13071 1523392 47680 ffffffff 00000000 S FinalizerWatchd +u0_a106 13085 13071 1523392 47680 ffffffff 00000000 S HeapTrimmerDaem +u0_a106 13086 13071 1523392 47680 ffffffff 00000000 S GCDaemon +u0_a106 13087 13071 1523392 47680 ffffffff 00000000 S Binder_1 +u0_a106 13088 13071 1523392 47680 ffffffff 00000000 S Binder_2 +u0_a106 13090 13071 1523392 47680 ffffffff 00000000 S SoundPool +u0_a106 13091 13071 1523392 47680 ffffffff 00000000 S SoundPoolThread +u0_a106 13276 13071 1523392 47680 ffffffff 00000000 S WifiManager +u0_a65 13345 205 1526244 52680 ffffffff 00000000 S com.google.android.apps.photos +u0_a65 13351 13345 1526244 52680 ffffffff 00000000 S Heap thread poo +u0_a65 13352 13345 1526244 52680 ffffffff 00000000 S Heap thread poo +u0_a65 13353 13345 1526244 52680 ffffffff 00000000 S Heap thread poo +u0_a65 13354 13345 1526244 52680 ffffffff 00000000 S Signal Catcher +u0_a65 13355 13345 1526244 52680 ffffffff 00000000 S JDWP +u0_a65 13356 13345 1526244 52680 ffffffff 00000000 S ReferenceQueueD +u0_a65 13357 13345 1526244 52680 ffffffff 00000000 S FinalizerDaemon +u0_a65 13358 13345 1526244 52680 ffffffff 00000000 S FinalizerWatchd +u0_a65 13359 13345 1526244 52680 ffffffff 00000000 S HeapTrimmerDaem +u0_a65 13360 13345 1526244 52680 ffffffff 00000000 S GCDaemon +u0_a65 13361 13345 1526244 52680 ffffffff 00000000 S Binder_1 +u0_a65 13362 13345 1526244 52680 ffffffff 00000000 S Binder_2 +u0_a65 13783 13345 1526244 52680 ffffffff 00000000 S pool-1-thread-1 +u0_a65 13796 13345 1526244 52680 ffffffff 00000000 S rotating_file-t +u0_a65 13904 13345 1526244 52680 ffffffff 00000000 S Binder_3 +u0_a67 13491 205 1567688 56576 ffffffff 00000000 S com.google.android.apps.plus +u0_a67 13493 13491 1567688 56576 ffffffff 00000000 S Heap thread poo +u0_a67 13494 13491 1567688 56576 ffffffff 00000000 S Heap thread poo +u0_a67 13495 13491 1567688 56576 ffffffff 00000000 S Heap thread poo +u0_a67 13497 13491 1567688 56576 ffffffff 00000000 S Signal Catcher +u0_a67 13499 13491 1567688 56576 ffffffff 00000000 S JDWP +u0_a67 13502 13491 1567688 56576 ffffffff 00000000 S ReferenceQueueD +u0_a67 13503 13491 1567688 56576 ffffffff 00000000 S FinalizerDaemon +u0_a67 13504 13491 1567688 56576 ffffffff 00000000 S FinalizerWatchd +u0_a67 13505 13491 1567688 56576 ffffffff 00000000 S HeapTrimmerDaem +u0_a67 13506 13491 1567688 56576 ffffffff 00000000 S GCDaemon +u0_a67 13507 13491 1567688 56576 ffffffff 00000000 S Binder_1 +u0_a67 13508 13491 1567688 56576 ffffffff 00000000 S Binder_2 +u0_a67 13512 13491 1567688 56576 ffffffff 00000000 S picasa-photo-pr +u0_a67 13528 13491 1567688 56576 ffffffff 00000000 S iu-sync-manager +u0_a67 13538 13491 1567688 56576 ffffffff 00000000 S pool-2-thread-1 +u0_a67 13881 13491 1567688 56576 ffffffff 00000000 S Gservices +u0_a4 13516 205 1503264 48612 ffffffff 00000000 S android.process.acore +u0_a4 13520 13516 1503264 48612 ffffffff 00000000 S Heap thread poo +u0_a4 13521 13516 1503264 48612 ffffffff 00000000 S Heap thread poo +u0_a4 13522 13516 1503264 48612 ffffffff 00000000 S Heap thread poo +u0_a4 13525 13516 1503264 48612 ffffffff 00000000 S Signal Catcher +u0_a4 13526 13516 1503264 48612 ffffffff 00000000 S JDWP +u0_a4 13527 13516 1503264 48612 ffffffff 00000000 S ReferenceQueueD +u0_a4 13529 13516 1503264 48612 ffffffff 00000000 S FinalizerDaemon +u0_a4 13530 13516 1503264 48612 ffffffff 00000000 S FinalizerWatchd +u0_a4 13531 13516 1503264 48612 ffffffff 00000000 S HeapTrimmerDaem +u0_a4 13532 13516 1503264 48612 ffffffff 00000000 S GCDaemon +u0_a4 13533 13516 1503264 48612 ffffffff 00000000 S Binder_1 +u0_a4 13534 13516 1503264 48612 ffffffff 00000000 S Binder_2 +u0_a4 13536 13516 1503264 48612 ffffffff 00000000 S ContactsProvide +u0_a4 13537 13516 1503264 48612 ffffffff 00000000 S CallLogProvider +u0_a102 13613 205 1521420 45204 ffffffff 00000000 S com.sohu.inputmethod.sogou:classic +u0_a102 13616 13613 1521420 45204 ffffffff 00000000 S Heap thread poo +u0_a102 13617 13613 1521420 45204 ffffffff 00000000 S Heap thread poo +u0_a102 13618 13613 1521420 45204 ffffffff 00000000 S Heap thread poo +u0_a102 13620 13613 1521420 45204 ffffffff 00000000 S Signal Catcher +u0_a102 13623 13613 1521420 45204 ffffffff 00000000 S JDWP +u0_a102 13624 13613 1521420 45204 ffffffff 00000000 S ReferenceQueueD +u0_a102 13625 13613 1521420 45204 ffffffff 00000000 S FinalizerDaemon +u0_a102 13626 13613 1521420 45204 ffffffff 00000000 S FinalizerWatchd +u0_a102 13627 13613 1521420 45204 ffffffff 00000000 S HeapTrimmerDaem +u0_a102 13628 13613 1521420 45204 ffffffff 00000000 S GCDaemon +u0_a102 13629 13613 1521420 45204 ffffffff 00000000 S Binder_1 +u0_a102 13630 13613 1521420 45204 ffffffff 00000000 S Binder_2 +u0_a102 13635 13613 1521420 45204 ffffffff 00000000 S Thread-1443 +u0_a102 13636 13613 1521420 45204 ffffffff 00000000 S Thread-1444 +u0_a102 13637 13613 1521420 45204 ffffffff 00000000 S Thread-1445 +u0_a102 13638 13613 1521420 45204 ffffffff 00000000 S Thread-1446 +u0_a102 13639 13613 1521420 45204 ffffffff 00000000 S Thread-1447 +u0_a102 13641 13613 1521420 45204 ffffffff 00000000 S WifiManager +u0_a102 13905 13613 1521420 45204 ffffffff 00000000 S Binder_3 +u0_a102 13647 205 1514052 44264 ffffffff 00000000 S com.sohu.inputmethod.sogou +u0_a102 13651 13647 1514052 44264 ffffffff 00000000 S Heap thread poo +u0_a102 13652 13647 1514052 44264 ffffffff 00000000 S Heap thread poo +u0_a102 13653 13647 1514052 44264 ffffffff 00000000 S Heap thread poo +u0_a102 13656 13647 1514052 44264 ffffffff 00000000 S Signal Catcher +u0_a102 13657 13647 1514052 44264 ffffffff 00000000 S JDWP +u0_a102 13658 13647 1514052 44264 ffffffff 00000000 S ReferenceQueueD +u0_a102 13659 13647 1514052 44264 ffffffff 00000000 S FinalizerDaemon +u0_a102 13660 13647 1514052 44264 ffffffff 00000000 S FinalizerWatchd +u0_a102 13661 13647 1514052 44264 ffffffff 00000000 S HeapTrimmerDaem +u0_a102 13662 13647 1514052 44264 ffffffff 00000000 S GCDaemon +u0_a102 13663 13647 1514052 44264 ffffffff 00000000 S Binder_1 +u0_a102 13664 13647 1514052 44264 ffffffff 00000000 S Binder_2 +u0_a102 13671 205 1519416 43248 ffffffff 00000000 S sogou.mobile.explorer.hotwords +u0_a102 13677 13671 1519416 43248 ffffffff 00000000 S Heap thread poo +u0_a102 13678 13671 1519416 43248 ffffffff 00000000 S Heap thread poo +u0_a102 13679 13671 1519416 43248 ffffffff 00000000 S Heap thread poo +u0_a102 13680 13671 1519416 43248 ffffffff 00000000 S Signal Catcher +u0_a102 13681 13671 1519416 43248 ffffffff 00000000 S JDWP +u0_a102 13682 13671 1519416 43248 ffffffff 00000000 S ReferenceQueueD +u0_a102 13683 13671 1519416 43248 ffffffff 00000000 S FinalizerDaemon +u0_a102 13684 13671 1519416 43248 ffffffff 00000000 S FinalizerWatchd +u0_a102 13685 13671 1519416 43248 ffffffff 00000000 S HeapTrimmerDaem +u0_a102 13686 13671 1519416 43248 ffffffff 00000000 S GCDaemon +u0_a102 13687 13671 1519416 43248 ffffffff 00000000 S Binder_1 +u0_a102 13688 13671 1519416 43248 ffffffff 00000000 S Binder_2 +u0_a102 13690 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-1 +u0_a102 13691 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-2 +u0_a102 13692 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-3 +u0_a102 13694 13671 1519416 43248 ffffffff 00000000 S Timer-0 +u0_a198 13695 205 1506040 40332 ffffffff 00000000 S org.chromium.chrome.shell +u0_a198 13701 13695 1506040 40332 ffffffff 00000000 S Heap thread poo +u0_a198 13702 13695 1506040 40332 ffffffff 00000000 S Heap thread poo +u0_a198 13703 13695 1506040 40332 ffffffff 00000000 S Heap thread poo +u0_a198 13704 13695 1506040 40332 ffffffff 00000000 S Signal Catcher +u0_a198 13705 13695 1506040 40332 ffffffff 00000000 S JDWP +u0_a198 13706 13695 1506040 40332 ffffffff 00000000 S ReferenceQueueD +u0_a198 13707 13695 1506040 40332 ffffffff 00000000 S FinalizerDaemon +u0_a198 13708 13695 1506040 40332 ffffffff 00000000 S FinalizerWatchd +u0_a198 13709 13695 1506040 40332 ffffffff 00000000 S HeapTrimmerDaem +u0_a198 13710 13695 1506040 40332 ffffffff 00000000 S GCDaemon +u0_a198 13711 13695 1506040 40332 ffffffff 00000000 S Binder_1 +u0_a198 13712 13695 1506040 40332 ffffffff 00000000 S Binder_2 +u0_a198 13713 13695 1506040 40332 ffffffff 00000000 S Binder_3 +u0_a200 13715 205 1511344 38748 ffffffff 00000000 S com.rolocule.motiontennis +u0_a200 13721 13715 1511344 38748 ffffffff 00000000 S Heap thread poo +u0_a200 13722 13715 1511344 38748 ffffffff 00000000 S Heap thread poo +u0_a200 13723 13715 1511344 38748 ffffffff 00000000 S Heap thread poo +u0_a200 13724 13715 1511344 38748 ffffffff 00000000 S Signal Catcher +u0_a200 13725 13715 1511344 38748 ffffffff 00000000 S JDWP +u0_a200 13731 13715 1511344 38748 ffffffff 00000000 S ReferenceQueueD +u0_a200 13732 13715 1511344 38748 ffffffff 00000000 S FinalizerDaemon +u0_a200 13733 13715 1511344 38748 ffffffff 00000000 S FinalizerWatchd +u0_a200 13734 13715 1511344 38748 ffffffff 00000000 S HeapTrimmerDaem +u0_a200 13735 13715 1511344 38748 ffffffff 00000000 S GCDaemon +u0_a200 13736 13715 1511344 38748 ffffffff 00000000 S Binder_1 +u0_a200 13737 13715 1511344 38748 ffffffff 00000000 S Binder_2 +u0_a175 13747 205 1510096 43460 ffffffff 00000000 S com.google.android.apps.chrome +u0_a175 13751 13747 1510096 43460 ffffffff 00000000 S Heap thread poo +u0_a175 13752 13747 1510096 43460 ffffffff 00000000 S Heap thread poo +u0_a175 13754 13747 1510096 43460 ffffffff 00000000 S Heap thread poo +u0_a175 13756 13747 1510096 43460 ffffffff 00000000 S Signal Catcher +u0_a175 13757 13747 1510096 43460 ffffffff 00000000 S JDWP +u0_a175 13758 13747 1510096 43460 ffffffff 00000000 S ReferenceQueueD +u0_a175 13759 13747 1510096 43460 ffffffff 00000000 S FinalizerDaemon +u0_a175 13760 13747 1510096 43460 ffffffff 00000000 S FinalizerWatchd +u0_a175 13761 13747 1510096 43460 ffffffff 00000000 S HeapTrimmerDaem +u0_a175 13762 13747 1510096 43460 ffffffff 00000000 S GCDaemon +u0_a175 13763 13747 1510096 43460 ffffffff 00000000 S Binder_1 +u0_a175 13764 13747 1510096 43460 ffffffff 00000000 S Binder_2 +u0_a85 13774 205 1594212 50972 ffffffff 00000000 S com.life360.android.safetymapd +u0_a85 13780 13774 1594212 50972 ffffffff 00000000 S Heap thread poo +u0_a85 13781 13774 1594212 50972 ffffffff 00000000 S Heap thread poo +u0_a85 13782 13774 1594212 50972 ffffffff 00000000 S Heap thread poo +u0_a85 13784 13774 1594212 50972 ffffffff 00000000 S Signal Catcher +u0_a85 13785 13774 1594212 50972 ffffffff 00000000 S JDWP +u0_a85 13786 13774 1594212 50972 ffffffff 00000000 S ReferenceQueueD +u0_a85 13787 13774 1594212 50972 ffffffff 00000000 S FinalizerDaemon +u0_a85 13788 13774 1594212 50972 ffffffff 00000000 S FinalizerWatchd +u0_a85 13789 13774 1594212 50972 ffffffff 00000000 S HeapTrimmerDaem +u0_a85 13790 13774 1594212 50972 ffffffff 00000000 S GCDaemon +u0_a85 13791 13774 1594212 50972 ffffffff 00000000 S Binder_1 +u0_a85 13792 13774 1594212 50972 ffffffff 00000000 S Binder_2 +u0_a16 13801 205 1538004 50644 ffffffff 00000000 S com.android.vending +u0_a16 13807 13801 1538004 50644 ffffffff 00000000 S Heap thread poo +u0_a16 13808 13801 1538004 50644 ffffffff 00000000 S Heap thread poo +u0_a16 13809 13801 1538004 50644 ffffffff 00000000 S Heap thread poo +u0_a16 13811 13801 1538004 50644 ffffffff 00000000 S Signal Catcher +u0_a16 13812 13801 1538004 50644 ffffffff 00000000 S JDWP +u0_a16 13813 13801 1538004 50644 ffffffff 00000000 S ReferenceQueueD +u0_a16 13814 13801 1538004 50644 ffffffff 00000000 S FinalizerDaemon +u0_a16 13815 13801 1538004 50644 ffffffff 00000000 S FinalizerWatchd +u0_a16 13816 13801 1538004 50644 ffffffff 00000000 S HeapTrimmerDaem +u0_a16 13817 13801 1538004 50644 ffffffff 00000000 S GCDaemon +u0_a16 13818 13801 1538004 50644 ffffffff 00000000 S Binder_1 +u0_a16 13819 13801 1538004 50644 ffffffff 00000000 S Binder_2 +u0_a16 13828 13801 1538004 50644 ffffffff 00000000 S Gservices +u0_a16 13833 13801 1538004 50644 ffffffff 00000000 S pool-1-thread-1 +u0_a16 13834 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@ +u0_a16 13837 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@ +u0_a16 13838 13801 1538004 50644 ffffffff 00000000 S Thread-1482 +u0_a16 13839 13801 1538004 50644 ffffffff 00000000 S Thread-1483 +u0_a16 13840 13801 1538004 50644 ffffffff 00000000 S Thread-1484 +u0_a16 13843 13801 1538004 50644 ffffffff 00000000 S download-manage +u0_a16 13844 13801 1538004 50644 ffffffff 00000000 S NetworkQualityQ +u0_a16 13845 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@ +u0_a16 13846 13801 1538004 50644 ffffffff 00000000 S Thread-1489 +u0_a16 13847 13801 1538004 50644 ffffffff 00000000 S Thread-1490 +u0_a16 13848 13801 1538004 50644 ffffffff 00000000 S Thread-1491 +u0_a16 13849 13801 1538004 50644 ffffffff 00000000 S Thread-1492 +u0_a16 13850 13801 1538004 50644 ffffffff 00000000 S Thread-1493 +u0_a16 13851 13801 1538004 50644 ffffffff 00000000 S PlayEventLogger +u0_a16 13852 13801 1538004 50644 ffffffff 00000000 S tentative-gc-ru +u0_a16 13862 13801 1538004 50644 ffffffff 00000000 S libraries-threa +u0_a16 13872 13801 1538004 50644 ffffffff 00000000 S AsyncTask #1 +u0_a16 13876 13801 1538004 50644 ffffffff 00000000 S AsyncTask #2 +u0_a16 13877 13801 1538004 50644 ffffffff 00000000 S AsyncTask #3 +u0_a16 13878 13801 1538004 50644 ffffffff 00000000 S PlayEventLogger +u0_a16 13880 13801 1538004 50644 ffffffff 00000000 S Thread-1501 +u0_a16 14407 13801 1538004 50644 ffffffff 00000000 S Binder_3 +u0_a8 13853 205 1573700 51720 ffffffff 00000000 S com.google.android.gms:car +u0_a8 13856 13853 1573700 51720 ffffffff 00000000 S Heap thread poo +u0_a8 13857 13853 1573700 51720 ffffffff 00000000 S Heap thread poo +u0_a8 13858 13853 1573700 51720 ffffffff 00000000 S Heap thread poo +u0_a8 13863 13853 1573700 51720 ffffffff 00000000 S Signal Catcher +u0_a8 13864 13853 1573700 51720 ffffffff 00000000 S JDWP +u0_a8 13865 13853 1573700 51720 ffffffff 00000000 S ReferenceQueueD +u0_a8 13866 13853 1573700 51720 ffffffff 00000000 S FinalizerDaemon +u0_a8 13867 13853 1573700 51720 ffffffff 00000000 S FinalizerWatchd +u0_a8 13868 13853 1573700 51720 ffffffff 00000000 S HeapTrimmerDaem +u0_a8 13869 13853 1573700 51720 ffffffff 00000000 S GCDaemon +u0_a8 13870 13853 1573700 51720 ffffffff 00000000 S Binder_1 +u0_a8 13871 13853 1573700 51720 ffffffff 00000000 S Binder_2 +u0_a8 13873 13853 1573700 51720 ffffffff 00000000 S Gservices +u0_a8 13913 13853 1573700 51720 ffffffff 00000000 S Binder_3 +u0_a8 13885 205 1572668 47460 ffffffff 00000000 S com.google.android.gms.wearable +u0_a8 13890 13885 1572668 47460 ffffffff 00000000 S Heap thread poo +u0_a8 13891 13885 1572668 47460 ffffffff 00000000 S Heap thread poo +u0_a8 13892 13885 1572668 47460 ffffffff 00000000 S Heap thread poo +u0_a8 13894 13885 1572668 47460 ffffffff 00000000 S Signal Catcher +u0_a8 13895 13885 1572668 47460 ffffffff 00000000 S JDWP +u0_a8 13896 13885 1572668 47460 ffffffff 00000000 S ReferenceQueueD +u0_a8 13897 13885 1572668 47460 ffffffff 00000000 S FinalizerDaemon +u0_a8 13898 13885 1572668 47460 ffffffff 00000000 S FinalizerWatchd +u0_a8 13899 13885 1572668 47460 ffffffff 00000000 S HeapTrimmerDaem +u0_a8 13900 13885 1572668 47460 ffffffff 00000000 S GCDaemon +u0_a8 13901 13885 1572668 47460 ffffffff 00000000 S Binder_1 +u0_a8 13902 13885 1572668 47460 ffffffff 00000000 S Binder_2 +u0_a8 13903 13885 1572668 47460 ffffffff 00000000 S Gservices +root 14061 2 0 0 ffffffff 00000000 S kworker/u:3 +root 14136 2 0 0 ffffffff 00000000 S kworker/0:0H +u0_a101 14356 205 1503136 44308 ffffffff 00000000 S com.google.android.apps.gcs +u0_a101 14362 14356 1503136 44308 ffffffff 00000000 S Heap thread poo +u0_a101 14363 14356 1503136 44308 ffffffff 00000000 S Heap thread poo +u0_a101 14364 14356 1503136 44308 ffffffff 00000000 S Heap thread poo +u0_a101 14365 14356 1503136 44308 ffffffff 00000000 S Signal Catcher +u0_a101 14366 14356 1503136 44308 ffffffff 00000000 S JDWP +u0_a101 14367 14356 1503136 44308 ffffffff 00000000 S ReferenceQueueD +u0_a101 14368 14356 1503136 44308 ffffffff 00000000 S FinalizerDaemon +u0_a101 14369 14356 1503136 44308 ffffffff 00000000 S FinalizerWatchd +u0_a101 14370 14356 1503136 44308 ffffffff 00000000 S HeapTrimmerDaem +u0_a101 14371 14356 1503136 44308 ffffffff 00000000 S GCDaemon +u0_a101 14372 14356 1503136 44308 ffffffff 00000000 S Binder_1 +u0_a101 14373 14356 1503136 44308 ffffffff 00000000 S Binder_2 +u0_a101 14375 14356 1503136 44308 ffffffff 00000000 S Gservices +u0_a101 14376 14356 1503136 44308 ffffffff 00000000 S RefQueueWorker@ +u0_a101 14377 14356 1503136 44308 ffffffff 00000000 S Thread-1495 +u0_a101 14378 14356 1503136 44308 ffffffff 00000000 S Thread-1496 +u0_a101 14379 14356 1503136 44308 ffffffff 00000000 S Thread-1497 +u0_a101 14380 14356 1503136 44308 ffffffff 00000000 S Thread-1498 +u0_a101 14381 14356 1503136 44308 ffffffff 00000000 S Thread-1499 +shell 14444 209 9316 612 c01a863c b6eeee44 S /system/bin/sh +shell 14448 14444 10672 768 00000000 b6ef0da8 R ps diff --git a/test_data/atrace_extracted_tgids b/catapult/systrace/systrace/test_data/atrace_extracted_tgids index 1084fba6..1084fba6 100644 --- a/test_data/atrace_extracted_tgids +++ b/catapult/systrace/systrace/test_data/atrace_extracted_tgids diff --git a/test_data/atrace_extracted_threads b/catapult/systrace/systrace/test_data/atrace_extracted_threads index bff5d1b7..bff5d1b7 100644 --- a/test_data/atrace_extracted_threads +++ b/catapult/systrace/systrace/test_data/atrace_extracted_threads diff --git a/test_data/atrace_fixed_tgids b/catapult/systrace/systrace/test_data/atrace_fixed_tgids index 92456d53..92456d53 100644 --- a/test_data/atrace_fixed_tgids +++ b/catapult/systrace/systrace/test_data/atrace_fixed_tgids diff --git a/test_data/atrace_missing_tgids b/catapult/systrace/systrace/test_data/atrace_missing_tgids index c662482d..c662482d 100644 --- a/test_data/atrace_missing_tgids +++ b/catapult/systrace/systrace/test_data/atrace_missing_tgids diff --git a/test_data/atrace_procfs_dump b/catapult/systrace/systrace/test_data/atrace_procfs_dump index f1f0c760..f1f0c760 100644 --- a/test_data/atrace_procfs_dump +++ b/catapult/systrace/systrace/test_data/atrace_procfs_dump diff --git a/test_data/atrace_ps_dump b/catapult/systrace/systrace/test_data/atrace_ps_dump index ad8fd74b..497918f1 100644 --- a/test_data/atrace_ps_dump +++ b/catapult/systrace/systrace/test_data/atrace_ps_dump @@ -1,1532 +1,1532 @@ -USER PID PPID VSIZE RSS WCHAN PC NAME
-root 1 0 8784 712 ffffffff 00000000 S /init
-root 2 0 0 0 ffffffff 00000000 S kthreadd
-root 3 2 0 0 ffffffff 00000000 S ksoftirqd/0
-root 7 2 0 0 ffffffff 00000000 D kworker/u:0H
-root 8 2 0 0 ffffffff 00000000 S migration/0
-root 13 2 0 0 ffffffff 00000000 S khelper
-root 14 2 0 0 ffffffff 00000000 S netns
-root 17 2 0 0 ffffffff 00000000 S kworker/0:1H
-root 18 2 0 0 ffffffff 00000000 S modem_notifier
-root 19 2 0 0 ffffffff 00000000 S smd_channel_clo
-root 20 2 0 0 ffffffff 00000000 S smsm_cb_wq
-root 21 2 0 0 ffffffff 00000000 S kworker/u:1
-root 22 2 0 0 ffffffff 00000000 S rpm-smd
-root 23 2 0 0 ffffffff 00000000 S kworker/u:1H
-root 24 2 0 0 ffffffff 00000000 S irq/317-earjack
-root 25 2 0 0 ffffffff 00000000 S sync_supers
-root 26 2 0 0 ffffffff 00000000 S bdi-default
-root 27 2 0 0 ffffffff 00000000 S kblockd
-root 28 2 0 0 ffffffff 00000000 S vmalloc
-root 29 2 0 0 ffffffff 00000000 S khubd
-root 30 2 0 0 ffffffff 00000000 S irq/102-msm_iom
-root 31 2 0 0 ffffffff 00000000 S irq/102-msm_iom
-root 32 2 0 0 ffffffff 00000000 S irq/102-msm_iom
-root 33 2 0 0 ffffffff 00000000 S irq/79-msm_iomm
-root 34 2 0 0 ffffffff 00000000 S irq/78-msm_iomm
-root 35 2 0 0 ffffffff 00000000 S irq/78-msm_iomm
-root 36 2 0 0 ffffffff 00000000 S irq/74-msm_iomm
-root 37 2 0 0 ffffffff 00000000 S irq/75-msm_iomm
-root 38 2 0 0 ffffffff 00000000 S irq/75-msm_iomm
-root 39 2 0 0 ffffffff 00000000 S irq/75-msm_iomm
-root 40 2 0 0 ffffffff 00000000 S irq/75-msm_iomm
-root 41 2 0 0 ffffffff 00000000 S irq/273-msm_iom
-root 42 2 0 0 ffffffff 00000000 S irq/273-msm_iom
-root 43 2 0 0 ffffffff 00000000 S irq/97-msm_iomm
-root 44 2 0 0 ffffffff 00000000 S irq/97-msm_iomm
-root 45 2 0 0 ffffffff 00000000 S irq/97-msm_iomm
-root 46 2 0 0 ffffffff 00000000 S l2cap
-root 47 2 0 0 ffffffff 00000000 S a2mp
-root 48 2 0 0 ffffffff 00000000 S cfg80211
-root 49 2 0 0 ffffffff 00000000 S qmi
-root 50 2 0 0 ffffffff 00000000 S nmea
-root 51 2 0 0 ffffffff 00000000 S msm_ipc_router
-root 52 2 0 0 ffffffff 00000000 S apr_driver
-root 54 2 0 0 ffffffff 00000000 S kswapd0
-root 55 2 0 0 ffffffff 00000000 S fsnotify_mark
-root 56 2 0 0 ffffffff 00000000 S cifsiod
-root 57 2 0 0 ffffffff 00000000 S crypto
-root 75 2 0 0 ffffffff 00000000 S ad_calc_wq
-root 76 2 0 0 ffffffff 00000000 S hdmi_tx_workq
-root 77 2 0 0 ffffffff 00000000 S anx7808_work
-root 78 2 0 0 ffffffff 00000000 S k_hsuart
-root 79 2 0 0 ffffffff 00000000 S diag_wq
-root 80 2 0 0 ffffffff 00000000 S diag_cntl_wq
-root 81 2 0 0 ffffffff 00000000 S diag_dci_wq
-root 82 2 0 0 ffffffff 00000000 S kgsl-3d0
-root 84 2 0 0 ffffffff 00000000 S f9966000.spi
-root 88 2 0 0 ffffffff 00000000 S usbnet
-root 89 2 0 0 ffffffff 00000000 S irq/329-anx7808
-root 90 2 0 0 ffffffff 00000000 S k_rmnet_mux_wor
-root 91 2 0 0 ffffffff 00000000 S f_mtp
-root 92 2 0 0 ffffffff 00000000 S file-storage
-root 93 2 0 0 ffffffff 00000000 S uether
-root 94 2 0 0 ffffffff 00000000 S synaptics_wq
-root 95 2 0 0 ffffffff 00000000 S irq/362-s3350
-root 96 2 0 0 ffffffff 00000000 S kworker/0:2
-root 97 2 0 0 ffffffff 00000000 S msm_vidc_worker
-root 98 2 0 0 ffffffff 00000000 S msm_vidc_worker
-root 99 2 0 0 ffffffff 00000000 S msm_cpp_workque
-root 100 2 0 0 ffffffff 00000000 S irq/350-bq51013
-root 102 2 0 0 ffffffff 00000000 S dm_bufio_cache
-root 103 2 0 0 ffffffff 00000000 D dbs_sync/0
-root 104 2 0 0 ffffffff 00000000 D dbs_sync/1
-root 105 2 0 0 ffffffff 00000000 D dbs_sync/2
-root 106 2 0 0 ffffffff 00000000 D dbs_sync/3
-root 107 2 0 0 ffffffff 00000000 S cfinteractive
-root 108 2 0 0 ffffffff 00000000 S irq/170-msm_sdc
-root 109 2 0 0 ffffffff 00000000 S binder
-root 110 2 0 0 ffffffff 00000000 S usb_bam_wq
-root 111 2 0 0 ffffffff 00000000 S krfcommd
-root 112 2 0 0 ffffffff 00000000 S bam_dmux_rx
-root 113 2 0 0 ffffffff 00000000 S bam_dmux_tx
-root 114 2 0 0 ffffffff 00000000 S rq_stats
-root 115 2 0 0 ffffffff 00000000 S deferwq
-root 117 2 0 0 ffffffff 00000000 S irq/361-MAX1704
-root 119 2 0 0 ffffffff 00000000 S mmcqd/1
-root 120 2 0 0 ffffffff 00000000 S mmcqd/1rpmb
-root 121 2 0 0 ffffffff 00000000 S wl_event_handle
-root 122 2 0 0 ffffffff 00000000 S dhd_watchdog_th
-root 123 2 0 0 ffffffff 00000000 S dhd_dpc
-root 124 2 0 0 ffffffff 00000000 S dhd_rxf
-root 125 2 0 0 ffffffff 00000000 S dhd_sysioc
-root 126 2 0 0 ffffffff 00000000 S vibrator
-root 127 2 0 0 ffffffff 00000000 S max1462x
-root 128 2 0 0 ffffffff 00000000 S irq/310-maxim_m
-root 129 2 0 0 ffffffff 00000000 S irq/311-maxim_m
-root 130 1 8780 576 ffffffff 00000000 S /sbin/ueventd
-root 132 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p25
-root 133 2 0 0 ffffffff 00000000 S ext4-dio-unwrit
-root 136 2 0 0 ffffffff 00000000 S flush-179:0
-root 138 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p28
-root 139 2 0 0 ffffffff 00000000 S ext4-dio-unwrit
-root 143 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p27
-root 144 2 0 0 ffffffff 00000000 S ext4-dio-unwrit
-root 145 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p16
-root 146 2 0 0 ffffffff 00000000 S ext4-dio-unwrit
-logd 169 1 18632 2740 ffffffff 00000000 S /system/bin/logd
-logd 216 169 18632 2740 ffffffff 00000000 S logd.reader
-logd 217 169 18632 2740 ffffffff 00000000 S logd.writer
-logd 218 169 18632 2740 ffffffff 00000000 S logd
-logd 244 169 18632 2740 ffffffff 00000000 S logd.auditd
-root 170 1 9832 304 ffffffff 00000000 S /sbin/healthd
-root 171 1 10620 1240 ffffffff 00000000 S /system/bin/lmkd
-system 172 1 9452 676 ffffffff 00000000 S /system/bin/servicemanager
-root 173 1 18028 1652 ffffffff 00000000 S /system/bin/vold
-root 223 173 18028 1652 ffffffff 00000000 S vold
-root 226 173 18028 1652 ffffffff 00000000 S vold
-root 174 2 0 0 ffffffff 00000000 S IPCRTR
-root 175 2 0 0 ffffffff 00000000 S sb-1
-root 177 2 0 0 ffffffff 00000000 S ipc_rtr_q6_ipcr
-root 179 2 0 0 ffffffff 00000000 S ngd_msm_ctrl_ng
-system 180 1 146792 9724 ffffffff 00000000 S /system/bin/surfaceflinger
-system 240 180 146792 9724 ffffffff 00000000 S Binder_1
-system 242 180 146792 9724 ffffffff 00000000 S DispSync
-system 243 180 146792 9724 ffffffff 00000000 S Binder_2
-system 361 180 146792 9724 ffffffff 00000000 S hwcUeventThread
-system 362 180 146792 9724 ffffffff 00000000 S hwcVsyncThread
-system 396 180 146792 9724 ffffffff 00000000 S GL updater
-system 397 180 146792 9724 ffffffff 00000000 S surfaceflinger
-system 398 180 146792 9724 ffffffff 00000000 S EventThread
-system 399 180 146792 9724 ffffffff 00000000 S surfaceflinger
-system 400 180 146792 9724 ffffffff 00000000 S EventThread
-system 401 180 146792 9724 ffffffff 00000000 S EventControl
-system 575 180 146792 9724 ffffffff 00000000 S Binder_3
-system 1501 180 146792 9724 ffffffff 00000000 S Binder_4
-system 5633 180 146792 9724 ffffffff 00000000 S Binder_5
-nobody 181 1 19792 1112 ffffffff 00000000 S /system/bin/rmt_storage
-nobody 571 181 19792 1112 ffffffff 00000000 S rmt_storage
-nobody 572 181 19792 1112 ffffffff 00000000 S rmt_storage
-nobody 573 181 19792 1112 ffffffff 00000000 S rmt_storage
-nobody 574 181 19792 1112 ffffffff 00000000 S rmt_storage
-system 182 1 11100 992 ffffffff 00000000 S /system/bin/qseecomd
-root 183 2 0 0 ffffffff 00000000 S msm_slim_qmi_cl
-root 184 2 0 0 ffffffff 00000000 S msm_qmi_rtx_q
-shell 185 1 9316 716 c047451c b6f58da8 S /system/bin/sh
-root 187 1 9200 368 ffffffff 00000000 S /system/bin/subsystem_ramdump
-root 188 1 22828 1404 ffffffff 00000000 S /system/bin/netd
-root 548 188 22828 1404 ffffffff 00000000 S netd
-root 549 188 22828 1404 ffffffff 00000000 S netd
-root 550 188 22828 1404 ffffffff 00000000 S netd
-root 551 188 22828 1404 ffffffff 00000000 S netd
-root 552 188 22828 1404 ffffffff 00000000 S netd
-root 553 188 22828 1404 ffffffff 00000000 S netd
-root 554 188 22828 1404 ffffffff 00000000 S netd
-root 555 188 22828 1404 ffffffff 00000000 S netd
-root 189 1 10048 848 ffffffff 00000000 S /system/bin/debuggerd
-radio 191 1 35988 4712 ffffffff 00000000 S /system/bin/rild
-radio 335 191 35988 4712 ffffffff 00000000 S rild
-radio 343 191 35988 4712 ffffffff 00000000 S rild
-radio 346 191 35988 4712 ffffffff 00000000 S rild
-radio 584 191 35988 4712 ffffffff 00000000 S rild
-radio 585 191 35988 4712 ffffffff 00000000 S rild
-radio 587 191 35988 4712 ffffffff 00000000 S rild
-radio 588 191 35988 4712 ffffffff 00000000 S rild
-radio 589 191 35988 4712 ffffffff 00000000 S rild
-radio 591 191 35988 4712 ffffffff 00000000 S rild
-radio 592 191 35988 4712 ffffffff 00000000 S rild
-radio 593 191 35988 4712 ffffffff 00000000 S rild
-radio 594 191 35988 4712 ffffffff 00000000 S rild
-drm 192 1 26084 3832 ffffffff 00000000 S /system/bin/drmserver
-drm 419 192 26084 3832 ffffffff 00000000 S Binder_1
-media 194 1 106516 8584 ffffffff 00000000 S /system/bin/mediaserver
-media 755 194 106516 8584 ffffffff 00000000 S ApmTone
-media 756 194 106516 8584 ffffffff 00000000 S ApmAudio
-media 757 194 106516 8584 ffffffff 00000000 S ApmOutput
-media 758 194 106516 8584 ffffffff 00000000 S mediaserver
-media 759 194 106516 8584 ffffffff 00000000 S FastMixer
-media 871 194 106516 8584 ffffffff 00000000 S AudioOut_2
-media 872 194 106516 8584 ffffffff 00000000 S AudioOut_4
-media 873 194 106516 8584 ffffffff 00000000 S FastMixer
-media 874 194 106516 8584 ffffffff 00000000 S AudioOut_6
-media 878 194 106516 8584 ffffffff 00000000 S Binder_1
-media 879 194 106516 8584 ffffffff 00000000 S Binder_2
-media 1133 194 106516 8584 ffffffff 00000000 S Binder_3
-install 195 1 9408 704 ffffffff 00000000 S /system/bin/installd
-keystore 197 1 12536 1848 ffffffff 00000000 S /system/bin/keystore
-radio 198 1 18856 636 ffffffff 00000000 S /system/bin/bridgemgrd
-radio 288 198 18856 636 ffffffff 00000000 S bridgemgrd
-radio 602 198 18856 636 ffffffff 00000000 S bridgemgrd
-radio 603 198 18856 636 ffffffff 00000000 S bridgemgrd
-radio 841 198 18856 636 ffffffff 00000000 S bridgemgrd
-radio 199 1 24060 732 ffffffff 00000000 S /system/bin/qmuxd
-radio 293 199 24060 732 ffffffff 00000000 S qmuxd
-radio 576 199 24060 732 ffffffff 00000000 S qmuxd
-radio 577 199 24060 732 ffffffff 00000000 S qmuxd
-radio 578 199 24060 732 ffffffff 00000000 S qmuxd
-radio 579 199 24060 732 ffffffff 00000000 S qmuxd
-radio 580 199 24060 732 ffffffff 00000000 S qmuxd
-radio 581 199 24060 732 ffffffff 00000000 S qmuxd
-radio 582 199 24060 732 ffffffff 00000000 S qmuxd
-radio 583 199 24060 732 ffffffff 00000000 S qmuxd
-radio 200 1 20036 996 ffffffff 00000000 S /system/bin/netmgrd
-radio 289 200 20036 996 ffffffff 00000000 S netmgrd
-radio 736 200 20036 996 ffffffff 00000000 S netmgrd
-radio 746 200 20036 996 ffffffff 00000000 S netmgrd
-radio 747 200 20036 996 ffffffff 00000000 S netmgrd
-radio 748 200 20036 996 ffffffff 00000000 S netmgrd
-nobody 201 1 59912 1748 ffffffff 00000000 S /system/bin/sensors.qcom
-nobody 290 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 292 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 560 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 563 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 564 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 605 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 614 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 621 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 622 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 623 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 624 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 625 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 626 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 627 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 628 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 629 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 633 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 643 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 650 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 651 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 760 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 763 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 784 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 790 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 792 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 794 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 796 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 798 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 800 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 802 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 804 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 806 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 808 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 810 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 812 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 814 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 816 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 818 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 820 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 822 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 824 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 1593 201 59912 1748 ffffffff 00000000 S sensors.qcom
-nobody 1600 201 59912 1748 ffffffff 00000000 S sensors.qcom
-root 204 1 58772 1524 ffffffff 00000000 S /system/bin/thermal-engine-hh
-root 247 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 250 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 252 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 253 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 254 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 255 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 257 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 258 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 259 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 260 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 261 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 262 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 263 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 264 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 265 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 266 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 267 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 268 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 269 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 270 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 272 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 273 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 275 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 276 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 277 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 278 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 280 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 281 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 282 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 283 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 284 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 286 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 287 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 295 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 297 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 299 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 300 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 301 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 559 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 596 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 600 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 601 204 58772 1524 ffffffff 00000000 S thermal-engine-
-root 205 1 1482684 53160 ffffffff 00000000 S zygote
-root 14357 205 1482684 53160 ffffffff 00000000 S ReferenceQueueD
-root 14358 205 1482684 53160 ffffffff 00000000 S FinalizerDaemon
-root 14359 205 1482684 53160 ffffffff 00000000 S FinalizerWatchd
-root 14360 205 1482684 53160 ffffffff 00000000 S HeapTrimmerDaem
-root 14361 205 1482684 53160 ffffffff 00000000 S GCDaemon
-media_rw 206 1 15400 5240 ffffffff 00000000 S /system/bin/sdcard
-media_rw 227 206 15400 5240 ffffffff 00000000 S sdcard
-media_rw 228 206 15400 5240 ffffffff 00000000 S sdcard
-camera 207 1 16300 4440 ffffffff 00000000 S /system/bin/mm-qcamera-daemon
-system 208 1 20500 1236 ffffffff 00000000 S /system/bin/time_daemon
-system 308 208 20500 1236 ffffffff 00000000 S time_daemon
-system 561 208 20500 1236 ffffffff 00000000 S time_daemon
-system 597 208 20500 1236 ffffffff 00000000 S time_daemon
-system 598 208 20500 1236 ffffffff 00000000 S time_daemon
-system 599 208 20500 1236 ffffffff 00000000 S time_daemon
-shell 209 1 16984 312 ffffffff 00000000 S /sbin/adbd
-shell 210 209 16984 312 ffffffff 00000000 S adbd
-shell 211 209 16984 312 ffffffff 00000000 S adbd
-shell 212 209 16984 308 ffffffff 00000000 S adbd
-shell 14445 209 16984 308 ffffffff 00000000 S adbd
-root 214 2 0 0 ffffffff 00000000 S irq/288-wcd9xxx
-root 219 2 0 0 ffffffff 00000000 S kauditd
-root 311 2 0 0 ffffffff 00000000 D msm_thermal:hot
-root 312 2 0 0 ffffffff 00000000 D msm_thermal:fre
-system 348 182 15288 564 ffffffff 00000000 S /system/bin/qseecomd
-system 349 348 15288 564 ffffffff 00000000 S qseecomd
-system 351 348 15288 564 ffffffff 00000000 S qseecomd
-system 386 348 15288 564 ffffffff 00000000 S qseecomd
-system 387 348 15288 564 ffffffff 00000000 S qseecomd
-root 360 2 0 0 ffffffff 00000000 D mdss_fb0
-root 557 2 0 0 ffffffff 00000000 S kworker/0:2H
-root 558 2 0 0 ffffffff 00000000 S IPCRTR
-root 562 2 0 0 ffffffff 00000000 S ipc_rtr_smd_ipc
-system 764 205 1701620 103200 ffffffff 00000000 S system_server
-system 767 764 1701620 103200 ffffffff 00000000 S Heap thread poo
-system 768 764 1701620 103200 ffffffff 00000000 S Heap thread poo
-system 770 764 1701620 103200 ffffffff 00000000 S Heap thread poo
-system 773 764 1701620 103200 ffffffff 00000000 S Signal Catcher
-system 774 764 1701620 103200 ffffffff 00000000 S JDWP
-system 775 764 1701620 103200 ffffffff 00000000 S ReferenceQueueD
-system 776 764 1701620 103200 ffffffff 00000000 S FinalizerDaemon
-system 777 764 1701620 103200 ffffffff 00000000 S FinalizerWatchd
-system 778 764 1701620 103200 ffffffff 00000000 S HeapTrimmerDaem
-system 779 764 1701620 103200 ffffffff 00000000 S GCDaemon
-system 780 764 1701620 103200 ffffffff 00000000 S Binder_1
-system 781 764 1701620 103200 ffffffff 00000000 S Binder_2
-system 782 764 1701620 103200 ffffffff 00000000 S system_server
-system 783 764 1701620 103200 ffffffff 00000000 S system_server
-system 785 764 1701620 103200 ffffffff 00000000 S system_server
-system 786 764 1701620 103200 ffffffff 00000000 S system_server
-system 788 764 1701620 103200 ffffffff 00000000 S system_server
-system 789 764 1701620 103200 ffffffff 00000000 S system_server
-system 791 764 1701620 103200 ffffffff 00000000 S system_server
-system 793 764 1701620 103200 ffffffff 00000000 S system_server
-system 795 764 1701620 103200 ffffffff 00000000 S system_server
-system 797 764 1701620 103200 ffffffff 00000000 S system_server
-system 799 764 1701620 103200 ffffffff 00000000 S system_server
-system 801 764 1701620 103200 ffffffff 00000000 S system_server
-system 803 764 1701620 103200 ffffffff 00000000 S system_server
-system 805 764 1701620 103200 ffffffff 00000000 S system_server
-system 807 764 1701620 103200 ffffffff 00000000 S system_server
-system 809 764 1701620 103200 ffffffff 00000000 S system_server
-system 811 764 1701620 103200 ffffffff 00000000 S system_server
-system 813 764 1701620 103200 ffffffff 00000000 S system_server
-system 815 764 1701620 103200 ffffffff 00000000 S system_server
-system 817 764 1701620 103200 ffffffff 00000000 S system_server
-system 819 764 1701620 103200 ffffffff 00000000 S system_server
-system 821 764 1701620 103200 ffffffff 00000000 S system_server
-system 823 764 1701620 103200 ffffffff 00000000 S system_server
-system 826 764 1701620 103200 ffffffff 00000000 S SensorEventAckR
-system 827 764 1701620 103200 ffffffff 00000000 S SensorService
-system 828 764 1701620 103200 ffffffff 00000000 S android.bg
-system 829 764 1701620 103200 ffffffff 00000000 S ActivityManager
-system 830 764 1701620 103200 ffffffff 00000000 S FileObserver
-system 831 764 1701620 103200 ffffffff 00000000 S android.fg
-system 832 764 1701620 103200 ffffffff 00000000 S android.ui
-system 833 764 1701620 103200 ffffffff 00000000 S android.io
-system 834 764 1701620 103200 ffffffff 00000000 S android.display
-system 835 764 1701620 103200 ffffffff 00000000 S CpuTracker
-system 836 764 1701620 103200 ffffffff 00000000 S PowerManagerSer
-system 837 764 1701620 103200 ffffffff 00000000 S system_server
-system 838 764 1701620 103200 ffffffff 00000000 S system_server
-system 839 764 1701620 103200 ffffffff 00000000 S BatteryStats_wa
-system 840 764 1701620 103200 ffffffff 00000000 S PackageManager
-system 842 764 1701620 103200 ffffffff 00000000 S PackageInstalle
-system 844 764 1701620 103200 ffffffff 00000000 S AlarmManager
-system 845 764 1701620 103200 ffffffff 00000000 S UEventObserver
-system 853 764 1701620 103200 ffffffff 00000000 S InputDispatcher
-system 854 764 1701620 103200 ffffffff 00000000 S InputReader
-system 857 764 1701620 103200 ffffffff 00000000 S MountService
-system 858 764 1701620 103200 ffffffff 00000000 S VoldConnector
-system 860 764 1701620 103200 ffffffff 00000000 S NetdConnector
-system 861 764 1701620 103200 ffffffff 00000000 S NetworkStats
-system 862 764 1701620 103200 ffffffff 00000000 S NetworkPolicy
-system 863 764 1701620 103200 ffffffff 00000000 S WifiP2pService
-system 864 764 1701620 103200 ffffffff 00000000 S WifiStateMachin
-system 865 764 1701620 103200 ffffffff 00000000 S WifiService
-system 866 764 1701620 103200 ffffffff 00000000 S ConnectivitySer
-system 867 764 1701620 103200 ffffffff 00000000 S NsdService
-system 868 764 1701620 103200 ffffffff 00000000 S mDnsConnector
-system 869 764 1701620 103200 ffffffff 00000000 S ranker
-system 870 764 1701620 103200 ffffffff 00000000 S AudioService
-system 882 764 1701620 103200 ffffffff 00000000 S WifiWatchdogSta
-system 883 764 1701620 103200 ffffffff 00000000 S WifiManager
-system 884 764 1701620 103200 ffffffff 00000000 S WifiScanningSer
-system 885 764 1701620 103200 ffffffff 00000000 S WifiRttService
-system 886 764 1701620 103200 ffffffff 00000000 S EthernetService
-system 887 764 1701620 103200 ffffffff 00000000 S backup
-system 889 764 1701620 103200 ffffffff 00000000 S Thread-69
-system 892 764 1701620 103200 ffffffff 00000000 S LazyTaskWriterT
-system 893 764 1701620 103200 ffffffff 00000000 S UsbService host
-system 894 764 1701620 103200 ffffffff 00000000 S Thread-73
-system 942 764 1701620 103200 ffffffff 00000000 S Binder_3
-system 1079 764 1701620 103200 ffffffff 00000000 S watchdog
-system 1094 764 1701620 103200 ffffffff 00000000 S SoundPool
-system 1095 764 1701620 103200 ffffffff 00000000 S SoundPoolThread
-system 1108 764 1701620 103200 ffffffff 00000000 S Binder_4
-system 1109 764 1701620 103200 ffffffff 00000000 S Binder_5
-system 1186 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1188 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1191 764 1701620 103200 ffffffff 00000000 S NetworkTimeUpda
-system 1192 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1226 764 1701620 103200 ffffffff 00000000 S Binder_6
-system 1233 764 1701620 103200 ffffffff 00000000 S Binder_7
-system 1247 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1256 764 1701620 103200 ffffffff 00000000 S Binder_8
-system 1260 764 1701620 103200 ffffffff 00000000 S WifiMonitor
-system 1271 764 1701620 103200 ffffffff 00000000 S Binder_9
-system 1288 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1289 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1319 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1320 764 1701620 103200 ffffffff 00000000 S FLP Service Cal
-system 1367 764 1701620 103200 ffffffff 00000000 S Thread-89
-system 1391 764 1701620 103200 ffffffff 00000000 S AsyncQueryWorke
-system 1654 764 1701620 103200 ffffffff 00000000 S Binder_A
-system 1693 764 1701620 103200 ffffffff 00000000 S NetworkMonitorN
-system 1695 764 1701620 103200 ffffffff 00000000 S DhcpStateMachin
-system 1781 764 1701620 103200 ffffffff 00000000 S AsyncTask #1
-system 1782 764 1701620 103200 ffffffff 00000000 S AsyncTask #2
-system 2097 764 1701620 103200 ffffffff 00000000 S AsyncTask #3
-system 2124 764 1701620 103200 ffffffff 00000000 S SyncHandler-0
-system 2905 764 1701620 103200 ffffffff 00000000 S PowerManagerSer
-system 4226 764 1701620 103200 ffffffff 00000000 S AsyncTask #4
-system 4265 764 1701620 103200 ffffffff 00000000 S UsbDebuggingMan
-system 5717 764 1701620 103200 ffffffff 00000000 S GL updater
-system 6709 764 1701620 103200 ffffffff 00000000 S Binder_B
-wifi 888 1 12568 2672 ffffffff 00000000 S /system/bin/wpa_supplicant
-u0_a20 915 205 1616624 108684 ffffffff 00000000 S com.android.systemui
-u0_a20 919 915 1616624 108684 ffffffff 00000000 S Heap thread poo
-u0_a20 920 915 1616624 108684 ffffffff 00000000 S Heap thread poo
-u0_a20 921 915 1616624 108684 ffffffff 00000000 S Heap thread poo
-u0_a20 925 915 1616624 108684 ffffffff 00000000 S Signal Catcher
-u0_a20 926 915 1616624 108684 ffffffff 00000000 S JDWP
-u0_a20 927 915 1616624 108684 ffffffff 00000000 S ReferenceQueueD
-u0_a20 928 915 1616624 108684 ffffffff 00000000 S FinalizerDaemon
-u0_a20 929 915 1616624 108684 ffffffff 00000000 S FinalizerWatchd
-u0_a20 930 915 1616624 108684 ffffffff 00000000 S HeapTrimmerDaem
-u0_a20 931 915 1616624 108684 ffffffff 00000000 S GCDaemon
-u0_a20 933 915 1616624 108684 ffffffff 00000000 S Binder_1
-u0_a20 934 915 1616624 108684 ffffffff 00000000 S Binder_2
-u0_a20 964 915 1616624 108684 ffffffff 00000000 S SoundPool
-u0_a20 965 915 1616624 108684 ffffffff 00000000 S SoundPoolThread
-u0_a20 970 915 1616624 108684 ffffffff 00000000 S Recents-TaskRes
-u0_a20 1078 915 1616624 108684 ffffffff 00000000 S SystemUI Storag
-u0_a20 1378 915 1616624 108684 ffffffff 00000000 S PhoneStatusBar
-u0_a20 1381 915 1616624 108684 ffffffff 00000000 S WifiManager
-u0_a20 1416 915 1616624 108684 ffffffff 00000000 S ConnectivityMan
-u0_a20 1428 915 1616624 108684 ffffffff 00000000 S Binder_3
-u0_a20 1431 915 1616624 108684 ffffffff 00000000 S FlashlightContr
-u0_a20 1434 915 1616624 108684 ffffffff 00000000 S AsyncTask #1
-u0_a20 1435 915 1616624 108684 ffffffff 00000000 S QSTileHost
-u0_a20 1438 915 1616624 108684 ffffffff 00000000 S AsyncTask #2
-u0_a20 1441 915 1616624 108684 ffffffff 00000000 S RenderThread
-u0_a20 1442 915 1616624 108684 ffffffff 00000000 S AsyncTask #3
-u0_a20 1565 915 1616624 108684 ffffffff 00000000 S hwuiTask1
-u0_a20 1566 915 1616624 108684 ffffffff 00000000 S hwuiTask2
-u0_a20 1637 915 1616624 108684 ffffffff 00000000 S AsyncTask #4
-u0_a20 1692 915 1616624 108684 ffffffff 00000000 S GL updater
-u0_a20 1807 915 1616624 108684 ffffffff 00000000 S RenderThread
-u0_a20 4480 915 1616624 108684 ffffffff 00000000 S Binder_4
-u0_a6 936 205 1506908 56892 ffffffff 00000000 S android.process.media
-u0_a6 943 936 1506908 56892 ffffffff 00000000 S Heap thread poo
-u0_a6 944 936 1506908 56892 ffffffff 00000000 S Heap thread poo
-u0_a6 945 936 1506908 56892 ffffffff 00000000 S Heap thread poo
-u0_a6 947 936 1506908 56892 ffffffff 00000000 S Signal Catcher
-u0_a6 949 936 1506908 56892 ffffffff 00000000 S JDWP
-u0_a6 950 936 1506908 56892 ffffffff 00000000 S ReferenceQueueD
-u0_a6 951 936 1506908 56892 ffffffff 00000000 S FinalizerDaemon
-u0_a6 952 936 1506908 56892 ffffffff 00000000 S FinalizerWatchd
-u0_a6 953 936 1506908 56892 ffffffff 00000000 S HeapTrimmerDaem
-u0_a6 954 936 1506908 56892 ffffffff 00000000 S GCDaemon
-u0_a6 956 936 1506908 56892 ffffffff 00000000 S Binder_1
-u0_a6 957 936 1506908 56892 ffffffff 00000000 S Binder_2
-u0_a6 1007 936 1506908 56892 ffffffff 00000000 S thumbs thread
-u0_a6 1020 936 1506908 56892 ffffffff 00000000 S MtpServer
-u0_a6 2810 936 1506908 56892 ffffffff 00000000 S DownloadReceive
-u0_a6 4917 936 1506908 56892 ffffffff 00000000 S Binder_3
-u0_a6 5816 936 1506908 56892 ffffffff 00000000 S Binder_4
-u0_a6 8575 936 1506908 56892 ffffffff 00000000 S Binder_5
-u0_a22 1111 205 1526156 42532 ffffffff 00000000 S com.google.android.googlequicksearchbox:interactor
-u0_a22 1113 1111 1526156 42532 ffffffff 00000000 S Heap thread poo
-u0_a22 1114 1111 1526156 42532 ffffffff 00000000 S Heap thread poo
-u0_a22 1116 1111 1526156 42532 ffffffff 00000000 S Heap thread poo
-u0_a22 1121 1111 1526156 42532 ffffffff 00000000 S Signal Catcher
-u0_a22 1124 1111 1526156 42532 ffffffff 00000000 S JDWP
-u0_a22 1125 1111 1526156 42532 ffffffff 00000000 S ReferenceQueueD
-u0_a22 1126 1111 1526156 42532 ffffffff 00000000 S FinalizerDaemon
-u0_a22 1127 1111 1526156 42532 ffffffff 00000000 S FinalizerWatchd
-u0_a22 1128 1111 1526156 42532 ffffffff 00000000 S HeapTrimmerDaem
-u0_a22 1129 1111 1526156 42532 ffffffff 00000000 S GCDaemon
-u0_a22 1131 1111 1526156 42532 ffffffff 00000000 S Binder_1
-u0_a22 1132 1111 1526156 42532 ffffffff 00000000 S Binder_2
-u0_a22 1561 1111 1526156 42532 ffffffff 00000000 S AsyncTask #1
-u0_a51 1136 205 1515064 46788 ffffffff 00000000 S com.google.android.inputmethod.pinyin
-u0_a51 1142 1136 1515064 46788 ffffffff 00000000 S Heap thread poo
-u0_a51 1143 1136 1515064 46788 ffffffff 00000000 S Heap thread poo
-u0_a51 1144 1136 1515064 46788 ffffffff 00000000 S Heap thread poo
-u0_a51 1145 1136 1515064 46788 ffffffff 00000000 S Signal Catcher
-u0_a51 1146 1136 1515064 46788 ffffffff 00000000 S JDWP
-u0_a51 1147 1136 1515064 46788 ffffffff 00000000 S ReferenceQueueD
-u0_a51 1148 1136 1515064 46788 ffffffff 00000000 S FinalizerDaemon
-u0_a51 1149 1136 1515064 46788 ffffffff 00000000 S FinalizerWatchd
-u0_a51 1151 1136 1515064 46788 ffffffff 00000000 S HeapTrimmerDaem
-u0_a51 1152 1136 1515064 46788 ffffffff 00000000 S GCDaemon
-u0_a51 1153 1136 1515064 46788 ffffffff 00000000 S Binder_1
-u0_a51 1154 1136 1515064 46788 ffffffff 00000000 S Binder_2
-u0_a51 1330 1136 1515064 46788 ffffffff 00000000 S GAThread
-u0_a51 1331 1136 1515064 46788 ffffffff 00000000 S measurement-1
-u0_a51 1336 1136 1515064 46788 ffffffff 00000000 S pool-1-thread-1
-u0_a51 1503 1136 1515064 46788 ffffffff 00000000 S AsyncTask #1
-u0_a51 1622 1136 1515064 46788 ffffffff 00000000 S AsyncTask #2
-nfc 1199 205 1511808 46336 ffffffff 00000000 S com.android.nfc
-nfc 1208 1199 1511808 46336 ffffffff 00000000 S Heap thread poo
-nfc 1209 1199 1511808 46336 ffffffff 00000000 S Heap thread poo
-nfc 1210 1199 1511808 46336 ffffffff 00000000 S Heap thread poo
-nfc 1211 1199 1511808 46336 ffffffff 00000000 S Signal Catcher
-nfc 1212 1199 1511808 46336 ffffffff 00000000 S JDWP
-nfc 1213 1199 1511808 46336 ffffffff 00000000 S ReferenceQueueD
-nfc 1214 1199 1511808 46336 ffffffff 00000000 S FinalizerDaemon
-nfc 1215 1199 1511808 46336 ffffffff 00000000 S FinalizerWatchd
-nfc 1216 1199 1511808 46336 ffffffff 00000000 S HeapTrimmerDaem
-nfc 1219 1199 1511808 46336 ffffffff 00000000 S GCDaemon
-nfc 1220 1199 1511808 46336 ffffffff 00000000 S Binder_1
-nfc 1221 1199 1511808 46336 ffffffff 00000000 S Binder_2
-nfc 1385 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1388 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1393 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1408 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1409 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1425 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1
-nfc 1573 1199 1511808 46336 ffffffff 00000000 S Thread-55
-nfc 1574 1199 1511808 46336 ffffffff 00000000 S Thread-56
-nfc 1575 1199 1511808 46336 ffffffff 00000000 S Thread-57
-nfc 1577 1199 1511808 46336 ffffffff 00000000 S SoundPool
-nfc 1578 1199 1511808 46336 ffffffff 00000000 S SoundPoolThread
-nfc 2906 1199 1511808 46336 ffffffff 00000000 S AsyncTask #2
-nfc 2915 1199 1511808 46336 ffffffff 00000000 S AsyncTask #3
-nfc 5610 1199 1511808 46336 ffffffff 00000000 S AsyncTask #4
-nfc 5719 1199 1511808 46336 ffffffff 00000000 S AsyncTask #5
-radio 1234 205 1493064 38832 ffffffff 00000000 S com.redbend.vdmc
-radio 1236 1234 1493064 38832 ffffffff 00000000 S Heap thread poo
-radio 1237 1234 1493064 38832 ffffffff 00000000 S Heap thread poo
-radio 1238 1234 1493064 38832 ffffffff 00000000 S Heap thread poo
-radio 1244 1234 1493064 38832 ffffffff 00000000 S Signal Catcher
-radio 1245 1234 1493064 38832 ffffffff 00000000 S JDWP
-radio 1246 1234 1493064 38832 ffffffff 00000000 S ReferenceQueueD
-radio 1248 1234 1493064 38832 ffffffff 00000000 S FinalizerDaemon
-radio 1249 1234 1493064 38832 ffffffff 00000000 S FinalizerWatchd
-radio 1250 1234 1493064 38832 ffffffff 00000000 S HeapTrimmerDaem
-radio 1251 1234 1493064 38832 ffffffff 00000000 S GCDaemon
-radio 1252 1234 1493064 38832 ffffffff 00000000 S Binder_1
-radio 1257 1234 1493064 38832 ffffffff 00000000 S Binder_2
-radio 1274 205 1525408 58916 ffffffff 00000000 S com.android.phone
-radio 1282 1274 1525408 58916 ffffffff 00000000 S Heap thread poo
-radio 1283 1274 1525408 58916 ffffffff 00000000 S Heap thread poo
-radio 1284 1274 1525408 58916 ffffffff 00000000 S Heap thread poo
-radio 1285 1274 1525408 58916 ffffffff 00000000 S Signal Catcher
-radio 1286 1274 1525408 58916 ffffffff 00000000 S JDWP
-radio 1287 1274 1525408 58916 ffffffff 00000000 S ReferenceQueueD
-radio 1290 1274 1525408 58916 ffffffff 00000000 S FinalizerDaemon
-radio 1291 1274 1525408 58916 ffffffff 00000000 S FinalizerWatchd
-radio 1292 1274 1525408 58916 ffffffff 00000000 S HeapTrimmerDaem
-radio 1293 1274 1525408 58916 ffffffff 00000000 S GCDaemon
-radio 1299 1274 1525408 58916 ffffffff 00000000 S Binder_1
-radio 1315 1274 1525408 58916 ffffffff 00000000 S Binder_2
-radio 1365 1274 1525408 58916 ffffffff 00000000 S RILSender0
-radio 1366 1274 1525408 58916 ffffffff 00000000 S RILReceiver0
-radio 1380 1274 1525408 58916 ffffffff 00000000 S DcHandlerThread
-radio 1392 1274 1525408 58916 ffffffff 00000000 S GsmCellBroadcas
-radio 1394 1274 1525408 58916 ffffffff 00000000 S GsmInboundSmsHa
-radio 1397 1274 1525408 58916 ffffffff 00000000 S CellBroadcastHa
-radio 1417 1274 1525408 58916 ffffffff 00000000 S CdmaInboundSmsH
-radio 1418 1274 1525408 58916 ffffffff 00000000 S CdmaServiceCate
-radio 1427 1274 1525408 58916 ffffffff 00000000 S DcSwitchStateMa
-radio 1429 1274 1525408 58916 ffffffff 00000000 S SyncHandler-0
-radio 1443 1274 1525408 58916 ffffffff 00000000 S AsyncTask #1
-radio 1473 1274 1525408 58916 ffffffff 00000000 S Binder_3
-radio 1517 1274 1525408 58916 ffffffff 00000000 S ervice.Executor
-radio 1518 1274 1525408 58916 ffffffff 00000000 S WifiManager
-radio 1563 1274 1525408 58916 ffffffff 00000000 S Cat Telephony s
-radio 1564 1274 1525408 58916 ffffffff 00000000 S RilMessageDecod
-radio 1567 1274 1525408 58916 ffffffff 00000000 S Cat Icon Loader
-radio 1690 1274 1525408 58916 ffffffff 00000000 S Binder_4
-radio 4571 1274 1525408 58916 ffffffff 00000000 S Stk App Service
-u0_a22 1305 205 1674592 127012 ffffffff 00000000 S com.google.android.googlequicksearchbox
-u0_a22 1306 1305 1674592 127012 ffffffff 00000000 S Heap thread poo
-u0_a22 1307 1305 1674592 127012 ffffffff 00000000 S Heap thread poo
-u0_a22 1308 1305 1674592 127012 ffffffff 00000000 S Heap thread poo
-u0_a22 1317 1305 1674592 127012 ffffffff 00000000 S Signal Catcher
-u0_a22 1318 1305 1674592 127012 ffffffff 00000000 S JDWP
-u0_a22 1322 1305 1674592 127012 ffffffff 00000000 S ReferenceQueueD
-u0_a22 1323 1305 1674592 127012 ffffffff 00000000 S FinalizerDaemon
-u0_a22 1324 1305 1674592 127012 ffffffff 00000000 S FinalizerWatchd
-u0_a22 1332 1305 1674592 127012 ffffffff 00000000 S HeapTrimmerDaem
-u0_a22 1333 1305 1674592 127012 ffffffff 00000000 S GCDaemon
-u0_a22 1334 1305 1674592 127012 ffffffff 00000000 S Binder_1
-u0_a22 1335 1305 1674592 127012 ffffffff 00000000 S Binder_2
-u0_a22 1386 1305 1674592 127012 ffffffff 00000000 S launcher-loader
-u0_a22 1395 1305 1674592 127012 ffffffff 00000000 S AsyncTask #1
-u0_a22 1432 1305 1674592 127012 ffffffff 00000000 S AsyncTask #2
-u0_a22 1484 1305 1674592 127012 ffffffff 00000000 S GELServices-0
-u0_a22 1514 1305 1674592 127012 ffffffff 00000000 S RenderThread
-u0_a22 1540 1305 1674592 127012 ffffffff 00000000 S AsyncTask #3
-u0_a22 1618 1305 1674592 127012 ffffffff 00000000 S GELServices-1
-u0_a22 1621 1305 1674592 127012 ffffffff 00000000 S GELServices-2
-u0_a22 1629 1305 1674592 127012 ffffffff 00000000 S GELServices-3
-u0_a22 1632 1305 1674592 127012 ffffffff 00000000 S AsyncTask #4
-u0_a22 1633 1305 1674592 127012 ffffffff 00000000 S AsyncTask #5
-u0_a22 1636 1305 1674592 127012 ffffffff 00000000 S GELServices-4
-u0_a22 1644 1305 1674592 127012 ffffffff 00000000 S GL updater
-u0_a22 1647 1305 1674592 127012 ffffffff 00000000 S GELServices-5
-u0_a22 1664 1305 1674592 127012 ffffffff 00000000 S GELServices-6
-u0_a22 1764 1305 1674592 127012 ffffffff 00000000 S Binder_3
-u0_a22 1766 1305 1674592 127012 ffffffff 00000000 S GELServices-7
-u0_a22 1772 1305 1674592 127012 ffffffff 00000000 S RenderThread
-u0_a22 1773 1305 1674592 127012 ffffffff 00000000 S RenderThread
-u0_a22 1774 1305 1674592 127012 ffffffff 00000000 S RenderThread
-u0_a22 1775 1305 1674592 127012 ffffffff 00000000 S RenderThread
-u0_a22 1998 1305 1674592 127012 ffffffff 00000000 S GELServices-8
-u0_a22 2320 1305 1674592 127012 ffffffff 00000000 S RemoteViewsCach
-u0_a22 2321 1305 1674592 127012 ffffffff 00000000 S RemoteViewsAdap
-u0_a22 2902 1305 1674592 127012 ffffffff 00000000 S GELServices-9
-u0_a22 1451 205 1584512 87716 ffffffff 00000000 S com.google.android.googlequicksearchbox:search
-u0_a22 1457 1451 1584512 87716 ffffffff 00000000 S Heap thread poo
-u0_a22 1458 1451 1584512 87716 ffffffff 00000000 S Heap thread poo
-u0_a22 1459 1451 1584512 87716 ffffffff 00000000 S Heap thread poo
-u0_a22 1460 1451 1584512 87716 ffffffff 00000000 S Signal Catcher
-u0_a22 1461 1451 1584512 87716 ffffffff 00000000 S JDWP
-u0_a22 1462 1451 1584512 87716 ffffffff 00000000 S ReferenceQueueD
-u0_a22 1463 1451 1584512 87716 ffffffff 00000000 S FinalizerDaemon
-u0_a22 1464 1451 1584512 87716 ffffffff 00000000 S FinalizerWatchd
-u0_a22 1466 1451 1584512 87716 ffffffff 00000000 S HeapTrimmerDaem
-u0_a22 1468 1451 1584512 87716 ffffffff 00000000 S GCDaemon
-u0_a22 1474 1451 1584512 87716 ffffffff 00000000 S Binder_1
-u0_a22 1475 1451 1584512 87716 ffffffff 00000000 S Binder_2
-u0_a22 1515 1451 1584512 87716 ffffffff 00000000 S User-Facing Non
-u0_a22 1516 1451 1584512 87716 ffffffff 00000000 S User-Facing Non
-u0_a22 1535 1451 1584512 87716 ffffffff 00000000 S User-Facing Non
-u0_a22 1538 1451 1584512 87716 ffffffff 00000000 S User-Facing Non
-u0_a22 1553 1451 1584512 87716 ffffffff 00000000 S User-Facing Non
-u0_a22 1560 1451 1584512 87716 ffffffff 00000000 S IcingConnection
-u0_a22 1580 1451 1584512 87716 ffffffff 00000000 S AudioRouter-0
-u0_a22 1626 1451 1584512 87716 ffffffff 00000000 S AsyncFileStorag
-u0_a22 1635 1451 1584512 87716 ffffffff 00000000 S WifiManager
-u0_a22 1643 1451 1584512 87716 ffffffff 00000000 S LocationOracleI
-u0_a22 1646 1451 1584512 87716 ffffffff 00000000 S GoogleApiClient
-u0_a22 1769 1451 1584512 87716 ffffffff 00000000 S Binder_3
-u0_a22 1770 1451 1584512 87716 ffffffff 00000000 S Gservices
-u0_a22 1810 1451 1584512 87716 ffffffff 00000000 S ChromiumNet
-u0_a22 1811 1451 1584512 87716 ffffffff 00000000 S DnsConfigServic
-u0_a22 1812 1451 1584512 87716 ffffffff 00000000 S inotify_reader
-u0_a22 1815 1451 1584512 87716 ffffffff 00000000 S Network File Th
-u0_a22 1816 1451 1584512 87716 ffffffff 00000000 S SimpleCacheWork
-u0_a22 1817 1451 1584512 87716 ffffffff 00000000 S SimpleCacheWork
-u0_a22 1823 1451 1584512 87716 ffffffff 00000000 S Binder_4
-u0_a22 1824 1451 1584512 87716 ffffffff 00000000 S Binder_5
-u0_a22 12193 1451 1584512 87716 ffffffff 00000000 S Background Bloc
-u0_a22 12207 1451 1584512 87716 ffffffff 00000000 S User-Facing Blo
-u0_a22 12211 1451 1584512 87716 ffffffff 00000000 S WorkerPool/1221
-u0_a22 12232 1451 1584512 87716 ffffffff 00000000 S Background Non-
-u0_a22 12235 1451 1584512 87716 ffffffff 00000000 S Background Bloc
-u0_a22 12236 1451 1584512 87716 ffffffff 00000000 S Background Bloc
-u0_a22 12237 1451 1584512 87716 ffffffff 00000000 S Background Non-
-u0_a8 1478 205 1613496 72932 ffffffff 00000000 S com.google.process.gapps
-u0_a8 1485 1478 1613496 72932 ffffffff 00000000 S Heap thread poo
-u0_a8 1486 1478 1613496 72932 ffffffff 00000000 S Heap thread poo
-u0_a8 1487 1478 1613496 72932 ffffffff 00000000 S Heap thread poo
-u0_a8 1488 1478 1613496 72932 ffffffff 00000000 S Signal Catcher
-u0_a8 1489 1478 1613496 72932 ffffffff 00000000 S JDWP
-u0_a8 1490 1478 1613496 72932 ffffffff 00000000 S ReferenceQueueD
-u0_a8 1491 1478 1613496 72932 ffffffff 00000000 S FinalizerDaemon
-u0_a8 1492 1478 1613496 72932 ffffffff 00000000 S FinalizerWatchd
-u0_a8 1493 1478 1613496 72932 ffffffff 00000000 S HeapTrimmerDaem
-u0_a8 1494 1478 1613496 72932 ffffffff 00000000 S GCDaemon
-u0_a8 1495 1478 1613496 72932 ffffffff 00000000 S Binder_1
-u0_a8 1496 1478 1613496 72932 ffffffff 00000000 S Binder_2
-u0_a8 1497 1478 1613496 72932 ffffffff 00000000 S Binder_3
-u0_a8 1613 1478 1613496 72932 ffffffff 00000000 S Gservices
-u0_a8 1614 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@
-u0_a8 1615 1478 1613496 72932 ffffffff 00000000 S Gservices
-u0_a8 1616 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@
-u0_a8 1620 1478 1613496 72932 ffffffff 00000000 S Gservices
-u0_a8 1996 1478 1613496 72932 ffffffff 00000000 S Binder_4
-u0_a8 1997 1478 1613496 72932 ffffffff 00000000 S Binder_5
-u0_a8 2510 1478 1613496 72932 ffffffff 00000000 S GCMWriter
-u0_a8 2512 1478 1613496 72932 ffffffff 00000000 S AsyncTask #1
-u0_a8 2536 1478 1613496 72932 ffffffff 00000000 S GCMReader
-u0_a8 2547 1478 1613496 72932 ffffffff 00000000 S pool-2-thread-1
-u0_a8 3680 1478 1613496 72932 ffffffff 00000000 S WifiManager
-u0_a8 4135 1478 1613496 72932 ffffffff 00000000 S AsyncTask #2
-u0_a8 4159 1478 1613496 72932 ffffffff 00000000 S AsyncTask #3
-u0_a8 4184 1478 1613496 72932 ffffffff 00000000 S AsyncTask #4
-u0_a8 4210 1478 1613496 72932 ffffffff 00000000 S AsyncTask #5
-u0_a8 4541 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@
-u0_a8 4735 1478 1613496 72932 ffffffff 00000000 S pool-8-thread-1
-u0_a8 4770 1478 1613496 72932 ffffffff 00000000 S Binder_6
-u0_a8 12448 1478 1613496 72932 ffffffff 00000000 S OkHttp Connecti
-u0_a8 14401 1478 1613496 72932 ffffffff 00000000 S Thread-233
-u0_a8 14409 1478 1613496 72932 ffffffff 00000000 S OkHttp Connecti
-dhcp 1700 1 9344 756 ffffffff 00000000 S /system/bin/dhcpcd
-u0_a8 1873 205 1756828 84724 ffffffff 00000000 S com.google.android.gms
-u0_a8 1878 1873 1756828 84724 ffffffff 00000000 S Heap thread poo
-u0_a8 1880 1873 1756828 84724 ffffffff 00000000 S Heap thread poo
-u0_a8 1881 1873 1756828 84724 ffffffff 00000000 S Heap thread poo
-u0_a8 1882 1873 1756828 84724 ffffffff 00000000 S Signal Catcher
-u0_a8 1883 1873 1756828 84724 ffffffff 00000000 S JDWP
-u0_a8 1884 1873 1756828 84724 ffffffff 00000000 S ReferenceQueueD
-u0_a8 1885 1873 1756828 84724 ffffffff 00000000 S FinalizerDaemon
-u0_a8 1886 1873 1756828 84724 ffffffff 00000000 S FinalizerWatchd
-u0_a8 1887 1873 1756828 84724 ffffffff 00000000 S HeapTrimmerDaem
-u0_a8 1888 1873 1756828 84724 ffffffff 00000000 S GCDaemon
-u0_a8 1889 1873 1756828 84724 ffffffff 00000000 S Binder_1
-u0_a8 1890 1873 1756828 84724 ffffffff 00000000 S Binder_2
-u0_a8 1895 1873 1756828 84724 ffffffff 00000000 S Gservices
-u0_a8 1898 1873 1756828 84724 ffffffff 00000000 S measurement-1
-u0_a8 1900 1873 1756828 84724 ffffffff 00000000 S AsyncTask #1
-u0_a8 1904 1873 1756828 84724 ffffffff 00000000 S AsyncTask #2
-u0_a8 2001 1873 1756828 84724 ffffffff 00000000 S Binder_3
-u0_a8 2497 1873 1756828 84724 ffffffff 00000000 S WifiManager
-u0_a8 2509 1873 1756828 84724 ffffffff 00000000 S picasa-uploads-
-u0_a8 2946 1873 1756828 84724 ffffffff 00000000 S pool-7-thread-1
-u0_a8 4390 1873 1756828 84724 ffffffff 00000000 S pool-13-thread-
-u0_a8 4391 1873 1756828 84724 ffffffff 00000000 S pool-18-thread-
-u0_a8 4392 1873 1756828 84724 ffffffff 00000000 S pool-11-thread-
-u0_a8 4394 1873 1756828 84724 ffffffff 00000000 S pool-25-thread-
-u0_a8 4395 1873 1756828 84724 ffffffff 00000000 S pool-25-thread-
-u0_a8 4396 1873 1756828 84724 ffffffff 00000000 S pool-25-thread-
-u0_a8 4397 1873 1756828 84724 ffffffff 00000000 S pool-25-thread-
-u0_a8 4398 1873 1756828 84724 ffffffff 00000000 S pool-14-thread-
-u0_a8 4521 1873 1756828 84724 ffffffff 00000000 S MediaTracker bu
-u0_a8 4766 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-0
-u0_a8 4771 1873 1756828 84724 ffffffff 00000000 S Icing-Worker-0
-u0_a8 4796 1873 1756828 84724 ffffffff 00000000 S Thread-200
-u0_a8 4797 1873 1756828 84724 ffffffff 00000000 S Thread-201
-u0_a8 4798 1873 1756828 84724 ffffffff 00000000 S Thread-202
-u0_a8 4799 1873 1756828 84724 ffffffff 00000000 S Thread-203
-u0_a8 4800 1873 1756828 84724 ffffffff 00000000 S Thread-204
-u0_a8 5793 1873 1756828 84724 ffffffff 00000000 S Binder_4
-u0_a8 6257 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-1
-u0_a8 6258 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-2
-u0_a8 6259 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-3
-u0_a8 6673 1873 1756828 84724 ffffffff 00000000 S pool-22-thread-
-u0_a8 8581 1873 1756828 84724 ffffffff 00000000 S Binder_5
-u0_a8 9001 1873 1756828 84724 ffffffff 00000000 S Gservices
-u0_a8 9024 1873 1756828 84724 ffffffff 00000000 S GamesProviderWo
-u0_a8 11865 1873 1756828 84724 ffffffff 00000000 S pool-37-thread-
-u0_a8 1949 205 1614008 81544 ffffffff 00000000 S com.google.android.gms.persistent
-u0_a8 1954 1949 1614008 81544 ffffffff 00000000 S Heap thread poo
-u0_a8 1955 1949 1614008 81544 ffffffff 00000000 S Heap thread poo
-u0_a8 1956 1949 1614008 81544 ffffffff 00000000 S Heap thread poo
-u0_a8 1959 1949 1614008 81544 ffffffff 00000000 S Signal Catcher
-u0_a8 1960 1949 1614008 81544 ffffffff 00000000 S JDWP
-u0_a8 1961 1949 1614008 81544 ffffffff 00000000 S ReferenceQueueD
-u0_a8 1962 1949 1614008 81544 ffffffff 00000000 S FinalizerDaemon
-u0_a8 1963 1949 1614008 81544 ffffffff 00000000 S FinalizerWatchd
-u0_a8 1964 1949 1614008 81544 ffffffff 00000000 S HeapTrimmerDaem
-u0_a8 1965 1949 1614008 81544 ffffffff 00000000 S GCDaemon
-u0_a8 1966 1949 1614008 81544 ffffffff 00000000 S Binder_1
-u0_a8 1967 1949 1614008 81544 ffffffff 00000000 S Binder_2
-u0_a8 1968 1949 1614008 81544 ffffffff 00000000 S Gservices
-u0_a8 1973 1949 1614008 81544 ffffffff 00000000 S IntentService[G
-u0_a8 1976 1949 1614008 81544 ffffffff 00000000 S FlpThread
-u0_a8 1977 1949 1614008 81544 ffffffff 00000000 S Binder_3
-u0_a8 1978 1949 1614008 81544 ffffffff 00000000 S WifiManager
-u0_a8 1979 1949 1614008 81544 ffffffff 00000000 S GeofencerStateM
-u0_a8 1980 1949 1614008 81544 ffffffff 00000000 S LocationService
-u0_a8 1984 1949 1614008 81544 ffffffff 00000000 S Binder_4
-u0_a8 1986 1949 1614008 81544 ffffffff 00000000 S Binder_5
-u0_a8 1990 1949 1614008 81544 ffffffff 00000000 S pool-4-thread-1
-u0_a8 1992 1949 1614008 81544 ffffffff 00000000 S GmsCoreStatsSer
-u0_a8 1995 1949 1614008 81544 ffffffff 00000000 S GoogleLocationS
-u0_a8 2004 1949 1614008 81544 ffffffff 00000000 S Thread-139
-u0_a8 2005 1949 1614008 81544 ffffffff 00000000 S Thread-140
-u0_a8 2006 1949 1614008 81544 ffffffff 00000000 S Thread-141
-u0_a8 2007 1949 1614008 81544 ffffffff 00000000 S Thread-142
-u0_a8 2021 1949 1614008 81544 ffffffff 00000000 S NetworkLocation
-u0_a8 2029 1949 1614008 81544 ffffffff 00000000 S UlrDispatchingS
-u0_a8 2030 1949 1614008 81544 ffffffff 00000000 S nlp-async-worke
-u0_a8 2521 1949 1614008 81544 ffffffff 00000000 S FitnessServiceF
-u0_a8 2522 1949 1614008 81544 ffffffff 00000000 S FitRecordingBro
-u0_a8 2526 1949 1614008 81544 ffffffff 00000000 S AsyncTask #1
-u0_a8 2530 1949 1614008 81544 ffffffff 00000000 S NearbyMessagesB
-u0_a8 4180 1949 1614008 81544 ffffffff 00000000 S AsyncTask #2
-u0_a8 4221 1949 1614008 81544 ffffffff 00000000 S AsyncTask #3
-u0_a8 4223 1949 1614008 81544 ffffffff 00000000 S AsyncTask #4
-u0_a8 4749 1949 1614008 81544 ffffffff 00000000 S CopresenceEvent
-u0_a8 6326 1949 1614008 81544 ffffffff 00000000 S AsyncTask #5
-u0_a8 6917 1949 1614008 81544 ffffffff 00000000 S Binder_6
-u0_a8 7196 1949 1614008 81544 ffffffff 00000000 S UlrDispatchingS
-u0_a8 7260 1949 1614008 81544 ffffffff 00000000 S Thread-174
-u0_a8 7261 1949 1614008 81544 ffffffff 00000000 S Thread-175
-u0_a8 7262 1949 1614008 81544 ffffffff 00000000 S Thread-176
-u0_a8 7263 1949 1614008 81544 ffffffff 00000000 S Thread-177
-u0_a8 7264 1949 1614008 81544 ffffffff 00000000 S Thread-178
-u0_a8 12449 1949 1614008 81544 ffffffff 00000000 S OkHttp Connecti
-root 2031 1 20256 880 ffffffff 00000000 S /system/bin/mpdecision
-root 2032 2031 20256 880 ffffffff 00000000 S mpdecision
-root 2033 2031 20256 880 ffffffff 00000000 S mpdecision
-root 2034 2031 20256 880 ffffffff 00000000 S mpdecision
-root 2035 2031 20256 880 ffffffff 00000000 S mpdecision
-root 2036 2031 20256 880 ffffffff 00000000 S mpdecision
-root 2046 2031 20256 880 ffffffff 00000000 S mpdecision
-u0_a193 2647 205 1541760 60840 ffffffff 00000000 S com.qiyi.video.market
-u0_a193 2653 2647 1541760 60840 ffffffff 00000000 S Heap thread poo
-u0_a193 2654 2647 1541760 60840 ffffffff 00000000 S Heap thread poo
-u0_a193 2655 2647 1541760 60840 ffffffff 00000000 S Heap thread poo
-u0_a193 2656 2647 1541760 60840 ffffffff 00000000 S Signal Catcher
-u0_a193 2657 2647 1541760 60840 ffffffff 00000000 S JDWP
-u0_a193 2658 2647 1541760 60840 ffffffff 00000000 S ReferenceQueueD
-u0_a193 2659 2647 1541760 60840 ffffffff 00000000 S FinalizerDaemon
-u0_a193 2660 2647 1541760 60840 ffffffff 00000000 S FinalizerWatchd
-u0_a193 2661 2647 1541760 60840 ffffffff 00000000 S HeapTrimmerDaem
-u0_a193 2662 2647 1541760 60840 ffffffff 00000000 S GCDaemon
-u0_a193 2663 2647 1541760 60840 ffffffff 00000000 S Binder_1
-u0_a193 2664 2647 1541760 60840 ffffffff 00000000 S Binder_2
-u0_a193 2671 2647 1541760 60840 ffffffff 00000000 S RefQueueWorker@
-u0_a193 2673 2647 1541760 60840 ffffffff 00000000 S .ProcessManager
-u0_a193 2675 2647 1541760 60840 ffffffff 00000000 S Binder_3
-u0_a193 2677 2647 1541760 60840 ffffffff 00000000 S Thread-208
-u0_a193 2679 2647 1541760 60840 ffffffff 00000000 S pool-2-thread-1
-u0_a193 2680 2647 1541760 60840 ffffffff 00000000 S WifiManager
-u0_a193 2682 2647 1541760 60840 ffffffff 00000000 S Timer-0
-u0_a193 2683 2647 1541760 60840 ffffffff 00000000 S Timer-1
-u0_a193 2710 2647 1541760 60840 ffffffff 00000000 S AsyncTask #1
-u0_a193 2718 2647 1541760 60840 ffffffff 00000000 S pool-3-thread-1
-u0_a193 3103 2647 1541760 60840 ffffffff 00000000 S pool-4-thread-1
-u0_a193 6672 2647 1541760 60840 ffffffff 00000000 S AsyncTask #2
-u0_a193 6752 2647 1541760 60840 ffffffff 00000000 S AsyncTask #3
-u0_a193 12484 2647 1541760 60840 ffffffff 00000000 S AsyncTask #4
-u0_a193 12576 2647 1541760 60840 ffffffff 00000000 S AsyncTask #5
-u0_a193 3104 205 1523132 46892 ffffffff 00000000 S com.qiyi.video.market:pluginDownloadService
-u0_a193 3110 3104 1523132 46892 ffffffff 00000000 S Heap thread poo
-u0_a193 3111 3104 1523132 46892 ffffffff 00000000 S Heap thread poo
-u0_a193 3112 3104 1523132 46892 ffffffff 00000000 S Heap thread poo
-u0_a193 3113 3104 1523132 46892 ffffffff 00000000 S Signal Catcher
-u0_a193 3114 3104 1523132 46892 ffffffff 00000000 S JDWP
-u0_a193 3115 3104 1523132 46892 ffffffff 00000000 S ReferenceQueueD
-u0_a193 3116 3104 1523132 46892 ffffffff 00000000 S FinalizerDaemon
-u0_a193 3117 3104 1523132 46892 ffffffff 00000000 S FinalizerWatchd
-u0_a193 3118 3104 1523132 46892 ffffffff 00000000 S HeapTrimmerDaem
-u0_a193 3119 3104 1523132 46892 ffffffff 00000000 S GCDaemon
-u0_a193 3120 3104 1523132 46892 ffffffff 00000000 S Binder_1
-u0_a193 3121 3104 1523132 46892 ffffffff 00000000 S Binder_2
-u0_a193 3141 3104 1523132 46892 ffffffff 00000000 S RefQueueWorker@
-u0_a193 3257 3104 1523132 46892 ffffffff 00000000 S pool-3-thread-1
-u0_a193 7173 3104 1523132 46892 ffffffff 00000000 S Binder_3
-u0_a193 3122 205 1538224 61140 ffffffff 00000000 S com.qiyi.video.market:bdservice_v1
-u0_a193 3128 3122 1538224 61140 ffffffff 00000000 S Heap thread poo
-u0_a193 3129 3122 1538224 61140 ffffffff 00000000 S Heap thread poo
-u0_a193 3130 3122 1538224 61140 ffffffff 00000000 S Heap thread poo
-u0_a193 3131 3122 1538224 61140 ffffffff 00000000 S Signal Catcher
-u0_a193 3132 3122 1538224 61140 ffffffff 00000000 S JDWP
-u0_a193 3133 3122 1538224 61140 ffffffff 00000000 S ReferenceQueueD
-u0_a193 3134 3122 1538224 61140 ffffffff 00000000 S FinalizerDaemon
-u0_a193 3135 3122 1538224 61140 ffffffff 00000000 S FinalizerWatchd
-u0_a193 3136 3122 1538224 61140 ffffffff 00000000 S HeapTrimmerDaem
-u0_a193 3137 3122 1538224 61140 ffffffff 00000000 S GCDaemon
-u0_a193 3138 3122 1538224 61140 ffffffff 00000000 S Binder_1
-u0_a193 3139 3122 1538224 61140 ffffffff 00000000 S Binder_2
-u0_a193 3145 3122 1538224 61140 ffffffff 00000000 S RefQueueWorker@
-u0_a193 3206 3122 1538224 61140 ffffffff 00000000 S WifiManager
-u0_a193 3208 3122 1538224 61140 ffffffff 00000000 S NanoHttpd Main
-u0_a193 7586 3122 1538224 61140 ffffffff 00000000 S pool-4-thread-1
-u0_a193 10584 3122 1538224 61140 ffffffff 00000000 S pool-2-thread-1
-u0_a193 3154 205 1522116 53536 ffffffff 00000000 S com.qiyi.video.market:baiduLocation
-u0_a193 3163 3154 1522116 53536 ffffffff 00000000 S Heap thread poo
-u0_a193 3164 3154 1522116 53536 ffffffff 00000000 S Heap thread poo
-u0_a193 3165 3154 1522116 53536 ffffffff 00000000 S Heap thread poo
-u0_a193 3166 3154 1522116 53536 ffffffff 00000000 S Signal Catcher
-u0_a193 3167 3154 1522116 53536 ffffffff 00000000 S JDWP
-u0_a193 3168 3154 1522116 53536 ffffffff 00000000 S ReferenceQueueD
-u0_a193 3169 3154 1522116 53536 ffffffff 00000000 S FinalizerDaemon
-u0_a193 3170 3154 1522116 53536 ffffffff 00000000 S FinalizerWatchd
-u0_a193 3171 3154 1522116 53536 ffffffff 00000000 S HeapTrimmerDaem
-u0_a193 3172 3154 1522116 53536 ffffffff 00000000 S GCDaemon
-u0_a193 3173 3154 1522116 53536 ffffffff 00000000 S Binder_1
-u0_a193 3174 3154 1522116 53536 ffffffff 00000000 S Binder_2
-u0_a193 3177 3154 1522116 53536 ffffffff 00000000 S RefQueueWorker@
-u0_a193 3199 3154 1522116 53536 ffffffff 00000000 S WifiManager
-u0_a86 3179 205 1561816 58376 ffffffff 00000000 S com.tencent.mm:push
-u0_a86 3183 3179 1561816 58376 ffffffff 00000000 S Heap thread poo
-u0_a86 3184 3179 1561816 58376 ffffffff 00000000 S Heap thread poo
-u0_a86 3185 3179 1561816 58376 ffffffff 00000000 S Heap thread poo
-u0_a86 3187 3179 1561816 58376 ffffffff 00000000 S Signal Catcher
-u0_a86 3189 3179 1561816 58376 ffffffff 00000000 S JDWP
-u0_a86 3190 3179 1561816 58376 ffffffff 00000000 S ReferenceQueueD
-u0_a86 3191 3179 1561816 58376 ffffffff 00000000 S FinalizerDaemon
-u0_a86 3192 3179 1561816 58376 ffffffff 00000000 S FinalizerWatchd
-u0_a86 3193 3179 1561816 58376 ffffffff 00000000 S HeapTrimmerDaem
-u0_a86 3194 3179 1561816 58376 ffffffff 00000000 S GCDaemon
-u0_a86 3195 3179 1561816 58376 ffffffff 00000000 S Binder_1
-u0_a86 3196 3179 1561816 58376 ffffffff 00000000 S Binder_2
-u0_a86 3210 3179 1561816 58376 ffffffff 00000000 S THREAD_POOL_HAN
-u0_a86 3212 3179 1561816 58376 ffffffff 00000000 S tencent.mm:push
-u0_a86 3216 3179 1561816 58376 ffffffff 00000000 S FileObserver
-u0_a86 3238 3179 1561816 58376 ffffffff 00000000 S tencent.mm:push
-u0_a86 3239 3179 1561816 58376 ffffffff 00000000 S default
-u0_a86 3240 3179 1561816 58376 ffffffff 00000000 S WifiManager
-u0_a86 5627 3179 1561816 58376 ffffffff 00000000 S Binder_3
-u0_a86 7150 3179 1561816 58376 ffffffff 00000000 S default
-u0_a170 3217 205 1531688 52204 ffffffff 00000000 S com.baidu.searchbox:bdservice_v1
-u0_a170 3220 3217 1531688 52204 ffffffff 00000000 S Heap thread poo
-u0_a170 3221 3217 1531688 52204 ffffffff 00000000 S Heap thread poo
-u0_a170 3223 3217 1531688 52204 ffffffff 00000000 S Heap thread poo
-u0_a170 3226 3217 1531688 52204 ffffffff 00000000 S Signal Catcher
-u0_a170 3228 3217 1531688 52204 ffffffff 00000000 S JDWP
-u0_a170 3229 3217 1531688 52204 ffffffff 00000000 S ReferenceQueueD
-u0_a170 3230 3217 1531688 52204 ffffffff 00000000 S FinalizerDaemon
-u0_a170 3231 3217 1531688 52204 ffffffff 00000000 S FinalizerWatchd
-u0_a170 3233 3217 1531688 52204 ffffffff 00000000 S HeapTrimmerDaem
-u0_a170 3234 3217 1531688 52204 ffffffff 00000000 S GCDaemon
-u0_a170 3235 3217 1531688 52204 ffffffff 00000000 S Binder_1
-u0_a170 3236 3217 1531688 52204 ffffffff 00000000 S Binder_2
-u0_a170 3303 3217 1531688 52204 ffffffff 00000000 S AsyncTask #1
-u0_a170 3304 3217 1531688 52204 ffffffff 00000000 S AsyncTask #2
-u0_a170 3518 3217 1531688 52204 ffffffff 00000000 S PushService-Pus
-u0_a170 3519 3217 1531688 52204 ffffffff 00000000 S PushService-Pus
-u0_a170 6201 3217 1531688 52204 ffffffff 00000000 S pool-1-thread-1
-u0_a170 10591 3217 1531688 52204 ffffffff 00000000 S RefQueueWorker@
-u0_a170 3260 205 1533384 53212 ffffffff 00000000 S com.baidu.searchbox:bdmoservice
-u0_a170 3264 3260 1533384 53212 ffffffff 00000000 S Heap thread poo
-u0_a170 3265 3260 1533384 53212 ffffffff 00000000 S Heap thread poo
-u0_a170 3266 3260 1533384 53212 ffffffff 00000000 S Heap thread poo
-u0_a170 3269 3260 1533384 53212 ffffffff 00000000 S Signal Catcher
-u0_a170 3270 3260 1533384 53212 ffffffff 00000000 S JDWP
-u0_a170 3271 3260 1533384 53212 ffffffff 00000000 S ReferenceQueueD
-u0_a170 3272 3260 1533384 53212 ffffffff 00000000 S FinalizerDaemon
-u0_a170 3273 3260 1533384 53212 ffffffff 00000000 S FinalizerWatchd
-u0_a170 3274 3260 1533384 53212 ffffffff 00000000 S HeapTrimmerDaem
-u0_a170 3275 3260 1533384 53212 ffffffff 00000000 S GCDaemon
-u0_a170 3276 3260 1533384 53212 ffffffff 00000000 S Binder_1
-u0_a170 3277 3260 1533384 53212 ffffffff 00000000 S Binder_2
-u0_a170 3738 3260 1533384 53212 ffffffff 00000000 S NanoHttpd Main
-u0_a170 5783 3260 1533384 53212 ffffffff 00000000 S WifiManager
-u0_a126 3633 205 1515740 46080 ffffffff 00000000 S com.tencent.portfolio:push
-u0_a126 3636 3633 1515740 46080 ffffffff 00000000 S Heap thread poo
-u0_a126 3638 3633 1515740 46080 ffffffff 00000000 S Heap thread poo
-u0_a126 3639 3633 1515740 46080 ffffffff 00000000 S Heap thread poo
-u0_a126 3642 3633 1515740 46080 ffffffff 00000000 S Signal Catcher
-u0_a126 3643 3633 1515740 46080 ffffffff 00000000 S JDWP
-u0_a126 3645 3633 1515740 46080 ffffffff 00000000 S ReferenceQueueD
-u0_a126 3646 3633 1515740 46080 ffffffff 00000000 S FinalizerDaemon
-u0_a126 3647 3633 1515740 46080 ffffffff 00000000 S FinalizerWatchd
-u0_a126 3648 3633 1515740 46080 ffffffff 00000000 S HeapTrimmerDaem
-u0_a126 3649 3633 1515740 46080 ffffffff 00000000 S GCDaemon
-u0_a126 3650 3633 1515740 46080 ffffffff 00000000 S Binder_1
-u0_a126 3651 3633 1515740 46080 ffffffff 00000000 S Binder_2
-u0_a126 3661 3633 1515740 46080 ffffffff 00000000 S TPPluginCenter
-u0_a126 3663 3633 1515740 46080 ffffffff 00000000 S pool-1-thread-1
-u0_a126 3665 3633 1515740 46080 ffffffff 00000000 S MidService
-u0_a126 3667 3633 1515740 46080 ffffffff 00000000 S pool-2-thread-1
-u0_a126 3668 3633 1515740 46080 ffffffff 00000000 S push core threa
-u0_a126 3670 3633 1515740 46080 ffffffff 00000000 S .ProcessManager
-u0_a126 3672 3633 1515740 46080 ffffffff 00000000 S Binder_3
-u0_a126 3674 3633 1515740 46080 ffffffff 00000000 S pool-4-thread-1
-u0_a126 3675 3633 1515740 46080 ffffffff 00000000 S pool-3-thread-1
-u0_a126 5638 3633 1515740 46080 ffffffff 00000000 S Timer-0
-bluetooth 4227 205 1527652 48088 ffffffff 00000000 S com.android.bluetooth
-bluetooth 4231 4227 1527652 48088 ffffffff 00000000 S Heap thread poo
-bluetooth 4233 4227 1527652 48088 ffffffff 00000000 S Heap thread poo
-bluetooth 4235 4227 1527652 48088 ffffffff 00000000 S Heap thread poo
-bluetooth 4236 4227 1527652 48088 ffffffff 00000000 S Signal Catcher
-bluetooth 4237 4227 1527652 48088 ffffffff 00000000 S JDWP
-bluetooth 4238 4227 1527652 48088 ffffffff 00000000 S ReferenceQueueD
-bluetooth 4239 4227 1527652 48088 ffffffff 00000000 S FinalizerDaemon
-bluetooth 4240 4227 1527652 48088 ffffffff 00000000 S FinalizerWatchd
-bluetooth 4241 4227 1527652 48088 ffffffff 00000000 S HeapTrimmerDaem
-bluetooth 4242 4227 1527652 48088 ffffffff 00000000 S GCDaemon
-bluetooth 4243 4227 1527652 48088 ffffffff 00000000 S Binder_1
-bluetooth 4244 4227 1527652 48088 ffffffff 00000000 S Binder_2
-bluetooth 4308 4227 1527652 48088 ffffffff 00000000 S BluetoothAdapte
-bluetooth 4309 4227 1527652 48088 ffffffff 00000000 S droid.bluetooth
-bluetooth 4311 4227 1527652 48088 ffffffff 00000000 S bluedroid wake/
-bluetooth 4312 4227 1527652 48088 ffffffff 00000000 S BT Service Call
-bluetooth 4315 4227 1527652 48088 ffffffff 00000000 S BondStateMachin
-bluetooth 4316 4227 1527652 48088 ffffffff 00000000 S Binder_3
-bluetooth 4317 4227 1527652 48088 ffffffff 00000000 S Binder_4
-bluetooth 4318 4227 1527652 48088 ffffffff 00000000 S HeadsetStateMac
-bluetooth 4320 4227 1527652 48088 ffffffff 00000000 S BluetoothAvrcpH
-bluetooth 4321 4227 1527652 48088 ffffffff 00000000 S A2dpStateMachin
-bluetooth 4322 4227 1527652 48088 ffffffff 00000000 S A2DP-MEDIA
-bluetooth 4323 4227 1527652 48088 ffffffff 00000000 S uipc-main
-bluetooth 4324 4227 1527652 48088 ffffffff 00000000 S BluetoothHdpHan
-bluetooth 4325 4227 1527652 48088 ffffffff 00000000 S droid.bluetooth
-bluetooth 4326 4227 1527652 48088 ffffffff 00000000 S BluetoothAdvert
-bluetooth 4327 4227 1527652 48088 ffffffff 00000000 S BluetoothScanMa
-bluetooth 4331 4227 1527652 48088 ffffffff 00000000 S bluedroid wake/
-bluetooth 4333 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker
-bluetooth 4338 4227 1527652 48088 ffffffff 00000000 S userial_read
-bluetooth 4478 4227 1527652 48088 ffffffff 00000000 S BT Service Call
-bluetooth 4479 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker
-bluetooth 4481 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker
-bluetooth 4482 4227 1527652 48088 ffffffff 00000000 S BluetoothMapAcc
-bluetooth 6459 4227 1527652 48088 ffffffff 00000000 S BluetoothPbapAc
-bluetooth 6473 4227 1527652 48088 ffffffff 00000000 S pool-1-thread-1
-bluetooth 6477 4227 1527652 48088 ffffffff 00000000 S BtOppRfcommList
-radio 4597 205 1493160 37460 ffffffff 00000000 S com.qualcomm.qcrilmsgtunnel
-radio 4603 4597 1493160 37460 ffffffff 00000000 S Heap thread poo
-radio 4604 4597 1493160 37460 ffffffff 00000000 S Heap thread poo
-radio 4605 4597 1493160 37460 ffffffff 00000000 S Heap thread poo
-radio 4606 4597 1493160 37460 ffffffff 00000000 S Signal Catcher
-radio 4607 4597 1493160 37460 ffffffff 00000000 S JDWP
-radio 4608 4597 1493160 37460 ffffffff 00000000 S ReferenceQueueD
-radio 4609 4597 1493160 37460 ffffffff 00000000 S FinalizerDaemon
-radio 4610 4597 1493160 37460 ffffffff 00000000 S FinalizerWatchd
-radio 4611 4597 1493160 37460 ffffffff 00000000 S HeapTrimmerDaem
-radio 4612 4597 1493160 37460 ffffffff 00000000 S GCDaemon
-radio 4613 4597 1493160 37460 ffffffff 00000000 S Binder_1
-radio 4614 4597 1493160 37460 ffffffff 00000000 S Binder_2
-radio 4615 4597 1493160 37460 ffffffff 00000000 S QcRilReceiver
-radio 4616 4597 1493160 37460 ffffffff 00000000 S QcRilSender
-u0_a193 5239 205 1528424 47860 ffffffff 00000000 S .iqiyipushserviceGlobal
-u0_a193 5242 5239 1528424 47860 ffffffff 00000000 S Heap thread poo
-u0_a193 5244 5239 1528424 47860 ffffffff 00000000 S Heap thread poo
-u0_a193 5245 5239 1528424 47860 ffffffff 00000000 S Heap thread poo
-u0_a193 5248 5239 1528424 47860 ffffffff 00000000 S Signal Catcher
-u0_a193 5249 5239 1528424 47860 ffffffff 00000000 S JDWP
-u0_a193 5250 5239 1528424 47860 ffffffff 00000000 S ReferenceQueueD
-u0_a193 5251 5239 1528424 47860 ffffffff 00000000 S FinalizerDaemon
-u0_a193 5252 5239 1528424 47860 ffffffff 00000000 S FinalizerWatchd
-u0_a193 5253 5239 1528424 47860 ffffffff 00000000 S HeapTrimmerDaem
-u0_a193 5254 5239 1528424 47860 ffffffff 00000000 S GCDaemon
-u0_a193 5255 5239 1528424 47860 ffffffff 00000000 S Binder_1
-u0_a193 5257 5239 1528424 47860 ffffffff 00000000 S Binder_2
-u0_a193 5280 5239 1528424 47860 ffffffff 00000000 S RefQueueWorker@
-u0_a193 5281 5239 1528424 47860 ffffffff 00000000 S Binder_3
-u0_a193 5361 5239 1528424 47860 ffffffff 00000000 S Micro Client Co
-u0_a193 5362 5239 1528424 47860 ffffffff 00000000 S Micro Client Co
-u0_a193 5363 5239 1528424 47860 ffffffff 00000000 S Micro Client Ca
-u0_a193 6740 5239 1528424 47860 ffffffff 00000000 S Binder_4
-u0_a193 7091 5239 1528424 47860 ffffffff 00000000 S Binder_5
-u0_a193 7557 5239 1528424 47860 ffffffff 00000000 S Binder_6
-u0_a193 5285 5239 1521088 34196 ffffffff 00000000 S .iqiyipushserviceGlobal
-u0_a90 5323 205 1557268 59988 ffffffff 00000000 S com.strava
-u0_a90 5327 5323 1557268 59988 ffffffff 00000000 S Heap thread poo
-u0_a90 5328 5323 1557268 59988 ffffffff 00000000 S Heap thread poo
-u0_a90 5329 5323 1557268 59988 ffffffff 00000000 S Heap thread poo
-u0_a90 5332 5323 1557268 59988 ffffffff 00000000 S Signal Catcher
-u0_a90 5333 5323 1557268 59988 ffffffff 00000000 S JDWP
-u0_a90 5334 5323 1557268 59988 ffffffff 00000000 S ReferenceQueueD
-u0_a90 5335 5323 1557268 59988 ffffffff 00000000 S FinalizerDaemon
-u0_a90 5336 5323 1557268 59988 ffffffff 00000000 S FinalizerWatchd
-u0_a90 5337 5323 1557268 59988 ffffffff 00000000 S HeapTrimmerDaem
-u0_a90 5338 5323 1557268 59988 ffffffff 00000000 S GCDaemon
-u0_a90 5339 5323 1557268 59988 ffffffff 00000000 S Binder_1
-u0_a90 5340 5323 1557268 59988 ffffffff 00000000 S Binder_2
-u0_a90 5345 5323 1557268 59988 ffffffff 00000000 S Queue
-u0_a90 5346 5323 1557268 59988 ffffffff 00000000 S Queue
-u0_a90 5347 5323 1557268 59988 ffffffff 00000000 S Queue
-u0_a90 5348 5323 1557268 59988 ffffffff 00000000 S Queue
-u0_a90 5349 5323 1557268 59988 ffffffff 00000000 S Queue
-u0_a90 5352 5323 1557268 59988 ffffffff 00000000 S Crashlytics Exc
-u0_a90 5354 5323 1557268 59988 ffffffff 00000000 S pool-3-thread-1
-u0_a90 5364 5323 1557268 59988 ffffffff 00000000 S Thread-584
-u0_a90 5365 5323 1557268 59988 ffffffff 00000000 S Thread-585
-u0_a90 5366 5323 1557268 59988 ffffffff 00000000 S Thread-586
-u0_a90 5367 5323 1557268 59988 ffffffff 00000000 S pool-4-thread-1
-u0_a90 5369 5323 1557268 59988 ffffffff 00000000 S Crashlytics Tra
-u0_a90 5372 5323 1557268 59988 ffffffff 00000000 S Thread-593
-u0_a90 5373 5323 1557268 59988 ffffffff 00000000 S Thread-594
-u0_a90 5374 5323 1557268 59988 ffffffff 00000000 S Thread-595
-u0_a90 5375 5323 1557268 59988 ffffffff 00000000 S Thread-596
-u0_a90 5376 5323 1557268 59988 ffffffff 00000000 S pool-6-thread-1
-u0_a90 5377 5323 1557268 59988 ffffffff 00000000 S Thread-598
-u0_a90 5378 5323 1557268 59988 ffffffff 00000000 S Thread-599
-u0_a90 5379 5323 1557268 59988 ffffffff 00000000 S Thread-600
-u0_a90 5381 5323 1557268 59988 ffffffff 00000000 S Thread-602
-u0_a90 5383 5323 1557268 59988 ffffffff 00000000 S Thread #1
-u0_a90 5384 5323 1557268 59988 ffffffff 00000000 S AsyncTask #1
-u0_a90 5387 5323 1557268 59988 ffffffff 00000000 S Thread-605
-u0_a90 5388 5323 1557268 59988 ffffffff 00000000 S Thread-606
-u0_a90 5389 5323 1557268 59988 ffffffff 00000000 S Thread-607
-u0_a90 5390 5323 1557268 59988 ffffffff 00000000 S Thread-608
-u0_a90 5391 5323 1557268 59988 ffffffff 00000000 S Thread-609
-u0_a90 5393 5323 1557268 59988 ffffffff 00000000 S eNowAuthService
-u0_a90 5394 5323 1557268 59988 ffffffff 00000000 S Thread #2
-u0_a90 5468 5323 1557268 59988 ffffffff 00000000 S Okio Watchdog
-u0_a90 5498 5323 1557268 59988 ffffffff 00000000 S Thread #3
-u0_a109 5395 205 1524968 53976 ffffffff 00000000 S com.pandora.android
-u0_a109 5397 5395 1524968 53976 ffffffff 00000000 S Heap thread poo
-u0_a109 5398 5395 1524968 53976 ffffffff 00000000 S Heap thread poo
-u0_a109 5399 5395 1524968 53976 ffffffff 00000000 S Heap thread poo
-u0_a109 5401 5395 1524968 53976 ffffffff 00000000 S Signal Catcher
-u0_a109 5403 5395 1524968 53976 ffffffff 00000000 S JDWP
-u0_a109 5407 5395 1524968 53976 ffffffff 00000000 S ReferenceQueueD
-u0_a109 5408 5395 1524968 53976 ffffffff 00000000 S FinalizerDaemon
-u0_a109 5409 5395 1524968 53976 ffffffff 00000000 S FinalizerWatchd
-u0_a109 5410 5395 1524968 53976 ffffffff 00000000 S HeapTrimmerDaem
-u0_a109 5411 5395 1524968 53976 ffffffff 00000000 S GCDaemon
-u0_a109 5414 5395 1524968 53976 ffffffff 00000000 S Binder_1
-u0_a109 5416 5395 1524968 53976 ffffffff 00000000 S Binder_2
-u0_a109 5422 5395 1524968 53976 ffffffff 00000000 S Crashlytics Exc
-u0_a109 5429 5395 1524968 53976 ffffffff 00000000 S pool-2-thread-1
-u0_a109 5430 5395 1524968 53976 ffffffff 00000000 S AsyncTask #1
-u0_a109 5437 5395 1524968 53976 ffffffff 00000000 S Crashlytics Tra
-u0_a109 5439 5395 1524968 53976 ffffffff 00000000 S AsyncTask #2
-u0_a109 5440 5395 1524968 53976 ffffffff 00000000 S pool-4-thread-1
-u0_a109 5443 5395 1524968 53976 ffffffff 00000000 S PurchasingManag
-u0_a109 5444 5395 1524968 53976 ffffffff 00000000 S BluetoothServer
-u0_a109 5445 5395 1524968 53976 ffffffff 00000000 S AsyncTask #3
-u0_a109 5446 5395 1524968 53976 ffffffff 00000000 S AsyncTask #4
-u0_a109 5590 5395 1524968 53976 ffffffff 00000000 S Binder_3
-u0_a109 6481 5395 1524968 53976 ffffffff 00000000 S AsyncTask #5
-u0_a110 5474 205 1525556 49828 ffffffff 00000000 S tunein.player
-u0_a110 5479 5474 1525556 49828 ffffffff 00000000 S Heap thread poo
-u0_a110 5480 5474 1525556 49828 ffffffff 00000000 S Heap thread poo
-u0_a110 5481 5474 1525556 49828 ffffffff 00000000 S Heap thread poo
-u0_a110 5483 5474 1525556 49828 ffffffff 00000000 S Signal Catcher
-u0_a110 5484 5474 1525556 49828 ffffffff 00000000 S JDWP
-u0_a110 5485 5474 1525556 49828 ffffffff 00000000 S ReferenceQueueD
-u0_a110 5486 5474 1525556 49828 ffffffff 00000000 S FinalizerDaemon
-u0_a110 5487 5474 1525556 49828 ffffffff 00000000 S FinalizerWatchd
-u0_a110 5488 5474 1525556 49828 ffffffff 00000000 S HeapTrimmerDaem
-u0_a110 5489 5474 1525556 49828 ffffffff 00000000 S GCDaemon
-u0_a110 5490 5474 1525556 49828 ffffffff 00000000 S Binder_1
-u0_a110 5492 5474 1525556 49828 ffffffff 00000000 S Binder_2
-u0_a110 5503 5474 1525556 49828 ffffffff 00000000 S geHandlerThread
-u0_a110 5504 5474 1525556 49828 ffffffff 00000000 S GAThread
-u0_a110 5507 5474 1525556 49828 ffffffff 00000000 S Crashlytics Exc
-u0_a110 5510 5474 1525556 49828 ffffffff 00000000 S AsyncTask #1
-u0_a110 5515 5474 1525556 49828 ffffffff 00000000 S Crashlytics Tra
-u0_a110 5518 5474 1525556 49828 ffffffff 00000000 S AsyncTask #2
-u0_a110 5587 5474 1525556 49828 ffffffff 00000000 S AcceptThreadSec
-u0_a88 5519 205 1556696 65876 ffffffff 00000000 S com.dropbox.android
-u0_a88 5525 5519 1556696 65876 ffffffff 00000000 S Heap thread poo
-u0_a88 5526 5519 1556696 65876 ffffffff 00000000 S Heap thread poo
-u0_a88 5527 5519 1556696 65876 ffffffff 00000000 S Heap thread poo
-u0_a88 5528 5519 1556696 65876 ffffffff 00000000 S Signal Catcher
-u0_a88 5529 5519 1556696 65876 ffffffff 00000000 S JDWP
-u0_a88 5530 5519 1556696 65876 ffffffff 00000000 S ReferenceQueueD
-u0_a88 5531 5519 1556696 65876 ffffffff 00000000 S FinalizerDaemon
-u0_a88 5532 5519 1556696 65876 ffffffff 00000000 S FinalizerWatchd
-u0_a88 5533 5519 1556696 65876 ffffffff 00000000 S HeapTrimmerDaem
-u0_a88 5534 5519 1556696 65876 ffffffff 00000000 S GCDaemon
-u0_a88 5535 5519 1556696 65876 ffffffff 00000000 S Binder_1
-u0_a88 5536 5519 1556696 65876 ffffffff 00000000 S Binder_2
-u0_a88 5562 5519 1556696 65876 ffffffff 00000000 S Dropbox log upl
-u0_a88 5563 5519 1556696 65876 ffffffff 00000000 S gandalf updater
-u0_a88 5568 5519 1556696 65876 ffffffff 00000000 S pool-10-thread-
-u0_a88 5569 5519 1556696 65876 ffffffff 00000000 S DbxFileObserver
-u0_a88 5570 5519 1556696 65876 ffffffff 00000000 S LocalThumbManag
-u0_a88 5574 5519 1556696 65876 ffffffff 00000000 S local AsyncTask
-u0_a88 5575 5519 1556696 65876 ffffffff 00000000 S remote AsyncTas
-u0_a88 5576 5519 1556696 65876 ffffffff 00000000 S local AsyncTask
-u0_a88 5577 5519 1556696 65876 ffffffff 00000000 S remote AsyncTas
-u0_a88 5578 5519 1556696 65876 ffffffff 00000000 S Dropbox notif o
-u0_a88 5579 5519 1556696 65876 ffffffff 00000000 S Dropbox notif s
-u0_a88 5580 5519 1556696 65876 ffffffff 00000000 S Picasso-Stats
-u0_a88 5581 5519 1556696 65876 ffffffff 00000000 S Picasso-Dispatc
-u0_a88 5582 5519 1556696 65876 ffffffff 00000000 S Picasso-refQueu
-u0_a88 5583 5519 1556696 65876 ffffffff 00000000 S gandalf updater
-u0_a88 5592 5519 1556696 65876 ffffffff 00000000 S DbxFileObserver
-u0_a88 5593 5519 1556696 65876 ffffffff 00000000 S dbxpool-34:r-th
-u0_a88 5594 5519 1556696 65876 ffffffff 00000000 S dbxpool-32:au-t
-u0_a88 5595 5519 1556696 65876 ffffffff 00000000 S dbxpool-38:a-th
-u0_a88 5596 5519 1556696 65876 ffffffff 00000000 S Timer-0
-u0_a88 5597 5519 1556696 65876 ffffffff 00000000 S dbxpool-6:a-thr
-u0_a88 5599 5519 1556696 65876 ffffffff 00000000 S Timer-1
-u0_a88 5718 5519 1556696 65876 ffffffff 00000000 S RefQueueWorker@
-u0_a88 5750 5519 1556696 65876 ffffffff 00000000 S Thread-625
-u0_a88 5818 5519 1556696 65876 ffffffff 00000000 S Binder_3
-u0_a88 8569 5519 1556696 65876 ffffffff 00000000 S Binder_4
-u0_a88 8572 5519 1556696 65876 ffffffff 00000000 S Binder_5
-u0_a88 8580 5519 1556696 65876 ffffffff 00000000 S Binder_6
-u0_a93 5688 205 1496212 39724 ffffffff 00000000 S com.devuni.flashlight:remote
-u0_a93 5693 5688 1496212 39724 ffffffff 00000000 S Heap thread poo
-u0_a93 5694 5688 1496212 39724 ffffffff 00000000 S Heap thread poo
-u0_a93 5695 5688 1496212 39724 ffffffff 00000000 S Heap thread poo
-u0_a93 5697 5688 1496212 39724 ffffffff 00000000 S Signal Catcher
-u0_a93 5698 5688 1496212 39724 ffffffff 00000000 S JDWP
-u0_a93 5699 5688 1496212 39724 ffffffff 00000000 S ReferenceQueueD
-u0_a93 5700 5688 1496212 39724 ffffffff 00000000 S FinalizerDaemon
-u0_a93 5701 5688 1496212 39724 ffffffff 00000000 S FinalizerWatchd
-u0_a93 5702 5688 1496212 39724 ffffffff 00000000 S HeapTrimmerDaem
-u0_a93 5703 5688 1496212 39724 ffffffff 00000000 S GCDaemon
-u0_a93 5704 5688 1496212 39724 ffffffff 00000000 S Binder_1
-u0_a93 5705 5688 1496212 39724 ffffffff 00000000 S Binder_2
-u0_a93 12039 5688 1496212 39724 ffffffff 00000000 S pool-1-thread-1
-u0_a86 6202 205 1809096 86876 ffffffff 00000000 S com.tencent.mm
-u0_a86 6206 6202 1809096 86876 ffffffff 00000000 S Heap thread poo
-u0_a86 6207 6202 1809096 86876 ffffffff 00000000 S Heap thread poo
-u0_a86 6208 6202 1809096 86876 ffffffff 00000000 S Heap thread poo
-u0_a86 6211 6202 1809096 86876 ffffffff 00000000 S Signal Catcher
-u0_a86 6212 6202 1809096 86876 ffffffff 00000000 S JDWP
-u0_a86 6213 6202 1809096 86876 ffffffff 00000000 S ReferenceQueueD
-u0_a86 6214 6202 1809096 86876 ffffffff 00000000 S FinalizerDaemon
-u0_a86 6215 6202 1809096 86876 ffffffff 00000000 S FinalizerWatchd
-u0_a86 6217 6202 1809096 86876 ffffffff 00000000 S HeapTrimmerDaem
-u0_a86 6218 6202 1809096 86876 ffffffff 00000000 S GCDaemon
-u0_a86 6220 6202 1809096 86876 ffffffff 00000000 S Binder_1
-u0_a86 6221 6202 1809096 86876 ffffffff 00000000 S Binder_2
-u0_a86 6236 6202 1809096 86876 ffffffff 00000000 S THREAD_POOL_HAN
-u0_a86 6237 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm
-u0_a86 6239 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm
-u0_a86 6240 6202 1809096 86876 ffffffff 00000000 S MonitorHandlerT
-u0_a86 6241 6202 1809096 86876 ffffffff 00000000 S .ProcessManager
-u0_a86 6243 6202 1809096 86876 ffffffff 00000000 S Binder_3
-u0_a86 6245 6202 1809096 86876 ffffffff 00000000 S default
-u0_a86 6246 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm
-u0_a86 6247 6202 1809096 86876 ffffffff 00000000 S MMHandlerThread
-u0_a86 6269 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6270 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6271 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6272 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6273 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6274 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6276 6202 1809096 86876 ffffffff 00000000 S ExdeviceHandler
-u0_a86 6277 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6279 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout
-u0_a86 6280 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout
-u0_a86 6282 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6284 6202 1809096 86876 ffffffff 00000000 S downloadStateCh
-u0_a86 6288 6202 1809096 86876 ffffffff 00000000 S WifiManager
-u0_a86 6289 6202 1809096 86876 ffffffff 00000000 S refresh Notific
-u0_a86 6292 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6293 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6294 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_
-u0_a86 6295 6202 1809096 86876 ffffffff 00000000 S SearchDaemon
-u0_a86 6303 6202 1809096 86876 ffffffff 00000000 S Binder_4
-u0_a86 6313 6202 1809096 86876 ffffffff 00000000 S pool-2-thread-1
-u0_a86 6373 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout
-u0_a86 6408 6202 1809096 86876 ffffffff 00000000 S h
-u0_a86 7230 6202 1809096 86876 ffffffff 00000000 S default
-u0_a86 7231 6202 1809096 86876 ffffffff 00000000 S MMHandlerThread
-u0_a191 8839 205 1510312 57352 ffffffff 00000000 S com.ushaqi.zhuishushenqi:pushservice
-u0_a191 8845 8839 1510312 57352 ffffffff 00000000 S Heap thread poo
-u0_a191 8846 8839 1510312 57352 ffffffff 00000000 S Heap thread poo
-u0_a191 8847 8839 1510312 57352 ffffffff 00000000 S Heap thread poo
-u0_a191 8849 8839 1510312 57352 ffffffff 00000000 S Signal Catcher
-u0_a191 8850 8839 1510312 57352 ffffffff 00000000 S JDWP
-u0_a191 8851 8839 1510312 57352 ffffffff 00000000 S ReferenceQueueD
-u0_a191 8852 8839 1510312 57352 ffffffff 00000000 S FinalizerDaemon
-u0_a191 8853 8839 1510312 57352 ffffffff 00000000 S FinalizerWatchd
-u0_a191 8854 8839 1510312 57352 ffffffff 00000000 S HeapTrimmerDaem
-u0_a191 8855 8839 1510312 57352 ffffffff 00000000 S GCDaemon
-u0_a191 8856 8839 1510312 57352 ffffffff 00000000 S Binder_1
-u0_a191 8857 8839 1510312 57352 ffffffff 00000000 S Binder_2
-u0_a191 8867 8839 1510312 57352 ffffffff 00000000 S local_job_dispa
-u0_a191 8869 8839 1510312 57352 ffffffff 00000000 S remote_job_disp
-u0_a191 8887 8839 1510312 57352 ffffffff 00000000 S Upload Http Rec
-u0_a191 8890 8839 1510312 57352 ffffffff 00000000 S Connection Cont
-u0_a191 8963 8839 1510312 57352 ffffffff 00000000 S Smack Packet Re
-root 11634 2 0 0 ffffffff 00000000 S kworker/u:0
-root 11779 2 0 0 ffffffff 00000000 S kworker/0:3H
-root 11928 2 0 0 ffffffff 00000000 S kworker/0:1
-root 12431 2 0 0 ffffffff 00000000 S kworker/u:2
-u0_a85 12971 205 1595348 59000 ffffffff 00000000 S com.life360.android.safetymapd:service
-u0_a85 12977 12971 1595348 59000 ffffffff 00000000 S Heap thread poo
-u0_a85 12978 12971 1595348 59000 ffffffff 00000000 S Heap thread poo
-u0_a85 12979 12971 1595348 59000 ffffffff 00000000 S Heap thread poo
-u0_a85 12980 12971 1595348 59000 ffffffff 00000000 S Signal Catcher
-u0_a85 12981 12971 1595348 59000 ffffffff 00000000 S JDWP
-u0_a85 12982 12971 1595348 59000 ffffffff 00000000 S ReferenceQueueD
-u0_a85 12983 12971 1595348 59000 ffffffff 00000000 S FinalizerDaemon
-u0_a85 12984 12971 1595348 59000 ffffffff 00000000 S FinalizerWatchd
-u0_a85 12985 12971 1595348 59000 ffffffff 00000000 S HeapTrimmerDaem
-u0_a85 12986 12971 1595348 59000 ffffffff 00000000 S GCDaemon
-u0_a85 12987 12971 1595348 59000 ffffffff 00000000 S Binder_1
-u0_a85 12988 12971 1595348 59000 ffffffff 00000000 S Binder_2
-u0_a85 13099 12971 1595348 59000 ffffffff 00000000 S WifiManager
-u0_a106 13071 205 1523392 47680 ffffffff 00000000 S com.xianguo.tingguo
-u0_a106 13075 13071 1523392 47680 ffffffff 00000000 S Heap thread poo
-u0_a106 13076 13071 1523392 47680 ffffffff 00000000 S Heap thread poo
-u0_a106 13077 13071 1523392 47680 ffffffff 00000000 S Heap thread poo
-u0_a106 13080 13071 1523392 47680 ffffffff 00000000 S Signal Catcher
-u0_a106 13081 13071 1523392 47680 ffffffff 00000000 S JDWP
-u0_a106 13082 13071 1523392 47680 ffffffff 00000000 S ReferenceQueueD
-u0_a106 13083 13071 1523392 47680 ffffffff 00000000 S FinalizerDaemon
-u0_a106 13084 13071 1523392 47680 ffffffff 00000000 S FinalizerWatchd
-u0_a106 13085 13071 1523392 47680 ffffffff 00000000 S HeapTrimmerDaem
-u0_a106 13086 13071 1523392 47680 ffffffff 00000000 S GCDaemon
-u0_a106 13087 13071 1523392 47680 ffffffff 00000000 S Binder_1
-u0_a106 13088 13071 1523392 47680 ffffffff 00000000 S Binder_2
-u0_a106 13090 13071 1523392 47680 ffffffff 00000000 S SoundPool
-u0_a106 13091 13071 1523392 47680 ffffffff 00000000 S SoundPoolThread
-u0_a106 13276 13071 1523392 47680 ffffffff 00000000 S WifiManager
-u0_a65 13345 205 1526244 52680 ffffffff 00000000 S com.google.android.apps.photos
-u0_a65 13351 13345 1526244 52680 ffffffff 00000000 S Heap thread poo
-u0_a65 13352 13345 1526244 52680 ffffffff 00000000 S Heap thread poo
-u0_a65 13353 13345 1526244 52680 ffffffff 00000000 S Heap thread poo
-u0_a65 13354 13345 1526244 52680 ffffffff 00000000 S Signal Catcher
-u0_a65 13355 13345 1526244 52680 ffffffff 00000000 S JDWP
-u0_a65 13356 13345 1526244 52680 ffffffff 00000000 S ReferenceQueueD
-u0_a65 13357 13345 1526244 52680 ffffffff 00000000 S FinalizerDaemon
-u0_a65 13358 13345 1526244 52680 ffffffff 00000000 S FinalizerWatchd
-u0_a65 13359 13345 1526244 52680 ffffffff 00000000 S HeapTrimmerDaem
-u0_a65 13360 13345 1526244 52680 ffffffff 00000000 S GCDaemon
-u0_a65 13361 13345 1526244 52680 ffffffff 00000000 S Binder_1
-u0_a65 13362 13345 1526244 52680 ffffffff 00000000 S Binder_2
-u0_a65 13783 13345 1526244 52680 ffffffff 00000000 S pool-1-thread-1
-u0_a65 13796 13345 1526244 52680 ffffffff 00000000 S rotating_file-t
-u0_a65 13904 13345 1526244 52680 ffffffff 00000000 S Binder_3
-u0_a67 13491 205 1567688 56576 ffffffff 00000000 S com.google.android.apps.plus
-u0_a67 13493 13491 1567688 56576 ffffffff 00000000 S Heap thread poo
-u0_a67 13494 13491 1567688 56576 ffffffff 00000000 S Heap thread poo
-u0_a67 13495 13491 1567688 56576 ffffffff 00000000 S Heap thread poo
-u0_a67 13497 13491 1567688 56576 ffffffff 00000000 S Signal Catcher
-u0_a67 13499 13491 1567688 56576 ffffffff 00000000 S JDWP
-u0_a67 13502 13491 1567688 56576 ffffffff 00000000 S ReferenceQueueD
-u0_a67 13503 13491 1567688 56576 ffffffff 00000000 S FinalizerDaemon
-u0_a67 13504 13491 1567688 56576 ffffffff 00000000 S FinalizerWatchd
-u0_a67 13505 13491 1567688 56576 ffffffff 00000000 S HeapTrimmerDaem
-u0_a67 13506 13491 1567688 56576 ffffffff 00000000 S GCDaemon
-u0_a67 13507 13491 1567688 56576 ffffffff 00000000 S Binder_1
-u0_a67 13508 13491 1567688 56576 ffffffff 00000000 S Binder_2
-u0_a67 13512 13491 1567688 56576 ffffffff 00000000 S picasa-photo-pr
-u0_a67 13528 13491 1567688 56576 ffffffff 00000000 S iu-sync-manager
-u0_a67 13538 13491 1567688 56576 ffffffff 00000000 S pool-2-thread-1
-u0_a67 13881 13491 1567688 56576 ffffffff 00000000 S Gservices
-u0_a4 13516 205 1503264 48612 ffffffff 00000000 S android.process.acore
-u0_a4 13520 13516 1503264 48612 ffffffff 00000000 S Heap thread poo
-u0_a4 13521 13516 1503264 48612 ffffffff 00000000 S Heap thread poo
-u0_a4 13522 13516 1503264 48612 ffffffff 00000000 S Heap thread poo
-u0_a4 13525 13516 1503264 48612 ffffffff 00000000 S Signal Catcher
-u0_a4 13526 13516 1503264 48612 ffffffff 00000000 S JDWP
-u0_a4 13527 13516 1503264 48612 ffffffff 00000000 S ReferenceQueueD
-u0_a4 13529 13516 1503264 48612 ffffffff 00000000 S FinalizerDaemon
-u0_a4 13530 13516 1503264 48612 ffffffff 00000000 S FinalizerWatchd
-u0_a4 13531 13516 1503264 48612 ffffffff 00000000 S HeapTrimmerDaem
-u0_a4 13532 13516 1503264 48612 ffffffff 00000000 S GCDaemon
-u0_a4 13533 13516 1503264 48612 ffffffff 00000000 S Binder_1
-u0_a4 13534 13516 1503264 48612 ffffffff 00000000 S Binder_2
-u0_a4 13536 13516 1503264 48612 ffffffff 00000000 S ContactsProvide
-u0_a4 13537 13516 1503264 48612 ffffffff 00000000 S CallLogProvider
-u0_a102 13613 205 1521420 45204 ffffffff 00000000 S com.sohu.inputmethod.sogou:classic
-u0_a102 13616 13613 1521420 45204 ffffffff 00000000 S Heap thread poo
-u0_a102 13617 13613 1521420 45204 ffffffff 00000000 S Heap thread poo
-u0_a102 13618 13613 1521420 45204 ffffffff 00000000 S Heap thread poo
-u0_a102 13620 13613 1521420 45204 ffffffff 00000000 S Signal Catcher
-u0_a102 13623 13613 1521420 45204 ffffffff 00000000 S JDWP
-u0_a102 13624 13613 1521420 45204 ffffffff 00000000 S ReferenceQueueD
-u0_a102 13625 13613 1521420 45204 ffffffff 00000000 S FinalizerDaemon
-u0_a102 13626 13613 1521420 45204 ffffffff 00000000 S FinalizerWatchd
-u0_a102 13627 13613 1521420 45204 ffffffff 00000000 S HeapTrimmerDaem
-u0_a102 13628 13613 1521420 45204 ffffffff 00000000 S GCDaemon
-u0_a102 13629 13613 1521420 45204 ffffffff 00000000 S Binder_1
-u0_a102 13630 13613 1521420 45204 ffffffff 00000000 S Binder_2
-u0_a102 13635 13613 1521420 45204 ffffffff 00000000 S Thread-1443
-u0_a102 13636 13613 1521420 45204 ffffffff 00000000 S Thread-1444
-u0_a102 13637 13613 1521420 45204 ffffffff 00000000 S Thread-1445
-u0_a102 13638 13613 1521420 45204 ffffffff 00000000 S Thread-1446
-u0_a102 13639 13613 1521420 45204 ffffffff 00000000 S Thread-1447
-u0_a102 13641 13613 1521420 45204 ffffffff 00000000 S WifiManager
-u0_a102 13905 13613 1521420 45204 ffffffff 00000000 S Binder_3
-u0_a102 13647 205 1514052 44264 ffffffff 00000000 S com.sohu.inputmethod.sogou
-u0_a102 13651 13647 1514052 44264 ffffffff 00000000 S Heap thread poo
-u0_a102 13652 13647 1514052 44264 ffffffff 00000000 S Heap thread poo
-u0_a102 13653 13647 1514052 44264 ffffffff 00000000 S Heap thread poo
-u0_a102 13656 13647 1514052 44264 ffffffff 00000000 S Signal Catcher
-u0_a102 13657 13647 1514052 44264 ffffffff 00000000 S JDWP
-u0_a102 13658 13647 1514052 44264 ffffffff 00000000 S ReferenceQueueD
-u0_a102 13659 13647 1514052 44264 ffffffff 00000000 S FinalizerDaemon
-u0_a102 13660 13647 1514052 44264 ffffffff 00000000 S FinalizerWatchd
-u0_a102 13661 13647 1514052 44264 ffffffff 00000000 S HeapTrimmerDaem
-u0_a102 13662 13647 1514052 44264 ffffffff 00000000 S GCDaemon
-u0_a102 13663 13647 1514052 44264 ffffffff 00000000 S Binder_1
-u0_a102 13664 13647 1514052 44264 ffffffff 00000000 S Binder_2
-u0_a102 13671 205 1519416 43248 ffffffff 00000000 S sogou.mobile.explorer.hotwords
-u0_a102 13677 13671 1519416 43248 ffffffff 00000000 S Heap thread poo
-u0_a102 13678 13671 1519416 43248 ffffffff 00000000 S Heap thread poo
-u0_a102 13679 13671 1519416 43248 ffffffff 00000000 S Heap thread poo
-u0_a102 13680 13671 1519416 43248 ffffffff 00000000 S Signal Catcher
-u0_a102 13681 13671 1519416 43248 ffffffff 00000000 S JDWP
-u0_a102 13682 13671 1519416 43248 ffffffff 00000000 S ReferenceQueueD
-u0_a102 13683 13671 1519416 43248 ffffffff 00000000 S FinalizerDaemon
-u0_a102 13684 13671 1519416 43248 ffffffff 00000000 S FinalizerWatchd
-u0_a102 13685 13671 1519416 43248 ffffffff 00000000 S HeapTrimmerDaem
-u0_a102 13686 13671 1519416 43248 ffffffff 00000000 S GCDaemon
-u0_a102 13687 13671 1519416 43248 ffffffff 00000000 S Binder_1
-u0_a102 13688 13671 1519416 43248 ffffffff 00000000 S Binder_2
-u0_a102 13690 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-1
-u0_a102 13691 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-2
-u0_a102 13692 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-3
-u0_a102 13694 13671 1519416 43248 ffffffff 00000000 S Timer-0
-u0_a198 13695 205 1506040 40332 ffffffff 00000000 S org.chromium.chrome.shell
-u0_a198 13701 13695 1506040 40332 ffffffff 00000000 S Heap thread poo
-u0_a198 13702 13695 1506040 40332 ffffffff 00000000 S Heap thread poo
-u0_a198 13703 13695 1506040 40332 ffffffff 00000000 S Heap thread poo
-u0_a198 13704 13695 1506040 40332 ffffffff 00000000 S Signal Catcher
-u0_a198 13705 13695 1506040 40332 ffffffff 00000000 S JDWP
-u0_a198 13706 13695 1506040 40332 ffffffff 00000000 S ReferenceQueueD
-u0_a198 13707 13695 1506040 40332 ffffffff 00000000 S FinalizerDaemon
-u0_a198 13708 13695 1506040 40332 ffffffff 00000000 S FinalizerWatchd
-u0_a198 13709 13695 1506040 40332 ffffffff 00000000 S HeapTrimmerDaem
-u0_a198 13710 13695 1506040 40332 ffffffff 00000000 S GCDaemon
-u0_a198 13711 13695 1506040 40332 ffffffff 00000000 S Binder_1
-u0_a198 13712 13695 1506040 40332 ffffffff 00000000 S Binder_2
-u0_a198 13713 13695 1506040 40332 ffffffff 00000000 S Binder_3
-u0_a200 13715 205 1511344 38748 ffffffff 00000000 S com.rolocule.motiontennis
-u0_a200 13721 13715 1511344 38748 ffffffff 00000000 S Heap thread poo
-u0_a200 13722 13715 1511344 38748 ffffffff 00000000 S Heap thread poo
-u0_a200 13723 13715 1511344 38748 ffffffff 00000000 S Heap thread poo
-u0_a200 13724 13715 1511344 38748 ffffffff 00000000 S Signal Catcher
-u0_a200 13725 13715 1511344 38748 ffffffff 00000000 S JDWP
-u0_a200 13731 13715 1511344 38748 ffffffff 00000000 S ReferenceQueueD
-u0_a200 13732 13715 1511344 38748 ffffffff 00000000 S FinalizerDaemon
-u0_a200 13733 13715 1511344 38748 ffffffff 00000000 S FinalizerWatchd
-u0_a200 13734 13715 1511344 38748 ffffffff 00000000 S HeapTrimmerDaem
-u0_a200 13735 13715 1511344 38748 ffffffff 00000000 S GCDaemon
-u0_a200 13736 13715 1511344 38748 ffffffff 00000000 S Binder_1
-u0_a200 13737 13715 1511344 38748 ffffffff 00000000 S Binder_2
-u0_a175 13747 205 1510096 43460 ffffffff 00000000 S com.google.android.apps.chrome
-u0_a175 13751 13747 1510096 43460 ffffffff 00000000 S Heap thread poo
-u0_a175 13752 13747 1510096 43460 ffffffff 00000000 S Heap thread poo
-u0_a175 13754 13747 1510096 43460 ffffffff 00000000 S Heap thread poo
-u0_a175 13756 13747 1510096 43460 ffffffff 00000000 S Signal Catcher
-u0_a175 13757 13747 1510096 43460 ffffffff 00000000 S JDWP
-u0_a175 13758 13747 1510096 43460 ffffffff 00000000 S ReferenceQueueD
-u0_a175 13759 13747 1510096 43460 ffffffff 00000000 S FinalizerDaemon
-u0_a175 13760 13747 1510096 43460 ffffffff 00000000 S FinalizerWatchd
-u0_a175 13761 13747 1510096 43460 ffffffff 00000000 S HeapTrimmerDaem
-u0_a175 13762 13747 1510096 43460 ffffffff 00000000 S GCDaemon
-u0_a175 13763 13747 1510096 43460 ffffffff 00000000 S Binder_1
-u0_a175 13764 13747 1510096 43460 ffffffff 00000000 S Binder_2
-u0_a85 13774 205 1594212 50972 ffffffff 00000000 S com.life360.android.safetymapd
-u0_a85 13780 13774 1594212 50972 ffffffff 00000000 S Heap thread poo
-u0_a85 13781 13774 1594212 50972 ffffffff 00000000 S Heap thread poo
-u0_a85 13782 13774 1594212 50972 ffffffff 00000000 S Heap thread poo
-u0_a85 13784 13774 1594212 50972 ffffffff 00000000 S Signal Catcher
-u0_a85 13785 13774 1594212 50972 ffffffff 00000000 S JDWP
-u0_a85 13786 13774 1594212 50972 ffffffff 00000000 S ReferenceQueueD
-u0_a85 13787 13774 1594212 50972 ffffffff 00000000 S FinalizerDaemon
-u0_a85 13788 13774 1594212 50972 ffffffff 00000000 S FinalizerWatchd
-u0_a85 13789 13774 1594212 50972 ffffffff 00000000 S HeapTrimmerDaem
-u0_a85 13790 13774 1594212 50972 ffffffff 00000000 S GCDaemon
-u0_a85 13791 13774 1594212 50972 ffffffff 00000000 S Binder_1
-u0_a85 13792 13774 1594212 50972 ffffffff 00000000 S Binder_2
-u0_a16 13801 205 1538004 50644 ffffffff 00000000 S com.android.vending
-u0_a16 13807 13801 1538004 50644 ffffffff 00000000 S Heap thread poo
-u0_a16 13808 13801 1538004 50644 ffffffff 00000000 S Heap thread poo
-u0_a16 13809 13801 1538004 50644 ffffffff 00000000 S Heap thread poo
-u0_a16 13811 13801 1538004 50644 ffffffff 00000000 S Signal Catcher
-u0_a16 13812 13801 1538004 50644 ffffffff 00000000 S JDWP
-u0_a16 13813 13801 1538004 50644 ffffffff 00000000 S ReferenceQueueD
-u0_a16 13814 13801 1538004 50644 ffffffff 00000000 S FinalizerDaemon
-u0_a16 13815 13801 1538004 50644 ffffffff 00000000 S FinalizerWatchd
-u0_a16 13816 13801 1538004 50644 ffffffff 00000000 S HeapTrimmerDaem
-u0_a16 13817 13801 1538004 50644 ffffffff 00000000 S GCDaemon
-u0_a16 13818 13801 1538004 50644 ffffffff 00000000 S Binder_1
-u0_a16 13819 13801 1538004 50644 ffffffff 00000000 S Binder_2
-u0_a16 13828 13801 1538004 50644 ffffffff 00000000 S Gservices
-u0_a16 13833 13801 1538004 50644 ffffffff 00000000 S pool-1-thread-1
-u0_a16 13834 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@
-u0_a16 13837 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@
-u0_a16 13838 13801 1538004 50644 ffffffff 00000000 S Thread-1482
-u0_a16 13839 13801 1538004 50644 ffffffff 00000000 S Thread-1483
-u0_a16 13840 13801 1538004 50644 ffffffff 00000000 S Thread-1484
-u0_a16 13843 13801 1538004 50644 ffffffff 00000000 S download-manage
-u0_a16 13844 13801 1538004 50644 ffffffff 00000000 S NetworkQualityQ
-u0_a16 13845 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@
-u0_a16 13846 13801 1538004 50644 ffffffff 00000000 S Thread-1489
-u0_a16 13847 13801 1538004 50644 ffffffff 00000000 S Thread-1490
-u0_a16 13848 13801 1538004 50644 ffffffff 00000000 S Thread-1491
-u0_a16 13849 13801 1538004 50644 ffffffff 00000000 S Thread-1492
-u0_a16 13850 13801 1538004 50644 ffffffff 00000000 S Thread-1493
-u0_a16 13851 13801 1538004 50644 ffffffff 00000000 S PlayEventLogger
-u0_a16 13852 13801 1538004 50644 ffffffff 00000000 S tentative-gc-ru
-u0_a16 13862 13801 1538004 50644 ffffffff 00000000 S libraries-threa
-u0_a16 13872 13801 1538004 50644 ffffffff 00000000 S AsyncTask #1
-u0_a16 13876 13801 1538004 50644 ffffffff 00000000 S AsyncTask #2
-u0_a16 13877 13801 1538004 50644 ffffffff 00000000 S AsyncTask #3
-u0_a16 13878 13801 1538004 50644 ffffffff 00000000 S PlayEventLogger
-u0_a16 13880 13801 1538004 50644 ffffffff 00000000 S Thread-1501
-u0_a16 14407 13801 1538004 50644 ffffffff 00000000 S Binder_3
-u0_a8 13853 205 1573700 51720 ffffffff 00000000 S com.google.android.gms:car
-u0_a8 13856 13853 1573700 51720 ffffffff 00000000 S Heap thread poo
-u0_a8 13857 13853 1573700 51720 ffffffff 00000000 S Heap thread poo
-u0_a8 13858 13853 1573700 51720 ffffffff 00000000 S Heap thread poo
-u0_a8 13863 13853 1573700 51720 ffffffff 00000000 S Signal Catcher
-u0_a8 13864 13853 1573700 51720 ffffffff 00000000 S JDWP
-u0_a8 13865 13853 1573700 51720 ffffffff 00000000 S ReferenceQueueD
-u0_a8 13866 13853 1573700 51720 ffffffff 00000000 S FinalizerDaemon
-u0_a8 13867 13853 1573700 51720 ffffffff 00000000 S FinalizerWatchd
-u0_a8 13868 13853 1573700 51720 ffffffff 00000000 S HeapTrimmerDaem
-u0_a8 13869 13853 1573700 51720 ffffffff 00000000 S GCDaemon
-u0_a8 13870 13853 1573700 51720 ffffffff 00000000 S Binder_1
-u0_a8 13871 13853 1573700 51720 ffffffff 00000000 S Binder_2
-u0_a8 13873 13853 1573700 51720 ffffffff 00000000 S Gservices
-u0_a8 13913 13853 1573700 51720 ffffffff 00000000 S Binder_3
-u0_a8 13885 205 1572668 47460 ffffffff 00000000 S com.google.android.gms.wearable
-u0_a8 13890 13885 1572668 47460 ffffffff 00000000 S Heap thread poo
-u0_a8 13891 13885 1572668 47460 ffffffff 00000000 S Heap thread poo
-u0_a8 13892 13885 1572668 47460 ffffffff 00000000 S Heap thread poo
-u0_a8 13894 13885 1572668 47460 ffffffff 00000000 S Signal Catcher
-u0_a8 13895 13885 1572668 47460 ffffffff 00000000 S JDWP
-u0_a8 13896 13885 1572668 47460 ffffffff 00000000 S ReferenceQueueD
-u0_a8 13897 13885 1572668 47460 ffffffff 00000000 S FinalizerDaemon
-u0_a8 13898 13885 1572668 47460 ffffffff 00000000 S FinalizerWatchd
-u0_a8 13899 13885 1572668 47460 ffffffff 00000000 S HeapTrimmerDaem
-u0_a8 13900 13885 1572668 47460 ffffffff 00000000 S GCDaemon
-u0_a8 13901 13885 1572668 47460 ffffffff 00000000 S Binder_1
-u0_a8 13902 13885 1572668 47460 ffffffff 00000000 S Binder_2
-u0_a8 13903 13885 1572668 47460 ffffffff 00000000 S Gservices
-root 14061 2 0 0 ffffffff 00000000 S kworker/u:3
-root 14136 2 0 0 ffffffff 00000000 S kworker/0:0H
-u0_a101 14356 205 1503136 44308 ffffffff 00000000 S com.google.android.apps.gcs
-u0_a101 14362 14356 1503136 44308 ffffffff 00000000 S Heap thread poo
-u0_a101 14363 14356 1503136 44308 ffffffff 00000000 S Heap thread poo
-u0_a101 14364 14356 1503136 44308 ffffffff 00000000 S Heap thread poo
-u0_a101 14365 14356 1503136 44308 ffffffff 00000000 S Signal Catcher
-u0_a101 14366 14356 1503136 44308 ffffffff 00000000 S JDWP
-u0_a101 14367 14356 1503136 44308 ffffffff 00000000 S ReferenceQueueD
-u0_a101 14368 14356 1503136 44308 ffffffff 00000000 S FinalizerDaemon
-u0_a101 14369 14356 1503136 44308 ffffffff 00000000 S FinalizerWatchd
-u0_a101 14370 14356 1503136 44308 ffffffff 00000000 S HeapTrimmerDaem
-u0_a101 14371 14356 1503136 44308 ffffffff 00000000 S GCDaemon
-u0_a101 14372 14356 1503136 44308 ffffffff 00000000 S Binder_1
-u0_a101 14373 14356 1503136 44308 ffffffff 00000000 S Binder_2
-u0_a101 14375 14356 1503136 44308 ffffffff 00000000 S Gservices
-u0_a101 14376 14356 1503136 44308 ffffffff 00000000 S RefQueueWorker@
-u0_a101 14377 14356 1503136 44308 ffffffff 00000000 S Thread-1495
-u0_a101 14378 14356 1503136 44308 ffffffff 00000000 S Thread-1496
-u0_a101 14379 14356 1503136 44308 ffffffff 00000000 S Thread-1497
-u0_a101 14380 14356 1503136 44308 ffffffff 00000000 S Thread-1498
-u0_a101 14381 14356 1503136 44308 ffffffff 00000000 S Thread-1499
-shell 14444 209 9316 612 c01a863c b6eeee44 S /system/bin/sh
-shell 14448 14444 10672 768 00000000 b6ef0da8 R ps
+USER PID PPID VSIZE RSS WCHAN PC NAME +root 1 0 8784 712 ffffffff 00000000 S /init +root 2 0 0 0 ffffffff 00000000 S kthreadd +root 3 2 0 0 ffffffff 00000000 S ksoftirqd/0 +root 7 2 0 0 ffffffff 00000000 D kworker/u:0H +root 8 2 0 0 ffffffff 00000000 S migration/0 +root 13 2 0 0 ffffffff 00000000 S khelper +root 14 2 0 0 ffffffff 00000000 S netns +root 17 2 0 0 ffffffff 00000000 S kworker/0:1H +root 18 2 0 0 ffffffff 00000000 S modem_notifier +root 19 2 0 0 ffffffff 00000000 S smd_channel_clo +root 20 2 0 0 ffffffff 00000000 S smsm_cb_wq +root 21 2 0 0 ffffffff 00000000 S kworker/u:1 +root 22 2 0 0 ffffffff 00000000 S rpm-smd +root 23 2 0 0 ffffffff 00000000 S kworker/u:1H +root 24 2 0 0 ffffffff 00000000 S irq/317-earjack +root 25 2 0 0 ffffffff 00000000 S sync_supers +root 26 2 0 0 ffffffff 00000000 S bdi-default +root 27 2 0 0 ffffffff 00000000 S kblockd +root 28 2 0 0 ffffffff 00000000 S vmalloc +root 29 2 0 0 ffffffff 00000000 S khubd +root 30 2 0 0 ffffffff 00000000 S irq/102-msm_iom +root 31 2 0 0 ffffffff 00000000 S irq/102-msm_iom +root 32 2 0 0 ffffffff 00000000 S irq/102-msm_iom +root 33 2 0 0 ffffffff 00000000 S irq/79-msm_iomm +root 34 2 0 0 ffffffff 00000000 S irq/78-msm_iomm +root 35 2 0 0 ffffffff 00000000 S irq/78-msm_iomm +root 36 2 0 0 ffffffff 00000000 S irq/74-msm_iomm +root 37 2 0 0 ffffffff 00000000 S irq/75-msm_iomm +root 38 2 0 0 ffffffff 00000000 S irq/75-msm_iomm +root 39 2 0 0 ffffffff 00000000 S irq/75-msm_iomm +root 40 2 0 0 ffffffff 00000000 S irq/75-msm_iomm +root 41 2 0 0 ffffffff 00000000 S irq/273-msm_iom +root 42 2 0 0 ffffffff 00000000 S irq/273-msm_iom +root 43 2 0 0 ffffffff 00000000 S irq/97-msm_iomm +root 44 2 0 0 ffffffff 00000000 S irq/97-msm_iomm +root 45 2 0 0 ffffffff 00000000 S irq/97-msm_iomm +root 46 2 0 0 ffffffff 00000000 S l2cap +root 47 2 0 0 ffffffff 00000000 S a2mp +root 48 2 0 0 ffffffff 00000000 S cfg80211 +root 49 2 0 0 ffffffff 00000000 S qmi +root 50 2 0 0 ffffffff 00000000 S nmea +root 51 2 0 0 ffffffff 00000000 S msm_ipc_router +root 52 2 0 0 ffffffff 00000000 S apr_driver +root 54 2 0 0 ffffffff 00000000 S kswapd0 +root 55 2 0 0 ffffffff 00000000 S fsnotify_mark +root 56 2 0 0 ffffffff 00000000 S cifsiod +root 57 2 0 0 ffffffff 00000000 S crypto +root 75 2 0 0 ffffffff 00000000 S ad_calc_wq +root 76 2 0 0 ffffffff 00000000 S hdmi_tx_workq +root 77 2 0 0 ffffffff 00000000 S anx7808_work +root 78 2 0 0 ffffffff 00000000 S k_hsuart +root 79 2 0 0 ffffffff 00000000 S diag_wq +root 80 2 0 0 ffffffff 00000000 S diag_cntl_wq +root 81 2 0 0 ffffffff 00000000 S diag_dci_wq +root 82 2 0 0 ffffffff 00000000 S kgsl-3d0 +root 84 2 0 0 ffffffff 00000000 S f9966000.spi +root 88 2 0 0 ffffffff 00000000 S usbnet +root 89 2 0 0 ffffffff 00000000 S irq/329-anx7808 +root 90 2 0 0 ffffffff 00000000 S k_rmnet_mux_wor +root 91 2 0 0 ffffffff 00000000 S f_mtp +root 92 2 0 0 ffffffff 00000000 S file-storage +root 93 2 0 0 ffffffff 00000000 S uether +root 94 2 0 0 ffffffff 00000000 S synaptics_wq +root 95 2 0 0 ffffffff 00000000 S irq/362-s3350 +root 96 2 0 0 ffffffff 00000000 S kworker/0:2 +root 97 2 0 0 ffffffff 00000000 S msm_vidc_worker +root 98 2 0 0 ffffffff 00000000 S msm_vidc_worker +root 99 2 0 0 ffffffff 00000000 S msm_cpp_workque +root 100 2 0 0 ffffffff 00000000 S irq/350-bq51013 +root 102 2 0 0 ffffffff 00000000 S dm_bufio_cache +root 103 2 0 0 ffffffff 00000000 D dbs_sync/0 +root 104 2 0 0 ffffffff 00000000 D dbs_sync/1 +root 105 2 0 0 ffffffff 00000000 D dbs_sync/2 +root 106 2 0 0 ffffffff 00000000 D dbs_sync/3 +root 107 2 0 0 ffffffff 00000000 S cfinteractive +root 108 2 0 0 ffffffff 00000000 S irq/170-msm_sdc +root 109 2 0 0 ffffffff 00000000 S binder +root 110 2 0 0 ffffffff 00000000 S usb_bam_wq +root 111 2 0 0 ffffffff 00000000 S krfcommd +root 112 2 0 0 ffffffff 00000000 S bam_dmux_rx +root 113 2 0 0 ffffffff 00000000 S bam_dmux_tx +root 114 2 0 0 ffffffff 00000000 S rq_stats +root 115 2 0 0 ffffffff 00000000 S deferwq +root 117 2 0 0 ffffffff 00000000 S irq/361-MAX1704 +root 119 2 0 0 ffffffff 00000000 S mmcqd/1 +root 120 2 0 0 ffffffff 00000000 S mmcqd/1rpmb +root 121 2 0 0 ffffffff 00000000 S wl_event_handle +root 122 2 0 0 ffffffff 00000000 S dhd_watchdog_th +root 123 2 0 0 ffffffff 00000000 S dhd_dpc +root 124 2 0 0 ffffffff 00000000 S dhd_rxf +root 125 2 0 0 ffffffff 00000000 S dhd_sysioc +root 126 2 0 0 ffffffff 00000000 S vibrator +root 127 2 0 0 ffffffff 00000000 S max1462x +root 128 2 0 0 ffffffff 00000000 S irq/310-maxim_m +root 129 2 0 0 ffffffff 00000000 S irq/311-maxim_m +root 130 1 8780 576 ffffffff 00000000 S /sbin/ueventd +root 132 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p25 +root 133 2 0 0 ffffffff 00000000 S ext4-dio-unwrit +root 136 2 0 0 ffffffff 00000000 S flush-179:0 +root 138 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p28 +root 139 2 0 0 ffffffff 00000000 S ext4-dio-unwrit +root 143 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p27 +root 144 2 0 0 ffffffff 00000000 S ext4-dio-unwrit +root 145 2 0 0 ffffffff 00000000 S jbd2/mmcblk0p16 +root 146 2 0 0 ffffffff 00000000 S ext4-dio-unwrit +logd 169 1 18632 2740 ffffffff 00000000 S /system/bin/logd +logd 216 169 18632 2740 ffffffff 00000000 S logd.reader +logd 217 169 18632 2740 ffffffff 00000000 S logd.writer +logd 218 169 18632 2740 ffffffff 00000000 S logd +logd 244 169 18632 2740 ffffffff 00000000 S logd.auditd +root 170 1 9832 304 ffffffff 00000000 S /sbin/healthd +root 171 1 10620 1240 ffffffff 00000000 S /system/bin/lmkd +system 172 1 9452 676 ffffffff 00000000 S /system/bin/servicemanager +root 173 1 18028 1652 ffffffff 00000000 S /system/bin/vold +root 223 173 18028 1652 ffffffff 00000000 S vold +root 226 173 18028 1652 ffffffff 00000000 S vold +root 174 2 0 0 ffffffff 00000000 S IPCRTR +root 175 2 0 0 ffffffff 00000000 S sb-1 +root 177 2 0 0 ffffffff 00000000 S ipc_rtr_q6_ipcr +root 179 2 0 0 ffffffff 00000000 S ngd_msm_ctrl_ng +system 180 1 146792 9724 ffffffff 00000000 S /system/bin/surfaceflinger +system 240 180 146792 9724 ffffffff 00000000 S Binder_1 +system 242 180 146792 9724 ffffffff 00000000 S DispSync +system 243 180 146792 9724 ffffffff 00000000 S Binder_2 +system 361 180 146792 9724 ffffffff 00000000 S hwcUeventThread +system 362 180 146792 9724 ffffffff 00000000 S hwcVsyncThread +system 396 180 146792 9724 ffffffff 00000000 S GL updater +system 397 180 146792 9724 ffffffff 00000000 S surfaceflinger +system 398 180 146792 9724 ffffffff 00000000 S EventThread +system 399 180 146792 9724 ffffffff 00000000 S surfaceflinger +system 400 180 146792 9724 ffffffff 00000000 S EventThread +system 401 180 146792 9724 ffffffff 00000000 S EventControl +system 575 180 146792 9724 ffffffff 00000000 S Binder_3 +system 1501 180 146792 9724 ffffffff 00000000 S Binder_4 +system 5633 180 146792 9724 ffffffff 00000000 S Binder_5 +nobody 181 1 19792 1112 ffffffff 00000000 S /system/bin/rmt_storage +nobody 571 181 19792 1112 ffffffff 00000000 S rmt_storage +nobody 572 181 19792 1112 ffffffff 00000000 S rmt_storage +nobody 573 181 19792 1112 ffffffff 00000000 S rmt_storage +nobody 574 181 19792 1112 ffffffff 00000000 S rmt_storage +system 182 1 11100 992 ffffffff 00000000 S /system/bin/qseecomd +root 183 2 0 0 ffffffff 00000000 S msm_slim_qmi_cl +root 184 2 0 0 ffffffff 00000000 S msm_qmi_rtx_q +shell 185 1 9316 716 c047451c b6f58da8 S /system/bin/sh +root 187 1 9200 368 ffffffff 00000000 S /system/bin/subsystem_ramdump +root 188 1 22828 1404 ffffffff 00000000 S /system/bin/netd +root 548 188 22828 1404 ffffffff 00000000 S netd +root 549 188 22828 1404 ffffffff 00000000 S netd +root 550 188 22828 1404 ffffffff 00000000 S netd +root 551 188 22828 1404 ffffffff 00000000 S netd +root 552 188 22828 1404 ffffffff 00000000 S netd +root 553 188 22828 1404 ffffffff 00000000 S netd +root 554 188 22828 1404 ffffffff 00000000 S netd +root 555 188 22828 1404 ffffffff 00000000 S netd +root 189 1 10048 848 ffffffff 00000000 S /system/bin/debuggerd +radio 191 1 35988 4712 ffffffff 00000000 S /system/bin/rild +radio 335 191 35988 4712 ffffffff 00000000 S rild +radio 343 191 35988 4712 ffffffff 00000000 S rild +radio 346 191 35988 4712 ffffffff 00000000 S rild +radio 584 191 35988 4712 ffffffff 00000000 S rild +radio 585 191 35988 4712 ffffffff 00000000 S rild +radio 587 191 35988 4712 ffffffff 00000000 S rild +radio 588 191 35988 4712 ffffffff 00000000 S rild +radio 589 191 35988 4712 ffffffff 00000000 S rild +radio 591 191 35988 4712 ffffffff 00000000 S rild +radio 592 191 35988 4712 ffffffff 00000000 S rild +radio 593 191 35988 4712 ffffffff 00000000 S rild +radio 594 191 35988 4712 ffffffff 00000000 S rild +drm 192 1 26084 3832 ffffffff 00000000 S /system/bin/drmserver +drm 419 192 26084 3832 ffffffff 00000000 S Binder_1 +media 194 1 106516 8584 ffffffff 00000000 S /system/bin/mediaserver +media 755 194 106516 8584 ffffffff 00000000 S ApmTone +media 756 194 106516 8584 ffffffff 00000000 S ApmAudio +media 757 194 106516 8584 ffffffff 00000000 S ApmOutput +media 758 194 106516 8584 ffffffff 00000000 S mediaserver +media 759 194 106516 8584 ffffffff 00000000 S FastMixer +media 871 194 106516 8584 ffffffff 00000000 S AudioOut_2 +media 872 194 106516 8584 ffffffff 00000000 S AudioOut_4 +media 873 194 106516 8584 ffffffff 00000000 S FastMixer +media 874 194 106516 8584 ffffffff 00000000 S AudioOut_6 +media 878 194 106516 8584 ffffffff 00000000 S Binder_1 +media 879 194 106516 8584 ffffffff 00000000 S Binder_2 +media 1133 194 106516 8584 ffffffff 00000000 S Binder_3 +install 195 1 9408 704 ffffffff 00000000 S /system/bin/installd +keystore 197 1 12536 1848 ffffffff 00000000 S /system/bin/keystore +radio 198 1 18856 636 ffffffff 00000000 S /system/bin/bridgemgrd +radio 288 198 18856 636 ffffffff 00000000 S bridgemgrd +radio 602 198 18856 636 ffffffff 00000000 S bridgemgrd +radio 603 198 18856 636 ffffffff 00000000 S bridgemgrd +radio 841 198 18856 636 ffffffff 00000000 S bridgemgrd +radio 199 1 24060 732 ffffffff 00000000 S /system/bin/qmuxd +radio 293 199 24060 732 ffffffff 00000000 S qmuxd +radio 576 199 24060 732 ffffffff 00000000 S qmuxd +radio 577 199 24060 732 ffffffff 00000000 S qmuxd +radio 578 199 24060 732 ffffffff 00000000 S qmuxd +radio 579 199 24060 732 ffffffff 00000000 S qmuxd +radio 580 199 24060 732 ffffffff 00000000 S qmuxd +radio 581 199 24060 732 ffffffff 00000000 S qmuxd +radio 582 199 24060 732 ffffffff 00000000 S qmuxd +radio 583 199 24060 732 ffffffff 00000000 S qmuxd +radio 200 1 20036 996 ffffffff 00000000 S /system/bin/netmgrd +radio 289 200 20036 996 ffffffff 00000000 S netmgrd +radio 736 200 20036 996 ffffffff 00000000 S netmgrd +radio 746 200 20036 996 ffffffff 00000000 S netmgrd +radio 747 200 20036 996 ffffffff 00000000 S netmgrd +radio 748 200 20036 996 ffffffff 00000000 S netmgrd +nobody 201 1 59912 1748 ffffffff 00000000 S /system/bin/sensors.qcom +nobody 290 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 292 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 560 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 563 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 564 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 605 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 614 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 621 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 622 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 623 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 624 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 625 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 626 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 627 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 628 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 629 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 633 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 643 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 650 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 651 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 760 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 763 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 784 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 790 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 792 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 794 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 796 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 798 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 800 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 802 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 804 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 806 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 808 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 810 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 812 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 814 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 816 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 818 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 820 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 822 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 824 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 1593 201 59912 1748 ffffffff 00000000 S sensors.qcom +nobody 1600 201 59912 1748 ffffffff 00000000 S sensors.qcom +root 204 1 58772 1524 ffffffff 00000000 S /system/bin/thermal-engine-hh +root 247 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 250 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 252 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 253 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 254 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 255 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 257 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 258 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 259 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 260 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 261 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 262 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 263 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 264 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 265 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 266 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 267 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 268 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 269 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 270 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 272 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 273 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 275 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 276 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 277 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 278 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 280 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 281 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 282 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 283 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 284 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 286 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 287 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 295 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 297 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 299 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 300 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 301 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 559 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 596 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 600 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 601 204 58772 1524 ffffffff 00000000 S thermal-engine- +root 205 1 1482684 53160 ffffffff 00000000 S zygote +root 14357 205 1482684 53160 ffffffff 00000000 S ReferenceQueueD +root 14358 205 1482684 53160 ffffffff 00000000 S FinalizerDaemon +root 14359 205 1482684 53160 ffffffff 00000000 S FinalizerWatchd +root 14360 205 1482684 53160 ffffffff 00000000 S HeapTrimmerDaem +root 14361 205 1482684 53160 ffffffff 00000000 S GCDaemon +media_rw 206 1 15400 5240 ffffffff 00000000 S /system/bin/sdcard +media_rw 227 206 15400 5240 ffffffff 00000000 S sdcard +media_rw 228 206 15400 5240 ffffffff 00000000 S sdcard +camera 207 1 16300 4440 ffffffff 00000000 S /system/bin/mm-qcamera-daemon +system 208 1 20500 1236 ffffffff 00000000 S /system/bin/time_daemon +system 308 208 20500 1236 ffffffff 00000000 S time_daemon +system 561 208 20500 1236 ffffffff 00000000 S time_daemon +system 597 208 20500 1236 ffffffff 00000000 S time_daemon +system 598 208 20500 1236 ffffffff 00000000 S time_daemon +system 599 208 20500 1236 ffffffff 00000000 S time_daemon +shell 209 1 16984 312 ffffffff 00000000 S /sbin/adbd +shell 210 209 16984 312 ffffffff 00000000 S adbd +shell 211 209 16984 312 ffffffff 00000000 S adbd +shell 212 209 16984 308 ffffffff 00000000 S adbd +shell 14445 209 16984 308 ffffffff 00000000 S adbd +root 214 2 0 0 ffffffff 00000000 S irq/288-wcd9xxx +root 219 2 0 0 ffffffff 00000000 S kauditd +root 311 2 0 0 ffffffff 00000000 D msm_thermal:hot +root 312 2 0 0 ffffffff 00000000 D msm_thermal:fre +system 348 182 15288 564 ffffffff 00000000 S /system/bin/qseecomd +system 349 348 15288 564 ffffffff 00000000 S qseecomd +system 351 348 15288 564 ffffffff 00000000 S qseecomd +system 386 348 15288 564 ffffffff 00000000 S qseecomd +system 387 348 15288 564 ffffffff 00000000 S qseecomd +root 360 2 0 0 ffffffff 00000000 D mdss_fb0 +root 557 2 0 0 ffffffff 00000000 S kworker/0:2H +root 558 2 0 0 ffffffff 00000000 S IPCRTR +root 562 2 0 0 ffffffff 00000000 S ipc_rtr_smd_ipc +system 764 205 1701620 103200 ffffffff 00000000 S system_server +system 767 764 1701620 103200 ffffffff 00000000 S Heap thread poo +system 768 764 1701620 103200 ffffffff 00000000 S Heap thread poo +system 770 764 1701620 103200 ffffffff 00000000 S Heap thread poo +system 773 764 1701620 103200 ffffffff 00000000 S Signal Catcher +system 774 764 1701620 103200 ffffffff 00000000 S JDWP +system 775 764 1701620 103200 ffffffff 00000000 S ReferenceQueueD +system 776 764 1701620 103200 ffffffff 00000000 S FinalizerDaemon +system 777 764 1701620 103200 ffffffff 00000000 S FinalizerWatchd +system 778 764 1701620 103200 ffffffff 00000000 S HeapTrimmerDaem +system 779 764 1701620 103200 ffffffff 00000000 S GCDaemon +system 780 764 1701620 103200 ffffffff 00000000 S Binder_1 +system 781 764 1701620 103200 ffffffff 00000000 S Binder_2 +system 782 764 1701620 103200 ffffffff 00000000 S system_server +system 783 764 1701620 103200 ffffffff 00000000 S system_server +system 785 764 1701620 103200 ffffffff 00000000 S system_server +system 786 764 1701620 103200 ffffffff 00000000 S system_server +system 788 764 1701620 103200 ffffffff 00000000 S system_server +system 789 764 1701620 103200 ffffffff 00000000 S system_server +system 791 764 1701620 103200 ffffffff 00000000 S system_server +system 793 764 1701620 103200 ffffffff 00000000 S system_server +system 795 764 1701620 103200 ffffffff 00000000 S system_server +system 797 764 1701620 103200 ffffffff 00000000 S system_server +system 799 764 1701620 103200 ffffffff 00000000 S system_server +system 801 764 1701620 103200 ffffffff 00000000 S system_server +system 803 764 1701620 103200 ffffffff 00000000 S system_server +system 805 764 1701620 103200 ffffffff 00000000 S system_server +system 807 764 1701620 103200 ffffffff 00000000 S system_server +system 809 764 1701620 103200 ffffffff 00000000 S system_server +system 811 764 1701620 103200 ffffffff 00000000 S system_server +system 813 764 1701620 103200 ffffffff 00000000 S system_server +system 815 764 1701620 103200 ffffffff 00000000 S system_server +system 817 764 1701620 103200 ffffffff 00000000 S system_server +system 819 764 1701620 103200 ffffffff 00000000 S system_server +system 821 764 1701620 103200 ffffffff 00000000 S system_server +system 823 764 1701620 103200 ffffffff 00000000 S system_server +system 826 764 1701620 103200 ffffffff 00000000 S SensorEventAckR +system 827 764 1701620 103200 ffffffff 00000000 S SensorService +system 828 764 1701620 103200 ffffffff 00000000 S android.bg +system 829 764 1701620 103200 ffffffff 00000000 S ActivityManager +system 830 764 1701620 103200 ffffffff 00000000 S FileObserver +system 831 764 1701620 103200 ffffffff 00000000 S android.fg +system 832 764 1701620 103200 ffffffff 00000000 S android.ui +system 833 764 1701620 103200 ffffffff 00000000 S android.io +system 834 764 1701620 103200 ffffffff 00000000 S android.display +system 835 764 1701620 103200 ffffffff 00000000 S CpuTracker +system 836 764 1701620 103200 ffffffff 00000000 S PowerManagerSer +system 837 764 1701620 103200 ffffffff 00000000 S system_server +system 838 764 1701620 103200 ffffffff 00000000 S system_server +system 839 764 1701620 103200 ffffffff 00000000 S BatteryStats_wa +system 840 764 1701620 103200 ffffffff 00000000 S PackageManager +system 842 764 1701620 103200 ffffffff 00000000 S PackageInstalle +system 844 764 1701620 103200 ffffffff 00000000 S AlarmManager +system 845 764 1701620 103200 ffffffff 00000000 S UEventObserver +system 853 764 1701620 103200 ffffffff 00000000 S InputDispatcher +system 854 764 1701620 103200 ffffffff 00000000 S InputReader +system 857 764 1701620 103200 ffffffff 00000000 S MountService +system 858 764 1701620 103200 ffffffff 00000000 S VoldConnector +system 860 764 1701620 103200 ffffffff 00000000 S NetdConnector +system 861 764 1701620 103200 ffffffff 00000000 S NetworkStats +system 862 764 1701620 103200 ffffffff 00000000 S NetworkPolicy +system 863 764 1701620 103200 ffffffff 00000000 S WifiP2pService +system 864 764 1701620 103200 ffffffff 00000000 S WifiStateMachin +system 865 764 1701620 103200 ffffffff 00000000 S WifiService +system 866 764 1701620 103200 ffffffff 00000000 S ConnectivitySer +system 867 764 1701620 103200 ffffffff 00000000 S NsdService +system 868 764 1701620 103200 ffffffff 00000000 S mDnsConnector +system 869 764 1701620 103200 ffffffff 00000000 S ranker +system 870 764 1701620 103200 ffffffff 00000000 S AudioService +system 882 764 1701620 103200 ffffffff 00000000 S WifiWatchdogSta +system 883 764 1701620 103200 ffffffff 00000000 S WifiManager +system 884 764 1701620 103200 ffffffff 00000000 S WifiScanningSer +system 885 764 1701620 103200 ffffffff 00000000 S WifiRttService +system 886 764 1701620 103200 ffffffff 00000000 S EthernetService +system 887 764 1701620 103200 ffffffff 00000000 S backup +system 889 764 1701620 103200 ffffffff 00000000 S Thread-69 +system 892 764 1701620 103200 ffffffff 00000000 S LazyTaskWriterT +system 893 764 1701620 103200 ffffffff 00000000 S UsbService host +system 894 764 1701620 103200 ffffffff 00000000 S Thread-73 +system 942 764 1701620 103200 ffffffff 00000000 S Binder_3 +system 1079 764 1701620 103200 ffffffff 00000000 S watchdog +system 1094 764 1701620 103200 ffffffff 00000000 S SoundPool +system 1095 764 1701620 103200 ffffffff 00000000 S SoundPoolThread +system 1108 764 1701620 103200 ffffffff 00000000 S Binder_4 +system 1109 764 1701620 103200 ffffffff 00000000 S Binder_5 +system 1186 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1188 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1191 764 1701620 103200 ffffffff 00000000 S NetworkTimeUpda +system 1192 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1226 764 1701620 103200 ffffffff 00000000 S Binder_6 +system 1233 764 1701620 103200 ffffffff 00000000 S Binder_7 +system 1247 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1256 764 1701620 103200 ffffffff 00000000 S Binder_8 +system 1260 764 1701620 103200 ffffffff 00000000 S WifiMonitor +system 1271 764 1701620 103200 ffffffff 00000000 S Binder_9 +system 1288 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1289 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1319 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1320 764 1701620 103200 ffffffff 00000000 S FLP Service Cal +system 1367 764 1701620 103200 ffffffff 00000000 S Thread-89 +system 1391 764 1701620 103200 ffffffff 00000000 S AsyncQueryWorke +system 1654 764 1701620 103200 ffffffff 00000000 S Binder_A +system 1693 764 1701620 103200 ffffffff 00000000 S NetworkMonitorN +system 1695 764 1701620 103200 ffffffff 00000000 S DhcpStateMachin +system 1781 764 1701620 103200 ffffffff 00000000 S AsyncTask #1 +system 1782 764 1701620 103200 ffffffff 00000000 S AsyncTask #2 +system 2097 764 1701620 103200 ffffffff 00000000 S AsyncTask #3 +system 2124 764 1701620 103200 ffffffff 00000000 S SyncHandler-0 +system 2905 764 1701620 103200 ffffffff 00000000 S PowerManagerSer +system 4226 764 1701620 103200 ffffffff 00000000 S AsyncTask #4 +system 4265 764 1701620 103200 ffffffff 00000000 S UsbDebuggingMan +system 5717 764 1701620 103200 ffffffff 00000000 S GL updater +system 6709 764 1701620 103200 ffffffff 00000000 S Binder_B +wifi 888 1 12568 2672 ffffffff 00000000 S /system/bin/wpa_supplicant +u0_a20 915 205 1616624 108684 ffffffff 00000000 S com.android.systemui +u0_a20 919 915 1616624 108684 ffffffff 00000000 S Heap thread poo +u0_a20 920 915 1616624 108684 ffffffff 00000000 S Heap thread poo +u0_a20 921 915 1616624 108684 ffffffff 00000000 S Heap thread poo +u0_a20 925 915 1616624 108684 ffffffff 00000000 S Signal Catcher +u0_a20 926 915 1616624 108684 ffffffff 00000000 S JDWP +u0_a20 927 915 1616624 108684 ffffffff 00000000 S ReferenceQueueD +u0_a20 928 915 1616624 108684 ffffffff 00000000 S FinalizerDaemon +u0_a20 929 915 1616624 108684 ffffffff 00000000 S FinalizerWatchd +u0_a20 930 915 1616624 108684 ffffffff 00000000 S HeapTrimmerDaem +u0_a20 931 915 1616624 108684 ffffffff 00000000 S GCDaemon +u0_a20 933 915 1616624 108684 ffffffff 00000000 S Binder_1 +u0_a20 934 915 1616624 108684 ffffffff 00000000 S Binder_2 +u0_a20 964 915 1616624 108684 ffffffff 00000000 S SoundPool +u0_a20 965 915 1616624 108684 ffffffff 00000000 S SoundPoolThread +u0_a20 970 915 1616624 108684 ffffffff 00000000 S Recents-TaskRes +u0_a20 1078 915 1616624 108684 ffffffff 00000000 S SystemUI Storag +u0_a20 1378 915 1616624 108684 ffffffff 00000000 S PhoneStatusBar +u0_a20 1381 915 1616624 108684 ffffffff 00000000 S WifiManager +u0_a20 1416 915 1616624 108684 ffffffff 00000000 S ConnectivityMan +u0_a20 1428 915 1616624 108684 ffffffff 00000000 S Binder_3 +u0_a20 1431 915 1616624 108684 ffffffff 00000000 S FlashlightContr +u0_a20 1434 915 1616624 108684 ffffffff 00000000 S AsyncTask #1 +u0_a20 1435 915 1616624 108684 ffffffff 00000000 S QSTileHost +u0_a20 1438 915 1616624 108684 ffffffff 00000000 S AsyncTask #2 +u0_a20 1441 915 1616624 108684 ffffffff 00000000 S RenderThread +u0_a20 1442 915 1616624 108684 ffffffff 00000000 S AsyncTask #3 +u0_a20 1565 915 1616624 108684 ffffffff 00000000 S hwuiTask1 +u0_a20 1566 915 1616624 108684 ffffffff 00000000 S hwuiTask2 +u0_a20 1637 915 1616624 108684 ffffffff 00000000 S AsyncTask #4 +u0_a20 1692 915 1616624 108684 ffffffff 00000000 S GL updater +u0_a20 1807 915 1616624 108684 ffffffff 00000000 S RenderThread +u0_a20 4480 915 1616624 108684 ffffffff 00000000 S Binder_4 +u0_a6 936 205 1506908 56892 ffffffff 00000000 S android.process.media +u0_a6 943 936 1506908 56892 ffffffff 00000000 S Heap thread poo +u0_a6 944 936 1506908 56892 ffffffff 00000000 S Heap thread poo +u0_a6 945 936 1506908 56892 ffffffff 00000000 S Heap thread poo +u0_a6 947 936 1506908 56892 ffffffff 00000000 S Signal Catcher +u0_a6 949 936 1506908 56892 ffffffff 00000000 S JDWP +u0_a6 950 936 1506908 56892 ffffffff 00000000 S ReferenceQueueD +u0_a6 951 936 1506908 56892 ffffffff 00000000 S FinalizerDaemon +u0_a6 952 936 1506908 56892 ffffffff 00000000 S FinalizerWatchd +u0_a6 953 936 1506908 56892 ffffffff 00000000 S HeapTrimmerDaem +u0_a6 954 936 1506908 56892 ffffffff 00000000 S GCDaemon +u0_a6 956 936 1506908 56892 ffffffff 00000000 S Binder_1 +u0_a6 957 936 1506908 56892 ffffffff 00000000 S Binder_2 +u0_a6 1007 936 1506908 56892 ffffffff 00000000 S thumbs thread +u0_a6 1020 936 1506908 56892 ffffffff 00000000 S MtpServer +u0_a6 2810 936 1506908 56892 ffffffff 00000000 S DownloadReceive +u0_a6 4917 936 1506908 56892 ffffffff 00000000 S Binder_3 +u0_a6 5816 936 1506908 56892 ffffffff 00000000 S Binder_4 +u0_a6 8575 936 1506908 56892 ffffffff 00000000 S Binder_5 +u0_a22 1111 205 1526156 42532 ffffffff 00000000 S com.google.android.googlequicksearchbox:interactor +u0_a22 1113 1111 1526156 42532 ffffffff 00000000 S Heap thread poo +u0_a22 1114 1111 1526156 42532 ffffffff 00000000 S Heap thread poo +u0_a22 1116 1111 1526156 42532 ffffffff 00000000 S Heap thread poo +u0_a22 1121 1111 1526156 42532 ffffffff 00000000 S Signal Catcher +u0_a22 1124 1111 1526156 42532 ffffffff 00000000 S JDWP +u0_a22 1125 1111 1526156 42532 ffffffff 00000000 S ReferenceQueueD +u0_a22 1126 1111 1526156 42532 ffffffff 00000000 S FinalizerDaemon +u0_a22 1127 1111 1526156 42532 ffffffff 00000000 S FinalizerWatchd +u0_a22 1128 1111 1526156 42532 ffffffff 00000000 S HeapTrimmerDaem +u0_a22 1129 1111 1526156 42532 ffffffff 00000000 S GCDaemon +u0_a22 1131 1111 1526156 42532 ffffffff 00000000 S Binder_1 +u0_a22 1132 1111 1526156 42532 ffffffff 00000000 S Binder_2 +u0_a22 1561 1111 1526156 42532 ffffffff 00000000 S AsyncTask #1 +u0_a51 1136 205 1515064 46788 ffffffff 00000000 S com.google.android.inputmethod.pinyin +u0_a51 1142 1136 1515064 46788 ffffffff 00000000 S Heap thread poo +u0_a51 1143 1136 1515064 46788 ffffffff 00000000 S Heap thread poo +u0_a51 1144 1136 1515064 46788 ffffffff 00000000 S Heap thread poo +u0_a51 1145 1136 1515064 46788 ffffffff 00000000 S Signal Catcher +u0_a51 1146 1136 1515064 46788 ffffffff 00000000 S JDWP +u0_a51 1147 1136 1515064 46788 ffffffff 00000000 S ReferenceQueueD +u0_a51 1148 1136 1515064 46788 ffffffff 00000000 S FinalizerDaemon +u0_a51 1149 1136 1515064 46788 ffffffff 00000000 S FinalizerWatchd +u0_a51 1151 1136 1515064 46788 ffffffff 00000000 S HeapTrimmerDaem +u0_a51 1152 1136 1515064 46788 ffffffff 00000000 S GCDaemon +u0_a51 1153 1136 1515064 46788 ffffffff 00000000 S Binder_1 +u0_a51 1154 1136 1515064 46788 ffffffff 00000000 S Binder_2 +u0_a51 1330 1136 1515064 46788 ffffffff 00000000 S GAThread +u0_a51 1331 1136 1515064 46788 ffffffff 00000000 S measurement-1 +u0_a51 1336 1136 1515064 46788 ffffffff 00000000 S pool-1-thread-1 +u0_a51 1503 1136 1515064 46788 ffffffff 00000000 S AsyncTask #1 +u0_a51 1622 1136 1515064 46788 ffffffff 00000000 S AsyncTask #2 +nfc 1199 205 1511808 46336 ffffffff 00000000 S com.android.nfc +nfc 1208 1199 1511808 46336 ffffffff 00000000 S Heap thread poo +nfc 1209 1199 1511808 46336 ffffffff 00000000 S Heap thread poo +nfc 1210 1199 1511808 46336 ffffffff 00000000 S Heap thread poo +nfc 1211 1199 1511808 46336 ffffffff 00000000 S Signal Catcher +nfc 1212 1199 1511808 46336 ffffffff 00000000 S JDWP +nfc 1213 1199 1511808 46336 ffffffff 00000000 S ReferenceQueueD +nfc 1214 1199 1511808 46336 ffffffff 00000000 S FinalizerDaemon +nfc 1215 1199 1511808 46336 ffffffff 00000000 S FinalizerWatchd +nfc 1216 1199 1511808 46336 ffffffff 00000000 S HeapTrimmerDaem +nfc 1219 1199 1511808 46336 ffffffff 00000000 S GCDaemon +nfc 1220 1199 1511808 46336 ffffffff 00000000 S Binder_1 +nfc 1221 1199 1511808 46336 ffffffff 00000000 S Binder_2 +nfc 1385 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1388 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1393 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1408 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1409 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1425 1199 1511808 46336 ffffffff 00000000 S AsyncTask #1 +nfc 1573 1199 1511808 46336 ffffffff 00000000 S Thread-55 +nfc 1574 1199 1511808 46336 ffffffff 00000000 S Thread-56 +nfc 1575 1199 1511808 46336 ffffffff 00000000 S Thread-57 +nfc 1577 1199 1511808 46336 ffffffff 00000000 S SoundPool +nfc 1578 1199 1511808 46336 ffffffff 00000000 S SoundPoolThread +nfc 2906 1199 1511808 46336 ffffffff 00000000 S AsyncTask #2 +nfc 2915 1199 1511808 46336 ffffffff 00000000 S AsyncTask #3 +nfc 5610 1199 1511808 46336 ffffffff 00000000 S AsyncTask #4 +nfc 5719 1199 1511808 46336 ffffffff 00000000 S AsyncTask #5 +radio 1234 205 1493064 38832 ffffffff 00000000 S com.redbend.vdmc +radio 1236 1234 1493064 38832 ffffffff 00000000 S Heap thread poo +radio 1237 1234 1493064 38832 ffffffff 00000000 S Heap thread poo +radio 1238 1234 1493064 38832 ffffffff 00000000 S Heap thread poo +radio 1244 1234 1493064 38832 ffffffff 00000000 S Signal Catcher +radio 1245 1234 1493064 38832 ffffffff 00000000 S JDWP +radio 1246 1234 1493064 38832 ffffffff 00000000 S ReferenceQueueD +radio 1248 1234 1493064 38832 ffffffff 00000000 S FinalizerDaemon +radio 1249 1234 1493064 38832 ffffffff 00000000 S FinalizerWatchd +radio 1250 1234 1493064 38832 ffffffff 00000000 S HeapTrimmerDaem +radio 1251 1234 1493064 38832 ffffffff 00000000 S GCDaemon +radio 1252 1234 1493064 38832 ffffffff 00000000 S Binder_1 +radio 1257 1234 1493064 38832 ffffffff 00000000 S Binder_2 +radio 1274 205 1525408 58916 ffffffff 00000000 S com.android.phone +radio 1282 1274 1525408 58916 ffffffff 00000000 S Heap thread poo +radio 1283 1274 1525408 58916 ffffffff 00000000 S Heap thread poo +radio 1284 1274 1525408 58916 ffffffff 00000000 S Heap thread poo +radio 1285 1274 1525408 58916 ffffffff 00000000 S Signal Catcher +radio 1286 1274 1525408 58916 ffffffff 00000000 S JDWP +radio 1287 1274 1525408 58916 ffffffff 00000000 S ReferenceQueueD +radio 1290 1274 1525408 58916 ffffffff 00000000 S FinalizerDaemon +radio 1291 1274 1525408 58916 ffffffff 00000000 S FinalizerWatchd +radio 1292 1274 1525408 58916 ffffffff 00000000 S HeapTrimmerDaem +radio 1293 1274 1525408 58916 ffffffff 00000000 S GCDaemon +radio 1299 1274 1525408 58916 ffffffff 00000000 S Binder_1 +radio 1315 1274 1525408 58916 ffffffff 00000000 S Binder_2 +radio 1365 1274 1525408 58916 ffffffff 00000000 S RILSender0 +radio 1366 1274 1525408 58916 ffffffff 00000000 S RILReceiver0 +radio 1380 1274 1525408 58916 ffffffff 00000000 S DcHandlerThread +radio 1392 1274 1525408 58916 ffffffff 00000000 S GsmCellBroadcas +radio 1394 1274 1525408 58916 ffffffff 00000000 S GsmInboundSmsHa +radio 1397 1274 1525408 58916 ffffffff 00000000 S CellBroadcastHa +radio 1417 1274 1525408 58916 ffffffff 00000000 S CdmaInboundSmsH +radio 1418 1274 1525408 58916 ffffffff 00000000 S CdmaServiceCate +radio 1427 1274 1525408 58916 ffffffff 00000000 S DcSwitchStateMa +radio 1429 1274 1525408 58916 ffffffff 00000000 S SyncHandler-0 +radio 1443 1274 1525408 58916 ffffffff 00000000 S AsyncTask #1 +radio 1473 1274 1525408 58916 ffffffff 00000000 S Binder_3 +radio 1517 1274 1525408 58916 ffffffff 00000000 S ervice.Executor +radio 1518 1274 1525408 58916 ffffffff 00000000 S WifiManager +radio 1563 1274 1525408 58916 ffffffff 00000000 S Cat Telephony s +radio 1564 1274 1525408 58916 ffffffff 00000000 S RilMessageDecod +radio 1567 1274 1525408 58916 ffffffff 00000000 S Cat Icon Loader +radio 1690 1274 1525408 58916 ffffffff 00000000 S Binder_4 +radio 4571 1274 1525408 58916 ffffffff 00000000 S Stk App Service +u0_a22 1305 205 1674592 127012 ffffffff 00000000 S com.google.android.googlequicksearchbox +u0_a22 1306 1305 1674592 127012 ffffffff 00000000 S Heap thread poo +u0_a22 1307 1305 1674592 127012 ffffffff 00000000 S Heap thread poo +u0_a22 1308 1305 1674592 127012 ffffffff 00000000 S Heap thread poo +u0_a22 1317 1305 1674592 127012 ffffffff 00000000 S Signal Catcher +u0_a22 1318 1305 1674592 127012 ffffffff 00000000 S JDWP +u0_a22 1322 1305 1674592 127012 ffffffff 00000000 S ReferenceQueueD +u0_a22 1323 1305 1674592 127012 ffffffff 00000000 S FinalizerDaemon +u0_a22 1324 1305 1674592 127012 ffffffff 00000000 S FinalizerWatchd +u0_a22 1332 1305 1674592 127012 ffffffff 00000000 S HeapTrimmerDaem +u0_a22 1333 1305 1674592 127012 ffffffff 00000000 S GCDaemon +u0_a22 1334 1305 1674592 127012 ffffffff 00000000 S Binder_1 +u0_a22 1335 1305 1674592 127012 ffffffff 00000000 S Binder_2 +u0_a22 1386 1305 1674592 127012 ffffffff 00000000 S launcher-loader +u0_a22 1395 1305 1674592 127012 ffffffff 00000000 S AsyncTask #1 +u0_a22 1432 1305 1674592 127012 ffffffff 00000000 S AsyncTask #2 +u0_a22 1484 1305 1674592 127012 ffffffff 00000000 S GELServices-0 +u0_a22 1514 1305 1674592 127012 ffffffff 00000000 S RenderThread +u0_a22 1540 1305 1674592 127012 ffffffff 00000000 S AsyncTask #3 +u0_a22 1618 1305 1674592 127012 ffffffff 00000000 S GELServices-1 +u0_a22 1621 1305 1674592 127012 ffffffff 00000000 S GELServices-2 +u0_a22 1629 1305 1674592 127012 ffffffff 00000000 S GELServices-3 +u0_a22 1632 1305 1674592 127012 ffffffff 00000000 S AsyncTask #4 +u0_a22 1633 1305 1674592 127012 ffffffff 00000000 S AsyncTask #5 +u0_a22 1636 1305 1674592 127012 ffffffff 00000000 S GELServices-4 +u0_a22 1644 1305 1674592 127012 ffffffff 00000000 S GL updater +u0_a22 1647 1305 1674592 127012 ffffffff 00000000 S GELServices-5 +u0_a22 1664 1305 1674592 127012 ffffffff 00000000 S GELServices-6 +u0_a22 1764 1305 1674592 127012 ffffffff 00000000 S Binder_3 +u0_a22 1766 1305 1674592 127012 ffffffff 00000000 S GELServices-7 +u0_a22 1772 1305 1674592 127012 ffffffff 00000000 S RenderThread +u0_a22 1773 1305 1674592 127012 ffffffff 00000000 S RenderThread +u0_a22 1774 1305 1674592 127012 ffffffff 00000000 S RenderThread +u0_a22 1775 1305 1674592 127012 ffffffff 00000000 S RenderThread +u0_a22 1998 1305 1674592 127012 ffffffff 00000000 S GELServices-8 +u0_a22 2320 1305 1674592 127012 ffffffff 00000000 S RemoteViewsCach +u0_a22 2321 1305 1674592 127012 ffffffff 00000000 S RemoteViewsAdap +u0_a22 2902 1305 1674592 127012 ffffffff 00000000 S GELServices-9 +u0_a22 1451 205 1584512 87716 ffffffff 00000000 S com.google.android.googlequicksearchbox:search +u0_a22 1457 1451 1584512 87716 ffffffff 00000000 S Heap thread poo +u0_a22 1458 1451 1584512 87716 ffffffff 00000000 S Heap thread poo +u0_a22 1459 1451 1584512 87716 ffffffff 00000000 S Heap thread poo +u0_a22 1460 1451 1584512 87716 ffffffff 00000000 S Signal Catcher +u0_a22 1461 1451 1584512 87716 ffffffff 00000000 S JDWP +u0_a22 1462 1451 1584512 87716 ffffffff 00000000 S ReferenceQueueD +u0_a22 1463 1451 1584512 87716 ffffffff 00000000 S FinalizerDaemon +u0_a22 1464 1451 1584512 87716 ffffffff 00000000 S FinalizerWatchd +u0_a22 1466 1451 1584512 87716 ffffffff 00000000 S HeapTrimmerDaem +u0_a22 1468 1451 1584512 87716 ffffffff 00000000 S GCDaemon +u0_a22 1474 1451 1584512 87716 ffffffff 00000000 S Binder_1 +u0_a22 1475 1451 1584512 87716 ffffffff 00000000 S Binder_2 +u0_a22 1515 1451 1584512 87716 ffffffff 00000000 S User-Facing Non +u0_a22 1516 1451 1584512 87716 ffffffff 00000000 S User-Facing Non +u0_a22 1535 1451 1584512 87716 ffffffff 00000000 S User-Facing Non +u0_a22 1538 1451 1584512 87716 ffffffff 00000000 S User-Facing Non +u0_a22 1553 1451 1584512 87716 ffffffff 00000000 S User-Facing Non +u0_a22 1560 1451 1584512 87716 ffffffff 00000000 S IcingConnection +u0_a22 1580 1451 1584512 87716 ffffffff 00000000 S AudioRouter-0 +u0_a22 1626 1451 1584512 87716 ffffffff 00000000 S AsyncFileStorag +u0_a22 1635 1451 1584512 87716 ffffffff 00000000 S WifiManager +u0_a22 1643 1451 1584512 87716 ffffffff 00000000 S LocationOracleI +u0_a22 1646 1451 1584512 87716 ffffffff 00000000 S GoogleApiClient +u0_a22 1769 1451 1584512 87716 ffffffff 00000000 S Binder_3 +u0_a22 1770 1451 1584512 87716 ffffffff 00000000 S Gservices +u0_a22 1810 1451 1584512 87716 ffffffff 00000000 S ChromiumNet +u0_a22 1811 1451 1584512 87716 ffffffff 00000000 S DnsConfigServic +u0_a22 1812 1451 1584512 87716 ffffffff 00000000 S inotify_reader +u0_a22 1815 1451 1584512 87716 ffffffff 00000000 S Network File Th +u0_a22 1816 1451 1584512 87716 ffffffff 00000000 S SimpleCacheWork +u0_a22 1817 1451 1584512 87716 ffffffff 00000000 S SimpleCacheWork +u0_a22 1823 1451 1584512 87716 ffffffff 00000000 S Binder_4 +u0_a22 1824 1451 1584512 87716 ffffffff 00000000 S Binder_5 +u0_a22 12193 1451 1584512 87716 ffffffff 00000000 S Background Bloc +u0_a22 12207 1451 1584512 87716 ffffffff 00000000 S User-Facing Blo +u0_a22 12211 1451 1584512 87716 ffffffff 00000000 S WorkerPool/1221 +u0_a22 12232 1451 1584512 87716 ffffffff 00000000 S Background Non- +u0_a22 12235 1451 1584512 87716 ffffffff 00000000 S Background Bloc +u0_a22 12236 1451 1584512 87716 ffffffff 00000000 S Background Bloc +u0_a22 12237 1451 1584512 87716 ffffffff 00000000 S Background Non- +u0_a8 1478 205 1613496 72932 ffffffff 00000000 S com.google.process.gapps +u0_a8 1485 1478 1613496 72932 ffffffff 00000000 S Heap thread poo +u0_a8 1486 1478 1613496 72932 ffffffff 00000000 S Heap thread poo +u0_a8 1487 1478 1613496 72932 ffffffff 00000000 S Heap thread poo +u0_a8 1488 1478 1613496 72932 ffffffff 00000000 S Signal Catcher +u0_a8 1489 1478 1613496 72932 ffffffff 00000000 S JDWP +u0_a8 1490 1478 1613496 72932 ffffffff 00000000 S ReferenceQueueD +u0_a8 1491 1478 1613496 72932 ffffffff 00000000 S FinalizerDaemon +u0_a8 1492 1478 1613496 72932 ffffffff 00000000 S FinalizerWatchd +u0_a8 1493 1478 1613496 72932 ffffffff 00000000 S HeapTrimmerDaem +u0_a8 1494 1478 1613496 72932 ffffffff 00000000 S GCDaemon +u0_a8 1495 1478 1613496 72932 ffffffff 00000000 S Binder_1 +u0_a8 1496 1478 1613496 72932 ffffffff 00000000 S Binder_2 +u0_a8 1497 1478 1613496 72932 ffffffff 00000000 S Binder_3 +u0_a8 1613 1478 1613496 72932 ffffffff 00000000 S Gservices +u0_a8 1614 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@ +u0_a8 1615 1478 1613496 72932 ffffffff 00000000 S Gservices +u0_a8 1616 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@ +u0_a8 1620 1478 1613496 72932 ffffffff 00000000 S Gservices +u0_a8 1996 1478 1613496 72932 ffffffff 00000000 S Binder_4 +u0_a8 1997 1478 1613496 72932 ffffffff 00000000 S Binder_5 +u0_a8 2510 1478 1613496 72932 ffffffff 00000000 S GCMWriter +u0_a8 2512 1478 1613496 72932 ffffffff 00000000 S AsyncTask #1 +u0_a8 2536 1478 1613496 72932 ffffffff 00000000 S GCMReader +u0_a8 2547 1478 1613496 72932 ffffffff 00000000 S pool-2-thread-1 +u0_a8 3680 1478 1613496 72932 ffffffff 00000000 S WifiManager +u0_a8 4135 1478 1613496 72932 ffffffff 00000000 S AsyncTask #2 +u0_a8 4159 1478 1613496 72932 ffffffff 00000000 S AsyncTask #3 +u0_a8 4184 1478 1613496 72932 ffffffff 00000000 S AsyncTask #4 +u0_a8 4210 1478 1613496 72932 ffffffff 00000000 S AsyncTask #5 +u0_a8 4541 1478 1613496 72932 ffffffff 00000000 S RefQueueWorker@ +u0_a8 4735 1478 1613496 72932 ffffffff 00000000 S pool-8-thread-1 +u0_a8 4770 1478 1613496 72932 ffffffff 00000000 S Binder_6 +u0_a8 12448 1478 1613496 72932 ffffffff 00000000 S OkHttp Connecti +u0_a8 14401 1478 1613496 72932 ffffffff 00000000 S Thread-233 +u0_a8 14409 1478 1613496 72932 ffffffff 00000000 S OkHttp Connecti +dhcp 1700 1 9344 756 ffffffff 00000000 S /system/bin/dhcpcd +u0_a8 1873 205 1756828 84724 ffffffff 00000000 S com.google.android.gms +u0_a8 1878 1873 1756828 84724 ffffffff 00000000 S Heap thread poo +u0_a8 1880 1873 1756828 84724 ffffffff 00000000 S Heap thread poo +u0_a8 1881 1873 1756828 84724 ffffffff 00000000 S Heap thread poo +u0_a8 1882 1873 1756828 84724 ffffffff 00000000 S Signal Catcher +u0_a8 1883 1873 1756828 84724 ffffffff 00000000 S JDWP +u0_a8 1884 1873 1756828 84724 ffffffff 00000000 S ReferenceQueueD +u0_a8 1885 1873 1756828 84724 ffffffff 00000000 S FinalizerDaemon +u0_a8 1886 1873 1756828 84724 ffffffff 00000000 S FinalizerWatchd +u0_a8 1887 1873 1756828 84724 ffffffff 00000000 S HeapTrimmerDaem +u0_a8 1888 1873 1756828 84724 ffffffff 00000000 S GCDaemon +u0_a8 1889 1873 1756828 84724 ffffffff 00000000 S Binder_1 +u0_a8 1890 1873 1756828 84724 ffffffff 00000000 S Binder_2 +u0_a8 1895 1873 1756828 84724 ffffffff 00000000 S Gservices +u0_a8 1898 1873 1756828 84724 ffffffff 00000000 S measurement-1 +u0_a8 1900 1873 1756828 84724 ffffffff 00000000 S AsyncTask #1 +u0_a8 1904 1873 1756828 84724 ffffffff 00000000 S AsyncTask #2 +u0_a8 2001 1873 1756828 84724 ffffffff 00000000 S Binder_3 +u0_a8 2497 1873 1756828 84724 ffffffff 00000000 S WifiManager +u0_a8 2509 1873 1756828 84724 ffffffff 00000000 S picasa-uploads- +u0_a8 2946 1873 1756828 84724 ffffffff 00000000 S pool-7-thread-1 +u0_a8 4390 1873 1756828 84724 ffffffff 00000000 S pool-13-thread- +u0_a8 4391 1873 1756828 84724 ffffffff 00000000 S pool-18-thread- +u0_a8 4392 1873 1756828 84724 ffffffff 00000000 S pool-11-thread- +u0_a8 4394 1873 1756828 84724 ffffffff 00000000 S pool-25-thread- +u0_a8 4395 1873 1756828 84724 ffffffff 00000000 S pool-25-thread- +u0_a8 4396 1873 1756828 84724 ffffffff 00000000 S pool-25-thread- +u0_a8 4397 1873 1756828 84724 ffffffff 00000000 S pool-25-thread- +u0_a8 4398 1873 1756828 84724 ffffffff 00000000 S pool-14-thread- +u0_a8 4521 1873 1756828 84724 ffffffff 00000000 S MediaTracker bu +u0_a8 4766 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-0 +u0_a8 4771 1873 1756828 84724 ffffffff 00000000 S Icing-Worker-0 +u0_a8 4796 1873 1756828 84724 ffffffff 00000000 S Thread-200 +u0_a8 4797 1873 1756828 84724 ffffffff 00000000 S Thread-201 +u0_a8 4798 1873 1756828 84724 ffffffff 00000000 S Thread-202 +u0_a8 4799 1873 1756828 84724 ffffffff 00000000 S Thread-203 +u0_a8 4800 1873 1756828 84724 ffffffff 00000000 S Thread-204 +u0_a8 5793 1873 1756828 84724 ffffffff 00000000 S Binder_4 +u0_a8 6257 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-1 +u0_a8 6258 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-2 +u0_a8 6259 1873 1756828 84724 ffffffff 00000000 S Icing-Pool-3 +u0_a8 6673 1873 1756828 84724 ffffffff 00000000 S pool-22-thread- +u0_a8 8581 1873 1756828 84724 ffffffff 00000000 S Binder_5 +u0_a8 9001 1873 1756828 84724 ffffffff 00000000 S Gservices +u0_a8 9024 1873 1756828 84724 ffffffff 00000000 S GamesProviderWo +u0_a8 11865 1873 1756828 84724 ffffffff 00000000 S pool-37-thread- +u0_a8 1949 205 1614008 81544 ffffffff 00000000 S com.google.android.gms.persistent +u0_a8 1954 1949 1614008 81544 ffffffff 00000000 S Heap thread poo +u0_a8 1955 1949 1614008 81544 ffffffff 00000000 S Heap thread poo +u0_a8 1956 1949 1614008 81544 ffffffff 00000000 S Heap thread poo +u0_a8 1959 1949 1614008 81544 ffffffff 00000000 S Signal Catcher +u0_a8 1960 1949 1614008 81544 ffffffff 00000000 S JDWP +u0_a8 1961 1949 1614008 81544 ffffffff 00000000 S ReferenceQueueD +u0_a8 1962 1949 1614008 81544 ffffffff 00000000 S FinalizerDaemon +u0_a8 1963 1949 1614008 81544 ffffffff 00000000 S FinalizerWatchd +u0_a8 1964 1949 1614008 81544 ffffffff 00000000 S HeapTrimmerDaem +u0_a8 1965 1949 1614008 81544 ffffffff 00000000 S GCDaemon +u0_a8 1966 1949 1614008 81544 ffffffff 00000000 S Binder_1 +u0_a8 1967 1949 1614008 81544 ffffffff 00000000 S Binder_2 +u0_a8 1968 1949 1614008 81544 ffffffff 00000000 S Gservices +u0_a8 1973 1949 1614008 81544 ffffffff 00000000 S IntentService[G +u0_a8 1976 1949 1614008 81544 ffffffff 00000000 S FlpThread +u0_a8 1977 1949 1614008 81544 ffffffff 00000000 S Binder_3 +u0_a8 1978 1949 1614008 81544 ffffffff 00000000 S WifiManager +u0_a8 1979 1949 1614008 81544 ffffffff 00000000 S GeofencerStateM +u0_a8 1980 1949 1614008 81544 ffffffff 00000000 S LocationService +u0_a8 1984 1949 1614008 81544 ffffffff 00000000 S Binder_4 +u0_a8 1986 1949 1614008 81544 ffffffff 00000000 S Binder_5 +u0_a8 1990 1949 1614008 81544 ffffffff 00000000 S pool-4-thread-1 +u0_a8 1992 1949 1614008 81544 ffffffff 00000000 S GmsCoreStatsSer +u0_a8 1995 1949 1614008 81544 ffffffff 00000000 S GoogleLocationS +u0_a8 2004 1949 1614008 81544 ffffffff 00000000 S Thread-139 +u0_a8 2005 1949 1614008 81544 ffffffff 00000000 S Thread-140 +u0_a8 2006 1949 1614008 81544 ffffffff 00000000 S Thread-141 +u0_a8 2007 1949 1614008 81544 ffffffff 00000000 S Thread-142 +u0_a8 2021 1949 1614008 81544 ffffffff 00000000 S NetworkLocation +u0_a8 2029 1949 1614008 81544 ffffffff 00000000 S UlrDispatchingS +u0_a8 2030 1949 1614008 81544 ffffffff 00000000 S nlp-async-worke +u0_a8 2521 1949 1614008 81544 ffffffff 00000000 S FitnessServiceF +u0_a8 2522 1949 1614008 81544 ffffffff 00000000 S FitRecordingBro +u0_a8 2526 1949 1614008 81544 ffffffff 00000000 S AsyncTask #1 +u0_a8 2530 1949 1614008 81544 ffffffff 00000000 S NearbyMessagesB +u0_a8 4180 1949 1614008 81544 ffffffff 00000000 S AsyncTask #2 +u0_a8 4221 1949 1614008 81544 ffffffff 00000000 S AsyncTask #3 +u0_a8 4223 1949 1614008 81544 ffffffff 00000000 S AsyncTask #4 +u0_a8 4749 1949 1614008 81544 ffffffff 00000000 S CopresenceEvent +u0_a8 6326 1949 1614008 81544 ffffffff 00000000 S AsyncTask #5 +u0_a8 6917 1949 1614008 81544 ffffffff 00000000 S Binder_6 +u0_a8 7196 1949 1614008 81544 ffffffff 00000000 S UlrDispatchingS +u0_a8 7260 1949 1614008 81544 ffffffff 00000000 S Thread-174 +u0_a8 7261 1949 1614008 81544 ffffffff 00000000 S Thread-175 +u0_a8 7262 1949 1614008 81544 ffffffff 00000000 S Thread-176 +u0_a8 7263 1949 1614008 81544 ffffffff 00000000 S Thread-177 +u0_a8 7264 1949 1614008 81544 ffffffff 00000000 S Thread-178 +u0_a8 12449 1949 1614008 81544 ffffffff 00000000 S OkHttp Connecti +root 2031 1 20256 880 ffffffff 00000000 S /system/bin/mpdecision +root 2032 2031 20256 880 ffffffff 00000000 S mpdecision +root 2033 2031 20256 880 ffffffff 00000000 S mpdecision +root 2034 2031 20256 880 ffffffff 00000000 S mpdecision +root 2035 2031 20256 880 ffffffff 00000000 S mpdecision +root 2036 2031 20256 880 ffffffff 00000000 S mpdecision +root 2046 2031 20256 880 ffffffff 00000000 S mpdecision +u0_a193 2647 205 1541760 60840 ffffffff 00000000 S com.qiyi.video.market +u0_a193 2653 2647 1541760 60840 ffffffff 00000000 S Heap thread poo +u0_a193 2654 2647 1541760 60840 ffffffff 00000000 S Heap thread poo +u0_a193 2655 2647 1541760 60840 ffffffff 00000000 S Heap thread poo +u0_a193 2656 2647 1541760 60840 ffffffff 00000000 S Signal Catcher +u0_a193 2657 2647 1541760 60840 ffffffff 00000000 S JDWP +u0_a193 2658 2647 1541760 60840 ffffffff 00000000 S ReferenceQueueD +u0_a193 2659 2647 1541760 60840 ffffffff 00000000 S FinalizerDaemon +u0_a193 2660 2647 1541760 60840 ffffffff 00000000 S FinalizerWatchd +u0_a193 2661 2647 1541760 60840 ffffffff 00000000 S HeapTrimmerDaem +u0_a193 2662 2647 1541760 60840 ffffffff 00000000 S GCDaemon +u0_a193 2663 2647 1541760 60840 ffffffff 00000000 S Binder_1 +u0_a193 2664 2647 1541760 60840 ffffffff 00000000 S Binder_2 +u0_a193 2671 2647 1541760 60840 ffffffff 00000000 S RefQueueWorker@ +u0_a193 2673 2647 1541760 60840 ffffffff 00000000 S .ProcessManager +u0_a193 2675 2647 1541760 60840 ffffffff 00000000 S Binder_3 +u0_a193 2677 2647 1541760 60840 ffffffff 00000000 S Thread-208 +u0_a193 2679 2647 1541760 60840 ffffffff 00000000 S pool-2-thread-1 +u0_a193 2680 2647 1541760 60840 ffffffff 00000000 S WifiManager +u0_a193 2682 2647 1541760 60840 ffffffff 00000000 S Timer-0 +u0_a193 2683 2647 1541760 60840 ffffffff 00000000 S Timer-1 +u0_a193 2710 2647 1541760 60840 ffffffff 00000000 S AsyncTask #1 +u0_a193 2718 2647 1541760 60840 ffffffff 00000000 S pool-3-thread-1 +u0_a193 3103 2647 1541760 60840 ffffffff 00000000 S pool-4-thread-1 +u0_a193 6672 2647 1541760 60840 ffffffff 00000000 S AsyncTask #2 +u0_a193 6752 2647 1541760 60840 ffffffff 00000000 S AsyncTask #3 +u0_a193 12484 2647 1541760 60840 ffffffff 00000000 S AsyncTask #4 +u0_a193 12576 2647 1541760 60840 ffffffff 00000000 S AsyncTask #5 +u0_a193 3104 205 1523132 46892 ffffffff 00000000 S com.qiyi.video.market:pluginDownloadService +u0_a193 3110 3104 1523132 46892 ffffffff 00000000 S Heap thread poo +u0_a193 3111 3104 1523132 46892 ffffffff 00000000 S Heap thread poo +u0_a193 3112 3104 1523132 46892 ffffffff 00000000 S Heap thread poo +u0_a193 3113 3104 1523132 46892 ffffffff 00000000 S Signal Catcher +u0_a193 3114 3104 1523132 46892 ffffffff 00000000 S JDWP +u0_a193 3115 3104 1523132 46892 ffffffff 00000000 S ReferenceQueueD +u0_a193 3116 3104 1523132 46892 ffffffff 00000000 S FinalizerDaemon +u0_a193 3117 3104 1523132 46892 ffffffff 00000000 S FinalizerWatchd +u0_a193 3118 3104 1523132 46892 ffffffff 00000000 S HeapTrimmerDaem +u0_a193 3119 3104 1523132 46892 ffffffff 00000000 S GCDaemon +u0_a193 3120 3104 1523132 46892 ffffffff 00000000 S Binder_1 +u0_a193 3121 3104 1523132 46892 ffffffff 00000000 S Binder_2 +u0_a193 3141 3104 1523132 46892 ffffffff 00000000 S RefQueueWorker@ +u0_a193 3257 3104 1523132 46892 ffffffff 00000000 S pool-3-thread-1 +u0_a193 7173 3104 1523132 46892 ffffffff 00000000 S Binder_3 +u0_a193 3122 205 1538224 61140 ffffffff 00000000 S com.qiyi.video.market:bdservice_v1 +u0_a193 3128 3122 1538224 61140 ffffffff 00000000 S Heap thread poo +u0_a193 3129 3122 1538224 61140 ffffffff 00000000 S Heap thread poo +u0_a193 3130 3122 1538224 61140 ffffffff 00000000 S Heap thread poo +u0_a193 3131 3122 1538224 61140 ffffffff 00000000 S Signal Catcher +u0_a193 3132 3122 1538224 61140 ffffffff 00000000 S JDWP +u0_a193 3133 3122 1538224 61140 ffffffff 00000000 S ReferenceQueueD +u0_a193 3134 3122 1538224 61140 ffffffff 00000000 S FinalizerDaemon +u0_a193 3135 3122 1538224 61140 ffffffff 00000000 S FinalizerWatchd +u0_a193 3136 3122 1538224 61140 ffffffff 00000000 S HeapTrimmerDaem +u0_a193 3137 3122 1538224 61140 ffffffff 00000000 S GCDaemon +u0_a193 3138 3122 1538224 61140 ffffffff 00000000 S Binder_1 +u0_a193 3139 3122 1538224 61140 ffffffff 00000000 S Binder_2 +u0_a193 3145 3122 1538224 61140 ffffffff 00000000 S RefQueueWorker@ +u0_a193 3206 3122 1538224 61140 ffffffff 00000000 S WifiManager +u0_a193 3208 3122 1538224 61140 ffffffff 00000000 S NanoHttpd Main +u0_a193 7586 3122 1538224 61140 ffffffff 00000000 S pool-4-thread-1 +u0_a193 10584 3122 1538224 61140 ffffffff 00000000 S pool-2-thread-1 +u0_a193 3154 205 1522116 53536 ffffffff 00000000 S com.qiyi.video.market:baiduLocation +u0_a193 3163 3154 1522116 53536 ffffffff 00000000 S Heap thread poo +u0_a193 3164 3154 1522116 53536 ffffffff 00000000 S Heap thread poo +u0_a193 3165 3154 1522116 53536 ffffffff 00000000 S Heap thread poo +u0_a193 3166 3154 1522116 53536 ffffffff 00000000 S Signal Catcher +u0_a193 3167 3154 1522116 53536 ffffffff 00000000 S JDWP +u0_a193 3168 3154 1522116 53536 ffffffff 00000000 S ReferenceQueueD +u0_a193 3169 3154 1522116 53536 ffffffff 00000000 S FinalizerDaemon +u0_a193 3170 3154 1522116 53536 ffffffff 00000000 S FinalizerWatchd +u0_a193 3171 3154 1522116 53536 ffffffff 00000000 S HeapTrimmerDaem +u0_a193 3172 3154 1522116 53536 ffffffff 00000000 S GCDaemon +u0_a193 3173 3154 1522116 53536 ffffffff 00000000 S Binder_1 +u0_a193 3174 3154 1522116 53536 ffffffff 00000000 S Binder_2 +u0_a193 3177 3154 1522116 53536 ffffffff 00000000 S RefQueueWorker@ +u0_a193 3199 3154 1522116 53536 ffffffff 00000000 S WifiManager +u0_a86 3179 205 1561816 58376 ffffffff 00000000 S com.tencent.mm:push +u0_a86 3183 3179 1561816 58376 ffffffff 00000000 S Heap thread poo +u0_a86 3184 3179 1561816 58376 ffffffff 00000000 S Heap thread poo +u0_a86 3185 3179 1561816 58376 ffffffff 00000000 S Heap thread poo +u0_a86 3187 3179 1561816 58376 ffffffff 00000000 S Signal Catcher +u0_a86 3189 3179 1561816 58376 ffffffff 00000000 S JDWP +u0_a86 3190 3179 1561816 58376 ffffffff 00000000 S ReferenceQueueD +u0_a86 3191 3179 1561816 58376 ffffffff 00000000 S FinalizerDaemon +u0_a86 3192 3179 1561816 58376 ffffffff 00000000 S FinalizerWatchd +u0_a86 3193 3179 1561816 58376 ffffffff 00000000 S HeapTrimmerDaem +u0_a86 3194 3179 1561816 58376 ffffffff 00000000 S GCDaemon +u0_a86 3195 3179 1561816 58376 ffffffff 00000000 S Binder_1 +u0_a86 3196 3179 1561816 58376 ffffffff 00000000 S Binder_2 +u0_a86 3210 3179 1561816 58376 ffffffff 00000000 S THREAD_POOL_HAN +u0_a86 3212 3179 1561816 58376 ffffffff 00000000 S tencent.mm:push +u0_a86 3216 3179 1561816 58376 ffffffff 00000000 S FileObserver +u0_a86 3238 3179 1561816 58376 ffffffff 00000000 S tencent.mm:push +u0_a86 3239 3179 1561816 58376 ffffffff 00000000 S default +u0_a86 3240 3179 1561816 58376 ffffffff 00000000 S WifiManager +u0_a86 5627 3179 1561816 58376 ffffffff 00000000 S Binder_3 +u0_a86 7150 3179 1561816 58376 ffffffff 00000000 S default +u0_a170 3217 205 1531688 52204 ffffffff 00000000 S com.baidu.searchbox:bdservice_v1 +u0_a170 3220 3217 1531688 52204 ffffffff 00000000 S Heap thread poo +u0_a170 3221 3217 1531688 52204 ffffffff 00000000 S Heap thread poo +u0_a170 3223 3217 1531688 52204 ffffffff 00000000 S Heap thread poo +u0_a170 3226 3217 1531688 52204 ffffffff 00000000 S Signal Catcher +u0_a170 3228 3217 1531688 52204 ffffffff 00000000 S JDWP +u0_a170 3229 3217 1531688 52204 ffffffff 00000000 S ReferenceQueueD +u0_a170 3230 3217 1531688 52204 ffffffff 00000000 S FinalizerDaemon +u0_a170 3231 3217 1531688 52204 ffffffff 00000000 S FinalizerWatchd +u0_a170 3233 3217 1531688 52204 ffffffff 00000000 S HeapTrimmerDaem +u0_a170 3234 3217 1531688 52204 ffffffff 00000000 S GCDaemon +u0_a170 3235 3217 1531688 52204 ffffffff 00000000 S Binder_1 +u0_a170 3236 3217 1531688 52204 ffffffff 00000000 S Binder_2 +u0_a170 3303 3217 1531688 52204 ffffffff 00000000 S AsyncTask #1 +u0_a170 3304 3217 1531688 52204 ffffffff 00000000 S AsyncTask #2 +u0_a170 3518 3217 1531688 52204 ffffffff 00000000 S PushService-Pus +u0_a170 3519 3217 1531688 52204 ffffffff 00000000 S PushService-Pus +u0_a170 6201 3217 1531688 52204 ffffffff 00000000 S pool-1-thread-1 +u0_a170 10591 3217 1531688 52204 ffffffff 00000000 S RefQueueWorker@ +u0_a170 3260 205 1533384 53212 ffffffff 00000000 S com.baidu.searchbox:bdmoservice +u0_a170 3264 3260 1533384 53212 ffffffff 00000000 S Heap thread poo +u0_a170 3265 3260 1533384 53212 ffffffff 00000000 S Heap thread poo +u0_a170 3266 3260 1533384 53212 ffffffff 00000000 S Heap thread poo +u0_a170 3269 3260 1533384 53212 ffffffff 00000000 S Signal Catcher +u0_a170 3270 3260 1533384 53212 ffffffff 00000000 S JDWP +u0_a170 3271 3260 1533384 53212 ffffffff 00000000 S ReferenceQueueD +u0_a170 3272 3260 1533384 53212 ffffffff 00000000 S FinalizerDaemon +u0_a170 3273 3260 1533384 53212 ffffffff 00000000 S FinalizerWatchd +u0_a170 3274 3260 1533384 53212 ffffffff 00000000 S HeapTrimmerDaem +u0_a170 3275 3260 1533384 53212 ffffffff 00000000 S GCDaemon +u0_a170 3276 3260 1533384 53212 ffffffff 00000000 S Binder_1 +u0_a170 3277 3260 1533384 53212 ffffffff 00000000 S Binder_2 +u0_a170 3738 3260 1533384 53212 ffffffff 00000000 S NanoHttpd Main +u0_a170 5783 3260 1533384 53212 ffffffff 00000000 S WifiManager +u0_a126 3633 205 1515740 46080 ffffffff 00000000 S com.tencent.portfolio:push +u0_a126 3636 3633 1515740 46080 ffffffff 00000000 S Heap thread poo +u0_a126 3638 3633 1515740 46080 ffffffff 00000000 S Heap thread poo +u0_a126 3639 3633 1515740 46080 ffffffff 00000000 S Heap thread poo +u0_a126 3642 3633 1515740 46080 ffffffff 00000000 S Signal Catcher +u0_a126 3643 3633 1515740 46080 ffffffff 00000000 S JDWP +u0_a126 3645 3633 1515740 46080 ffffffff 00000000 S ReferenceQueueD +u0_a126 3646 3633 1515740 46080 ffffffff 00000000 S FinalizerDaemon +u0_a126 3647 3633 1515740 46080 ffffffff 00000000 S FinalizerWatchd +u0_a126 3648 3633 1515740 46080 ffffffff 00000000 S HeapTrimmerDaem +u0_a126 3649 3633 1515740 46080 ffffffff 00000000 S GCDaemon +u0_a126 3650 3633 1515740 46080 ffffffff 00000000 S Binder_1 +u0_a126 3651 3633 1515740 46080 ffffffff 00000000 S Binder_2 +u0_a126 3661 3633 1515740 46080 ffffffff 00000000 S TPPluginCenter +u0_a126 3663 3633 1515740 46080 ffffffff 00000000 S pool-1-thread-1 +u0_a126 3665 3633 1515740 46080 ffffffff 00000000 S MidService +u0_a126 3667 3633 1515740 46080 ffffffff 00000000 S pool-2-thread-1 +u0_a126 3668 3633 1515740 46080 ffffffff 00000000 S push core threa +u0_a126 3670 3633 1515740 46080 ffffffff 00000000 S .ProcessManager +u0_a126 3672 3633 1515740 46080 ffffffff 00000000 S Binder_3 +u0_a126 3674 3633 1515740 46080 ffffffff 00000000 S pool-4-thread-1 +u0_a126 3675 3633 1515740 46080 ffffffff 00000000 S pool-3-thread-1 +u0_a126 5638 3633 1515740 46080 ffffffff 00000000 S Timer-0 +bluetooth 4227 205 1527652 48088 ffffffff 00000000 S com.android.bluetooth +bluetooth 4231 4227 1527652 48088 ffffffff 00000000 S Heap thread poo +bluetooth 4233 4227 1527652 48088 ffffffff 00000000 S Heap thread poo +bluetooth 4235 4227 1527652 48088 ffffffff 00000000 S Heap thread poo +bluetooth 4236 4227 1527652 48088 ffffffff 00000000 S Signal Catcher +bluetooth 4237 4227 1527652 48088 ffffffff 00000000 S JDWP +bluetooth 4238 4227 1527652 48088 ffffffff 00000000 S ReferenceQueueD +bluetooth 4239 4227 1527652 48088 ffffffff 00000000 S FinalizerDaemon +bluetooth 4240 4227 1527652 48088 ffffffff 00000000 S FinalizerWatchd +bluetooth 4241 4227 1527652 48088 ffffffff 00000000 S HeapTrimmerDaem +bluetooth 4242 4227 1527652 48088 ffffffff 00000000 S GCDaemon +bluetooth 4243 4227 1527652 48088 ffffffff 00000000 S Binder_1 +bluetooth 4244 4227 1527652 48088 ffffffff 00000000 S Binder_2 +bluetooth 4308 4227 1527652 48088 ffffffff 00000000 S BluetoothAdapte +bluetooth 4309 4227 1527652 48088 ffffffff 00000000 S droid.bluetooth +bluetooth 4311 4227 1527652 48088 ffffffff 00000000 S bluedroid wake/ +bluetooth 4312 4227 1527652 48088 ffffffff 00000000 S BT Service Call +bluetooth 4315 4227 1527652 48088 ffffffff 00000000 S BondStateMachin +bluetooth 4316 4227 1527652 48088 ffffffff 00000000 S Binder_3 +bluetooth 4317 4227 1527652 48088 ffffffff 00000000 S Binder_4 +bluetooth 4318 4227 1527652 48088 ffffffff 00000000 S HeadsetStateMac +bluetooth 4320 4227 1527652 48088 ffffffff 00000000 S BluetoothAvrcpH +bluetooth 4321 4227 1527652 48088 ffffffff 00000000 S A2dpStateMachin +bluetooth 4322 4227 1527652 48088 ffffffff 00000000 S A2DP-MEDIA +bluetooth 4323 4227 1527652 48088 ffffffff 00000000 S uipc-main +bluetooth 4324 4227 1527652 48088 ffffffff 00000000 S BluetoothHdpHan +bluetooth 4325 4227 1527652 48088 ffffffff 00000000 S droid.bluetooth +bluetooth 4326 4227 1527652 48088 ffffffff 00000000 S BluetoothAdvert +bluetooth 4327 4227 1527652 48088 ffffffff 00000000 S BluetoothScanMa +bluetooth 4331 4227 1527652 48088 ffffffff 00000000 S bluedroid wake/ +bluetooth 4333 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker +bluetooth 4338 4227 1527652 48088 ffffffff 00000000 S userial_read +bluetooth 4478 4227 1527652 48088 ffffffff 00000000 S BT Service Call +bluetooth 4479 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker +bluetooth 4481 4227 1527652 48088 ffffffff 00000000 S bt_hc_worker +bluetooth 4482 4227 1527652 48088 ffffffff 00000000 S BluetoothMapAcc +bluetooth 6459 4227 1527652 48088 ffffffff 00000000 S BluetoothPbapAc +bluetooth 6473 4227 1527652 48088 ffffffff 00000000 S pool-1-thread-1 +bluetooth 6477 4227 1527652 48088 ffffffff 00000000 S BtOppRfcommList +radio 4597 205 1493160 37460 ffffffff 00000000 S com.qualcomm.qcrilmsgtunnel +radio 4603 4597 1493160 37460 ffffffff 00000000 S Heap thread poo +radio 4604 4597 1493160 37460 ffffffff 00000000 S Heap thread poo +radio 4605 4597 1493160 37460 ffffffff 00000000 S Heap thread poo +radio 4606 4597 1493160 37460 ffffffff 00000000 S Signal Catcher +radio 4607 4597 1493160 37460 ffffffff 00000000 S JDWP +radio 4608 4597 1493160 37460 ffffffff 00000000 S ReferenceQueueD +radio 4609 4597 1493160 37460 ffffffff 00000000 S FinalizerDaemon +radio 4610 4597 1493160 37460 ffffffff 00000000 S FinalizerWatchd +radio 4611 4597 1493160 37460 ffffffff 00000000 S HeapTrimmerDaem +radio 4612 4597 1493160 37460 ffffffff 00000000 S GCDaemon +radio 4613 4597 1493160 37460 ffffffff 00000000 S Binder_1 +radio 4614 4597 1493160 37460 ffffffff 00000000 S Binder_2 +radio 4615 4597 1493160 37460 ffffffff 00000000 S QcRilReceiver +radio 4616 4597 1493160 37460 ffffffff 00000000 S QcRilSender +u0_a193 5239 205 1528424 47860 ffffffff 00000000 S .iqiyipushserviceGlobal +u0_a193 5242 5239 1528424 47860 ffffffff 00000000 S Heap thread poo +u0_a193 5244 5239 1528424 47860 ffffffff 00000000 S Heap thread poo +u0_a193 5245 5239 1528424 47860 ffffffff 00000000 S Heap thread poo +u0_a193 5248 5239 1528424 47860 ffffffff 00000000 S Signal Catcher +u0_a193 5249 5239 1528424 47860 ffffffff 00000000 S JDWP +u0_a193 5250 5239 1528424 47860 ffffffff 00000000 S ReferenceQueueD +u0_a193 5251 5239 1528424 47860 ffffffff 00000000 S FinalizerDaemon +u0_a193 5252 5239 1528424 47860 ffffffff 00000000 S FinalizerWatchd +u0_a193 5253 5239 1528424 47860 ffffffff 00000000 S HeapTrimmerDaem +u0_a193 5254 5239 1528424 47860 ffffffff 00000000 S GCDaemon +u0_a193 5255 5239 1528424 47860 ffffffff 00000000 S Binder_1 +u0_a193 5257 5239 1528424 47860 ffffffff 00000000 S Binder_2 +u0_a193 5280 5239 1528424 47860 ffffffff 00000000 S RefQueueWorker@ +u0_a193 5281 5239 1528424 47860 ffffffff 00000000 S Binder_3 +u0_a193 5361 5239 1528424 47860 ffffffff 00000000 S Micro Client Co +u0_a193 5362 5239 1528424 47860 ffffffff 00000000 S Micro Client Co +u0_a193 5363 5239 1528424 47860 ffffffff 00000000 S Micro Client Ca +u0_a193 6740 5239 1528424 47860 ffffffff 00000000 S Binder_4 +u0_a193 7091 5239 1528424 47860 ffffffff 00000000 S Binder_5 +u0_a193 7557 5239 1528424 47860 ffffffff 00000000 S Binder_6 +u0_a193 5285 5239 1521088 34196 ffffffff 00000000 S .iqiyipushserviceGlobal +u0_a90 5323 205 1557268 59988 ffffffff 00000000 S com.strava +u0_a90 5327 5323 1557268 59988 ffffffff 00000000 S Heap thread poo +u0_a90 5328 5323 1557268 59988 ffffffff 00000000 S Heap thread poo +u0_a90 5329 5323 1557268 59988 ffffffff 00000000 S Heap thread poo +u0_a90 5332 5323 1557268 59988 ffffffff 00000000 S Signal Catcher +u0_a90 5333 5323 1557268 59988 ffffffff 00000000 S JDWP +u0_a90 5334 5323 1557268 59988 ffffffff 00000000 S ReferenceQueueD +u0_a90 5335 5323 1557268 59988 ffffffff 00000000 S FinalizerDaemon +u0_a90 5336 5323 1557268 59988 ffffffff 00000000 S FinalizerWatchd +u0_a90 5337 5323 1557268 59988 ffffffff 00000000 S HeapTrimmerDaem +u0_a90 5338 5323 1557268 59988 ffffffff 00000000 S GCDaemon +u0_a90 5339 5323 1557268 59988 ffffffff 00000000 S Binder_1 +u0_a90 5340 5323 1557268 59988 ffffffff 00000000 S Binder_2 +u0_a90 5345 5323 1557268 59988 ffffffff 00000000 S Queue +u0_a90 5346 5323 1557268 59988 ffffffff 00000000 S Queue +u0_a90 5347 5323 1557268 59988 ffffffff 00000000 S Queue +u0_a90 5348 5323 1557268 59988 ffffffff 00000000 S Queue +u0_a90 5349 5323 1557268 59988 ffffffff 00000000 S Queue +u0_a90 5352 5323 1557268 59988 ffffffff 00000000 S Crashlytics Exc +u0_a90 5354 5323 1557268 59988 ffffffff 00000000 S pool-3-thread-1 +u0_a90 5364 5323 1557268 59988 ffffffff 00000000 S Thread-584 +u0_a90 5365 5323 1557268 59988 ffffffff 00000000 S Thread-585 +u0_a90 5366 5323 1557268 59988 ffffffff 00000000 S Thread-586 +u0_a90 5367 5323 1557268 59988 ffffffff 00000000 S pool-4-thread-1 +u0_a90 5369 5323 1557268 59988 ffffffff 00000000 S Crashlytics Tra +u0_a90 5372 5323 1557268 59988 ffffffff 00000000 S Thread-593 +u0_a90 5373 5323 1557268 59988 ffffffff 00000000 S Thread-594 +u0_a90 5374 5323 1557268 59988 ffffffff 00000000 S Thread-595 +u0_a90 5375 5323 1557268 59988 ffffffff 00000000 S Thread-596 +u0_a90 5376 5323 1557268 59988 ffffffff 00000000 S pool-6-thread-1 +u0_a90 5377 5323 1557268 59988 ffffffff 00000000 S Thread-598 +u0_a90 5378 5323 1557268 59988 ffffffff 00000000 S Thread-599 +u0_a90 5379 5323 1557268 59988 ffffffff 00000000 S Thread-600 +u0_a90 5381 5323 1557268 59988 ffffffff 00000000 S Thread-602 +u0_a90 5383 5323 1557268 59988 ffffffff 00000000 S Thread #1 +u0_a90 5384 5323 1557268 59988 ffffffff 00000000 S AsyncTask #1 +u0_a90 5387 5323 1557268 59988 ffffffff 00000000 S Thread-605 +u0_a90 5388 5323 1557268 59988 ffffffff 00000000 S Thread-606 +u0_a90 5389 5323 1557268 59988 ffffffff 00000000 S Thread-607 +u0_a90 5390 5323 1557268 59988 ffffffff 00000000 S Thread-608 +u0_a90 5391 5323 1557268 59988 ffffffff 00000000 S Thread-609 +u0_a90 5393 5323 1557268 59988 ffffffff 00000000 S eNowAuthService +u0_a90 5394 5323 1557268 59988 ffffffff 00000000 S Thread #2 +u0_a90 5468 5323 1557268 59988 ffffffff 00000000 S Okio Watchdog +u0_a90 5498 5323 1557268 59988 ffffffff 00000000 S Thread #3 +u0_a109 5395 205 1524968 53976 ffffffff 00000000 S com.pandora.android +u0_a109 5397 5395 1524968 53976 ffffffff 00000000 S Heap thread poo +u0_a109 5398 5395 1524968 53976 ffffffff 00000000 S Heap thread poo +u0_a109 5399 5395 1524968 53976 ffffffff 00000000 S Heap thread poo +u0_a109 5401 5395 1524968 53976 ffffffff 00000000 S Signal Catcher +u0_a109 5403 5395 1524968 53976 ffffffff 00000000 S JDWP +u0_a109 5407 5395 1524968 53976 ffffffff 00000000 S ReferenceQueueD +u0_a109 5408 5395 1524968 53976 ffffffff 00000000 S FinalizerDaemon +u0_a109 5409 5395 1524968 53976 ffffffff 00000000 S FinalizerWatchd +u0_a109 5410 5395 1524968 53976 ffffffff 00000000 S HeapTrimmerDaem +u0_a109 5411 5395 1524968 53976 ffffffff 00000000 S GCDaemon +u0_a109 5414 5395 1524968 53976 ffffffff 00000000 S Binder_1 +u0_a109 5416 5395 1524968 53976 ffffffff 00000000 S Binder_2 +u0_a109 5422 5395 1524968 53976 ffffffff 00000000 S Crashlytics Exc +u0_a109 5429 5395 1524968 53976 ffffffff 00000000 S pool-2-thread-1 +u0_a109 5430 5395 1524968 53976 ffffffff 00000000 S AsyncTask #1 +u0_a109 5437 5395 1524968 53976 ffffffff 00000000 S Crashlytics Tra +u0_a109 5439 5395 1524968 53976 ffffffff 00000000 S AsyncTask #2 +u0_a109 5440 5395 1524968 53976 ffffffff 00000000 S pool-4-thread-1 +u0_a109 5443 5395 1524968 53976 ffffffff 00000000 S PurchasingManag +u0_a109 5444 5395 1524968 53976 ffffffff 00000000 S BluetoothServer +u0_a109 5445 5395 1524968 53976 ffffffff 00000000 S AsyncTask #3 +u0_a109 5446 5395 1524968 53976 ffffffff 00000000 S AsyncTask #4 +u0_a109 5590 5395 1524968 53976 ffffffff 00000000 S Binder_3 +u0_a109 6481 5395 1524968 53976 ffffffff 00000000 S AsyncTask #5 +u0_a110 5474 205 1525556 49828 ffffffff 00000000 S tunein.player +u0_a110 5479 5474 1525556 49828 ffffffff 00000000 S Heap thread poo +u0_a110 5480 5474 1525556 49828 ffffffff 00000000 S Heap thread poo +u0_a110 5481 5474 1525556 49828 ffffffff 00000000 S Heap thread poo +u0_a110 5483 5474 1525556 49828 ffffffff 00000000 S Signal Catcher +u0_a110 5484 5474 1525556 49828 ffffffff 00000000 S JDWP +u0_a110 5485 5474 1525556 49828 ffffffff 00000000 S ReferenceQueueD +u0_a110 5486 5474 1525556 49828 ffffffff 00000000 S FinalizerDaemon +u0_a110 5487 5474 1525556 49828 ffffffff 00000000 S FinalizerWatchd +u0_a110 5488 5474 1525556 49828 ffffffff 00000000 S HeapTrimmerDaem +u0_a110 5489 5474 1525556 49828 ffffffff 00000000 S GCDaemon +u0_a110 5490 5474 1525556 49828 ffffffff 00000000 S Binder_1 +u0_a110 5492 5474 1525556 49828 ffffffff 00000000 S Binder_2 +u0_a110 5503 5474 1525556 49828 ffffffff 00000000 S geHandlerThread +u0_a110 5504 5474 1525556 49828 ffffffff 00000000 S GAThread +u0_a110 5507 5474 1525556 49828 ffffffff 00000000 S Crashlytics Exc +u0_a110 5510 5474 1525556 49828 ffffffff 00000000 S AsyncTask #1 +u0_a110 5515 5474 1525556 49828 ffffffff 00000000 S Crashlytics Tra +u0_a110 5518 5474 1525556 49828 ffffffff 00000000 S AsyncTask #2 +u0_a110 5587 5474 1525556 49828 ffffffff 00000000 S AcceptThreadSec +u0_a88 5519 205 1556696 65876 ffffffff 00000000 S com.dropbox.android +u0_a88 5525 5519 1556696 65876 ffffffff 00000000 S Heap thread poo +u0_a88 5526 5519 1556696 65876 ffffffff 00000000 S Heap thread poo +u0_a88 5527 5519 1556696 65876 ffffffff 00000000 S Heap thread poo +u0_a88 5528 5519 1556696 65876 ffffffff 00000000 S Signal Catcher +u0_a88 5529 5519 1556696 65876 ffffffff 00000000 S JDWP +u0_a88 5530 5519 1556696 65876 ffffffff 00000000 S ReferenceQueueD +u0_a88 5531 5519 1556696 65876 ffffffff 00000000 S FinalizerDaemon +u0_a88 5532 5519 1556696 65876 ffffffff 00000000 S FinalizerWatchd +u0_a88 5533 5519 1556696 65876 ffffffff 00000000 S HeapTrimmerDaem +u0_a88 5534 5519 1556696 65876 ffffffff 00000000 S GCDaemon +u0_a88 5535 5519 1556696 65876 ffffffff 00000000 S Binder_1 +u0_a88 5536 5519 1556696 65876 ffffffff 00000000 S Binder_2 +u0_a88 5562 5519 1556696 65876 ffffffff 00000000 S Dropbox log upl +u0_a88 5563 5519 1556696 65876 ffffffff 00000000 S gandalf updater +u0_a88 5568 5519 1556696 65876 ffffffff 00000000 S pool-10-thread- +u0_a88 5569 5519 1556696 65876 ffffffff 00000000 S DbxFileObserver +u0_a88 5570 5519 1556696 65876 ffffffff 00000000 S LocalThumbManag +u0_a88 5574 5519 1556696 65876 ffffffff 00000000 S local AsyncTask +u0_a88 5575 5519 1556696 65876 ffffffff 00000000 S remote AsyncTas +u0_a88 5576 5519 1556696 65876 ffffffff 00000000 S local AsyncTask +u0_a88 5577 5519 1556696 65876 ffffffff 00000000 S remote AsyncTas +u0_a88 5578 5519 1556696 65876 ffffffff 00000000 S Dropbox notif o +u0_a88 5579 5519 1556696 65876 ffffffff 00000000 S Dropbox notif s +u0_a88 5580 5519 1556696 65876 ffffffff 00000000 S Picasso-Stats +u0_a88 5581 5519 1556696 65876 ffffffff 00000000 S Picasso-Dispatc +u0_a88 5582 5519 1556696 65876 ffffffff 00000000 S Picasso-refQueu +u0_a88 5583 5519 1556696 65876 ffffffff 00000000 S gandalf updater +u0_a88 5592 5519 1556696 65876 ffffffff 00000000 S DbxFileObserver +u0_a88 5593 5519 1556696 65876 ffffffff 00000000 S dbxpool-34:r-th +u0_a88 5594 5519 1556696 65876 ffffffff 00000000 S dbxpool-32:au-t +u0_a88 5595 5519 1556696 65876 ffffffff 00000000 S dbxpool-38:a-th +u0_a88 5596 5519 1556696 65876 ffffffff 00000000 S Timer-0 +u0_a88 5597 5519 1556696 65876 ffffffff 00000000 S dbxpool-6:a-thr +u0_a88 5599 5519 1556696 65876 ffffffff 00000000 S Timer-1 +u0_a88 5718 5519 1556696 65876 ffffffff 00000000 S RefQueueWorker@ +u0_a88 5750 5519 1556696 65876 ffffffff 00000000 S Thread-625 +u0_a88 5818 5519 1556696 65876 ffffffff 00000000 S Binder_3 +u0_a88 8569 5519 1556696 65876 ffffffff 00000000 S Binder_4 +u0_a88 8572 5519 1556696 65876 ffffffff 00000000 S Binder_5 +u0_a88 8580 5519 1556696 65876 ffffffff 00000000 S Binder_6 +u0_a93 5688 205 1496212 39724 ffffffff 00000000 S com.devuni.flashlight:remote +u0_a93 5693 5688 1496212 39724 ffffffff 00000000 S Heap thread poo +u0_a93 5694 5688 1496212 39724 ffffffff 00000000 S Heap thread poo +u0_a93 5695 5688 1496212 39724 ffffffff 00000000 S Heap thread poo +u0_a93 5697 5688 1496212 39724 ffffffff 00000000 S Signal Catcher +u0_a93 5698 5688 1496212 39724 ffffffff 00000000 S JDWP +u0_a93 5699 5688 1496212 39724 ffffffff 00000000 S ReferenceQueueD +u0_a93 5700 5688 1496212 39724 ffffffff 00000000 S FinalizerDaemon +u0_a93 5701 5688 1496212 39724 ffffffff 00000000 S FinalizerWatchd +u0_a93 5702 5688 1496212 39724 ffffffff 00000000 S HeapTrimmerDaem +u0_a93 5703 5688 1496212 39724 ffffffff 00000000 S GCDaemon +u0_a93 5704 5688 1496212 39724 ffffffff 00000000 S Binder_1 +u0_a93 5705 5688 1496212 39724 ffffffff 00000000 S Binder_2 +u0_a93 12039 5688 1496212 39724 ffffffff 00000000 S pool-1-thread-1 +u0_a86 6202 205 1809096 86876 ffffffff 00000000 S com.tencent.mm +u0_a86 6206 6202 1809096 86876 ffffffff 00000000 S Heap thread poo +u0_a86 6207 6202 1809096 86876 ffffffff 00000000 S Heap thread poo +u0_a86 6208 6202 1809096 86876 ffffffff 00000000 S Heap thread poo +u0_a86 6211 6202 1809096 86876 ffffffff 00000000 S Signal Catcher +u0_a86 6212 6202 1809096 86876 ffffffff 00000000 S JDWP +u0_a86 6213 6202 1809096 86876 ffffffff 00000000 S ReferenceQueueD +u0_a86 6214 6202 1809096 86876 ffffffff 00000000 S FinalizerDaemon +u0_a86 6215 6202 1809096 86876 ffffffff 00000000 S FinalizerWatchd +u0_a86 6217 6202 1809096 86876 ffffffff 00000000 S HeapTrimmerDaem +u0_a86 6218 6202 1809096 86876 ffffffff 00000000 S GCDaemon +u0_a86 6220 6202 1809096 86876 ffffffff 00000000 S Binder_1 +u0_a86 6221 6202 1809096 86876 ffffffff 00000000 S Binder_2 +u0_a86 6236 6202 1809096 86876 ffffffff 00000000 S THREAD_POOL_HAN +u0_a86 6237 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm +u0_a86 6239 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm +u0_a86 6240 6202 1809096 86876 ffffffff 00000000 S MonitorHandlerT +u0_a86 6241 6202 1809096 86876 ffffffff 00000000 S .ProcessManager +u0_a86 6243 6202 1809096 86876 ffffffff 00000000 S Binder_3 +u0_a86 6245 6202 1809096 86876 ffffffff 00000000 S default +u0_a86 6246 6202 1809096 86876 ffffffff 00000000 S com.tencent.mm +u0_a86 6247 6202 1809096 86876 ffffffff 00000000 S MMHandlerThread +u0_a86 6269 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6270 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6271 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6272 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6273 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6274 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6276 6202 1809096 86876 ffffffff 00000000 S ExdeviceHandler +u0_a86 6277 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6279 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout +u0_a86 6280 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout +u0_a86 6282 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6284 6202 1809096 86876 ffffffff 00000000 S downloadStateCh +u0_a86 6288 6202 1809096 86876 ffffffff 00000000 S WifiManager +u0_a86 6289 6202 1809096 86876 ffffffff 00000000 S refresh Notific +u0_a86 6292 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6293 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6294 6202 1809096 86876 ffffffff 00000000 S MM_Thread_Pool_ +u0_a86 6295 6202 1809096 86876 ffffffff 00000000 S SearchDaemon +u0_a86 6303 6202 1809096 86876 ffffffff 00000000 S Binder_4 +u0_a86 6313 6202 1809096 86876 ffffffff 00000000 S pool-2-thread-1 +u0_a86 6373 6202 1809096 86876 ffffffff 00000000 S RWCache_timeout +u0_a86 6408 6202 1809096 86876 ffffffff 00000000 S h +u0_a86 7230 6202 1809096 86876 ffffffff 00000000 S default +u0_a86 7231 6202 1809096 86876 ffffffff 00000000 S MMHandlerThread +u0_a191 8839 205 1510312 57352 ffffffff 00000000 S com.ushaqi.zhuishushenqi:pushservice +u0_a191 8845 8839 1510312 57352 ffffffff 00000000 S Heap thread poo +u0_a191 8846 8839 1510312 57352 ffffffff 00000000 S Heap thread poo +u0_a191 8847 8839 1510312 57352 ffffffff 00000000 S Heap thread poo +u0_a191 8849 8839 1510312 57352 ffffffff 00000000 S Signal Catcher +u0_a191 8850 8839 1510312 57352 ffffffff 00000000 S JDWP +u0_a191 8851 8839 1510312 57352 ffffffff 00000000 S ReferenceQueueD +u0_a191 8852 8839 1510312 57352 ffffffff 00000000 S FinalizerDaemon +u0_a191 8853 8839 1510312 57352 ffffffff 00000000 S FinalizerWatchd +u0_a191 8854 8839 1510312 57352 ffffffff 00000000 S HeapTrimmerDaem +u0_a191 8855 8839 1510312 57352 ffffffff 00000000 S GCDaemon +u0_a191 8856 8839 1510312 57352 ffffffff 00000000 S Binder_1 +u0_a191 8857 8839 1510312 57352 ffffffff 00000000 S Binder_2 +u0_a191 8867 8839 1510312 57352 ffffffff 00000000 S local_job_dispa +u0_a191 8869 8839 1510312 57352 ffffffff 00000000 S remote_job_disp +u0_a191 8887 8839 1510312 57352 ffffffff 00000000 S Upload Http Rec +u0_a191 8890 8839 1510312 57352 ffffffff 00000000 S Connection Cont +u0_a191 8963 8839 1510312 57352 ffffffff 00000000 S Smack Packet Re +root 11634 2 0 0 ffffffff 00000000 S kworker/u:0 +root 11779 2 0 0 ffffffff 00000000 S kworker/0:3H +root 11928 2 0 0 ffffffff 00000000 S kworker/0:1 +root 12431 2 0 0 ffffffff 00000000 S kworker/u:2 +u0_a85 12971 205 1595348 59000 ffffffff 00000000 S com.life360.android.safetymapd:service +u0_a85 12977 12971 1595348 59000 ffffffff 00000000 S Heap thread poo +u0_a85 12978 12971 1595348 59000 ffffffff 00000000 S Heap thread poo +u0_a85 12979 12971 1595348 59000 ffffffff 00000000 S Heap thread poo +u0_a85 12980 12971 1595348 59000 ffffffff 00000000 S Signal Catcher +u0_a85 12981 12971 1595348 59000 ffffffff 00000000 S JDWP +u0_a85 12982 12971 1595348 59000 ffffffff 00000000 S ReferenceQueueD +u0_a85 12983 12971 1595348 59000 ffffffff 00000000 S FinalizerDaemon +u0_a85 12984 12971 1595348 59000 ffffffff 00000000 S FinalizerWatchd +u0_a85 12985 12971 1595348 59000 ffffffff 00000000 S HeapTrimmerDaem +u0_a85 12986 12971 1595348 59000 ffffffff 00000000 S GCDaemon +u0_a85 12987 12971 1595348 59000 ffffffff 00000000 S Binder_1 +u0_a85 12988 12971 1595348 59000 ffffffff 00000000 S Binder_2 +u0_a85 13099 12971 1595348 59000 ffffffff 00000000 S WifiManager +u0_a106 13071 205 1523392 47680 ffffffff 00000000 S com.xianguo.tingguo +u0_a106 13075 13071 1523392 47680 ffffffff 00000000 S Heap thread poo +u0_a106 13076 13071 1523392 47680 ffffffff 00000000 S Heap thread poo +u0_a106 13077 13071 1523392 47680 ffffffff 00000000 S Heap thread poo +u0_a106 13080 13071 1523392 47680 ffffffff 00000000 S Signal Catcher +u0_a106 13081 13071 1523392 47680 ffffffff 00000000 S JDWP +u0_a106 13082 13071 1523392 47680 ffffffff 00000000 S ReferenceQueueD +u0_a106 13083 13071 1523392 47680 ffffffff 00000000 S FinalizerDaemon +u0_a106 13084 13071 1523392 47680 ffffffff 00000000 S FinalizerWatchd +u0_a106 13085 13071 1523392 47680 ffffffff 00000000 S HeapTrimmerDaem +u0_a106 13086 13071 1523392 47680 ffffffff 00000000 S GCDaemon +u0_a106 13087 13071 1523392 47680 ffffffff 00000000 S Binder_1 +u0_a106 13088 13071 1523392 47680 ffffffff 00000000 S Binder_2 +u0_a106 13090 13071 1523392 47680 ffffffff 00000000 S SoundPool +u0_a106 13091 13071 1523392 47680 ffffffff 00000000 S SoundPoolThread +u0_a106 13276 13071 1523392 47680 ffffffff 00000000 S WifiManager +u0_a65 13345 205 1526244 52680 ffffffff 00000000 S com.google.android.apps.photos +u0_a65 13351 13345 1526244 52680 ffffffff 00000000 S Heap thread poo +u0_a65 13352 13345 1526244 52680 ffffffff 00000000 S Heap thread poo +u0_a65 13353 13345 1526244 52680 ffffffff 00000000 S Heap thread poo +u0_a65 13354 13345 1526244 52680 ffffffff 00000000 S Signal Catcher +u0_a65 13355 13345 1526244 52680 ffffffff 00000000 S JDWP +u0_a65 13356 13345 1526244 52680 ffffffff 00000000 S ReferenceQueueD +u0_a65 13357 13345 1526244 52680 ffffffff 00000000 S FinalizerDaemon +u0_a65 13358 13345 1526244 52680 ffffffff 00000000 S FinalizerWatchd +u0_a65 13359 13345 1526244 52680 ffffffff 00000000 S HeapTrimmerDaem +u0_a65 13360 13345 1526244 52680 ffffffff 00000000 S GCDaemon +u0_a65 13361 13345 1526244 52680 ffffffff 00000000 S Binder_1 +u0_a65 13362 13345 1526244 52680 ffffffff 00000000 S Binder_2 +u0_a65 13783 13345 1526244 52680 ffffffff 00000000 S pool-1-thread-1 +u0_a65 13796 13345 1526244 52680 ffffffff 00000000 S rotating_file-t +u0_a65 13904 13345 1526244 52680 ffffffff 00000000 S Binder_3 +u0_a67 13491 205 1567688 56576 ffffffff 00000000 S com.google.android.apps.plus +u0_a67 13493 13491 1567688 56576 ffffffff 00000000 S Heap thread poo +u0_a67 13494 13491 1567688 56576 ffffffff 00000000 S Heap thread poo +u0_a67 13495 13491 1567688 56576 ffffffff 00000000 S Heap thread poo +u0_a67 13497 13491 1567688 56576 ffffffff 00000000 S Signal Catcher +u0_a67 13499 13491 1567688 56576 ffffffff 00000000 S JDWP +u0_a67 13502 13491 1567688 56576 ffffffff 00000000 S ReferenceQueueD +u0_a67 13503 13491 1567688 56576 ffffffff 00000000 S FinalizerDaemon +u0_a67 13504 13491 1567688 56576 ffffffff 00000000 S FinalizerWatchd +u0_a67 13505 13491 1567688 56576 ffffffff 00000000 S HeapTrimmerDaem +u0_a67 13506 13491 1567688 56576 ffffffff 00000000 S GCDaemon +u0_a67 13507 13491 1567688 56576 ffffffff 00000000 S Binder_1 +u0_a67 13508 13491 1567688 56576 ffffffff 00000000 S Binder_2 +u0_a67 13512 13491 1567688 56576 ffffffff 00000000 S picasa-photo-pr +u0_a67 13528 13491 1567688 56576 ffffffff 00000000 S iu-sync-manager +u0_a67 13538 13491 1567688 56576 ffffffff 00000000 S pool-2-thread-1 +u0_a67 13881 13491 1567688 56576 ffffffff 00000000 S Gservices +u0_a4 13516 205 1503264 48612 ffffffff 00000000 S android.process.acore +u0_a4 13520 13516 1503264 48612 ffffffff 00000000 S Heap thread poo +u0_a4 13521 13516 1503264 48612 ffffffff 00000000 S Heap thread poo +u0_a4 13522 13516 1503264 48612 ffffffff 00000000 S Heap thread poo +u0_a4 13525 13516 1503264 48612 ffffffff 00000000 S Signal Catcher +u0_a4 13526 13516 1503264 48612 ffffffff 00000000 S JDWP +u0_a4 13527 13516 1503264 48612 ffffffff 00000000 S ReferenceQueueD +u0_a4 13529 13516 1503264 48612 ffffffff 00000000 S FinalizerDaemon +u0_a4 13530 13516 1503264 48612 ffffffff 00000000 S FinalizerWatchd +u0_a4 13531 13516 1503264 48612 ffffffff 00000000 S HeapTrimmerDaem +u0_a4 13532 13516 1503264 48612 ffffffff 00000000 S GCDaemon +u0_a4 13533 13516 1503264 48612 ffffffff 00000000 S Binder_1 +u0_a4 13534 13516 1503264 48612 ffffffff 00000000 S Binder_2 +u0_a4 13536 13516 1503264 48612 ffffffff 00000000 S ContactsProvide +u0_a4 13537 13516 1503264 48612 ffffffff 00000000 S CallLogProvider +u0_a102 13613 205 1521420 45204 ffffffff 00000000 S com.sohu.inputmethod.sogou:classic +u0_a102 13616 13613 1521420 45204 ffffffff 00000000 S Heap thread poo +u0_a102 13617 13613 1521420 45204 ffffffff 00000000 S Heap thread poo +u0_a102 13618 13613 1521420 45204 ffffffff 00000000 S Heap thread poo +u0_a102 13620 13613 1521420 45204 ffffffff 00000000 S Signal Catcher +u0_a102 13623 13613 1521420 45204 ffffffff 00000000 S JDWP +u0_a102 13624 13613 1521420 45204 ffffffff 00000000 S ReferenceQueueD +u0_a102 13625 13613 1521420 45204 ffffffff 00000000 S FinalizerDaemon +u0_a102 13626 13613 1521420 45204 ffffffff 00000000 S FinalizerWatchd +u0_a102 13627 13613 1521420 45204 ffffffff 00000000 S HeapTrimmerDaem +u0_a102 13628 13613 1521420 45204 ffffffff 00000000 S GCDaemon +u0_a102 13629 13613 1521420 45204 ffffffff 00000000 S Binder_1 +u0_a102 13630 13613 1521420 45204 ffffffff 00000000 S Binder_2 +u0_a102 13635 13613 1521420 45204 ffffffff 00000000 S Thread-1443 +u0_a102 13636 13613 1521420 45204 ffffffff 00000000 S Thread-1444 +u0_a102 13637 13613 1521420 45204 ffffffff 00000000 S Thread-1445 +u0_a102 13638 13613 1521420 45204 ffffffff 00000000 S Thread-1446 +u0_a102 13639 13613 1521420 45204 ffffffff 00000000 S Thread-1447 +u0_a102 13641 13613 1521420 45204 ffffffff 00000000 S WifiManager +u0_a102 13905 13613 1521420 45204 ffffffff 00000000 S Binder_3 +u0_a102 13647 205 1514052 44264 ffffffff 00000000 S com.sohu.inputmethod.sogou +u0_a102 13651 13647 1514052 44264 ffffffff 00000000 S Heap thread poo +u0_a102 13652 13647 1514052 44264 ffffffff 00000000 S Heap thread poo +u0_a102 13653 13647 1514052 44264 ffffffff 00000000 S Heap thread poo +u0_a102 13656 13647 1514052 44264 ffffffff 00000000 S Signal Catcher +u0_a102 13657 13647 1514052 44264 ffffffff 00000000 S JDWP +u0_a102 13658 13647 1514052 44264 ffffffff 00000000 S ReferenceQueueD +u0_a102 13659 13647 1514052 44264 ffffffff 00000000 S FinalizerDaemon +u0_a102 13660 13647 1514052 44264 ffffffff 00000000 S FinalizerWatchd +u0_a102 13661 13647 1514052 44264 ffffffff 00000000 S HeapTrimmerDaem +u0_a102 13662 13647 1514052 44264 ffffffff 00000000 S GCDaemon +u0_a102 13663 13647 1514052 44264 ffffffff 00000000 S Binder_1 +u0_a102 13664 13647 1514052 44264 ffffffff 00000000 S Binder_2 +u0_a102 13671 205 1519416 43248 ffffffff 00000000 S sogou.mobile.explorer.hotwords +u0_a102 13677 13671 1519416 43248 ffffffff 00000000 S Heap thread poo +u0_a102 13678 13671 1519416 43248 ffffffff 00000000 S Heap thread poo +u0_a102 13679 13671 1519416 43248 ffffffff 00000000 S Heap thread poo +u0_a102 13680 13671 1519416 43248 ffffffff 00000000 S Signal Catcher +u0_a102 13681 13671 1519416 43248 ffffffff 00000000 S JDWP +u0_a102 13682 13671 1519416 43248 ffffffff 00000000 S ReferenceQueueD +u0_a102 13683 13671 1519416 43248 ffffffff 00000000 S FinalizerDaemon +u0_a102 13684 13671 1519416 43248 ffffffff 00000000 S FinalizerWatchd +u0_a102 13685 13671 1519416 43248 ffffffff 00000000 S HeapTrimmerDaem +u0_a102 13686 13671 1519416 43248 ffffffff 00000000 S GCDaemon +u0_a102 13687 13671 1519416 43248 ffffffff 00000000 S Binder_1 +u0_a102 13688 13671 1519416 43248 ffffffff 00000000 S Binder_2 +u0_a102 13690 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-1 +u0_a102 13691 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-2 +u0_a102 13692 13671 1519416 43248 ffffffff 00000000 S pool-1-thread-3 +u0_a102 13694 13671 1519416 43248 ffffffff 00000000 S Timer-0 +u0_a198 13695 205 1506040 40332 ffffffff 00000000 S org.chromium.chrome.shell +u0_a198 13701 13695 1506040 40332 ffffffff 00000000 S Heap thread poo +u0_a198 13702 13695 1506040 40332 ffffffff 00000000 S Heap thread poo +u0_a198 13703 13695 1506040 40332 ffffffff 00000000 S Heap thread poo +u0_a198 13704 13695 1506040 40332 ffffffff 00000000 S Signal Catcher +u0_a198 13705 13695 1506040 40332 ffffffff 00000000 S JDWP +u0_a198 13706 13695 1506040 40332 ffffffff 00000000 S ReferenceQueueD +u0_a198 13707 13695 1506040 40332 ffffffff 00000000 S FinalizerDaemon +u0_a198 13708 13695 1506040 40332 ffffffff 00000000 S FinalizerWatchd +u0_a198 13709 13695 1506040 40332 ffffffff 00000000 S HeapTrimmerDaem +u0_a198 13710 13695 1506040 40332 ffffffff 00000000 S GCDaemon +u0_a198 13711 13695 1506040 40332 ffffffff 00000000 S Binder_1 +u0_a198 13712 13695 1506040 40332 ffffffff 00000000 S Binder_2 +u0_a198 13713 13695 1506040 40332 ffffffff 00000000 S Binder_3 +u0_a200 13715 205 1511344 38748 ffffffff 00000000 S com.rolocule.motiontennis +u0_a200 13721 13715 1511344 38748 ffffffff 00000000 S Heap thread poo +u0_a200 13722 13715 1511344 38748 ffffffff 00000000 S Heap thread poo +u0_a200 13723 13715 1511344 38748 ffffffff 00000000 S Heap thread poo +u0_a200 13724 13715 1511344 38748 ffffffff 00000000 S Signal Catcher +u0_a200 13725 13715 1511344 38748 ffffffff 00000000 S JDWP +u0_a200 13731 13715 1511344 38748 ffffffff 00000000 S ReferenceQueueD +u0_a200 13732 13715 1511344 38748 ffffffff 00000000 S FinalizerDaemon +u0_a200 13733 13715 1511344 38748 ffffffff 00000000 S FinalizerWatchd +u0_a200 13734 13715 1511344 38748 ffffffff 00000000 S HeapTrimmerDaem +u0_a200 13735 13715 1511344 38748 ffffffff 00000000 S GCDaemon +u0_a200 13736 13715 1511344 38748 ffffffff 00000000 S Binder_1 +u0_a200 13737 13715 1511344 38748 ffffffff 00000000 S Binder_2 +u0_a175 13747 205 1510096 43460 ffffffff 00000000 S com.google.android.apps.chrome +u0_a175 13751 13747 1510096 43460 ffffffff 00000000 S Heap thread poo +u0_a175 13752 13747 1510096 43460 ffffffff 00000000 S Heap thread poo +u0_a175 13754 13747 1510096 43460 ffffffff 00000000 S Heap thread poo +u0_a175 13756 13747 1510096 43460 ffffffff 00000000 S Signal Catcher +u0_a175 13757 13747 1510096 43460 ffffffff 00000000 S JDWP +u0_a175 13758 13747 1510096 43460 ffffffff 00000000 S ReferenceQueueD +u0_a175 13759 13747 1510096 43460 ffffffff 00000000 S FinalizerDaemon +u0_a175 13760 13747 1510096 43460 ffffffff 00000000 S FinalizerWatchd +u0_a175 13761 13747 1510096 43460 ffffffff 00000000 S HeapTrimmerDaem +u0_a175 13762 13747 1510096 43460 ffffffff 00000000 S GCDaemon +u0_a175 13763 13747 1510096 43460 ffffffff 00000000 S Binder_1 +u0_a175 13764 13747 1510096 43460 ffffffff 00000000 S Binder_2 +u0_a85 13774 205 1594212 50972 ffffffff 00000000 S com.life360.android.safetymapd +u0_a85 13780 13774 1594212 50972 ffffffff 00000000 S Heap thread poo +u0_a85 13781 13774 1594212 50972 ffffffff 00000000 S Heap thread poo +u0_a85 13782 13774 1594212 50972 ffffffff 00000000 S Heap thread poo +u0_a85 13784 13774 1594212 50972 ffffffff 00000000 S Signal Catcher +u0_a85 13785 13774 1594212 50972 ffffffff 00000000 S JDWP +u0_a85 13786 13774 1594212 50972 ffffffff 00000000 S ReferenceQueueD +u0_a85 13787 13774 1594212 50972 ffffffff 00000000 S FinalizerDaemon +u0_a85 13788 13774 1594212 50972 ffffffff 00000000 S FinalizerWatchd +u0_a85 13789 13774 1594212 50972 ffffffff 00000000 S HeapTrimmerDaem +u0_a85 13790 13774 1594212 50972 ffffffff 00000000 S GCDaemon +u0_a85 13791 13774 1594212 50972 ffffffff 00000000 S Binder_1 +u0_a85 13792 13774 1594212 50972 ffffffff 00000000 S Binder_2 +u0_a16 13801 205 1538004 50644 ffffffff 00000000 S com.android.vending +u0_a16 13807 13801 1538004 50644 ffffffff 00000000 S Heap thread poo +u0_a16 13808 13801 1538004 50644 ffffffff 00000000 S Heap thread poo +u0_a16 13809 13801 1538004 50644 ffffffff 00000000 S Heap thread poo +u0_a16 13811 13801 1538004 50644 ffffffff 00000000 S Signal Catcher +u0_a16 13812 13801 1538004 50644 ffffffff 00000000 S JDWP +u0_a16 13813 13801 1538004 50644 ffffffff 00000000 S ReferenceQueueD +u0_a16 13814 13801 1538004 50644 ffffffff 00000000 S FinalizerDaemon +u0_a16 13815 13801 1538004 50644 ffffffff 00000000 S FinalizerWatchd +u0_a16 13816 13801 1538004 50644 ffffffff 00000000 S HeapTrimmerDaem +u0_a16 13817 13801 1538004 50644 ffffffff 00000000 S GCDaemon +u0_a16 13818 13801 1538004 50644 ffffffff 00000000 S Binder_1 +u0_a16 13819 13801 1538004 50644 ffffffff 00000000 S Binder_2 +u0_a16 13828 13801 1538004 50644 ffffffff 00000000 S Gservices +u0_a16 13833 13801 1538004 50644 ffffffff 00000000 S pool-1-thread-1 +u0_a16 13834 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@ +u0_a16 13837 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@ +u0_a16 13838 13801 1538004 50644 ffffffff 00000000 S Thread-1482 +u0_a16 13839 13801 1538004 50644 ffffffff 00000000 S Thread-1483 +u0_a16 13840 13801 1538004 50644 ffffffff 00000000 S Thread-1484 +u0_a16 13843 13801 1538004 50644 ffffffff 00000000 S download-manage +u0_a16 13844 13801 1538004 50644 ffffffff 00000000 S NetworkQualityQ +u0_a16 13845 13801 1538004 50644 ffffffff 00000000 S RefQueueWorker@ +u0_a16 13846 13801 1538004 50644 ffffffff 00000000 S Thread-1489 +u0_a16 13847 13801 1538004 50644 ffffffff 00000000 S Thread-1490 +u0_a16 13848 13801 1538004 50644 ffffffff 00000000 S Thread-1491 +u0_a16 13849 13801 1538004 50644 ffffffff 00000000 S Thread-1492 +u0_a16 13850 13801 1538004 50644 ffffffff 00000000 S Thread-1493 +u0_a16 13851 13801 1538004 50644 ffffffff 00000000 S PlayEventLogger +u0_a16 13852 13801 1538004 50644 ffffffff 00000000 S tentative-gc-ru +u0_a16 13862 13801 1538004 50644 ffffffff 00000000 S libraries-threa +u0_a16 13872 13801 1538004 50644 ffffffff 00000000 S AsyncTask #1 +u0_a16 13876 13801 1538004 50644 ffffffff 00000000 S AsyncTask #2 +u0_a16 13877 13801 1538004 50644 ffffffff 00000000 S AsyncTask #3 +u0_a16 13878 13801 1538004 50644 ffffffff 00000000 S PlayEventLogger +u0_a16 13880 13801 1538004 50644 ffffffff 00000000 S Thread-1501 +u0_a16 14407 13801 1538004 50644 ffffffff 00000000 S Binder_3 +u0_a8 13853 205 1573700 51720 ffffffff 00000000 S com.google.android.gms:car +u0_a8 13856 13853 1573700 51720 ffffffff 00000000 S Heap thread poo +u0_a8 13857 13853 1573700 51720 ffffffff 00000000 S Heap thread poo +u0_a8 13858 13853 1573700 51720 ffffffff 00000000 S Heap thread poo +u0_a8 13863 13853 1573700 51720 ffffffff 00000000 S Signal Catcher +u0_a8 13864 13853 1573700 51720 ffffffff 00000000 S JDWP +u0_a8 13865 13853 1573700 51720 ffffffff 00000000 S ReferenceQueueD +u0_a8 13866 13853 1573700 51720 ffffffff 00000000 S FinalizerDaemon +u0_a8 13867 13853 1573700 51720 ffffffff 00000000 S FinalizerWatchd +u0_a8 13868 13853 1573700 51720 ffffffff 00000000 S HeapTrimmerDaem +u0_a8 13869 13853 1573700 51720 ffffffff 00000000 S GCDaemon +u0_a8 13870 13853 1573700 51720 ffffffff 00000000 S Binder_1 +u0_a8 13871 13853 1573700 51720 ffffffff 00000000 S Binder_2 +u0_a8 13873 13853 1573700 51720 ffffffff 00000000 S Gservices +u0_a8 13913 13853 1573700 51720 ffffffff 00000000 S Binder_3 +u0_a8 13885 205 1572668 47460 ffffffff 00000000 S com.google.android.gms.wearable +u0_a8 13890 13885 1572668 47460 ffffffff 00000000 S Heap thread poo +u0_a8 13891 13885 1572668 47460 ffffffff 00000000 S Heap thread poo +u0_a8 13892 13885 1572668 47460 ffffffff 00000000 S Heap thread poo +u0_a8 13894 13885 1572668 47460 ffffffff 00000000 S Signal Catcher +u0_a8 13895 13885 1572668 47460 ffffffff 00000000 S JDWP +u0_a8 13896 13885 1572668 47460 ffffffff 00000000 S ReferenceQueueD +u0_a8 13897 13885 1572668 47460 ffffffff 00000000 S FinalizerDaemon +u0_a8 13898 13885 1572668 47460 ffffffff 00000000 S FinalizerWatchd +u0_a8 13899 13885 1572668 47460 ffffffff 00000000 S HeapTrimmerDaem +u0_a8 13900 13885 1572668 47460 ffffffff 00000000 S GCDaemon +u0_a8 13901 13885 1572668 47460 ffffffff 00000000 S Binder_1 +u0_a8 13902 13885 1572668 47460 ffffffff 00000000 S Binder_2 +u0_a8 13903 13885 1572668 47460 ffffffff 00000000 S Gservices +root 14061 2 0 0 ffffffff 00000000 S kworker/u:3 +root 14136 2 0 0 ffffffff 00000000 S kworker/0:0H +u0_a101 14356 205 1503136 44308 ffffffff 00000000 S com.google.android.apps.gcs +u0_a101 14362 14356 1503136 44308 ffffffff 00000000 S Heap thread poo +u0_a101 14363 14356 1503136 44308 ffffffff 00000000 S Heap thread poo +u0_a101 14364 14356 1503136 44308 ffffffff 00000000 S Heap thread poo +u0_a101 14365 14356 1503136 44308 ffffffff 00000000 S Signal Catcher +u0_a101 14366 14356 1503136 44308 ffffffff 00000000 S JDWP +u0_a101 14367 14356 1503136 44308 ffffffff 00000000 S ReferenceQueueD +u0_a101 14368 14356 1503136 44308 ffffffff 00000000 S FinalizerDaemon +u0_a101 14369 14356 1503136 44308 ffffffff 00000000 S FinalizerWatchd +u0_a101 14370 14356 1503136 44308 ffffffff 00000000 S HeapTrimmerDaem +u0_a101 14371 14356 1503136 44308 ffffffff 00000000 S GCDaemon +u0_a101 14372 14356 1503136 44308 ffffffff 00000000 S Binder_1 +u0_a101 14373 14356 1503136 44308 ffffffff 00000000 S Binder_2 +u0_a101 14375 14356 1503136 44308 ffffffff 00000000 S Gservices +u0_a101 14376 14356 1503136 44308 ffffffff 00000000 S RefQueueWorker@ +u0_a101 14377 14356 1503136 44308 ffffffff 00000000 S Thread-1495 +u0_a101 14378 14356 1503136 44308 ffffffff 00000000 S Thread-1496 +u0_a101 14379 14356 1503136 44308 ffffffff 00000000 S Thread-1497 +u0_a101 14380 14356 1503136 44308 ffffffff 00000000 S Thread-1498 +u0_a101 14381 14356 1503136 44308 ffffffff 00000000 S Thread-1499 +shell 14444 209 9316 612 c01a863c b6eeee44 S /system/bin/sh +shell 14448 14444 10672 768 00000000 b6ef0da8 R ps diff --git a/test_data/atrace_thread_names b/catapult/systrace/systrace/test_data/atrace_thread_names index bff5d1b7..bff5d1b7 100644 --- a/test_data/atrace_thread_names +++ b/catapult/systrace/systrace/test_data/atrace_thread_names diff --git a/catapult/systrace/systrace/update_systrace_trace_viewer.py b/catapult/systrace/systrace/update_systrace_trace_viewer.py new file mode 100755 index 00000000..71eece03 --- /dev/null +++ b/catapult/systrace/systrace/update_systrace_trace_viewer.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import codecs +import optparse +import os +import re +import subprocess +import sys + +catapult_path = os.path.abspath( + os.path.join(os.path.dirname(__file__), '../..')) +sys.path.append(os.path.join(catapult_path, 'tracing')) +from tracing_build import vulcanize_trace_viewer + +SYSTRACE_TRACE_VIEWER_HTML_FILE_ = 'systrace_trace_viewer.html' +CATAPULT_REV_ = 'CATAPULT_REV' +NO_AUTO_UPDATE_ = 'NO_AUTO_UPDATE' + + +def create_catapult_rev_str_(revision): + return '<!--' + CATAPULT_REV_ + '=' + str(revision) + '-->' + +def get_catapult_rev_in_file_(): + assert os.path.exists(SYSTRACE_TRACE_VIEWER_HTML_FILE_) + rev = '' + with open(SYSTRACE_TRACE_VIEWER_HTML_FILE_, 'r') as f: + lines = f.readlines() + for line in lines[::-1]: + if CATAPULT_REV_ in line: + tokens = line.split(CATAPULT_REV_) + rev = re.sub('[=\->]', '', tokens[1]).strip() + break + return rev + +def get_catapult_rev_in_git_(): + try: + return subprocess.check_output( + ['git', 'rev-parse', 'HEAD'], + cwd=os.path.dirname(os.path.abspath(__file__))).strip() + except subprocess.CalledProcessError: + return '' + + +def update(no_auto_update=False, no_min=False): + """Update the systrace trace viewer html file. + + When the html file exists, do not update the file if + 1. the revision is NO_AUTO_UPDATE_; + 2. or the revision is not changed. + + Args: + no_auto_update: If true, force updating the file with revision + NO_AUTO_UPDATE_. Future updates will be skipped unless this + argument is true again. + no_min: If true, skip minification when updating the file. + """ + new_rev = None + if no_auto_update: + new_rev = NO_AUTO_UPDATE_ + else: + new_rev = get_catapult_rev_in_git_() + if not new_rev: + return + + if os.path.exists(SYSTRACE_TRACE_VIEWER_HTML_FILE_): + rev_in_file = get_catapult_rev_in_file_() + if rev_in_file == NO_AUTO_UPDATE_ or rev_in_file == new_rev: + return + + # Generate the vulcanized result. + output_html_file = SYSTRACE_TRACE_VIEWER_HTML_FILE_ + with codecs.open(output_html_file, encoding='utf-8', mode='w') as f: + vulcanize_trace_viewer.WriteTraceViewer( + f, + config_name='systrace', + minify=(not no_min), + output_html_head_and_body=False) + f.write(create_catapult_rev_str_(new_rev)) + print 'Generated %s with revision %s.' % (output_html_file, new_rev) + + +def main(): + parser = optparse.OptionParser() + parser.add_option('--no-auto-update', dest='no_auto_update', + default=False, action='store_true', help='force update the ' + 'systrace trace viewer html file. Future auto updates will ' + 'be skipped unless this flag is specified again.') + parser.add_option('--no-min', dest='no_min', default=False, + action='store_true', help='skip minification') + # pylint: disable=unused-variable + options, unused_args = parser.parse_args(sys.argv[1:]) + + update(options.no_auto_update, options.no_min) + + +if __name__ == '__main__': + main() diff --git a/util.py b/catapult/systrace/systrace/util.py index 5fb61a8c..6566d084 100644 --- a/util.py +++ b/catapult/systrace/systrace/util.py @@ -13,16 +13,16 @@ class OptionParserIgnoreErrors(optparse.OptionParser): def error(self, msg): pass - def exit(self): + def exit(self, status=0, msg=None): pass - def print_usage(self): + def print_usage(self, out_file=None): pass - def print_help(self): + def print_help(self, out_file=None): pass - def print_version(self): + def print_version(self, out_file=None): pass @@ -60,9 +60,10 @@ def run_adb_shell(shell_args, device_serial): # This usually means that the adb executable was not found in the path. print >> sys.stderr, ('\nThe command "%s" failed with the following error:' % ' '.join(adb_command)) - print >> sys.stderr, ' %s\n' % str(error) + print >> sys.stderr, ' %s' % str(error) print >> sys.stderr, 'Is adb in your path?' - sys.exit(1) + adb_return_code = error.errno + adb_output = error except subprocess.CalledProcessError as error: # The process exited with an error. adb_return_code = error.returncode @@ -70,7 +71,6 @@ def run_adb_shell(shell_args, device_serial): return (adb_output, adb_return_code) - def get_device_sdk_version(): """Uses adb to attempt to determine the SDK version of a running device.""" @@ -81,7 +81,7 @@ def get_device_sdk_version(): # command-line so we can send the adb command to the correct device. parser = OptionParserIgnoreErrors() parser.add_option('-e', '--serial', dest='device_serial', type='string') - options, unused_args = parser.parse_args() + options, unused_args = parser.parse_args() # pylint: disable=unused-variable success = False diff --git a/catapult/systrace/systrace/util_unittest.py b/catapult/systrace/systrace/util_unittest.py new file mode 100644 index 00000000..585f6821 --- /dev/null +++ b/catapult/systrace/systrace/util_unittest.py @@ -0,0 +1,26 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import unittest + +import util + +DEVICE_SERIAL = 'AG8404EC0444AGC' +LIST_TMP_ARGS = ['ls', '/data/local/tmp'] +ATRACE_ARGS = ['atrace', '-z', '-t', '10', '-b', '4096'] +ADB_SHELL = ['adb', '-s', DEVICE_SERIAL, 'shell'] + + +class UtilTest(unittest.TestCase): + def test_construct_adb_shell_command(self): + command = util.construct_adb_shell_command(LIST_TMP_ARGS, None) + self.assertEqual(' '.join(command), 'adb shell ls /data/local/tmp') + + command = util.construct_adb_shell_command(LIST_TMP_ARGS, DEVICE_SERIAL) + self.assertEqual(' '.join(command), + 'adb -s AG8404EC0444AGC shell ls /data/local/tmp') + + command = util.construct_adb_shell_command(ATRACE_ARGS, DEVICE_SERIAL) + self.assertEqual(' '.join(command), + 'adb -s AG8404EC0444AGC shell atrace -z -t 10 -b 4096') diff --git a/catapult/third_party/html5lib-python/.gitignore b/catapult/third_party/html5lib-python/.gitignore new file mode 100644 index 00000000..6aed95b2 --- /dev/null +++ b/catapult/third_party/html5lib-python/.gitignore @@ -0,0 +1,82 @@ +# Copyright (c) 2014 GitHub, 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. + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +doc/_build/ + +# PyBuilder +target/ + +# Generated by parse.py -p +stats.prof diff --git a/catapult/third_party/html5lib-python/.gitmodules b/catapult/third_party/html5lib-python/.gitmodules new file mode 100644 index 00000000..dbca4703 --- /dev/null +++ b/catapult/third_party/html5lib-python/.gitmodules @@ -0,0 +1,3 @@ +[submodule "testdata"] + path = html5lib/tests/testdata + url = https://github.com/html5lib/html5lib-tests.git diff --git a/catapult/third_party/html5lib-python/.travis.yml b/catapult/third_party/html5lib-python/.travis.yml new file mode 100644 index 00000000..dd313001 --- /dev/null +++ b/catapult/third_party/html5lib-python/.travis.yml @@ -0,0 +1,37 @@ +language: python +python: + - "2.6" + - "2.7" + - "3.2" + - "3.3" + - "3.4" + - "pypy" + +env: + - USE_OPTIONAL=true + - USE_OPTIONAL=false + +matrix: + exclude: + - python: "2.7" + env: USE_OPTIONAL=false + - python: "3.4" + env: USE_OPTIONAL=false + include: + - python: "2.7" + env: USE_OPTIONAL=false FLAKE=true + - python: "3.4" + env: USE_OPTIONAL=false FLAKE=true + +before_install: + - git submodule update --init --recursive + +install: + - bash requirements-install.sh + +script: + - nosetests + - bash flake8-run.sh + +after_script: + - python debug-info.py diff --git a/catapult/third_party/html5lib-python/AUTHORS.rst b/catapult/third_party/html5lib-python/AUTHORS.rst new file mode 100644 index 00000000..fe9ae89b --- /dev/null +++ b/catapult/third_party/html5lib-python/AUTHORS.rst @@ -0,0 +1,43 @@ +Credits +======= + +``html5lib`` is written and maintained by: + +- James Graham +- Geoffrey Sneddon +- Łukasz Langa + + +Patches and suggestions +----------------------- +(In chronological order, by first commit:) + +- Anne van Kesteren +- Lachlan Hunt +- lantis63 +- Sam Ruby +- Thomas Broyer +- Tim Fletcher +- Mark Pilgrim +- Ryan King +- Philip Taylor +- Edward Z. Yang +- fantasai +- Mike West +- Philip Jägenstedt +- Ms2ger +- Mohammad Taha Jahangir +- Andy Wingo +- Juan Carlos Garcia Segovia +- Andreas Madsack +- Karim Valiev +- Marc DM +- Tony Lopes +- lilbludevil +- Simon Sapin +- Jon Dufresne +- Drew Hubl +- Austin Kumbera +- Jim Baker +- Michael[tm] Smith +- Marc Abramowitz diff --git a/catapult/third_party/html5lib-python/CHANGES.rst b/catapult/third_party/html5lib-python/CHANGES.rst new file mode 100644 index 00000000..1279c277 --- /dev/null +++ b/catapult/third_party/html5lib-python/CHANGES.rst @@ -0,0 +1,217 @@ +Change Log +---------- + +0.9999999/1.0b8 +~~~~~~~~~~~~~~~ + +Released on XXX + +* XXX + + +0.999999/1.0b7 +~~~~~~~~~~~~~~ + +Released on July 7, 2015 + +* Fix #189: fix the sanitizer to allow relative URLs again (as it did + prior to 0.9999/1.0b5). + + +0.99999/1.0b6 +~~~~~~~~~~~~~ + +Released on April 30, 2015 + +* Fix #188: fix the sanitizer to not throw an exception when sanitizing + bogus data URLs. + + +0.9999/1.0b5 +~~~~~~~~~~~~ + +Released on April 29, 2015 + +* Fix #153: Sanitizer fails to treat some attributes as URLs. Despite how + this sounds, this has no known security implications. No known version + of IE (5.5 to current), Firefox (3 to current), Safari (6 to current), + Chrome (1 to current), or Opera (12 to current) will run any script + provided in these attributes. + +* Pass error message to the ParseError exception in strict parsing mode. + +* Allow data URIs in the sanitizer, with a whitelist of content-types. + +* Add support for Python implementations that don't support lone + surrogates (read: Jython). Fixes #2. + +* Remove localization of error messages. This functionality was totally + unused (and untested that everything was localizable), so we may as + well follow numerous browsers in not supporting translating technical + strings. + +* Expose treewalkers.pprint as a public API. + +* Add a documentEncoding property to HTML5Parser, fix #121. + + +0.999 +~~~~~ + +Released on December 23, 2013 + +* Fix #127: add work-around for CPython issue #20007: .read(0) on + http.client.HTTPResponse drops the rest of the content. + +* Fix #115: lxml treewalker can now deal with fragments containing, at + their root level, text nodes with non-ASCII characters on Python 2. + + +0.99 +~~~~ + +Released on September 10, 2013 + +* No library changes from 1.0b3; released as 0.99 as pip has changed + behaviour from 1.4 to avoid installing pre-release versions per + PEP 440. + + +1.0b3 +~~~~~ + +Released on July 24, 2013 + +* Removed ``RecursiveTreeWalker`` from ``treewalkers._base``. Any + implementation using it should be moved to + ``NonRecursiveTreeWalker``, as everything bundled with html5lib has + for years. + +* Fix #67 so that ``BufferedStream`` to correctly returns a bytes + object, thereby fixing any case where html5lib is passed a + non-seekable RawIOBase-like object. + + +1.0b2 +~~~~~ + +Released on June 27, 2013 + +* Removed reordering of attributes within the serializer. There is now + an ``alphabetical_attributes`` option which preserves the previous + behaviour through a new filter. This allows attribute order to be + preserved through html5lib if the tree builder preserves order. + +* Removed ``dom2sax`` from DOM treebuilders. It has been replaced by + ``treeadapters.sax.to_sax`` which is generic and supports any + treewalker; it also resolves all known bugs with ``dom2sax``. + +* Fix treewalker assertions on hitting bytes strings on + Python 2. Previous to 1.0b1, treewalkers coped with mixed + bytes/unicode data on Python 2; this reintroduces this prior + behaviour on Python 2. Behaviour is unchanged on Python 3. + + +1.0b1 +~~~~~ + +Released on May 17, 2013 + +* Implementation updated to implement the `HTML specification + <http://www.whatwg.org/specs/web-apps/current-work/>`_ as of 5th May + 2013 (`SVN <http://svn.whatwg.org/webapps/>`_ revision r7867). + +* Python 3.2+ supported in a single codebase using the ``six`` library. + +* Removed support for Python 2.5 and older. + +* Removed the deprecated Beautiful Soup 3 treebuilder. + ``beautifulsoup4`` can use ``html5lib`` as a parser instead. Note that + since it doesn't support namespaces, foreign content like SVG and + MathML is parsed incorrectly. + +* Removed ``simpletree`` from the package. The default tree builder is + now ``etree`` (using the ``xml.etree.cElementTree`` implementation if + available, and ``xml.etree.ElementTree`` otherwise). + +* Removed the ``XHTMLSerializer`` as it never actually guaranteed its + output was well-formed XML, and hence provided little of use. + +* Removed default DOM treebuilder, so ``html5lib.treebuilders.dom`` is no + longer supported. ``html5lib.treebuilders.getTreeBuilder("dom")`` will + return the default DOM treebuilder, which uses ``xml.dom.minidom``. + +* Optional heuristic character encoding detection now based on + ``charade`` for Python 2.6 - 3.3 compatibility. + +* Optional ``Genshi`` treewalker support fixed. + +* Many bugfixes, including: + + * #33: null in attribute value breaks XML AttValue; + + * #4: nested, indirect descendant, <button> causes infinite loop; + + * `Google Code 215 + <http://code.google.com/p/html5lib/issues/detail?id=215>`_: Properly + detect seekable streams; + + * `Google Code 206 + <http://code.google.com/p/html5lib/issues/detail?id=206>`_: add + support for <video preload=...>, <audio preload=...>; + + * `Google Code 205 + <http://code.google.com/p/html5lib/issues/detail?id=205>`_: add + support for <video poster=...>; + + * `Google Code 202 + <http://code.google.com/p/html5lib/issues/detail?id=202>`_: Unicode + file breaks InputStream. + +* Source code is now mostly PEP 8 compliant. + +* Test harness has been improved and now depends on ``nose``. + +* Documentation updated and moved to http://html5lib.readthedocs.org/. + + +0.95 +~~~~ + +Released on February 11, 2012 + + +0.90 +~~~~ + +Released on January 17, 2010 + + +0.11.1 +~~~~~~ + +Released on June 12, 2008 + + +0.11 +~~~~ + +Released on June 10, 2008 + + +0.10 +~~~~ + +Released on October 7, 2007 + + +0.9 +~~~ + +Released on March 11, 2007 + + +0.2 +~~~ + +Released on January 8, 2007 diff --git a/catapult/third_party/html5lib-python/CONTRIBUTING.rst b/catapult/third_party/html5lib-python/CONTRIBUTING.rst new file mode 100644 index 00000000..8c5e1985 --- /dev/null +++ b/catapult/third_party/html5lib-python/CONTRIBUTING.rst @@ -0,0 +1,60 @@ +Contributing +============ + +Pull requests are more than welcome — both to the library and to the +documentation. Some useful information: + +- We aim to follow PEP 8 in the library, but ignoring the + 79-character-per-line limit, instead following a soft limit of 99, + but allowing lines over this where it is the readable thing to do. + +- We aim to follow PEP 257 for all docstrings, and make them properly + parseable by Sphinx while generating API documentation. + +- We keep ``pyflakes`` reporting no errors or warnings at all times. + +- We keep the master branch passing all tests at all times on all + supported versions. + +`Travis CI <https://travis-ci.org/html5lib/html5lib-python/>`_ is run +against all pull requests and should enforce all of the above. + +We use `Opera Critic <https://critic.hoppipolla.co.uk/>`_ as an external +code-review tool, which uses your GitHub login to authenticate. You'll +get email notifications for issues raised in the review. + + +Patch submission guidelines +--------------------------- + +- **Create a new Git branch specific to your change.** Do not put + multiple fixes/features in the same pull request. If you find an + unrelated bug, create a distinct branch and submit a separate pull + request for the bugfix. This makes life much easier for maintainers + and will speed up merging your patches. + +- **Write a test** whenever possible. Following existing tests is often + easiest, and a good way to tell whether the feature you're modifying + is easily testable. + +- **Make sure documentation is updated.** Keep docstrings current, and + if necessary, update the Sphinx documentation in ``doc/``. + +- **Add a changelog entry** at the top of ``CHANGES.rst`` following + existing entries' styles. + +- **Run tests with tox** if possible, to make sure your changes are + compatible with all supported Python versions. + +- **Squash commits** before submitting the pull request so that a single + commit contains the entire change, and only that change (see the first + bullet). + +- **Don't rebase after creating the pull request.** Merge with upstream, + if necessary, and use ``git commit --fixup`` for fixing issues raised + in a Critic review or by a failing Travis build. The reviewer will + squash and rebase your pull request while accepting it. Even though + GitHub won't recognize the pull request as accepted, the squashed + commits will properly specify you as the author. + +- **Attribute yourself** in ``AUTHORS.rst``. diff --git a/catapult/third_party/html5lib-python/LICENSE b/catapult/third_party/html5lib-python/LICENSE new file mode 100644 index 00000000..c87fa7a0 --- /dev/null +++ b/catapult/third_party/html5lib-python/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2006-2013 James Graham and other contributors + +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. diff --git a/catapult/third_party/html5lib-python/MANIFEST.in b/catapult/third_party/html5lib-python/MANIFEST.in new file mode 100644 index 00000000..1edd0b7d --- /dev/null +++ b/catapult/third_party/html5lib-python/MANIFEST.in @@ -0,0 +1,6 @@ +include LICENSE +include CHANGES.rst +include README.rst +include requirements*.txt +graft html5lib/tests/testdata +recursive-include html5lib/tests *.py diff --git a/catapult/third_party/html5lib-python/README.chromium b/catapult/third_party/html5lib-python/README.chromium new file mode 100644 index 00000000..18b86c0d --- /dev/null +++ b/catapult/third_party/html5lib-python/README.chromium @@ -0,0 +1,11 @@ +Name: html5lib-python +Short Name: html5lib +URL: https://github.com/html5lib/html5lib-python +Version: 01b1ebb7ce0146b8082b1a7315431aac023eb046 +License: MIT + +Description: +Standards-compliant library for parsing and serializing HTML documents and +fragments in Python + +Local Modifications: None diff --git a/catapult/third_party/html5lib-python/README.rst b/catapult/third_party/html5lib-python/README.rst new file mode 100644 index 00000000..9e0a0f74 --- /dev/null +++ b/catapult/third_party/html5lib-python/README.rst @@ -0,0 +1,157 @@ +html5lib +======== + +.. image:: https://travis-ci.org/html5lib/html5lib-python.png?branch=master + :target: https://travis-ci.org/html5lib/html5lib-python + +html5lib is a pure-python library for parsing HTML. It is designed to +conform to the WHATWG HTML specification, as is implemented by all major +web browsers. + + +Usage +----- + +Simple usage follows this pattern: + +.. code-block:: python + + import html5lib + with open("mydocument.html", "rb") as f: + document = html5lib.parse(f) + +or: + +.. code-block:: python + + import html5lib + document = html5lib.parse("<p>Hello World!") + +By default, the ``document`` will be an ``xml.etree`` element instance. +Whenever possible, html5lib chooses the accelerated ``ElementTree`` +implementation (i.e. ``xml.etree.cElementTree`` on Python 2.x). + +Two other tree types are supported: ``xml.dom.minidom`` and +``lxml.etree``. To use an alternative format, specify the name of +a treebuilder: + +.. code-block:: python + + import html5lib + with open("mydocument.html", "rb") as f: + lxml_etree_document = html5lib.parse(f, treebuilder="lxml") + +When using with ``urllib2`` (Python 2), the charset from HTTP should be +pass into html5lib as follows: + +.. code-block:: python + + from contextlib import closing + from urllib2 import urlopen + import html5lib + + with closing(urlopen("http://example.com/")) as f: + document = html5lib.parse(f, encoding=f.info().getparam("charset")) + +When using with ``urllib.request`` (Python 3), the charset from HTTP +should be pass into html5lib as follows: + +.. code-block:: python + + from urllib.request import urlopen + import html5lib + + with urlopen("http://example.com/") as f: + document = html5lib.parse(f, encoding=f.info().get_content_charset()) + +To have more control over the parser, create a parser object explicitly. +For instance, to make the parser raise exceptions on parse errors, use: + +.. code-block:: python + + import html5lib + with open("mydocument.html", "rb") as f: + parser = html5lib.HTMLParser(strict=True) + document = parser.parse(f) + +When you're instantiating parser objects explicitly, pass a treebuilder +class as the ``tree`` keyword argument to use an alternative document +format: + +.. code-block:: python + + import html5lib + parser = html5lib.HTMLParser(tree=html5lib.getTreeBuilder("dom")) + minidom_document = parser.parse("<p>Hello World!") + +More documentation is available at http://html5lib.readthedocs.org/. + + +Installation +------------ + +html5lib works on CPython 2.6+, CPython 3.2+ and PyPy. To install it, +use: + +.. code-block:: bash + + $ pip install html5lib + + +Optional Dependencies +--------------------- + +The following third-party libraries may be used for additional +functionality: + +- ``datrie`` can be used to improve parsing performance (though in + almost all cases the improvement is marginal); + +- ``lxml`` is supported as a tree format (for both building and + walking) under CPython (but *not* PyPy where it is known to cause + segfaults); + +- ``genshi`` has a treewalker (but not builder); and + +- ``charade`` can be used as a fallback when character encoding cannot + be determined; ``chardet``, from which it was forked, can also be used + on Python 2. + +- ``ordereddict`` can be used under Python 2.6 + (``collections.OrderedDict`` is used instead on later versions) to + serialize attributes in alphabetical order. + + +Bugs +---- + +Please report any bugs on the `issue tracker +<https://github.com/html5lib/html5lib-python/issues>`_. + + +Tests +----- + +Unit tests require the ``nose`` library and can be run using the +``nosetests`` command in the root directory; ``ordereddict`` is +required under Python 2.6. All should pass. + +Test data are contained in a separate `html5lib-tests +<https://github.com/html5lib/html5lib-tests>`_ repository and included +as a submodule, thus for git checkouts they must be initialized:: + + $ git submodule init + $ git submodule update + +If you have all compatible Python implementations available on your +system, you can run tests on all of them using the ``tox`` utility, +which can be found on PyPI. + + +Questions? +---------- + +There's a mailing list available for support on Google Groups, +`html5lib-discuss <http://groups.google.com/group/html5lib-discuss>`_, +though you may get a quicker response asking on IRC in `#whatwg on +irc.freenode.net <http://wiki.whatwg.org/wiki/IRC>`_. diff --git a/catapult/third_party/html5lib-python/debug-info.py b/catapult/third_party/html5lib-python/debug-info.py new file mode 100644 index 00000000..b5d2bb6a --- /dev/null +++ b/catapult/third_party/html5lib-python/debug-info.py @@ -0,0 +1,37 @@ +from __future__ import print_function, unicode_literals + +import platform +import sys + + +info = { + "impl": platform.python_implementation(), + "version": platform.python_version(), + "revision": platform.python_revision(), + "maxunicode": sys.maxunicode, + "maxsize": sys.maxsize +} + +search_modules = ["charade", "chardet", "datrie", "genshi", "html5lib", "lxml", "six"] +found_modules = [] + +for m in search_modules: + try: + __import__(m) + except ImportError: + pass + else: + found_modules.append(m) + +info["modules"] = ", ".join(found_modules) + + +print("""html5lib debug info: + +Python %(version)s (revision: %(revision)s) +Implementation: %(impl)s + +sys.maxunicode: %(maxunicode)X +sys.maxsize: %(maxsize)X + +Installed modules: %(modules)s""" % info) diff --git a/catapult/third_party/html5lib-python/doc/Makefile b/catapult/third_party/html5lib-python/doc/Makefile new file mode 100644 index 00000000..e0e58667 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/html5lib.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/html5lib.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/html5lib" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/html5lib" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/catapult/third_party/html5lib-python/doc/changes.rst b/catapult/third_party/html5lib-python/doc/changes.rst new file mode 100644 index 00000000..ded3b705 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/changes.rst @@ -0,0 +1,3 @@ +.. :changelog: + +.. include:: ../CHANGES.rst diff --git a/catapult/third_party/html5lib-python/doc/conf.py b/catapult/third_party/html5lib-python/doc/conf.py new file mode 100644 index 00000000..434f21c4 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/conf.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# html5lib documentation build configuration file, created by +# sphinx-quickstart on Wed May 8 00:04:49 2013. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.viewcode'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'html5lib' +copyright = '2006 - 2013, James Graham, Geoffrey Sneddon, and contributors' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +sys.path.append(os.path.abspath('..')) +from html5lib import __version__ +release = __version__ + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = 'en' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build', 'theme'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'html5libdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'html5lib.tex', 'html5lib Documentation', + 'James Graham, Geoffrey Sneddon, and contributors', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'html5lib', 'html5lib Documentation', + ['James Graham, Geoffrey Sneddon, and contributors'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'html5lib', 'html5lib Documentation', + 'James Graham, Geoffrey Sneddon, and contributors', 'html5lib', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + +class CExtMock(object): + """Required for autodoc on readthedocs.org where you cannot build C extensions.""" + def __init__(self, *args, **kwargs): + pass + + def __call__(self, *args, **kwargs): + return CExtMock() + + @classmethod + def __getattr__(cls, name): + if name in ('__file__', '__path__'): + return '/dev/null' + else: + return CExtMock() + +try: + import lxml # flake8: noqa +except ImportError: + sys.modules['lxml'] = CExtMock() + sys.modules['lxml.etree'] = CExtMock() + print("warning: lxml modules mocked.") + +try: + import genshi # flake8: noqa +except ImportError: + sys.modules['genshi'] = CExtMock() + sys.modules['genshi.core'] = CExtMock() + print("warning: genshi modules mocked.") diff --git a/catapult/third_party/html5lib-python/doc/html5lib.filters.rst b/catapult/third_party/html5lib-python/doc/html5lib.filters.rst new file mode 100644 index 00000000..1fda38a7 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/html5lib.filters.rst @@ -0,0 +1,59 @@ +filters Package +=============== + +:mod:`_base` Module +------------------- + +.. automodule:: html5lib.filters._base + :members: + :undoc-members: + :show-inheritance: + +:mod:`alphabeticalattributes` Module +------------------------------------ + +.. automodule:: html5lib.filters.alphabeticalattributes + :members: + :undoc-members: + :show-inheritance: + +:mod:`inject_meta_charset` Module +--------------------------------- + +.. automodule:: html5lib.filters.inject_meta_charset + :members: + :undoc-members: + :show-inheritance: + +:mod:`lint` Module +------------------ + +.. automodule:: html5lib.filters.lint + :members: + :undoc-members: + :show-inheritance: + +:mod:`optionaltags` Module +-------------------------- + +.. automodule:: html5lib.filters.optionaltags + :members: + :undoc-members: + :show-inheritance: + +:mod:`sanitizer` Module +----------------------- + +.. automodule:: html5lib.filters.sanitizer + :members: + :undoc-members: + :show-inheritance: + +:mod:`whitespace` Module +------------------------ + +.. automodule:: html5lib.filters.whitespace + :members: + :undoc-members: + :show-inheritance: + diff --git a/catapult/third_party/html5lib-python/doc/html5lib.rst b/catapult/third_party/html5lib-python/doc/html5lib.rst new file mode 100644 index 00000000..d4ed12b4 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/html5lib.rst @@ -0,0 +1,77 @@ +html5lib Package +================ + +:mod:`html5lib` Package +----------------------- + +.. automodule:: html5lib.__init__ + :members: + :undoc-members: + :show-inheritance: + +:mod:`constants` Module +----------------------- + +.. automodule:: html5lib.constants + :members: + :undoc-members: + :show-inheritance: + +:mod:`html5parser` Module +------------------------- + +.. automodule:: html5lib.html5parser + :members: + :undoc-members: + :show-inheritance: + +:mod:`ihatexml` Module +---------------------- + +.. automodule:: html5lib.ihatexml + :members: + :undoc-members: + :show-inheritance: + +:mod:`inputstream` Module +------------------------- + +.. automodule:: html5lib.inputstream + :members: + :undoc-members: + :show-inheritance: + +:mod:`sanitizer` Module +----------------------- + +.. automodule:: html5lib.sanitizer + :members: + :undoc-members: + :show-inheritance: + +:mod:`tokenizer` Module +----------------------- + +.. automodule:: html5lib.tokenizer + :members: + :undoc-members: + :show-inheritance: + +:mod:`utils` Module +------------------- + +.. automodule:: html5lib.utils + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + + html5lib.filters + html5lib.serializer + html5lib.treebuilders + html5lib.treewalkers + diff --git a/catapult/third_party/html5lib-python/doc/html5lib.serializer.rst b/catapult/third_party/html5lib-python/doc/html5lib.serializer.rst new file mode 100644 index 00000000..fa954742 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/html5lib.serializer.rst @@ -0,0 +1,19 @@ +serializer Package +================== + +:mod:`serializer` Package +------------------------- + +.. automodule:: html5lib.serializer + :members: + :undoc-members: + :show-inheritance: + +:mod:`htmlserializer` Module +---------------------------- + +.. automodule:: html5lib.serializer.htmlserializer + :members: + :undoc-members: + :show-inheritance: + diff --git a/catapult/third_party/html5lib-python/doc/html5lib.treebuilders.rst b/catapult/third_party/html5lib-python/doc/html5lib.treebuilders.rst new file mode 100644 index 00000000..99119839 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/html5lib.treebuilders.rst @@ -0,0 +1,43 @@ +treebuilders Package +==================== + +:mod:`treebuilders` Package +--------------------------- + +.. automodule:: html5lib.treebuilders + :members: + :undoc-members: + :show-inheritance: + +:mod:`_base` Module +------------------- + +.. automodule:: html5lib.treebuilders._base + :members: + :undoc-members: + :show-inheritance: + +:mod:`dom` Module +----------------- + +.. automodule:: html5lib.treebuilders.dom + :members: + :undoc-members: + :show-inheritance: + +:mod:`etree` Module +------------------- + +.. automodule:: html5lib.treebuilders.etree + :members: + :undoc-members: + :show-inheritance: + +:mod:`etree_lxml` Module +------------------------ + +.. automodule:: html5lib.treebuilders.etree_lxml + :members: + :undoc-members: + :show-inheritance: + diff --git a/catapult/third_party/html5lib-python/doc/html5lib.treewalkers.rst b/catapult/third_party/html5lib-python/doc/html5lib.treewalkers.rst new file mode 100644 index 00000000..80595e2d --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/html5lib.treewalkers.rst @@ -0,0 +1,59 @@ +treewalkers Package +=================== + +:mod:`treewalkers` Package +-------------------------- + +.. automodule:: html5lib.treewalkers + :members: + :undoc-members: + :show-inheritance: + +:mod:`_base` Module +------------------- + +.. automodule:: html5lib.treewalkers._base + :members: + :undoc-members: + :show-inheritance: + +:mod:`dom` Module +----------------- + +.. automodule:: html5lib.treewalkers.dom + :members: + :undoc-members: + :show-inheritance: + +:mod:`etree` Module +------------------- + +.. automodule:: html5lib.treewalkers.etree + :members: + :undoc-members: + :show-inheritance: + +:mod:`genshistream` Module +-------------------------- + +.. automodule:: html5lib.treewalkers.genshistream + :members: + :undoc-members: + :show-inheritance: + +:mod:`lxmletree` Module +----------------------- + +.. automodule:: html5lib.treewalkers.lxmletree + :members: + :undoc-members: + :show-inheritance: + +:mod:`pulldom` Module +--------------------- + +.. automodule:: html5lib.treewalkers.pulldom + :members: + :undoc-members: + :show-inheritance: + diff --git a/catapult/third_party/html5lib-python/doc/index.rst b/catapult/third_party/html5lib-python/doc/index.rst new file mode 100644 index 00000000..ca2e1b96 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/index.rst @@ -0,0 +1,21 @@ +Overview +======== + +.. include:: ../README.rst + :start-line: 6 + +.. toctree:: + :maxdepth: 2 + + movingparts + changes + License <license> + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/catapult/third_party/html5lib-python/doc/license.rst b/catapult/third_party/html5lib-python/doc/license.rst new file mode 100644 index 00000000..7e6291f3 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/license.rst @@ -0,0 +1,4 @@ +License +======= + +.. include:: ../LICENSE diff --git a/catapult/third_party/html5lib-python/doc/make.bat b/catapult/third_party/html5lib-python/doc/make.bat new file mode 100644 index 00000000..1df9d181 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/make.bat @@ -0,0 +1,242 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^<target^>` where ^<target^> is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\html5lib.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\html5lib.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/catapult/third_party/html5lib-python/doc/modules.rst b/catapult/third_party/html5lib-python/doc/modules.rst new file mode 100644 index 00000000..59fbcc86 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/modules.rst @@ -0,0 +1,7 @@ +html5lib +======== + +.. toctree:: + :maxdepth: 4 + + html5lib diff --git a/catapult/third_party/html5lib-python/doc/movingparts.rst b/catapult/third_party/html5lib-python/doc/movingparts.rst new file mode 100644 index 00000000..36539785 --- /dev/null +++ b/catapult/third_party/html5lib-python/doc/movingparts.rst @@ -0,0 +1,209 @@ +The moving parts +================ + +html5lib consists of a number of components, which are responsible for +handling its features. + + +Tree builders +------------- + +The parser reads HTML by tokenizing the content and building a tree that +the user can later access. There are three main types of trees that +html5lib can build: + +* ``etree`` - this is the default; builds a tree based on ``xml.etree``, + which can be found in the standard library. Whenever possible, the + accelerated ``ElementTree`` implementation (i.e. + ``xml.etree.cElementTree`` on Python 2.x) is used. + +* ``dom`` - builds a tree based on ``xml.dom.minidom``. + +* ``lxml.etree`` - uses lxml's implementation of the ``ElementTree`` + API. The performance gains are relatively small compared to using the + accelerated ``ElementTree`` module. + +You can specify the builder by name when using the shorthand API: + +.. code-block:: python + + import html5lib + with open("mydocument.html", "rb") as f: + lxml_etree_document = html5lib.parse(f, treebuilder="lxml") + +When instantiating a parser object, you have to pass a tree builder +class in the ``tree`` keyword attribute: + +.. code-block:: python + + import html5lib + parser = html5lib.HTMLParser(tree=SomeTreeBuilder) + document = parser.parse("<p>Hello World!") + +To get a builder class by name, use the ``getTreeBuilder`` function: + +.. code-block:: python + + import html5lib + parser = html5lib.HTMLParser(tree=html5lib.getTreeBuilder("dom")) + minidom_document = parser.parse("<p>Hello World!") + +The implementation of builders can be found in `html5lib/treebuilders/ +<https://github.com/html5lib/html5lib-python/tree/master/html5lib/treebuilders>`_. + + +Tree walkers +------------ + +Once a tree is ready, you can work on it either manually, or using +a tree walker, which provides a streaming view of the tree. html5lib +provides walkers for all three supported types of trees (``etree``, +``dom`` and ``lxml``). + +The implementation of walkers can be found in `html5lib/treewalkers/ +<https://github.com/html5lib/html5lib-python/tree/master/html5lib/treewalkers>`_. + +Walkers make consuming HTML easier. html5lib uses them to provide you +with has a couple of handy tools. + + +HTMLSerializer +~~~~~~~~~~~~~~ + +The serializer lets you write HTML back as a stream of bytes. + +.. code-block:: pycon + + >>> import html5lib + >>> element = html5lib.parse('<p xml:lang="pl">Witam wszystkich') + >>> walker = html5lib.getTreeWalker("etree") + >>> stream = walker(element) + >>> s = html5lib.serializer.HTMLSerializer() + >>> output = s.serialize(stream) + >>> for item in output: + ... print("%r" % item) + '<p' + ' ' + 'xml:lang' + '=' + 'pl' + '>' + 'Witam wszystkich' + +You can customize the serializer behaviour in a variety of ways, consult +the :class:`~html5lib.serializer.htmlserializer.HTMLSerializer` +documentation. + + +Filters +~~~~~~~ + +You can alter the stream content with filters provided by html5lib: + +* :class:`alphabeticalattributes.Filter + <html5lib.filters.alphabeticalattributes.Filter>` sorts attributes on + tags to be in alphabetical order + +* :class:`inject_meta_charset.Filter + <html5lib.filters.inject_meta_charset.Filter>` sets a user-specified + encoding in the correct ``<meta>`` tag in the ``<head>`` section of + the document + +* :class:`lint.Filter <html5lib.filters.lint.Filter>` raises + ``LintError`` exceptions on invalid tag and attribute names, invalid + PCDATA, etc. + +* :class:`optionaltags.Filter <html5lib.filters.optionaltags.Filter>` + removes tags from the stream which are not necessary to produce valid + HTML + +* :class:`sanitizer.Filter <html5lib.filters.sanitizer.Filter>` removes + unsafe markup and CSS. Elements that are known to be safe are passed + through and the rest is converted to visible text. The default + configuration of the sanitizer follows the `WHATWG Sanitization Rules + <http://wiki.whatwg.org/wiki/Sanitization_rules>`_. + +* :class:`whitespace.Filter <html5lib.filters.whitespace.Filter>` + collapses all whitespace characters to single spaces unless they're in + ``<pre/>`` or ``textarea`` tags. + +To use a filter, simply wrap it around a stream: + +.. code-block:: python + + >>> import html5lib + >>> from html5lib.filters import sanitizer + >>> dom = html5lib.parse("<p><script>alert('Boo!')", treebuilder="dom") + >>> walker = html5lib.getTreeWalker("dom") + >>> stream = walker(dom) + >>> sane_stream = sanitizer.Filter(stream) clean_stream = sanitizer.Filter(stream) + + +Tree adapters +------------- + +Used to translate one type of tree to another. More documentation +pending, sorry. + + +Encoding discovery +------------------ + +Parsed trees are always Unicode. However a large variety of input +encodings are supported. The encoding of the document is determined in +the following way: + +* The encoding may be explicitly specified by passing the name of the + encoding as the encoding parameter to the + :meth:`~html5lib.html5parser.HTMLParser.parse` method on + ``HTMLParser`` objects. + +* If no encoding is specified, the parser will attempt to detect the + encoding from a ``<meta>`` element in the first 512 bytes of the + document (this is only a partial implementation of the current HTML + 5 specification). + +* If no encoding can be found and the chardet library is available, an + attempt will be made to sniff the encoding from the byte pattern. + +* If all else fails, the default encoding will be used. This is usually + `Windows-1252 <http://en.wikipedia.org/wiki/Windows-1252>`_, which is + a common fallback used by Web browsers. + + +Tokenizers +---------- + +The part of the parser responsible for translating a raw input stream +into meaningful tokens is the tokenizer. Currently html5lib provides +two. + +To set up a tokenizer, simply pass it when instantiating +a :class:`~html5lib.html5parser.HTMLParser`: + +.. code-block:: python + + import html5lib + from html5lib import sanitizer + + p = html5lib.HTMLParser(tokenizer=sanitizer.HTMLSanitizer) + p.parse("<p>Surprise!<script>alert('Boo!');</script>") + +HTMLTokenizer +~~~~~~~~~~~~~ + +This is the default tokenizer, the heart of html5lib. The implementation +can be found in `html5lib/tokenizer.py +<https://github.com/html5lib/html5lib-python/blob/master/html5lib/tokenizer.py>`_. + +HTMLSanitizer +~~~~~~~~~~~~~ + +This is a tokenizer that removes unsafe markup and CSS styles from the +input. Elements that are known to be safe are passed through and the +rest is converted to visible text. The default configuration of the +sanitizer follows the `WHATWG Sanitization Rules +<http://wiki.whatwg.org/wiki/Sanitization_rules>`_. + +The implementation can be found in `html5lib/sanitizer.py +<https://github.com/html5lib/html5lib-python/blob/master/html5lib/sanitizer.py>`_. diff --git a/catapult/third_party/html5lib-python/flake8-run.sh b/catapult/third_party/html5lib-python/flake8-run.sh new file mode 100755 index 00000000..d1a587d3 --- /dev/null +++ b/catapult/third_party/html5lib-python/flake8-run.sh @@ -0,0 +1,14 @@ +#!/bin/bash -e + +if [[ ! -x $(which flake8) ]]; then + echo "fatal: flake8 not found on $PATH. Exiting." + exit 1 +fi + +if [[ $TRAVIS != "true" || $FLAKE == "true" ]]; then + find html5lib/ -name '*.py' -and -not -name 'constants.py' -print0 | xargs -0 flake8 --ignore=E501 + flake1=$? + flake8 --max-line-length=99 --ignore=E126 html5lib/constants.py + flake2=$? + exit $[$flake1 || $flake2] +fi diff --git a/catapult/third_party/html5lib-python/html5lib/__init__.py b/catapult/third_party/html5lib-python/html5lib/__init__.py new file mode 100644 index 00000000..3765c676 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/__init__.py @@ -0,0 +1,25 @@ +""" +HTML parsing library based on the WHATWG "HTML5" +specification. The parser is designed to be compatible with existing +HTML found in the wild and implements well-defined error recovery that +is largely compatible with modern desktop web browsers. + +Example usage: + +import html5lib +f = open("my_document.html") +tree = html5lib.parse(f) +""" + +from __future__ import absolute_import, division, unicode_literals + +from .html5parser import HTMLParser, parse, parseFragment +from .treebuilders import getTreeBuilder +from .treewalkers import getTreeWalker +from .serializer import serialize + +__all__ = ["HTMLParser", "parse", "parseFragment", "getTreeBuilder", + "getTreeWalker", "serialize"] + +# this has to be at the top level, see how setup.py parses this +__version__ = "0.9999999-dev" diff --git a/catapult/third_party/html5lib-python/html5lib/constants.py b/catapult/third_party/html5lib-python/html5lib/constants.py new file mode 100644 index 00000000..d938e0ae --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/constants.py @@ -0,0 +1,3102 @@ +from __future__ import absolute_import, division, unicode_literals + +import string + +EOF = None + +E = { + "null-character": + "Null character in input stream, replaced with U+FFFD.", + "invalid-codepoint": + "Invalid codepoint in stream.", + "incorrectly-placed-solidus": + "Solidus (/) incorrectly placed in tag.", + "incorrect-cr-newline-entity": + "Incorrect CR newline entity, replaced with LF.", + "illegal-windows-1252-entity": + "Entity used with illegal number (windows-1252 reference).", + "cant-convert-numeric-entity": + "Numeric entity couldn't be converted to character " + "(codepoint U+%(charAsInt)08x).", + "illegal-codepoint-for-numeric-entity": + "Numeric entity represents an illegal codepoint: " + "U+%(charAsInt)08x.", + "numeric-entity-without-semicolon": + "Numeric entity didn't end with ';'.", + "expected-numeric-entity-but-got-eof": + "Numeric entity expected. Got end of file instead.", + "expected-numeric-entity": + "Numeric entity expected but none found.", + "named-entity-without-semicolon": + "Named entity didn't end with ';'.", + "expected-named-entity": + "Named entity expected. Got none.", + "attributes-in-end-tag": + "End tag contains unexpected attributes.", + 'self-closing-flag-on-end-tag': + "End tag contains unexpected self-closing flag.", + "expected-tag-name-but-got-right-bracket": + "Expected tag name. Got '>' instead.", + "expected-tag-name-but-got-question-mark": + "Expected tag name. Got '?' instead. (HTML doesn't " + "support processing instructions.)", + "expected-tag-name": + "Expected tag name. Got something else instead", + "expected-closing-tag-but-got-right-bracket": + "Expected closing tag. Got '>' instead. Ignoring '</>'.", + "expected-closing-tag-but-got-eof": + "Expected closing tag. Unexpected end of file.", + "expected-closing-tag-but-got-char": + "Expected closing tag. Unexpected character '%(data)s' found.", + "eof-in-tag-name": + "Unexpected end of file in the tag name.", + "expected-attribute-name-but-got-eof": + "Unexpected end of file. Expected attribute name instead.", + "eof-in-attribute-name": + "Unexpected end of file in attribute name.", + "invalid-character-in-attribute-name": + "Invalid character in attribute name", + "duplicate-attribute": + "Dropped duplicate attribute on tag.", + "expected-end-of-tag-name-but-got-eof": + "Unexpected end of file. Expected = or end of tag.", + "expected-attribute-value-but-got-eof": + "Unexpected end of file. Expected attribute value.", + "expected-attribute-value-but-got-right-bracket": + "Expected attribute value. Got '>' instead.", + 'equals-in-unquoted-attribute-value': + "Unexpected = in unquoted attribute", + 'unexpected-character-in-unquoted-attribute-value': + "Unexpected character in unquoted attribute", + "invalid-character-after-attribute-name": + "Unexpected character after attribute name.", + "unexpected-character-after-attribute-value": + "Unexpected character after attribute value.", + "eof-in-attribute-value-double-quote": + "Unexpected end of file in attribute value (\").", + "eof-in-attribute-value-single-quote": + "Unexpected end of file in attribute value (').", + "eof-in-attribute-value-no-quotes": + "Unexpected end of file in attribute value.", + "unexpected-EOF-after-solidus-in-tag": + "Unexpected end of file in tag. Expected >", + "unexpected-character-after-solidus-in-tag": + "Unexpected character after / in tag. Expected >", + "expected-dashes-or-doctype": + "Expected '--' or 'DOCTYPE'. Not found.", + "unexpected-bang-after-double-dash-in-comment": + "Unexpected ! after -- in comment", + "unexpected-space-after-double-dash-in-comment": + "Unexpected space after -- in comment", + "incorrect-comment": + "Incorrect comment.", + "eof-in-comment": + "Unexpected end of file in comment.", + "eof-in-comment-end-dash": + "Unexpected end of file in comment (-)", + "unexpected-dash-after-double-dash-in-comment": + "Unexpected '-' after '--' found in comment.", + "eof-in-comment-double-dash": + "Unexpected end of file in comment (--).", + "eof-in-comment-end-space-state": + "Unexpected end of file in comment.", + "eof-in-comment-end-bang-state": + "Unexpected end of file in comment.", + "unexpected-char-in-comment": + "Unexpected character in comment found.", + "need-space-after-doctype": + "No space after literal string 'DOCTYPE'.", + "expected-doctype-name-but-got-right-bracket": + "Unexpected > character. Expected DOCTYPE name.", + "expected-doctype-name-but-got-eof": + "Unexpected end of file. Expected DOCTYPE name.", + "eof-in-doctype-name": + "Unexpected end of file in DOCTYPE name.", + "eof-in-doctype": + "Unexpected end of file in DOCTYPE.", + "expected-space-or-right-bracket-in-doctype": + "Expected space or '>'. Got '%(data)s'", + "unexpected-end-of-doctype": + "Unexpected end of DOCTYPE.", + "unexpected-char-in-doctype": + "Unexpected character in DOCTYPE.", + "eof-in-innerhtml": + "XXX innerHTML EOF", + "unexpected-doctype": + "Unexpected DOCTYPE. Ignored.", + "non-html-root": + "html needs to be the first start tag.", + "expected-doctype-but-got-eof": + "Unexpected End of file. Expected DOCTYPE.", + "unknown-doctype": + "Erroneous DOCTYPE.", + "expected-doctype-but-got-chars": + "Unexpected non-space characters. Expected DOCTYPE.", + "expected-doctype-but-got-start-tag": + "Unexpected start tag (%(name)s). Expected DOCTYPE.", + "expected-doctype-but-got-end-tag": + "Unexpected end tag (%(name)s). Expected DOCTYPE.", + "end-tag-after-implied-root": + "Unexpected end tag (%(name)s) after the (implied) root element.", + "expected-named-closing-tag-but-got-eof": + "Unexpected end of file. Expected end tag (%(name)s).", + "two-heads-are-not-better-than-one": + "Unexpected start tag head in existing head. Ignored.", + "unexpected-end-tag": + "Unexpected end tag (%(name)s). Ignored.", + "unexpected-start-tag-out-of-my-head": + "Unexpected start tag (%(name)s) that can be in head. Moved.", + "unexpected-start-tag": + "Unexpected start tag (%(name)s).", + "missing-end-tag": + "Missing end tag (%(name)s).", + "missing-end-tags": + "Missing end tags (%(name)s).", + "unexpected-start-tag-implies-end-tag": + "Unexpected start tag (%(startName)s) " + "implies end tag (%(endName)s).", + "unexpected-start-tag-treated-as": + "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", + "deprecated-tag": + "Unexpected start tag %(name)s. Don't use it!", + "unexpected-start-tag-ignored": + "Unexpected start tag %(name)s. Ignored.", + "expected-one-end-tag-but-got-another": + "Unexpected end tag (%(gotName)s). " + "Missing end tag (%(expectedName)s).", + "end-tag-too-early": + "End tag (%(name)s) seen too early. Expected other end tag.", + "end-tag-too-early-named": + "Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s).", + "end-tag-too-early-ignored": + "End tag (%(name)s) seen too early. Ignored.", + "adoption-agency-1.1": + "End tag (%(name)s) violates step 1, " + "paragraph 1 of the adoption agency algorithm.", + "adoption-agency-1.2": + "End tag (%(name)s) violates step 1, " + "paragraph 2 of the adoption agency algorithm.", + "adoption-agency-1.3": + "End tag (%(name)s) violates step 1, " + "paragraph 3 of the adoption agency algorithm.", + "adoption-agency-4.4": + "End tag (%(name)s) violates step 4, " + "paragraph 4 of the adoption agency algorithm.", + "unexpected-end-tag-treated-as": + "Unexpected end tag (%(originalName)s). Treated as %(newName)s.", + "no-end-tag": + "This element (%(name)s) has no end tag.", + "unexpected-implied-end-tag-in-table": + "Unexpected implied end tag (%(name)s) in the table phase.", + "unexpected-implied-end-tag-in-table-body": + "Unexpected implied end tag (%(name)s) in the table body phase.", + "unexpected-char-implies-table-voodoo": + "Unexpected non-space characters in " + "table context caused voodoo mode.", + "unexpected-hidden-input-in-table": + "Unexpected input with type hidden in table context.", + "unexpected-form-in-table": + "Unexpected form in table context.", + "unexpected-start-tag-implies-table-voodoo": + "Unexpected start tag (%(name)s) in " + "table context caused voodoo mode.", + "unexpected-end-tag-implies-table-voodoo": + "Unexpected end tag (%(name)s) in " + "table context caused voodoo mode.", + "unexpected-cell-in-table-body": + "Unexpected table cell start tag (%(name)s) " + "in the table body phase.", + "unexpected-cell-end-tag": + "Got table cell end tag (%(name)s) " + "while required end tags are missing.", + "unexpected-end-tag-in-table-body": + "Unexpected end tag (%(name)s) in the table body phase. Ignored.", + "unexpected-implied-end-tag-in-table-row": + "Unexpected implied end tag (%(name)s) in the table row phase.", + "unexpected-end-tag-in-table-row": + "Unexpected end tag (%(name)s) in the table row phase. Ignored.", + "unexpected-select-in-select": + "Unexpected select start tag in the select phase " + "treated as select end tag.", + "unexpected-input-in-select": + "Unexpected input start tag in the select phase.", + "unexpected-start-tag-in-select": + "Unexpected start tag token (%(name)s in the select phase. " + "Ignored.", + "unexpected-end-tag-in-select": + "Unexpected end tag (%(name)s) in the select phase. Ignored.", + "unexpected-table-element-start-tag-in-select-in-table": + "Unexpected table element start tag (%(name)s) in the select in table phase.", + "unexpected-table-element-end-tag-in-select-in-table": + "Unexpected table element end tag (%(name)s) in the select in table phase.", + "unexpected-char-after-body": + "Unexpected non-space characters in the after body phase.", + "unexpected-start-tag-after-body": + "Unexpected start tag token (%(name)s)" + " in the after body phase.", + "unexpected-end-tag-after-body": + "Unexpected end tag token (%(name)s)" + " in the after body phase.", + "unexpected-char-in-frameset": + "Unexpected characters in the frameset phase. Characters ignored.", + "unexpected-start-tag-in-frameset": + "Unexpected start tag token (%(name)s)" + " in the frameset phase. Ignored.", + "unexpected-frameset-in-frameset-innerhtml": + "Unexpected end tag token (frameset) " + "in the frameset phase (innerHTML).", + "unexpected-end-tag-in-frameset": + "Unexpected end tag token (%(name)s)" + " in the frameset phase. Ignored.", + "unexpected-char-after-frameset": + "Unexpected non-space characters in the " + "after frameset phase. Ignored.", + "unexpected-start-tag-after-frameset": + "Unexpected start tag (%(name)s)" + " in the after frameset phase. Ignored.", + "unexpected-end-tag-after-frameset": + "Unexpected end tag (%(name)s)" + " in the after frameset phase. Ignored.", + "unexpected-end-tag-after-body-innerhtml": + "Unexpected end tag after body(innerHtml)", + "expected-eof-but-got-char": + "Unexpected non-space characters. Expected end of file.", + "expected-eof-but-got-start-tag": + "Unexpected start tag (%(name)s)" + ". Expected end of file.", + "expected-eof-but-got-end-tag": + "Unexpected end tag (%(name)s)" + ". Expected end of file.", + "eof-in-table": + "Unexpected end of file. Expected table content.", + "eof-in-select": + "Unexpected end of file. Expected select content.", + "eof-in-frameset": + "Unexpected end of file. Expected frameset content.", + "eof-in-script-in-script": + "Unexpected end of file. Expected script content.", + "eof-in-foreign-lands": + "Unexpected end of file. Expected foreign content", + "non-void-element-with-trailing-solidus": + "Trailing solidus not allowed on element %(name)s", + "unexpected-html-element-in-foreign-content": + "Element %(name)s not allowed in a non-html context", + "unexpected-end-tag-before-html": + "Unexpected end tag (%(name)s) before html.", + "XXX-undefined-error": + "Undefined error (this sucks and should be fixed)", +} + +namespaces = { + "html": "http://www.w3.org/1999/xhtml", + "mathml": "http://www.w3.org/1998/Math/MathML", + "svg": "http://www.w3.org/2000/svg", + "xlink": "http://www.w3.org/1999/xlink", + "xml": "http://www.w3.org/XML/1998/namespace", + "xmlns": "http://www.w3.org/2000/xmlns/" +} + +scopingElements = frozenset([ + (namespaces["html"], "applet"), + (namespaces["html"], "caption"), + (namespaces["html"], "html"), + (namespaces["html"], "marquee"), + (namespaces["html"], "object"), + (namespaces["html"], "table"), + (namespaces["html"], "td"), + (namespaces["html"], "th"), + (namespaces["mathml"], "mi"), + (namespaces["mathml"], "mo"), + (namespaces["mathml"], "mn"), + (namespaces["mathml"], "ms"), + (namespaces["mathml"], "mtext"), + (namespaces["mathml"], "annotation-xml"), + (namespaces["svg"], "foreignObject"), + (namespaces["svg"], "desc"), + (namespaces["svg"], "title"), +]) + +formattingElements = frozenset([ + (namespaces["html"], "a"), + (namespaces["html"], "b"), + (namespaces["html"], "big"), + (namespaces["html"], "code"), + (namespaces["html"], "em"), + (namespaces["html"], "font"), + (namespaces["html"], "i"), + (namespaces["html"], "nobr"), + (namespaces["html"], "s"), + (namespaces["html"], "small"), + (namespaces["html"], "strike"), + (namespaces["html"], "strong"), + (namespaces["html"], "tt"), + (namespaces["html"], "u") +]) + +specialElements = frozenset([ + (namespaces["html"], "address"), + (namespaces["html"], "applet"), + (namespaces["html"], "area"), + (namespaces["html"], "article"), + (namespaces["html"], "aside"), + (namespaces["html"], "base"), + (namespaces["html"], "basefont"), + (namespaces["html"], "bgsound"), + (namespaces["html"], "blockquote"), + (namespaces["html"], "body"), + (namespaces["html"], "br"), + (namespaces["html"], "button"), + (namespaces["html"], "caption"), + (namespaces["html"], "center"), + (namespaces["html"], "col"), + (namespaces["html"], "colgroup"), + (namespaces["html"], "command"), + (namespaces["html"], "dd"), + (namespaces["html"], "details"), + (namespaces["html"], "dir"), + (namespaces["html"], "div"), + (namespaces["html"], "dl"), + (namespaces["html"], "dt"), + (namespaces["html"], "embed"), + (namespaces["html"], "fieldset"), + (namespaces["html"], "figure"), + (namespaces["html"], "footer"), + (namespaces["html"], "form"), + (namespaces["html"], "frame"), + (namespaces["html"], "frameset"), + (namespaces["html"], "h1"), + (namespaces["html"], "h2"), + (namespaces["html"], "h3"), + (namespaces["html"], "h4"), + (namespaces["html"], "h5"), + (namespaces["html"], "h6"), + (namespaces["html"], "head"), + (namespaces["html"], "header"), + (namespaces["html"], "hr"), + (namespaces["html"], "html"), + (namespaces["html"], "iframe"), + # Note that image is commented out in the spec as "this isn't an + # element that can end up on the stack, so it doesn't matter," + (namespaces["html"], "image"), + (namespaces["html"], "img"), + (namespaces["html"], "input"), + (namespaces["html"], "isindex"), + (namespaces["html"], "li"), + (namespaces["html"], "link"), + (namespaces["html"], "listing"), + (namespaces["html"], "marquee"), + (namespaces["html"], "menu"), + (namespaces["html"], "meta"), + (namespaces["html"], "nav"), + (namespaces["html"], "noembed"), + (namespaces["html"], "noframes"), + (namespaces["html"], "noscript"), + (namespaces["html"], "object"), + (namespaces["html"], "ol"), + (namespaces["html"], "p"), + (namespaces["html"], "param"), + (namespaces["html"], "plaintext"), + (namespaces["html"], "pre"), + (namespaces["html"], "script"), + (namespaces["html"], "section"), + (namespaces["html"], "select"), + (namespaces["html"], "style"), + (namespaces["html"], "table"), + (namespaces["html"], "tbody"), + (namespaces["html"], "td"), + (namespaces["html"], "textarea"), + (namespaces["html"], "tfoot"), + (namespaces["html"], "th"), + (namespaces["html"], "thead"), + (namespaces["html"], "title"), + (namespaces["html"], "tr"), + (namespaces["html"], "ul"), + (namespaces["html"], "wbr"), + (namespaces["html"], "xmp"), + (namespaces["svg"], "foreignObject") +]) + +htmlIntegrationPointElements = frozenset([ + (namespaces["mathml"], "annotaion-xml"), + (namespaces["svg"], "foreignObject"), + (namespaces["svg"], "desc"), + (namespaces["svg"], "title") +]) + +mathmlTextIntegrationPointElements = frozenset([ + (namespaces["mathml"], "mi"), + (namespaces["mathml"], "mo"), + (namespaces["mathml"], "mn"), + (namespaces["mathml"], "ms"), + (namespaces["mathml"], "mtext") +]) + +adjustForeignAttributes = { + "xlink:actuate": ("xlink", "actuate", namespaces["xlink"]), + "xlink:arcrole": ("xlink", "arcrole", namespaces["xlink"]), + "xlink:href": ("xlink", "href", namespaces["xlink"]), + "xlink:role": ("xlink", "role", namespaces["xlink"]), + "xlink:show": ("xlink", "show", namespaces["xlink"]), + "xlink:title": ("xlink", "title", namespaces["xlink"]), + "xlink:type": ("xlink", "type", namespaces["xlink"]), + "xml:base": ("xml", "base", namespaces["xml"]), + "xml:lang": ("xml", "lang", namespaces["xml"]), + "xml:space": ("xml", "space", namespaces["xml"]), + "xmlns": (None, "xmlns", namespaces["xmlns"]), + "xmlns:xlink": ("xmlns", "xlink", namespaces["xmlns"]) +} + +unadjustForeignAttributes = dict([((ns, local), qname) for qname, (prefix, local, ns) in + adjustForeignAttributes.items()]) + +spaceCharacters = frozenset([ + "\t", + "\n", + "\u000C", + " ", + "\r" +]) + +tableInsertModeElements = frozenset([ + "table", + "tbody", + "tfoot", + "thead", + "tr" +]) + +asciiLowercase = frozenset(string.ascii_lowercase) +asciiUppercase = frozenset(string.ascii_uppercase) +asciiLetters = frozenset(string.ascii_letters) +digits = frozenset(string.digits) +hexDigits = frozenset(string.hexdigits) + +asciiUpper2Lower = dict([(ord(c), ord(c.lower())) + for c in string.ascii_uppercase]) + +# Heading elements need to be ordered +headingElements = ( + "h1", + "h2", + "h3", + "h4", + "h5", + "h6" +) + +voidElements = frozenset([ + "base", + "command", + "event-source", + "link", + "meta", + "hr", + "br", + "img", + "embed", + "param", + "area", + "col", + "input", + "source", + "track" +]) + +cdataElements = frozenset(['title', 'textarea']) + +rcdataElements = frozenset([ + 'style', + 'script', + 'xmp', + 'iframe', + 'noembed', + 'noframes', + 'noscript' +]) + +booleanAttributes = { + "": frozenset(["irrelevant"]), + "style": frozenset(["scoped"]), + "img": frozenset(["ismap"]), + "audio": frozenset(["autoplay", "controls"]), + "video": frozenset(["autoplay", "controls"]), + "script": frozenset(["defer", "async"]), + "details": frozenset(["open"]), + "datagrid": frozenset(["multiple", "disabled"]), + "command": frozenset(["hidden", "disabled", "checked", "default"]), + "hr": frozenset(["noshade"]), + "menu": frozenset(["autosubmit"]), + "fieldset": frozenset(["disabled", "readonly"]), + "option": frozenset(["disabled", "readonly", "selected"]), + "optgroup": frozenset(["disabled", "readonly"]), + "button": frozenset(["disabled", "autofocus"]), + "input": frozenset(["disabled", "readonly", "required", "autofocus", "checked", "ismap"]), + "select": frozenset(["disabled", "readonly", "autofocus", "multiple"]), + "output": frozenset(["disabled", "readonly"]), +} + +# entitiesWindows1252 has to be _ordered_ and needs to have an index. It +# therefore can't be a frozenset. +entitiesWindows1252 = ( + 8364, # 0x80 0x20AC EURO SIGN + 65533, # 0x81 UNDEFINED + 8218, # 0x82 0x201A SINGLE LOW-9 QUOTATION MARK + 402, # 0x83 0x0192 LATIN SMALL LETTER F WITH HOOK + 8222, # 0x84 0x201E DOUBLE LOW-9 QUOTATION MARK + 8230, # 0x85 0x2026 HORIZONTAL ELLIPSIS + 8224, # 0x86 0x2020 DAGGER + 8225, # 0x87 0x2021 DOUBLE DAGGER + 710, # 0x88 0x02C6 MODIFIER LETTER CIRCUMFLEX ACCENT + 8240, # 0x89 0x2030 PER MILLE SIGN + 352, # 0x8A 0x0160 LATIN CAPITAL LETTER S WITH CARON + 8249, # 0x8B 0x2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK + 338, # 0x8C 0x0152 LATIN CAPITAL LIGATURE OE + 65533, # 0x8D UNDEFINED + 381, # 0x8E 0x017D LATIN CAPITAL LETTER Z WITH CARON + 65533, # 0x8F UNDEFINED + 65533, # 0x90 UNDEFINED + 8216, # 0x91 0x2018 LEFT SINGLE QUOTATION MARK + 8217, # 0x92 0x2019 RIGHT SINGLE QUOTATION MARK + 8220, # 0x93 0x201C LEFT DOUBLE QUOTATION MARK + 8221, # 0x94 0x201D RIGHT DOUBLE QUOTATION MARK + 8226, # 0x95 0x2022 BULLET + 8211, # 0x96 0x2013 EN DASH + 8212, # 0x97 0x2014 EM DASH + 732, # 0x98 0x02DC SMALL TILDE + 8482, # 0x99 0x2122 TRADE MARK SIGN + 353, # 0x9A 0x0161 LATIN SMALL LETTER S WITH CARON + 8250, # 0x9B 0x203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + 339, # 0x9C 0x0153 LATIN SMALL LIGATURE OE + 65533, # 0x9D UNDEFINED + 382, # 0x9E 0x017E LATIN SMALL LETTER Z WITH CARON + 376 # 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS +) + +xmlEntities = frozenset(['lt;', 'gt;', 'amp;', 'apos;', 'quot;']) + +entities = { + "AElig": "\xc6", + "AElig;": "\xc6", + "AMP": "&", + "AMP;": "&", + "Aacute": "\xc1", + "Aacute;": "\xc1", + "Abreve;": "\u0102", + "Acirc": "\xc2", + "Acirc;": "\xc2", + "Acy;": "\u0410", + "Afr;": "\U0001d504", + "Agrave": "\xc0", + "Agrave;": "\xc0", + "Alpha;": "\u0391", + "Amacr;": "\u0100", + "And;": "\u2a53", + "Aogon;": "\u0104", + "Aopf;": "\U0001d538", + "ApplyFunction;": "\u2061", + "Aring": "\xc5", + "Aring;": "\xc5", + "Ascr;": "\U0001d49c", + "Assign;": "\u2254", + "Atilde": "\xc3", + "Atilde;": "\xc3", + "Auml": "\xc4", + "Auml;": "\xc4", + "Backslash;": "\u2216", + "Barv;": "\u2ae7", + "Barwed;": "\u2306", + "Bcy;": "\u0411", + "Because;": "\u2235", + "Bernoullis;": "\u212c", + "Beta;": "\u0392", + "Bfr;": "\U0001d505", + "Bopf;": "\U0001d539", + "Breve;": "\u02d8", + "Bscr;": "\u212c", + "Bumpeq;": "\u224e", + "CHcy;": "\u0427", + "COPY": "\xa9", + "COPY;": "\xa9", + "Cacute;": "\u0106", + "Cap;": "\u22d2", + "CapitalDifferentialD;": "\u2145", + "Cayleys;": "\u212d", + "Ccaron;": "\u010c", + "Ccedil": "\xc7", + "Ccedil;": "\xc7", + "Ccirc;": "\u0108", + "Cconint;": "\u2230", + "Cdot;": "\u010a", + "Cedilla;": "\xb8", + "CenterDot;": "\xb7", + "Cfr;": "\u212d", + "Chi;": "\u03a7", + "CircleDot;": "\u2299", + "CircleMinus;": "\u2296", + "CirclePlus;": "\u2295", + "CircleTimes;": "\u2297", + "ClockwiseContourIntegral;": "\u2232", + "CloseCurlyDoubleQuote;": "\u201d", + "CloseCurlyQuote;": "\u2019", + "Colon;": "\u2237", + "Colone;": "\u2a74", + "Congruent;": "\u2261", + "Conint;": "\u222f", + "ContourIntegral;": "\u222e", + "Copf;": "\u2102", + "Coproduct;": "\u2210", + "CounterClockwiseContourIntegral;": "\u2233", + "Cross;": "\u2a2f", + "Cscr;": "\U0001d49e", + "Cup;": "\u22d3", + "CupCap;": "\u224d", + "DD;": "\u2145", + "DDotrahd;": "\u2911", + "DJcy;": "\u0402", + "DScy;": "\u0405", + "DZcy;": "\u040f", + "Dagger;": "\u2021", + "Darr;": "\u21a1", + "Dashv;": "\u2ae4", + "Dcaron;": "\u010e", + "Dcy;": "\u0414", + "Del;": "\u2207", + "Delta;": "\u0394", + "Dfr;": "\U0001d507", + "DiacriticalAcute;": "\xb4", + "DiacriticalDot;": "\u02d9", + "DiacriticalDoubleAcute;": "\u02dd", + "DiacriticalGrave;": "`", + "DiacriticalTilde;": "\u02dc", + "Diamond;": "\u22c4", + "DifferentialD;": "\u2146", + "Dopf;": "\U0001d53b", + "Dot;": "\xa8", + "DotDot;": "\u20dc", + "DotEqual;": "\u2250", + "DoubleContourIntegral;": "\u222f", + "DoubleDot;": "\xa8", + "DoubleDownArrow;": "\u21d3", + "DoubleLeftArrow;": "\u21d0", + "DoubleLeftRightArrow;": "\u21d4", + "DoubleLeftTee;": "\u2ae4", + "DoubleLongLeftArrow;": "\u27f8", + "DoubleLongLeftRightArrow;": "\u27fa", + "DoubleLongRightArrow;": "\u27f9", + "DoubleRightArrow;": "\u21d2", + "DoubleRightTee;": "\u22a8", + "DoubleUpArrow;": "\u21d1", + "DoubleUpDownArrow;": "\u21d5", + "DoubleVerticalBar;": "\u2225", + "DownArrow;": "\u2193", + "DownArrowBar;": "\u2913", + "DownArrowUpArrow;": "\u21f5", + "DownBreve;": "\u0311", + "DownLeftRightVector;": "\u2950", + "DownLeftTeeVector;": "\u295e", + "DownLeftVector;": "\u21bd", + "DownLeftVectorBar;": "\u2956", + "DownRightTeeVector;": "\u295f", + "DownRightVector;": "\u21c1", + "DownRightVectorBar;": "\u2957", + "DownTee;": "\u22a4", + "DownTeeArrow;": "\u21a7", + "Downarrow;": "\u21d3", + "Dscr;": "\U0001d49f", + "Dstrok;": "\u0110", + "ENG;": "\u014a", + "ETH": "\xd0", + "ETH;": "\xd0", + "Eacute": "\xc9", + "Eacute;": "\xc9", + "Ecaron;": "\u011a", + "Ecirc": "\xca", + "Ecirc;": "\xca", + "Ecy;": "\u042d", + "Edot;": "\u0116", + "Efr;": "\U0001d508", + "Egrave": "\xc8", + "Egrave;": "\xc8", + "Element;": "\u2208", + "Emacr;": "\u0112", + "EmptySmallSquare;": "\u25fb", + "EmptyVerySmallSquare;": "\u25ab", + "Eogon;": "\u0118", + "Eopf;": "\U0001d53c", + "Epsilon;": "\u0395", + "Equal;": "\u2a75", + "EqualTilde;": "\u2242", + "Equilibrium;": "\u21cc", + "Escr;": "\u2130", + "Esim;": "\u2a73", + "Eta;": "\u0397", + "Euml": "\xcb", + "Euml;": "\xcb", + "Exists;": "\u2203", + "ExponentialE;": "\u2147", + "Fcy;": "\u0424", + "Ffr;": "\U0001d509", + "FilledSmallSquare;": "\u25fc", + "FilledVerySmallSquare;": "\u25aa", + "Fopf;": "\U0001d53d", + "ForAll;": "\u2200", + "Fouriertrf;": "\u2131", + "Fscr;": "\u2131", + "GJcy;": "\u0403", + "GT": ">", + "GT;": ">", + "Gamma;": "\u0393", + "Gammad;": "\u03dc", + "Gbreve;": "\u011e", + "Gcedil;": "\u0122", + "Gcirc;": "\u011c", + "Gcy;": "\u0413", + "Gdot;": "\u0120", + "Gfr;": "\U0001d50a", + "Gg;": "\u22d9", + "Gopf;": "\U0001d53e", + "GreaterEqual;": "\u2265", + "GreaterEqualLess;": "\u22db", + "GreaterFullEqual;": "\u2267", + "GreaterGreater;": "\u2aa2", + "GreaterLess;": "\u2277", + "GreaterSlantEqual;": "\u2a7e", + "GreaterTilde;": "\u2273", + "Gscr;": "\U0001d4a2", + "Gt;": "\u226b", + "HARDcy;": "\u042a", + "Hacek;": "\u02c7", + "Hat;": "^", + "Hcirc;": "\u0124", + "Hfr;": "\u210c", + "HilbertSpace;": "\u210b", + "Hopf;": "\u210d", + "HorizontalLine;": "\u2500", + "Hscr;": "\u210b", + "Hstrok;": "\u0126", + "HumpDownHump;": "\u224e", + "HumpEqual;": "\u224f", + "IEcy;": "\u0415", + "IJlig;": "\u0132", + "IOcy;": "\u0401", + "Iacute": "\xcd", + "Iacute;": "\xcd", + "Icirc": "\xce", + "Icirc;": "\xce", + "Icy;": "\u0418", + "Idot;": "\u0130", + "Ifr;": "\u2111", + "Igrave": "\xcc", + "Igrave;": "\xcc", + "Im;": "\u2111", + "Imacr;": "\u012a", + "ImaginaryI;": "\u2148", + "Implies;": "\u21d2", + "Int;": "\u222c", + "Integral;": "\u222b", + "Intersection;": "\u22c2", + "InvisibleComma;": "\u2063", + "InvisibleTimes;": "\u2062", + "Iogon;": "\u012e", + "Iopf;": "\U0001d540", + "Iota;": "\u0399", + "Iscr;": "\u2110", + "Itilde;": "\u0128", + "Iukcy;": "\u0406", + "Iuml": "\xcf", + "Iuml;": "\xcf", + "Jcirc;": "\u0134", + "Jcy;": "\u0419", + "Jfr;": "\U0001d50d", + "Jopf;": "\U0001d541", + "Jscr;": "\U0001d4a5", + "Jsercy;": "\u0408", + "Jukcy;": "\u0404", + "KHcy;": "\u0425", + "KJcy;": "\u040c", + "Kappa;": "\u039a", + "Kcedil;": "\u0136", + "Kcy;": "\u041a", + "Kfr;": "\U0001d50e", + "Kopf;": "\U0001d542", + "Kscr;": "\U0001d4a6", + "LJcy;": "\u0409", + "LT": "<", + "LT;": "<", + "Lacute;": "\u0139", + "Lambda;": "\u039b", + "Lang;": "\u27ea", + "Laplacetrf;": "\u2112", + "Larr;": "\u219e", + "Lcaron;": "\u013d", + "Lcedil;": "\u013b", + "Lcy;": "\u041b", + "LeftAngleBracket;": "\u27e8", + "LeftArrow;": "\u2190", + "LeftArrowBar;": "\u21e4", + "LeftArrowRightArrow;": "\u21c6", + "LeftCeiling;": "\u2308", + "LeftDoubleBracket;": "\u27e6", + "LeftDownTeeVector;": "\u2961", + "LeftDownVector;": "\u21c3", + "LeftDownVectorBar;": "\u2959", + "LeftFloor;": "\u230a", + "LeftRightArrow;": "\u2194", + "LeftRightVector;": "\u294e", + "LeftTee;": "\u22a3", + "LeftTeeArrow;": "\u21a4", + "LeftTeeVector;": "\u295a", + "LeftTriangle;": "\u22b2", + "LeftTriangleBar;": "\u29cf", + "LeftTriangleEqual;": "\u22b4", + "LeftUpDownVector;": "\u2951", + "LeftUpTeeVector;": "\u2960", + "LeftUpVector;": "\u21bf", + "LeftUpVectorBar;": "\u2958", + "LeftVector;": "\u21bc", + "LeftVectorBar;": "\u2952", + "Leftarrow;": "\u21d0", + "Leftrightarrow;": "\u21d4", + "LessEqualGreater;": "\u22da", + "LessFullEqual;": "\u2266", + "LessGreater;": "\u2276", + "LessLess;": "\u2aa1", + "LessSlantEqual;": "\u2a7d", + "LessTilde;": "\u2272", + "Lfr;": "\U0001d50f", + "Ll;": "\u22d8", + "Lleftarrow;": "\u21da", + "Lmidot;": "\u013f", + "LongLeftArrow;": "\u27f5", + "LongLeftRightArrow;": "\u27f7", + "LongRightArrow;": "\u27f6", + "Longleftarrow;": "\u27f8", + "Longleftrightarrow;": "\u27fa", + "Longrightarrow;": "\u27f9", + "Lopf;": "\U0001d543", + "LowerLeftArrow;": "\u2199", + "LowerRightArrow;": "\u2198", + "Lscr;": "\u2112", + "Lsh;": "\u21b0", + "Lstrok;": "\u0141", + "Lt;": "\u226a", + "Map;": "\u2905", + "Mcy;": "\u041c", + "MediumSpace;": "\u205f", + "Mellintrf;": "\u2133", + "Mfr;": "\U0001d510", + "MinusPlus;": "\u2213", + "Mopf;": "\U0001d544", + "Mscr;": "\u2133", + "Mu;": "\u039c", + "NJcy;": "\u040a", + "Nacute;": "\u0143", + "Ncaron;": "\u0147", + "Ncedil;": "\u0145", + "Ncy;": "\u041d", + "NegativeMediumSpace;": "\u200b", + "NegativeThickSpace;": "\u200b", + "NegativeThinSpace;": "\u200b", + "NegativeVeryThinSpace;": "\u200b", + "NestedGreaterGreater;": "\u226b", + "NestedLessLess;": "\u226a", + "NewLine;": "\n", + "Nfr;": "\U0001d511", + "NoBreak;": "\u2060", + "NonBreakingSpace;": "\xa0", + "Nopf;": "\u2115", + "Not;": "\u2aec", + "NotCongruent;": "\u2262", + "NotCupCap;": "\u226d", + "NotDoubleVerticalBar;": "\u2226", + "NotElement;": "\u2209", + "NotEqual;": "\u2260", + "NotEqualTilde;": "\u2242\u0338", + "NotExists;": "\u2204", + "NotGreater;": "\u226f", + "NotGreaterEqual;": "\u2271", + "NotGreaterFullEqual;": "\u2267\u0338", + "NotGreaterGreater;": "\u226b\u0338", + "NotGreaterLess;": "\u2279", + "NotGreaterSlantEqual;": "\u2a7e\u0338", + "NotGreaterTilde;": "\u2275", + "NotHumpDownHump;": "\u224e\u0338", + "NotHumpEqual;": "\u224f\u0338", + "NotLeftTriangle;": "\u22ea", + "NotLeftTriangleBar;": "\u29cf\u0338", + "NotLeftTriangleEqual;": "\u22ec", + "NotLess;": "\u226e", + "NotLessEqual;": "\u2270", + "NotLessGreater;": "\u2278", + "NotLessLess;": "\u226a\u0338", + "NotLessSlantEqual;": "\u2a7d\u0338", + "NotLessTilde;": "\u2274", + "NotNestedGreaterGreater;": "\u2aa2\u0338", + "NotNestedLessLess;": "\u2aa1\u0338", + "NotPrecedes;": "\u2280", + "NotPrecedesEqual;": "\u2aaf\u0338", + "NotPrecedesSlantEqual;": "\u22e0", + "NotReverseElement;": "\u220c", + "NotRightTriangle;": "\u22eb", + "NotRightTriangleBar;": "\u29d0\u0338", + "NotRightTriangleEqual;": "\u22ed", + "NotSquareSubset;": "\u228f\u0338", + "NotSquareSubsetEqual;": "\u22e2", + "NotSquareSuperset;": "\u2290\u0338", + "NotSquareSupersetEqual;": "\u22e3", + "NotSubset;": "\u2282\u20d2", + "NotSubsetEqual;": "\u2288", + "NotSucceeds;": "\u2281", + "NotSucceedsEqual;": "\u2ab0\u0338", + "NotSucceedsSlantEqual;": "\u22e1", + "NotSucceedsTilde;": "\u227f\u0338", + "NotSuperset;": "\u2283\u20d2", + "NotSupersetEqual;": "\u2289", + "NotTilde;": "\u2241", + "NotTildeEqual;": "\u2244", + "NotTildeFullEqual;": "\u2247", + "NotTildeTilde;": "\u2249", + "NotVerticalBar;": "\u2224", + "Nscr;": "\U0001d4a9", + "Ntilde": "\xd1", + "Ntilde;": "\xd1", + "Nu;": "\u039d", + "OElig;": "\u0152", + "Oacute": "\xd3", + "Oacute;": "\xd3", + "Ocirc": "\xd4", + "Ocirc;": "\xd4", + "Ocy;": "\u041e", + "Odblac;": "\u0150", + "Ofr;": "\U0001d512", + "Ograve": "\xd2", + "Ograve;": "\xd2", + "Omacr;": "\u014c", + "Omega;": "\u03a9", + "Omicron;": "\u039f", + "Oopf;": "\U0001d546", + "OpenCurlyDoubleQuote;": "\u201c", + "OpenCurlyQuote;": "\u2018", + "Or;": "\u2a54", + "Oscr;": "\U0001d4aa", + "Oslash": "\xd8", + "Oslash;": "\xd8", + "Otilde": "\xd5", + "Otilde;": "\xd5", + "Otimes;": "\u2a37", + "Ouml": "\xd6", + "Ouml;": "\xd6", + "OverBar;": "\u203e", + "OverBrace;": "\u23de", + "OverBracket;": "\u23b4", + "OverParenthesis;": "\u23dc", + "PartialD;": "\u2202", + "Pcy;": "\u041f", + "Pfr;": "\U0001d513", + "Phi;": "\u03a6", + "Pi;": "\u03a0", + "PlusMinus;": "\xb1", + "Poincareplane;": "\u210c", + "Popf;": "\u2119", + "Pr;": "\u2abb", + "Precedes;": "\u227a", + "PrecedesEqual;": "\u2aaf", + "PrecedesSlantEqual;": "\u227c", + "PrecedesTilde;": "\u227e", + "Prime;": "\u2033", + "Product;": "\u220f", + "Proportion;": "\u2237", + "Proportional;": "\u221d", + "Pscr;": "\U0001d4ab", + "Psi;": "\u03a8", + "QUOT": "\"", + "QUOT;": "\"", + "Qfr;": "\U0001d514", + "Qopf;": "\u211a", + "Qscr;": "\U0001d4ac", + "RBarr;": "\u2910", + "REG": "\xae", + "REG;": "\xae", + "Racute;": "\u0154", + "Rang;": "\u27eb", + "Rarr;": "\u21a0", + "Rarrtl;": "\u2916", + "Rcaron;": "\u0158", + "Rcedil;": "\u0156", + "Rcy;": "\u0420", + "Re;": "\u211c", + "ReverseElement;": "\u220b", + "ReverseEquilibrium;": "\u21cb", + "ReverseUpEquilibrium;": "\u296f", + "Rfr;": "\u211c", + "Rho;": "\u03a1", + "RightAngleBracket;": "\u27e9", + "RightArrow;": "\u2192", + "RightArrowBar;": "\u21e5", + "RightArrowLeftArrow;": "\u21c4", + "RightCeiling;": "\u2309", + "RightDoubleBracket;": "\u27e7", + "RightDownTeeVector;": "\u295d", + "RightDownVector;": "\u21c2", + "RightDownVectorBar;": "\u2955", + "RightFloor;": "\u230b", + "RightTee;": "\u22a2", + "RightTeeArrow;": "\u21a6", + "RightTeeVector;": "\u295b", + "RightTriangle;": "\u22b3", + "RightTriangleBar;": "\u29d0", + "RightTriangleEqual;": "\u22b5", + "RightUpDownVector;": "\u294f", + "RightUpTeeVector;": "\u295c", + "RightUpVector;": "\u21be", + "RightUpVectorBar;": "\u2954", + "RightVector;": "\u21c0", + "RightVectorBar;": "\u2953", + "Rightarrow;": "\u21d2", + "Ropf;": "\u211d", + "RoundImplies;": "\u2970", + "Rrightarrow;": "\u21db", + "Rscr;": "\u211b", + "Rsh;": "\u21b1", + "RuleDelayed;": "\u29f4", + "SHCHcy;": "\u0429", + "SHcy;": "\u0428", + "SOFTcy;": "\u042c", + "Sacute;": "\u015a", + "Sc;": "\u2abc", + "Scaron;": "\u0160", + "Scedil;": "\u015e", + "Scirc;": "\u015c", + "Scy;": "\u0421", + "Sfr;": "\U0001d516", + "ShortDownArrow;": "\u2193", + "ShortLeftArrow;": "\u2190", + "ShortRightArrow;": "\u2192", + "ShortUpArrow;": "\u2191", + "Sigma;": "\u03a3", + "SmallCircle;": "\u2218", + "Sopf;": "\U0001d54a", + "Sqrt;": "\u221a", + "Square;": "\u25a1", + "SquareIntersection;": "\u2293", + "SquareSubset;": "\u228f", + "SquareSubsetEqual;": "\u2291", + "SquareSuperset;": "\u2290", + "SquareSupersetEqual;": "\u2292", + "SquareUnion;": "\u2294", + "Sscr;": "\U0001d4ae", + "Star;": "\u22c6", + "Sub;": "\u22d0", + "Subset;": "\u22d0", + "SubsetEqual;": "\u2286", + "Succeeds;": "\u227b", + "SucceedsEqual;": "\u2ab0", + "SucceedsSlantEqual;": "\u227d", + "SucceedsTilde;": "\u227f", + "SuchThat;": "\u220b", + "Sum;": "\u2211", + "Sup;": "\u22d1", + "Superset;": "\u2283", + "SupersetEqual;": "\u2287", + "Supset;": "\u22d1", + "THORN": "\xde", + "THORN;": "\xde", + "TRADE;": "\u2122", + "TSHcy;": "\u040b", + "TScy;": "\u0426", + "Tab;": "\t", + "Tau;": "\u03a4", + "Tcaron;": "\u0164", + "Tcedil;": "\u0162", + "Tcy;": "\u0422", + "Tfr;": "\U0001d517", + "Therefore;": "\u2234", + "Theta;": "\u0398", + "ThickSpace;": "\u205f\u200a", + "ThinSpace;": "\u2009", + "Tilde;": "\u223c", + "TildeEqual;": "\u2243", + "TildeFullEqual;": "\u2245", + "TildeTilde;": "\u2248", + "Topf;": "\U0001d54b", + "TripleDot;": "\u20db", + "Tscr;": "\U0001d4af", + "Tstrok;": "\u0166", + "Uacute": "\xda", + "Uacute;": "\xda", + "Uarr;": "\u219f", + "Uarrocir;": "\u2949", + "Ubrcy;": "\u040e", + "Ubreve;": "\u016c", + "Ucirc": "\xdb", + "Ucirc;": "\xdb", + "Ucy;": "\u0423", + "Udblac;": "\u0170", + "Ufr;": "\U0001d518", + "Ugrave": "\xd9", + "Ugrave;": "\xd9", + "Umacr;": "\u016a", + "UnderBar;": "_", + "UnderBrace;": "\u23df", + "UnderBracket;": "\u23b5", + "UnderParenthesis;": "\u23dd", + "Union;": "\u22c3", + "UnionPlus;": "\u228e", + "Uogon;": "\u0172", + "Uopf;": "\U0001d54c", + "UpArrow;": "\u2191", + "UpArrowBar;": "\u2912", + "UpArrowDownArrow;": "\u21c5", + "UpDownArrow;": "\u2195", + "UpEquilibrium;": "\u296e", + "UpTee;": "\u22a5", + "UpTeeArrow;": "\u21a5", + "Uparrow;": "\u21d1", + "Updownarrow;": "\u21d5", + "UpperLeftArrow;": "\u2196", + "UpperRightArrow;": "\u2197", + "Upsi;": "\u03d2", + "Upsilon;": "\u03a5", + "Uring;": "\u016e", + "Uscr;": "\U0001d4b0", + "Utilde;": "\u0168", + "Uuml": "\xdc", + "Uuml;": "\xdc", + "VDash;": "\u22ab", + "Vbar;": "\u2aeb", + "Vcy;": "\u0412", + "Vdash;": "\u22a9", + "Vdashl;": "\u2ae6", + "Vee;": "\u22c1", + "Verbar;": "\u2016", + "Vert;": "\u2016", + "VerticalBar;": "\u2223", + "VerticalLine;": "|", + "VerticalSeparator;": "\u2758", + "VerticalTilde;": "\u2240", + "VeryThinSpace;": "\u200a", + "Vfr;": "\U0001d519", + "Vopf;": "\U0001d54d", + "Vscr;": "\U0001d4b1", + "Vvdash;": "\u22aa", + "Wcirc;": "\u0174", + "Wedge;": "\u22c0", + "Wfr;": "\U0001d51a", + "Wopf;": "\U0001d54e", + "Wscr;": "\U0001d4b2", + "Xfr;": "\U0001d51b", + "Xi;": "\u039e", + "Xopf;": "\U0001d54f", + "Xscr;": "\U0001d4b3", + "YAcy;": "\u042f", + "YIcy;": "\u0407", + "YUcy;": "\u042e", + "Yacute": "\xdd", + "Yacute;": "\xdd", + "Ycirc;": "\u0176", + "Ycy;": "\u042b", + "Yfr;": "\U0001d51c", + "Yopf;": "\U0001d550", + "Yscr;": "\U0001d4b4", + "Yuml;": "\u0178", + "ZHcy;": "\u0416", + "Zacute;": "\u0179", + "Zcaron;": "\u017d", + "Zcy;": "\u0417", + "Zdot;": "\u017b", + "ZeroWidthSpace;": "\u200b", + "Zeta;": "\u0396", + "Zfr;": "\u2128", + "Zopf;": "\u2124", + "Zscr;": "\U0001d4b5", + "aacute": "\xe1", + "aacute;": "\xe1", + "abreve;": "\u0103", + "ac;": "\u223e", + "acE;": "\u223e\u0333", + "acd;": "\u223f", + "acirc": "\xe2", + "acirc;": "\xe2", + "acute": "\xb4", + "acute;": "\xb4", + "acy;": "\u0430", + "aelig": "\xe6", + "aelig;": "\xe6", + "af;": "\u2061", + "afr;": "\U0001d51e", + "agrave": "\xe0", + "agrave;": "\xe0", + "alefsym;": "\u2135", + "aleph;": "\u2135", + "alpha;": "\u03b1", + "amacr;": "\u0101", + "amalg;": "\u2a3f", + "amp": "&", + "amp;": "&", + "and;": "\u2227", + "andand;": "\u2a55", + "andd;": "\u2a5c", + "andslope;": "\u2a58", + "andv;": "\u2a5a", + "ang;": "\u2220", + "ange;": "\u29a4", + "angle;": "\u2220", + "angmsd;": "\u2221", + "angmsdaa;": "\u29a8", + "angmsdab;": "\u29a9", + "angmsdac;": "\u29aa", + "angmsdad;": "\u29ab", + "angmsdae;": "\u29ac", + "angmsdaf;": "\u29ad", + "angmsdag;": "\u29ae", + "angmsdah;": "\u29af", + "angrt;": "\u221f", + "angrtvb;": "\u22be", + "angrtvbd;": "\u299d", + "angsph;": "\u2222", + "angst;": "\xc5", + "angzarr;": "\u237c", + "aogon;": "\u0105", + "aopf;": "\U0001d552", + "ap;": "\u2248", + "apE;": "\u2a70", + "apacir;": "\u2a6f", + "ape;": "\u224a", + "apid;": "\u224b", + "apos;": "'", + "approx;": "\u2248", + "approxeq;": "\u224a", + "aring": "\xe5", + "aring;": "\xe5", + "ascr;": "\U0001d4b6", + "ast;": "*", + "asymp;": "\u2248", + "asympeq;": "\u224d", + "atilde": "\xe3", + "atilde;": "\xe3", + "auml": "\xe4", + "auml;": "\xe4", + "awconint;": "\u2233", + "awint;": "\u2a11", + "bNot;": "\u2aed", + "backcong;": "\u224c", + "backepsilon;": "\u03f6", + "backprime;": "\u2035", + "backsim;": "\u223d", + "backsimeq;": "\u22cd", + "barvee;": "\u22bd", + "barwed;": "\u2305", + "barwedge;": "\u2305", + "bbrk;": "\u23b5", + "bbrktbrk;": "\u23b6", + "bcong;": "\u224c", + "bcy;": "\u0431", + "bdquo;": "\u201e", + "becaus;": "\u2235", + "because;": "\u2235", + "bemptyv;": "\u29b0", + "bepsi;": "\u03f6", + "bernou;": "\u212c", + "beta;": "\u03b2", + "beth;": "\u2136", + "between;": "\u226c", + "bfr;": "\U0001d51f", + "bigcap;": "\u22c2", + "bigcirc;": "\u25ef", + "bigcup;": "\u22c3", + "bigodot;": "\u2a00", + "bigoplus;": "\u2a01", + "bigotimes;": "\u2a02", + "bigsqcup;": "\u2a06", + "bigstar;": "\u2605", + "bigtriangledown;": "\u25bd", + "bigtriangleup;": "\u25b3", + "biguplus;": "\u2a04", + "bigvee;": "\u22c1", + "bigwedge;": "\u22c0", + "bkarow;": "\u290d", + "blacklozenge;": "\u29eb", + "blacksquare;": "\u25aa", + "blacktriangle;": "\u25b4", + "blacktriangledown;": "\u25be", + "blacktriangleleft;": "\u25c2", + "blacktriangleright;": "\u25b8", + "blank;": "\u2423", + "blk12;": "\u2592", + "blk14;": "\u2591", + "blk34;": "\u2593", + "block;": "\u2588", + "bne;": "=\u20e5", + "bnequiv;": "\u2261\u20e5", + "bnot;": "\u2310", + "bopf;": "\U0001d553", + "bot;": "\u22a5", + "bottom;": "\u22a5", + "bowtie;": "\u22c8", + "boxDL;": "\u2557", + "boxDR;": "\u2554", + "boxDl;": "\u2556", + "boxDr;": "\u2553", + "boxH;": "\u2550", + "boxHD;": "\u2566", + "boxHU;": "\u2569", + "boxHd;": "\u2564", + "boxHu;": "\u2567", + "boxUL;": "\u255d", + "boxUR;": "\u255a", + "boxUl;": "\u255c", + "boxUr;": "\u2559", + "boxV;": "\u2551", + "boxVH;": "\u256c", + "boxVL;": "\u2563", + "boxVR;": "\u2560", + "boxVh;": "\u256b", + "boxVl;": "\u2562", + "boxVr;": "\u255f", + "boxbox;": "\u29c9", + "boxdL;": "\u2555", + "boxdR;": "\u2552", + "boxdl;": "\u2510", + "boxdr;": "\u250c", + "boxh;": "\u2500", + "boxhD;": "\u2565", + "boxhU;": "\u2568", + "boxhd;": "\u252c", + "boxhu;": "\u2534", + "boxminus;": "\u229f", + "boxplus;": "\u229e", + "boxtimes;": "\u22a0", + "boxuL;": "\u255b", + "boxuR;": "\u2558", + "boxul;": "\u2518", + "boxur;": "\u2514", + "boxv;": "\u2502", + "boxvH;": "\u256a", + "boxvL;": "\u2561", + "boxvR;": "\u255e", + "boxvh;": "\u253c", + "boxvl;": "\u2524", + "boxvr;": "\u251c", + "bprime;": "\u2035", + "breve;": "\u02d8", + "brvbar": "\xa6", + "brvbar;": "\xa6", + "bscr;": "\U0001d4b7", + "bsemi;": "\u204f", + "bsim;": "\u223d", + "bsime;": "\u22cd", + "bsol;": "\\", + "bsolb;": "\u29c5", + "bsolhsub;": "\u27c8", + "bull;": "\u2022", + "bullet;": "\u2022", + "bump;": "\u224e", + "bumpE;": "\u2aae", + "bumpe;": "\u224f", + "bumpeq;": "\u224f", + "cacute;": "\u0107", + "cap;": "\u2229", + "capand;": "\u2a44", + "capbrcup;": "\u2a49", + "capcap;": "\u2a4b", + "capcup;": "\u2a47", + "capdot;": "\u2a40", + "caps;": "\u2229\ufe00", + "caret;": "\u2041", + "caron;": "\u02c7", + "ccaps;": "\u2a4d", + "ccaron;": "\u010d", + "ccedil": "\xe7", + "ccedil;": "\xe7", + "ccirc;": "\u0109", + "ccups;": "\u2a4c", + "ccupssm;": "\u2a50", + "cdot;": "\u010b", + "cedil": "\xb8", + "cedil;": "\xb8", + "cemptyv;": "\u29b2", + "cent": "\xa2", + "cent;": "\xa2", + "centerdot;": "\xb7", + "cfr;": "\U0001d520", + "chcy;": "\u0447", + "check;": "\u2713", + "checkmark;": "\u2713", + "chi;": "\u03c7", + "cir;": "\u25cb", + "cirE;": "\u29c3", + "circ;": "\u02c6", + "circeq;": "\u2257", + "circlearrowleft;": "\u21ba", + "circlearrowright;": "\u21bb", + "circledR;": "\xae", + "circledS;": "\u24c8", + "circledast;": "\u229b", + "circledcirc;": "\u229a", + "circleddash;": "\u229d", + "cire;": "\u2257", + "cirfnint;": "\u2a10", + "cirmid;": "\u2aef", + "cirscir;": "\u29c2", + "clubs;": "\u2663", + "clubsuit;": "\u2663", + "colon;": ":", + "colone;": "\u2254", + "coloneq;": "\u2254", + "comma;": ",", + "commat;": "@", + "comp;": "\u2201", + "compfn;": "\u2218", + "complement;": "\u2201", + "complexes;": "\u2102", + "cong;": "\u2245", + "congdot;": "\u2a6d", + "conint;": "\u222e", + "copf;": "\U0001d554", + "coprod;": "\u2210", + "copy": "\xa9", + "copy;": "\xa9", + "copysr;": "\u2117", + "crarr;": "\u21b5", + "cross;": "\u2717", + "cscr;": "\U0001d4b8", + "csub;": "\u2acf", + "csube;": "\u2ad1", + "csup;": "\u2ad0", + "csupe;": "\u2ad2", + "ctdot;": "\u22ef", + "cudarrl;": "\u2938", + "cudarrr;": "\u2935", + "cuepr;": "\u22de", + "cuesc;": "\u22df", + "cularr;": "\u21b6", + "cularrp;": "\u293d", + "cup;": "\u222a", + "cupbrcap;": "\u2a48", + "cupcap;": "\u2a46", + "cupcup;": "\u2a4a", + "cupdot;": "\u228d", + "cupor;": "\u2a45", + "cups;": "\u222a\ufe00", + "curarr;": "\u21b7", + "curarrm;": "\u293c", + "curlyeqprec;": "\u22de", + "curlyeqsucc;": "\u22df", + "curlyvee;": "\u22ce", + "curlywedge;": "\u22cf", + "curren": "\xa4", + "curren;": "\xa4", + "curvearrowleft;": "\u21b6", + "curvearrowright;": "\u21b7", + "cuvee;": "\u22ce", + "cuwed;": "\u22cf", + "cwconint;": "\u2232", + "cwint;": "\u2231", + "cylcty;": "\u232d", + "dArr;": "\u21d3", + "dHar;": "\u2965", + "dagger;": "\u2020", + "daleth;": "\u2138", + "darr;": "\u2193", + "dash;": "\u2010", + "dashv;": "\u22a3", + "dbkarow;": "\u290f", + "dblac;": "\u02dd", + "dcaron;": "\u010f", + "dcy;": "\u0434", + "dd;": "\u2146", + "ddagger;": "\u2021", + "ddarr;": "\u21ca", + "ddotseq;": "\u2a77", + "deg": "\xb0", + "deg;": "\xb0", + "delta;": "\u03b4", + "demptyv;": "\u29b1", + "dfisht;": "\u297f", + "dfr;": "\U0001d521", + "dharl;": "\u21c3", + "dharr;": "\u21c2", + "diam;": "\u22c4", + "diamond;": "\u22c4", + "diamondsuit;": "\u2666", + "diams;": "\u2666", + "die;": "\xa8", + "digamma;": "\u03dd", + "disin;": "\u22f2", + "div;": "\xf7", + "divide": "\xf7", + "divide;": "\xf7", + "divideontimes;": "\u22c7", + "divonx;": "\u22c7", + "djcy;": "\u0452", + "dlcorn;": "\u231e", + "dlcrop;": "\u230d", + "dollar;": "$", + "dopf;": "\U0001d555", + "dot;": "\u02d9", + "doteq;": "\u2250", + "doteqdot;": "\u2251", + "dotminus;": "\u2238", + "dotplus;": "\u2214", + "dotsquare;": "\u22a1", + "doublebarwedge;": "\u2306", + "downarrow;": "\u2193", + "downdownarrows;": "\u21ca", + "downharpoonleft;": "\u21c3", + "downharpoonright;": "\u21c2", + "drbkarow;": "\u2910", + "drcorn;": "\u231f", + "drcrop;": "\u230c", + "dscr;": "\U0001d4b9", + "dscy;": "\u0455", + "dsol;": "\u29f6", + "dstrok;": "\u0111", + "dtdot;": "\u22f1", + "dtri;": "\u25bf", + "dtrif;": "\u25be", + "duarr;": "\u21f5", + "duhar;": "\u296f", + "dwangle;": "\u29a6", + "dzcy;": "\u045f", + "dzigrarr;": "\u27ff", + "eDDot;": "\u2a77", + "eDot;": "\u2251", + "eacute": "\xe9", + "eacute;": "\xe9", + "easter;": "\u2a6e", + "ecaron;": "\u011b", + "ecir;": "\u2256", + "ecirc": "\xea", + "ecirc;": "\xea", + "ecolon;": "\u2255", + "ecy;": "\u044d", + "edot;": "\u0117", + "ee;": "\u2147", + "efDot;": "\u2252", + "efr;": "\U0001d522", + "eg;": "\u2a9a", + "egrave": "\xe8", + "egrave;": "\xe8", + "egs;": "\u2a96", + "egsdot;": "\u2a98", + "el;": "\u2a99", + "elinters;": "\u23e7", + "ell;": "\u2113", + "els;": "\u2a95", + "elsdot;": "\u2a97", + "emacr;": "\u0113", + "empty;": "\u2205", + "emptyset;": "\u2205", + "emptyv;": "\u2205", + "emsp13;": "\u2004", + "emsp14;": "\u2005", + "emsp;": "\u2003", + "eng;": "\u014b", + "ensp;": "\u2002", + "eogon;": "\u0119", + "eopf;": "\U0001d556", + "epar;": "\u22d5", + "eparsl;": "\u29e3", + "eplus;": "\u2a71", + "epsi;": "\u03b5", + "epsilon;": "\u03b5", + "epsiv;": "\u03f5", + "eqcirc;": "\u2256", + "eqcolon;": "\u2255", + "eqsim;": "\u2242", + "eqslantgtr;": "\u2a96", + "eqslantless;": "\u2a95", + "equals;": "=", + "equest;": "\u225f", + "equiv;": "\u2261", + "equivDD;": "\u2a78", + "eqvparsl;": "\u29e5", + "erDot;": "\u2253", + "erarr;": "\u2971", + "escr;": "\u212f", + "esdot;": "\u2250", + "esim;": "\u2242", + "eta;": "\u03b7", + "eth": "\xf0", + "eth;": "\xf0", + "euml": "\xeb", + "euml;": "\xeb", + "euro;": "\u20ac", + "excl;": "!", + "exist;": "\u2203", + "expectation;": "\u2130", + "exponentiale;": "\u2147", + "fallingdotseq;": "\u2252", + "fcy;": "\u0444", + "female;": "\u2640", + "ffilig;": "\ufb03", + "fflig;": "\ufb00", + "ffllig;": "\ufb04", + "ffr;": "\U0001d523", + "filig;": "\ufb01", + "fjlig;": "fj", + "flat;": "\u266d", + "fllig;": "\ufb02", + "fltns;": "\u25b1", + "fnof;": "\u0192", + "fopf;": "\U0001d557", + "forall;": "\u2200", + "fork;": "\u22d4", + "forkv;": "\u2ad9", + "fpartint;": "\u2a0d", + "frac12": "\xbd", + "frac12;": "\xbd", + "frac13;": "\u2153", + "frac14": "\xbc", + "frac14;": "\xbc", + "frac15;": "\u2155", + "frac16;": "\u2159", + "frac18;": "\u215b", + "frac23;": "\u2154", + "frac25;": "\u2156", + "frac34": "\xbe", + "frac34;": "\xbe", + "frac35;": "\u2157", + "frac38;": "\u215c", + "frac45;": "\u2158", + "frac56;": "\u215a", + "frac58;": "\u215d", + "frac78;": "\u215e", + "frasl;": "\u2044", + "frown;": "\u2322", + "fscr;": "\U0001d4bb", + "gE;": "\u2267", + "gEl;": "\u2a8c", + "gacute;": "\u01f5", + "gamma;": "\u03b3", + "gammad;": "\u03dd", + "gap;": "\u2a86", + "gbreve;": "\u011f", + "gcirc;": "\u011d", + "gcy;": "\u0433", + "gdot;": "\u0121", + "ge;": "\u2265", + "gel;": "\u22db", + "geq;": "\u2265", + "geqq;": "\u2267", + "geqslant;": "\u2a7e", + "ges;": "\u2a7e", + "gescc;": "\u2aa9", + "gesdot;": "\u2a80", + "gesdoto;": "\u2a82", + "gesdotol;": "\u2a84", + "gesl;": "\u22db\ufe00", + "gesles;": "\u2a94", + "gfr;": "\U0001d524", + "gg;": "\u226b", + "ggg;": "\u22d9", + "gimel;": "\u2137", + "gjcy;": "\u0453", + "gl;": "\u2277", + "glE;": "\u2a92", + "gla;": "\u2aa5", + "glj;": "\u2aa4", + "gnE;": "\u2269", + "gnap;": "\u2a8a", + "gnapprox;": "\u2a8a", + "gne;": "\u2a88", + "gneq;": "\u2a88", + "gneqq;": "\u2269", + "gnsim;": "\u22e7", + "gopf;": "\U0001d558", + "grave;": "`", + "gscr;": "\u210a", + "gsim;": "\u2273", + "gsime;": "\u2a8e", + "gsiml;": "\u2a90", + "gt": ">", + "gt;": ">", + "gtcc;": "\u2aa7", + "gtcir;": "\u2a7a", + "gtdot;": "\u22d7", + "gtlPar;": "\u2995", + "gtquest;": "\u2a7c", + "gtrapprox;": "\u2a86", + "gtrarr;": "\u2978", + "gtrdot;": "\u22d7", + "gtreqless;": "\u22db", + "gtreqqless;": "\u2a8c", + "gtrless;": "\u2277", + "gtrsim;": "\u2273", + "gvertneqq;": "\u2269\ufe00", + "gvnE;": "\u2269\ufe00", + "hArr;": "\u21d4", + "hairsp;": "\u200a", + "half;": "\xbd", + "hamilt;": "\u210b", + "hardcy;": "\u044a", + "harr;": "\u2194", + "harrcir;": "\u2948", + "harrw;": "\u21ad", + "hbar;": "\u210f", + "hcirc;": "\u0125", + "hearts;": "\u2665", + "heartsuit;": "\u2665", + "hellip;": "\u2026", + "hercon;": "\u22b9", + "hfr;": "\U0001d525", + "hksearow;": "\u2925", + "hkswarow;": "\u2926", + "hoarr;": "\u21ff", + "homtht;": "\u223b", + "hookleftarrow;": "\u21a9", + "hookrightarrow;": "\u21aa", + "hopf;": "\U0001d559", + "horbar;": "\u2015", + "hscr;": "\U0001d4bd", + "hslash;": "\u210f", + "hstrok;": "\u0127", + "hybull;": "\u2043", + "hyphen;": "\u2010", + "iacute": "\xed", + "iacute;": "\xed", + "ic;": "\u2063", + "icirc": "\xee", + "icirc;": "\xee", + "icy;": "\u0438", + "iecy;": "\u0435", + "iexcl": "\xa1", + "iexcl;": "\xa1", + "iff;": "\u21d4", + "ifr;": "\U0001d526", + "igrave": "\xec", + "igrave;": "\xec", + "ii;": "\u2148", + "iiiint;": "\u2a0c", + "iiint;": "\u222d", + "iinfin;": "\u29dc", + "iiota;": "\u2129", + "ijlig;": "\u0133", + "imacr;": "\u012b", + "image;": "\u2111", + "imagline;": "\u2110", + "imagpart;": "\u2111", + "imath;": "\u0131", + "imof;": "\u22b7", + "imped;": "\u01b5", + "in;": "\u2208", + "incare;": "\u2105", + "infin;": "\u221e", + "infintie;": "\u29dd", + "inodot;": "\u0131", + "int;": "\u222b", + "intcal;": "\u22ba", + "integers;": "\u2124", + "intercal;": "\u22ba", + "intlarhk;": "\u2a17", + "intprod;": "\u2a3c", + "iocy;": "\u0451", + "iogon;": "\u012f", + "iopf;": "\U0001d55a", + "iota;": "\u03b9", + "iprod;": "\u2a3c", + "iquest": "\xbf", + "iquest;": "\xbf", + "iscr;": "\U0001d4be", + "isin;": "\u2208", + "isinE;": "\u22f9", + "isindot;": "\u22f5", + "isins;": "\u22f4", + "isinsv;": "\u22f3", + "isinv;": "\u2208", + "it;": "\u2062", + "itilde;": "\u0129", + "iukcy;": "\u0456", + "iuml": "\xef", + "iuml;": "\xef", + "jcirc;": "\u0135", + "jcy;": "\u0439", + "jfr;": "\U0001d527", + "jmath;": "\u0237", + "jopf;": "\U0001d55b", + "jscr;": "\U0001d4bf", + "jsercy;": "\u0458", + "jukcy;": "\u0454", + "kappa;": "\u03ba", + "kappav;": "\u03f0", + "kcedil;": "\u0137", + "kcy;": "\u043a", + "kfr;": "\U0001d528", + "kgreen;": "\u0138", + "khcy;": "\u0445", + "kjcy;": "\u045c", + "kopf;": "\U0001d55c", + "kscr;": "\U0001d4c0", + "lAarr;": "\u21da", + "lArr;": "\u21d0", + "lAtail;": "\u291b", + "lBarr;": "\u290e", + "lE;": "\u2266", + "lEg;": "\u2a8b", + "lHar;": "\u2962", + "lacute;": "\u013a", + "laemptyv;": "\u29b4", + "lagran;": "\u2112", + "lambda;": "\u03bb", + "lang;": "\u27e8", + "langd;": "\u2991", + "langle;": "\u27e8", + "lap;": "\u2a85", + "laquo": "\xab", + "laquo;": "\xab", + "larr;": "\u2190", + "larrb;": "\u21e4", + "larrbfs;": "\u291f", + "larrfs;": "\u291d", + "larrhk;": "\u21a9", + "larrlp;": "\u21ab", + "larrpl;": "\u2939", + "larrsim;": "\u2973", + "larrtl;": "\u21a2", + "lat;": "\u2aab", + "latail;": "\u2919", + "late;": "\u2aad", + "lates;": "\u2aad\ufe00", + "lbarr;": "\u290c", + "lbbrk;": "\u2772", + "lbrace;": "{", + "lbrack;": "[", + "lbrke;": "\u298b", + "lbrksld;": "\u298f", + "lbrkslu;": "\u298d", + "lcaron;": "\u013e", + "lcedil;": "\u013c", + "lceil;": "\u2308", + "lcub;": "{", + "lcy;": "\u043b", + "ldca;": "\u2936", + "ldquo;": "\u201c", + "ldquor;": "\u201e", + "ldrdhar;": "\u2967", + "ldrushar;": "\u294b", + "ldsh;": "\u21b2", + "le;": "\u2264", + "leftarrow;": "\u2190", + "leftarrowtail;": "\u21a2", + "leftharpoondown;": "\u21bd", + "leftharpoonup;": "\u21bc", + "leftleftarrows;": "\u21c7", + "leftrightarrow;": "\u2194", + "leftrightarrows;": "\u21c6", + "leftrightharpoons;": "\u21cb", + "leftrightsquigarrow;": "\u21ad", + "leftthreetimes;": "\u22cb", + "leg;": "\u22da", + "leq;": "\u2264", + "leqq;": "\u2266", + "leqslant;": "\u2a7d", + "les;": "\u2a7d", + "lescc;": "\u2aa8", + "lesdot;": "\u2a7f", + "lesdoto;": "\u2a81", + "lesdotor;": "\u2a83", + "lesg;": "\u22da\ufe00", + "lesges;": "\u2a93", + "lessapprox;": "\u2a85", + "lessdot;": "\u22d6", + "lesseqgtr;": "\u22da", + "lesseqqgtr;": "\u2a8b", + "lessgtr;": "\u2276", + "lesssim;": "\u2272", + "lfisht;": "\u297c", + "lfloor;": "\u230a", + "lfr;": "\U0001d529", + "lg;": "\u2276", + "lgE;": "\u2a91", + "lhard;": "\u21bd", + "lharu;": "\u21bc", + "lharul;": "\u296a", + "lhblk;": "\u2584", + "ljcy;": "\u0459", + "ll;": "\u226a", + "llarr;": "\u21c7", + "llcorner;": "\u231e", + "llhard;": "\u296b", + "lltri;": "\u25fa", + "lmidot;": "\u0140", + "lmoust;": "\u23b0", + "lmoustache;": "\u23b0", + "lnE;": "\u2268", + "lnap;": "\u2a89", + "lnapprox;": "\u2a89", + "lne;": "\u2a87", + "lneq;": "\u2a87", + "lneqq;": "\u2268", + "lnsim;": "\u22e6", + "loang;": "\u27ec", + "loarr;": "\u21fd", + "lobrk;": "\u27e6", + "longleftarrow;": "\u27f5", + "longleftrightarrow;": "\u27f7", + "longmapsto;": "\u27fc", + "longrightarrow;": "\u27f6", + "looparrowleft;": "\u21ab", + "looparrowright;": "\u21ac", + "lopar;": "\u2985", + "lopf;": "\U0001d55d", + "loplus;": "\u2a2d", + "lotimes;": "\u2a34", + "lowast;": "\u2217", + "lowbar;": "_", + "loz;": "\u25ca", + "lozenge;": "\u25ca", + "lozf;": "\u29eb", + "lpar;": "(", + "lparlt;": "\u2993", + "lrarr;": "\u21c6", + "lrcorner;": "\u231f", + "lrhar;": "\u21cb", + "lrhard;": "\u296d", + "lrm;": "\u200e", + "lrtri;": "\u22bf", + "lsaquo;": "\u2039", + "lscr;": "\U0001d4c1", + "lsh;": "\u21b0", + "lsim;": "\u2272", + "lsime;": "\u2a8d", + "lsimg;": "\u2a8f", + "lsqb;": "[", + "lsquo;": "\u2018", + "lsquor;": "\u201a", + "lstrok;": "\u0142", + "lt": "<", + "lt;": "<", + "ltcc;": "\u2aa6", + "ltcir;": "\u2a79", + "ltdot;": "\u22d6", + "lthree;": "\u22cb", + "ltimes;": "\u22c9", + "ltlarr;": "\u2976", + "ltquest;": "\u2a7b", + "ltrPar;": "\u2996", + "ltri;": "\u25c3", + "ltrie;": "\u22b4", + "ltrif;": "\u25c2", + "lurdshar;": "\u294a", + "luruhar;": "\u2966", + "lvertneqq;": "\u2268\ufe00", + "lvnE;": "\u2268\ufe00", + "mDDot;": "\u223a", + "macr": "\xaf", + "macr;": "\xaf", + "male;": "\u2642", + "malt;": "\u2720", + "maltese;": "\u2720", + "map;": "\u21a6", + "mapsto;": "\u21a6", + "mapstodown;": "\u21a7", + "mapstoleft;": "\u21a4", + "mapstoup;": "\u21a5", + "marker;": "\u25ae", + "mcomma;": "\u2a29", + "mcy;": "\u043c", + "mdash;": "\u2014", + "measuredangle;": "\u2221", + "mfr;": "\U0001d52a", + "mho;": "\u2127", + "micro": "\xb5", + "micro;": "\xb5", + "mid;": "\u2223", + "midast;": "*", + "midcir;": "\u2af0", + "middot": "\xb7", + "middot;": "\xb7", + "minus;": "\u2212", + "minusb;": "\u229f", + "minusd;": "\u2238", + "minusdu;": "\u2a2a", + "mlcp;": "\u2adb", + "mldr;": "\u2026", + "mnplus;": "\u2213", + "models;": "\u22a7", + "mopf;": "\U0001d55e", + "mp;": "\u2213", + "mscr;": "\U0001d4c2", + "mstpos;": "\u223e", + "mu;": "\u03bc", + "multimap;": "\u22b8", + "mumap;": "\u22b8", + "nGg;": "\u22d9\u0338", + "nGt;": "\u226b\u20d2", + "nGtv;": "\u226b\u0338", + "nLeftarrow;": "\u21cd", + "nLeftrightarrow;": "\u21ce", + "nLl;": "\u22d8\u0338", + "nLt;": "\u226a\u20d2", + "nLtv;": "\u226a\u0338", + "nRightarrow;": "\u21cf", + "nVDash;": "\u22af", + "nVdash;": "\u22ae", + "nabla;": "\u2207", + "nacute;": "\u0144", + "nang;": "\u2220\u20d2", + "nap;": "\u2249", + "napE;": "\u2a70\u0338", + "napid;": "\u224b\u0338", + "napos;": "\u0149", + "napprox;": "\u2249", + "natur;": "\u266e", + "natural;": "\u266e", + "naturals;": "\u2115", + "nbsp": "\xa0", + "nbsp;": "\xa0", + "nbump;": "\u224e\u0338", + "nbumpe;": "\u224f\u0338", + "ncap;": "\u2a43", + "ncaron;": "\u0148", + "ncedil;": "\u0146", + "ncong;": "\u2247", + "ncongdot;": "\u2a6d\u0338", + "ncup;": "\u2a42", + "ncy;": "\u043d", + "ndash;": "\u2013", + "ne;": "\u2260", + "neArr;": "\u21d7", + "nearhk;": "\u2924", + "nearr;": "\u2197", + "nearrow;": "\u2197", + "nedot;": "\u2250\u0338", + "nequiv;": "\u2262", + "nesear;": "\u2928", + "nesim;": "\u2242\u0338", + "nexist;": "\u2204", + "nexists;": "\u2204", + "nfr;": "\U0001d52b", + "ngE;": "\u2267\u0338", + "nge;": "\u2271", + "ngeq;": "\u2271", + "ngeqq;": "\u2267\u0338", + "ngeqslant;": "\u2a7e\u0338", + "nges;": "\u2a7e\u0338", + "ngsim;": "\u2275", + "ngt;": "\u226f", + "ngtr;": "\u226f", + "nhArr;": "\u21ce", + "nharr;": "\u21ae", + "nhpar;": "\u2af2", + "ni;": "\u220b", + "nis;": "\u22fc", + "nisd;": "\u22fa", + "niv;": "\u220b", + "njcy;": "\u045a", + "nlArr;": "\u21cd", + "nlE;": "\u2266\u0338", + "nlarr;": "\u219a", + "nldr;": "\u2025", + "nle;": "\u2270", + "nleftarrow;": "\u219a", + "nleftrightarrow;": "\u21ae", + "nleq;": "\u2270", + "nleqq;": "\u2266\u0338", + "nleqslant;": "\u2a7d\u0338", + "nles;": "\u2a7d\u0338", + "nless;": "\u226e", + "nlsim;": "\u2274", + "nlt;": "\u226e", + "nltri;": "\u22ea", + "nltrie;": "\u22ec", + "nmid;": "\u2224", + "nopf;": "\U0001d55f", + "not": "\xac", + "not;": "\xac", + "notin;": "\u2209", + "notinE;": "\u22f9\u0338", + "notindot;": "\u22f5\u0338", + "notinva;": "\u2209", + "notinvb;": "\u22f7", + "notinvc;": "\u22f6", + "notni;": "\u220c", + "notniva;": "\u220c", + "notnivb;": "\u22fe", + "notnivc;": "\u22fd", + "npar;": "\u2226", + "nparallel;": "\u2226", + "nparsl;": "\u2afd\u20e5", + "npart;": "\u2202\u0338", + "npolint;": "\u2a14", + "npr;": "\u2280", + "nprcue;": "\u22e0", + "npre;": "\u2aaf\u0338", + "nprec;": "\u2280", + "npreceq;": "\u2aaf\u0338", + "nrArr;": "\u21cf", + "nrarr;": "\u219b", + "nrarrc;": "\u2933\u0338", + "nrarrw;": "\u219d\u0338", + "nrightarrow;": "\u219b", + "nrtri;": "\u22eb", + "nrtrie;": "\u22ed", + "nsc;": "\u2281", + "nsccue;": "\u22e1", + "nsce;": "\u2ab0\u0338", + "nscr;": "\U0001d4c3", + "nshortmid;": "\u2224", + "nshortparallel;": "\u2226", + "nsim;": "\u2241", + "nsime;": "\u2244", + "nsimeq;": "\u2244", + "nsmid;": "\u2224", + "nspar;": "\u2226", + "nsqsube;": "\u22e2", + "nsqsupe;": "\u22e3", + "nsub;": "\u2284", + "nsubE;": "\u2ac5\u0338", + "nsube;": "\u2288", + "nsubset;": "\u2282\u20d2", + "nsubseteq;": "\u2288", + "nsubseteqq;": "\u2ac5\u0338", + "nsucc;": "\u2281", + "nsucceq;": "\u2ab0\u0338", + "nsup;": "\u2285", + "nsupE;": "\u2ac6\u0338", + "nsupe;": "\u2289", + "nsupset;": "\u2283\u20d2", + "nsupseteq;": "\u2289", + "nsupseteqq;": "\u2ac6\u0338", + "ntgl;": "\u2279", + "ntilde": "\xf1", + "ntilde;": "\xf1", + "ntlg;": "\u2278", + "ntriangleleft;": "\u22ea", + "ntrianglelefteq;": "\u22ec", + "ntriangleright;": "\u22eb", + "ntrianglerighteq;": "\u22ed", + "nu;": "\u03bd", + "num;": "#", + "numero;": "\u2116", + "numsp;": "\u2007", + "nvDash;": "\u22ad", + "nvHarr;": "\u2904", + "nvap;": "\u224d\u20d2", + "nvdash;": "\u22ac", + "nvge;": "\u2265\u20d2", + "nvgt;": ">\u20d2", + "nvinfin;": "\u29de", + "nvlArr;": "\u2902", + "nvle;": "\u2264\u20d2", + "nvlt;": "<\u20d2", + "nvltrie;": "\u22b4\u20d2", + "nvrArr;": "\u2903", + "nvrtrie;": "\u22b5\u20d2", + "nvsim;": "\u223c\u20d2", + "nwArr;": "\u21d6", + "nwarhk;": "\u2923", + "nwarr;": "\u2196", + "nwarrow;": "\u2196", + "nwnear;": "\u2927", + "oS;": "\u24c8", + "oacute": "\xf3", + "oacute;": "\xf3", + "oast;": "\u229b", + "ocir;": "\u229a", + "ocirc": "\xf4", + "ocirc;": "\xf4", + "ocy;": "\u043e", + "odash;": "\u229d", + "odblac;": "\u0151", + "odiv;": "\u2a38", + "odot;": "\u2299", + "odsold;": "\u29bc", + "oelig;": "\u0153", + "ofcir;": "\u29bf", + "ofr;": "\U0001d52c", + "ogon;": "\u02db", + "ograve": "\xf2", + "ograve;": "\xf2", + "ogt;": "\u29c1", + "ohbar;": "\u29b5", + "ohm;": "\u03a9", + "oint;": "\u222e", + "olarr;": "\u21ba", + "olcir;": "\u29be", + "olcross;": "\u29bb", + "oline;": "\u203e", + "olt;": "\u29c0", + "omacr;": "\u014d", + "omega;": "\u03c9", + "omicron;": "\u03bf", + "omid;": "\u29b6", + "ominus;": "\u2296", + "oopf;": "\U0001d560", + "opar;": "\u29b7", + "operp;": "\u29b9", + "oplus;": "\u2295", + "or;": "\u2228", + "orarr;": "\u21bb", + "ord;": "\u2a5d", + "order;": "\u2134", + "orderof;": "\u2134", + "ordf": "\xaa", + "ordf;": "\xaa", + "ordm": "\xba", + "ordm;": "\xba", + "origof;": "\u22b6", + "oror;": "\u2a56", + "orslope;": "\u2a57", + "orv;": "\u2a5b", + "oscr;": "\u2134", + "oslash": "\xf8", + "oslash;": "\xf8", + "osol;": "\u2298", + "otilde": "\xf5", + "otilde;": "\xf5", + "otimes;": "\u2297", + "otimesas;": "\u2a36", + "ouml": "\xf6", + "ouml;": "\xf6", + "ovbar;": "\u233d", + "par;": "\u2225", + "para": "\xb6", + "para;": "\xb6", + "parallel;": "\u2225", + "parsim;": "\u2af3", + "parsl;": "\u2afd", + "part;": "\u2202", + "pcy;": "\u043f", + "percnt;": "%", + "period;": ".", + "permil;": "\u2030", + "perp;": "\u22a5", + "pertenk;": "\u2031", + "pfr;": "\U0001d52d", + "phi;": "\u03c6", + "phiv;": "\u03d5", + "phmmat;": "\u2133", + "phone;": "\u260e", + "pi;": "\u03c0", + "pitchfork;": "\u22d4", + "piv;": "\u03d6", + "planck;": "\u210f", + "planckh;": "\u210e", + "plankv;": "\u210f", + "plus;": "+", + "plusacir;": "\u2a23", + "plusb;": "\u229e", + "pluscir;": "\u2a22", + "plusdo;": "\u2214", + "plusdu;": "\u2a25", + "pluse;": "\u2a72", + "plusmn": "\xb1", + "plusmn;": "\xb1", + "plussim;": "\u2a26", + "plustwo;": "\u2a27", + "pm;": "\xb1", + "pointint;": "\u2a15", + "popf;": "\U0001d561", + "pound": "\xa3", + "pound;": "\xa3", + "pr;": "\u227a", + "prE;": "\u2ab3", + "prap;": "\u2ab7", + "prcue;": "\u227c", + "pre;": "\u2aaf", + "prec;": "\u227a", + "precapprox;": "\u2ab7", + "preccurlyeq;": "\u227c", + "preceq;": "\u2aaf", + "precnapprox;": "\u2ab9", + "precneqq;": "\u2ab5", + "precnsim;": "\u22e8", + "precsim;": "\u227e", + "prime;": "\u2032", + "primes;": "\u2119", + "prnE;": "\u2ab5", + "prnap;": "\u2ab9", + "prnsim;": "\u22e8", + "prod;": "\u220f", + "profalar;": "\u232e", + "profline;": "\u2312", + "profsurf;": "\u2313", + "prop;": "\u221d", + "propto;": "\u221d", + "prsim;": "\u227e", + "prurel;": "\u22b0", + "pscr;": "\U0001d4c5", + "psi;": "\u03c8", + "puncsp;": "\u2008", + "qfr;": "\U0001d52e", + "qint;": "\u2a0c", + "qopf;": "\U0001d562", + "qprime;": "\u2057", + "qscr;": "\U0001d4c6", + "quaternions;": "\u210d", + "quatint;": "\u2a16", + "quest;": "?", + "questeq;": "\u225f", + "quot": "\"", + "quot;": "\"", + "rAarr;": "\u21db", + "rArr;": "\u21d2", + "rAtail;": "\u291c", + "rBarr;": "\u290f", + "rHar;": "\u2964", + "race;": "\u223d\u0331", + "racute;": "\u0155", + "radic;": "\u221a", + "raemptyv;": "\u29b3", + "rang;": "\u27e9", + "rangd;": "\u2992", + "range;": "\u29a5", + "rangle;": "\u27e9", + "raquo": "\xbb", + "raquo;": "\xbb", + "rarr;": "\u2192", + "rarrap;": "\u2975", + "rarrb;": "\u21e5", + "rarrbfs;": "\u2920", + "rarrc;": "\u2933", + "rarrfs;": "\u291e", + "rarrhk;": "\u21aa", + "rarrlp;": "\u21ac", + "rarrpl;": "\u2945", + "rarrsim;": "\u2974", + "rarrtl;": "\u21a3", + "rarrw;": "\u219d", + "ratail;": "\u291a", + "ratio;": "\u2236", + "rationals;": "\u211a", + "rbarr;": "\u290d", + "rbbrk;": "\u2773", + "rbrace;": "}", + "rbrack;": "]", + "rbrke;": "\u298c", + "rbrksld;": "\u298e", + "rbrkslu;": "\u2990", + "rcaron;": "\u0159", + "rcedil;": "\u0157", + "rceil;": "\u2309", + "rcub;": "}", + "rcy;": "\u0440", + "rdca;": "\u2937", + "rdldhar;": "\u2969", + "rdquo;": "\u201d", + "rdquor;": "\u201d", + "rdsh;": "\u21b3", + "real;": "\u211c", + "realine;": "\u211b", + "realpart;": "\u211c", + "reals;": "\u211d", + "rect;": "\u25ad", + "reg": "\xae", + "reg;": "\xae", + "rfisht;": "\u297d", + "rfloor;": "\u230b", + "rfr;": "\U0001d52f", + "rhard;": "\u21c1", + "rharu;": "\u21c0", + "rharul;": "\u296c", + "rho;": "\u03c1", + "rhov;": "\u03f1", + "rightarrow;": "\u2192", + "rightarrowtail;": "\u21a3", + "rightharpoondown;": "\u21c1", + "rightharpoonup;": "\u21c0", + "rightleftarrows;": "\u21c4", + "rightleftharpoons;": "\u21cc", + "rightrightarrows;": "\u21c9", + "rightsquigarrow;": "\u219d", + "rightthreetimes;": "\u22cc", + "ring;": "\u02da", + "risingdotseq;": "\u2253", + "rlarr;": "\u21c4", + "rlhar;": "\u21cc", + "rlm;": "\u200f", + "rmoust;": "\u23b1", + "rmoustache;": "\u23b1", + "rnmid;": "\u2aee", + "roang;": "\u27ed", + "roarr;": "\u21fe", + "robrk;": "\u27e7", + "ropar;": "\u2986", + "ropf;": "\U0001d563", + "roplus;": "\u2a2e", + "rotimes;": "\u2a35", + "rpar;": ")", + "rpargt;": "\u2994", + "rppolint;": "\u2a12", + "rrarr;": "\u21c9", + "rsaquo;": "\u203a", + "rscr;": "\U0001d4c7", + "rsh;": "\u21b1", + "rsqb;": "]", + "rsquo;": "\u2019", + "rsquor;": "\u2019", + "rthree;": "\u22cc", + "rtimes;": "\u22ca", + "rtri;": "\u25b9", + "rtrie;": "\u22b5", + "rtrif;": "\u25b8", + "rtriltri;": "\u29ce", + "ruluhar;": "\u2968", + "rx;": "\u211e", + "sacute;": "\u015b", + "sbquo;": "\u201a", + "sc;": "\u227b", + "scE;": "\u2ab4", + "scap;": "\u2ab8", + "scaron;": "\u0161", + "sccue;": "\u227d", + "sce;": "\u2ab0", + "scedil;": "\u015f", + "scirc;": "\u015d", + "scnE;": "\u2ab6", + "scnap;": "\u2aba", + "scnsim;": "\u22e9", + "scpolint;": "\u2a13", + "scsim;": "\u227f", + "scy;": "\u0441", + "sdot;": "\u22c5", + "sdotb;": "\u22a1", + "sdote;": "\u2a66", + "seArr;": "\u21d8", + "searhk;": "\u2925", + "searr;": "\u2198", + "searrow;": "\u2198", + "sect": "\xa7", + "sect;": "\xa7", + "semi;": ";", + "seswar;": "\u2929", + "setminus;": "\u2216", + "setmn;": "\u2216", + "sext;": "\u2736", + "sfr;": "\U0001d530", + "sfrown;": "\u2322", + "sharp;": "\u266f", + "shchcy;": "\u0449", + "shcy;": "\u0448", + "shortmid;": "\u2223", + "shortparallel;": "\u2225", + "shy": "\xad", + "shy;": "\xad", + "sigma;": "\u03c3", + "sigmaf;": "\u03c2", + "sigmav;": "\u03c2", + "sim;": "\u223c", + "simdot;": "\u2a6a", + "sime;": "\u2243", + "simeq;": "\u2243", + "simg;": "\u2a9e", + "simgE;": "\u2aa0", + "siml;": "\u2a9d", + "simlE;": "\u2a9f", + "simne;": "\u2246", + "simplus;": "\u2a24", + "simrarr;": "\u2972", + "slarr;": "\u2190", + "smallsetminus;": "\u2216", + "smashp;": "\u2a33", + "smeparsl;": "\u29e4", + "smid;": "\u2223", + "smile;": "\u2323", + "smt;": "\u2aaa", + "smte;": "\u2aac", + "smtes;": "\u2aac\ufe00", + "softcy;": "\u044c", + "sol;": "/", + "solb;": "\u29c4", + "solbar;": "\u233f", + "sopf;": "\U0001d564", + "spades;": "\u2660", + "spadesuit;": "\u2660", + "spar;": "\u2225", + "sqcap;": "\u2293", + "sqcaps;": "\u2293\ufe00", + "sqcup;": "\u2294", + "sqcups;": "\u2294\ufe00", + "sqsub;": "\u228f", + "sqsube;": "\u2291", + "sqsubset;": "\u228f", + "sqsubseteq;": "\u2291", + "sqsup;": "\u2290", + "sqsupe;": "\u2292", + "sqsupset;": "\u2290", + "sqsupseteq;": "\u2292", + "squ;": "\u25a1", + "square;": "\u25a1", + "squarf;": "\u25aa", + "squf;": "\u25aa", + "srarr;": "\u2192", + "sscr;": "\U0001d4c8", + "ssetmn;": "\u2216", + "ssmile;": "\u2323", + "sstarf;": "\u22c6", + "star;": "\u2606", + "starf;": "\u2605", + "straightepsilon;": "\u03f5", + "straightphi;": "\u03d5", + "strns;": "\xaf", + "sub;": "\u2282", + "subE;": "\u2ac5", + "subdot;": "\u2abd", + "sube;": "\u2286", + "subedot;": "\u2ac3", + "submult;": "\u2ac1", + "subnE;": "\u2acb", + "subne;": "\u228a", + "subplus;": "\u2abf", + "subrarr;": "\u2979", + "subset;": "\u2282", + "subseteq;": "\u2286", + "subseteqq;": "\u2ac5", + "subsetneq;": "\u228a", + "subsetneqq;": "\u2acb", + "subsim;": "\u2ac7", + "subsub;": "\u2ad5", + "subsup;": "\u2ad3", + "succ;": "\u227b", + "succapprox;": "\u2ab8", + "succcurlyeq;": "\u227d", + "succeq;": "\u2ab0", + "succnapprox;": "\u2aba", + "succneqq;": "\u2ab6", + "succnsim;": "\u22e9", + "succsim;": "\u227f", + "sum;": "\u2211", + "sung;": "\u266a", + "sup1": "\xb9", + "sup1;": "\xb9", + "sup2": "\xb2", + "sup2;": "\xb2", + "sup3": "\xb3", + "sup3;": "\xb3", + "sup;": "\u2283", + "supE;": "\u2ac6", + "supdot;": "\u2abe", + "supdsub;": "\u2ad8", + "supe;": "\u2287", + "supedot;": "\u2ac4", + "suphsol;": "\u27c9", + "suphsub;": "\u2ad7", + "suplarr;": "\u297b", + "supmult;": "\u2ac2", + "supnE;": "\u2acc", + "supne;": "\u228b", + "supplus;": "\u2ac0", + "supset;": "\u2283", + "supseteq;": "\u2287", + "supseteqq;": "\u2ac6", + "supsetneq;": "\u228b", + "supsetneqq;": "\u2acc", + "supsim;": "\u2ac8", + "supsub;": "\u2ad4", + "supsup;": "\u2ad6", + "swArr;": "\u21d9", + "swarhk;": "\u2926", + "swarr;": "\u2199", + "swarrow;": "\u2199", + "swnwar;": "\u292a", + "szlig": "\xdf", + "szlig;": "\xdf", + "target;": "\u2316", + "tau;": "\u03c4", + "tbrk;": "\u23b4", + "tcaron;": "\u0165", + "tcedil;": "\u0163", + "tcy;": "\u0442", + "tdot;": "\u20db", + "telrec;": "\u2315", + "tfr;": "\U0001d531", + "there4;": "\u2234", + "therefore;": "\u2234", + "theta;": "\u03b8", + "thetasym;": "\u03d1", + "thetav;": "\u03d1", + "thickapprox;": "\u2248", + "thicksim;": "\u223c", + "thinsp;": "\u2009", + "thkap;": "\u2248", + "thksim;": "\u223c", + "thorn": "\xfe", + "thorn;": "\xfe", + "tilde;": "\u02dc", + "times": "\xd7", + "times;": "\xd7", + "timesb;": "\u22a0", + "timesbar;": "\u2a31", + "timesd;": "\u2a30", + "tint;": "\u222d", + "toea;": "\u2928", + "top;": "\u22a4", + "topbot;": "\u2336", + "topcir;": "\u2af1", + "topf;": "\U0001d565", + "topfork;": "\u2ada", + "tosa;": "\u2929", + "tprime;": "\u2034", + "trade;": "\u2122", + "triangle;": "\u25b5", + "triangledown;": "\u25bf", + "triangleleft;": "\u25c3", + "trianglelefteq;": "\u22b4", + "triangleq;": "\u225c", + "triangleright;": "\u25b9", + "trianglerighteq;": "\u22b5", + "tridot;": "\u25ec", + "trie;": "\u225c", + "triminus;": "\u2a3a", + "triplus;": "\u2a39", + "trisb;": "\u29cd", + "tritime;": "\u2a3b", + "trpezium;": "\u23e2", + "tscr;": "\U0001d4c9", + "tscy;": "\u0446", + "tshcy;": "\u045b", + "tstrok;": "\u0167", + "twixt;": "\u226c", + "twoheadleftarrow;": "\u219e", + "twoheadrightarrow;": "\u21a0", + "uArr;": "\u21d1", + "uHar;": "\u2963", + "uacute": "\xfa", + "uacute;": "\xfa", + "uarr;": "\u2191", + "ubrcy;": "\u045e", + "ubreve;": "\u016d", + "ucirc": "\xfb", + "ucirc;": "\xfb", + "ucy;": "\u0443", + "udarr;": "\u21c5", + "udblac;": "\u0171", + "udhar;": "\u296e", + "ufisht;": "\u297e", + "ufr;": "\U0001d532", + "ugrave": "\xf9", + "ugrave;": "\xf9", + "uharl;": "\u21bf", + "uharr;": "\u21be", + "uhblk;": "\u2580", + "ulcorn;": "\u231c", + "ulcorner;": "\u231c", + "ulcrop;": "\u230f", + "ultri;": "\u25f8", + "umacr;": "\u016b", + "uml": "\xa8", + "uml;": "\xa8", + "uogon;": "\u0173", + "uopf;": "\U0001d566", + "uparrow;": "\u2191", + "updownarrow;": "\u2195", + "upharpoonleft;": "\u21bf", + "upharpoonright;": "\u21be", + "uplus;": "\u228e", + "upsi;": "\u03c5", + "upsih;": "\u03d2", + "upsilon;": "\u03c5", + "upuparrows;": "\u21c8", + "urcorn;": "\u231d", + "urcorner;": "\u231d", + "urcrop;": "\u230e", + "uring;": "\u016f", + "urtri;": "\u25f9", + "uscr;": "\U0001d4ca", + "utdot;": "\u22f0", + "utilde;": "\u0169", + "utri;": "\u25b5", + "utrif;": "\u25b4", + "uuarr;": "\u21c8", + "uuml": "\xfc", + "uuml;": "\xfc", + "uwangle;": "\u29a7", + "vArr;": "\u21d5", + "vBar;": "\u2ae8", + "vBarv;": "\u2ae9", + "vDash;": "\u22a8", + "vangrt;": "\u299c", + "varepsilon;": "\u03f5", + "varkappa;": "\u03f0", + "varnothing;": "\u2205", + "varphi;": "\u03d5", + "varpi;": "\u03d6", + "varpropto;": "\u221d", + "varr;": "\u2195", + "varrho;": "\u03f1", + "varsigma;": "\u03c2", + "varsubsetneq;": "\u228a\ufe00", + "varsubsetneqq;": "\u2acb\ufe00", + "varsupsetneq;": "\u228b\ufe00", + "varsupsetneqq;": "\u2acc\ufe00", + "vartheta;": "\u03d1", + "vartriangleleft;": "\u22b2", + "vartriangleright;": "\u22b3", + "vcy;": "\u0432", + "vdash;": "\u22a2", + "vee;": "\u2228", + "veebar;": "\u22bb", + "veeeq;": "\u225a", + "vellip;": "\u22ee", + "verbar;": "|", + "vert;": "|", + "vfr;": "\U0001d533", + "vltri;": "\u22b2", + "vnsub;": "\u2282\u20d2", + "vnsup;": "\u2283\u20d2", + "vopf;": "\U0001d567", + "vprop;": "\u221d", + "vrtri;": "\u22b3", + "vscr;": "\U0001d4cb", + "vsubnE;": "\u2acb\ufe00", + "vsubne;": "\u228a\ufe00", + "vsupnE;": "\u2acc\ufe00", + "vsupne;": "\u228b\ufe00", + "vzigzag;": "\u299a", + "wcirc;": "\u0175", + "wedbar;": "\u2a5f", + "wedge;": "\u2227", + "wedgeq;": "\u2259", + "weierp;": "\u2118", + "wfr;": "\U0001d534", + "wopf;": "\U0001d568", + "wp;": "\u2118", + "wr;": "\u2240", + "wreath;": "\u2240", + "wscr;": "\U0001d4cc", + "xcap;": "\u22c2", + "xcirc;": "\u25ef", + "xcup;": "\u22c3", + "xdtri;": "\u25bd", + "xfr;": "\U0001d535", + "xhArr;": "\u27fa", + "xharr;": "\u27f7", + "xi;": "\u03be", + "xlArr;": "\u27f8", + "xlarr;": "\u27f5", + "xmap;": "\u27fc", + "xnis;": "\u22fb", + "xodot;": "\u2a00", + "xopf;": "\U0001d569", + "xoplus;": "\u2a01", + "xotime;": "\u2a02", + "xrArr;": "\u27f9", + "xrarr;": "\u27f6", + "xscr;": "\U0001d4cd", + "xsqcup;": "\u2a06", + "xuplus;": "\u2a04", + "xutri;": "\u25b3", + "xvee;": "\u22c1", + "xwedge;": "\u22c0", + "yacute": "\xfd", + "yacute;": "\xfd", + "yacy;": "\u044f", + "ycirc;": "\u0177", + "ycy;": "\u044b", + "yen": "\xa5", + "yen;": "\xa5", + "yfr;": "\U0001d536", + "yicy;": "\u0457", + "yopf;": "\U0001d56a", + "yscr;": "\U0001d4ce", + "yucy;": "\u044e", + "yuml": "\xff", + "yuml;": "\xff", + "zacute;": "\u017a", + "zcaron;": "\u017e", + "zcy;": "\u0437", + "zdot;": "\u017c", + "zeetrf;": "\u2128", + "zeta;": "\u03b6", + "zfr;": "\U0001d537", + "zhcy;": "\u0436", + "zigrarr;": "\u21dd", + "zopf;": "\U0001d56b", + "zscr;": "\U0001d4cf", + "zwj;": "\u200d", + "zwnj;": "\u200c", +} + +replacementCharacters = { + 0x0: "\uFFFD", + 0x0d: "\u000D", + 0x80: "\u20AC", + 0x81: "\u0081", + 0x81: "\u0081", + 0x82: "\u201A", + 0x83: "\u0192", + 0x84: "\u201E", + 0x85: "\u2026", + 0x86: "\u2020", + 0x87: "\u2021", + 0x88: "\u02C6", + 0x89: "\u2030", + 0x8A: "\u0160", + 0x8B: "\u2039", + 0x8C: "\u0152", + 0x8D: "\u008D", + 0x8E: "\u017D", + 0x8F: "\u008F", + 0x90: "\u0090", + 0x91: "\u2018", + 0x92: "\u2019", + 0x93: "\u201C", + 0x94: "\u201D", + 0x95: "\u2022", + 0x96: "\u2013", + 0x97: "\u2014", + 0x98: "\u02DC", + 0x99: "\u2122", + 0x9A: "\u0161", + 0x9B: "\u203A", + 0x9C: "\u0153", + 0x9D: "\u009D", + 0x9E: "\u017E", + 0x9F: "\u0178", +} + +encodings = { + '437': 'cp437', + '850': 'cp850', + '852': 'cp852', + '855': 'cp855', + '857': 'cp857', + '860': 'cp860', + '861': 'cp861', + '862': 'cp862', + '863': 'cp863', + '865': 'cp865', + '866': 'cp866', + '869': 'cp869', + 'ansix341968': 'ascii', + 'ansix341986': 'ascii', + 'arabic': 'iso8859-6', + 'ascii': 'ascii', + 'asmo708': 'iso8859-6', + 'big5': 'big5', + 'big5hkscs': 'big5hkscs', + 'chinese': 'gbk', + 'cp037': 'cp037', + 'cp1026': 'cp1026', + 'cp154': 'ptcp154', + 'cp367': 'ascii', + 'cp424': 'cp424', + 'cp437': 'cp437', + 'cp500': 'cp500', + 'cp775': 'cp775', + 'cp819': 'windows-1252', + 'cp850': 'cp850', + 'cp852': 'cp852', + 'cp855': 'cp855', + 'cp857': 'cp857', + 'cp860': 'cp860', + 'cp861': 'cp861', + 'cp862': 'cp862', + 'cp863': 'cp863', + 'cp864': 'cp864', + 'cp865': 'cp865', + 'cp866': 'cp866', + 'cp869': 'cp869', + 'cp936': 'gbk', + 'cpgr': 'cp869', + 'cpis': 'cp861', + 'csascii': 'ascii', + 'csbig5': 'big5', + 'cseuckr': 'cp949', + 'cseucpkdfmtjapanese': 'euc_jp', + 'csgb2312': 'gbk', + 'cshproman8': 'hp-roman8', + 'csibm037': 'cp037', + 'csibm1026': 'cp1026', + 'csibm424': 'cp424', + 'csibm500': 'cp500', + 'csibm855': 'cp855', + 'csibm857': 'cp857', + 'csibm860': 'cp860', + 'csibm861': 'cp861', + 'csibm863': 'cp863', + 'csibm864': 'cp864', + 'csibm865': 'cp865', + 'csibm866': 'cp866', + 'csibm869': 'cp869', + 'csiso2022jp': 'iso2022_jp', + 'csiso2022jp2': 'iso2022_jp_2', + 'csiso2022kr': 'iso2022_kr', + 'csiso58gb231280': 'gbk', + 'csisolatin1': 'windows-1252', + 'csisolatin2': 'iso8859-2', + 'csisolatin3': 'iso8859-3', + 'csisolatin4': 'iso8859-4', + 'csisolatin5': 'windows-1254', + 'csisolatin6': 'iso8859-10', + 'csisolatinarabic': 'iso8859-6', + 'csisolatincyrillic': 'iso8859-5', + 'csisolatingreek': 'iso8859-7', + 'csisolatinhebrew': 'iso8859-8', + 'cskoi8r': 'koi8-r', + 'csksc56011987': 'cp949', + 'cspc775baltic': 'cp775', + 'cspc850multilingual': 'cp850', + 'cspc862latinhebrew': 'cp862', + 'cspc8codepage437': 'cp437', + 'cspcp852': 'cp852', + 'csptcp154': 'ptcp154', + 'csshiftjis': 'shift_jis', + 'csunicode11utf7': 'utf-7', + 'cyrillic': 'iso8859-5', + 'cyrillicasian': 'ptcp154', + 'ebcdiccpbe': 'cp500', + 'ebcdiccpca': 'cp037', + 'ebcdiccpch': 'cp500', + 'ebcdiccphe': 'cp424', + 'ebcdiccpnl': 'cp037', + 'ebcdiccpus': 'cp037', + 'ebcdiccpwt': 'cp037', + 'ecma114': 'iso8859-6', + 'ecma118': 'iso8859-7', + 'elot928': 'iso8859-7', + 'eucjp': 'euc_jp', + 'euckr': 'cp949', + 'extendedunixcodepackedformatforjapanese': 'euc_jp', + 'gb18030': 'gb18030', + 'gb2312': 'gbk', + 'gb231280': 'gbk', + 'gbk': 'gbk', + 'greek': 'iso8859-7', + 'greek8': 'iso8859-7', + 'hebrew': 'iso8859-8', + 'hproman8': 'hp-roman8', + 'hzgb2312': 'hz', + 'ibm037': 'cp037', + 'ibm1026': 'cp1026', + 'ibm367': 'ascii', + 'ibm424': 'cp424', + 'ibm437': 'cp437', + 'ibm500': 'cp500', + 'ibm775': 'cp775', + 'ibm819': 'windows-1252', + 'ibm850': 'cp850', + 'ibm852': 'cp852', + 'ibm855': 'cp855', + 'ibm857': 'cp857', + 'ibm860': 'cp860', + 'ibm861': 'cp861', + 'ibm862': 'cp862', + 'ibm863': 'cp863', + 'ibm864': 'cp864', + 'ibm865': 'cp865', + 'ibm866': 'cp866', + 'ibm869': 'cp869', + 'iso2022jp': 'iso2022_jp', + 'iso2022jp2': 'iso2022_jp_2', + 'iso2022kr': 'iso2022_kr', + 'iso646irv1991': 'ascii', + 'iso646us': 'ascii', + 'iso88591': 'windows-1252', + 'iso885910': 'iso8859-10', + 'iso8859101992': 'iso8859-10', + 'iso885911987': 'windows-1252', + 'iso885913': 'iso8859-13', + 'iso885914': 'iso8859-14', + 'iso8859141998': 'iso8859-14', + 'iso885915': 'iso8859-15', + 'iso885916': 'iso8859-16', + 'iso8859162001': 'iso8859-16', + 'iso88592': 'iso8859-2', + 'iso885921987': 'iso8859-2', + 'iso88593': 'iso8859-3', + 'iso885931988': 'iso8859-3', + 'iso88594': 'iso8859-4', + 'iso885941988': 'iso8859-4', + 'iso88595': 'iso8859-5', + 'iso885951988': 'iso8859-5', + 'iso88596': 'iso8859-6', + 'iso885961987': 'iso8859-6', + 'iso88597': 'iso8859-7', + 'iso885971987': 'iso8859-7', + 'iso88598': 'iso8859-8', + 'iso885981988': 'iso8859-8', + 'iso88599': 'windows-1254', + 'iso885991989': 'windows-1254', + 'isoceltic': 'iso8859-14', + 'isoir100': 'windows-1252', + 'isoir101': 'iso8859-2', + 'isoir109': 'iso8859-3', + 'isoir110': 'iso8859-4', + 'isoir126': 'iso8859-7', + 'isoir127': 'iso8859-6', + 'isoir138': 'iso8859-8', + 'isoir144': 'iso8859-5', + 'isoir148': 'windows-1254', + 'isoir149': 'cp949', + 'isoir157': 'iso8859-10', + 'isoir199': 'iso8859-14', + 'isoir226': 'iso8859-16', + 'isoir58': 'gbk', + 'isoir6': 'ascii', + 'koi8r': 'koi8-r', + 'koi8u': 'koi8-u', + 'korean': 'cp949', + 'ksc5601': 'cp949', + 'ksc56011987': 'cp949', + 'ksc56011989': 'cp949', + 'l1': 'windows-1252', + 'l10': 'iso8859-16', + 'l2': 'iso8859-2', + 'l3': 'iso8859-3', + 'l4': 'iso8859-4', + 'l5': 'windows-1254', + 'l6': 'iso8859-10', + 'l8': 'iso8859-14', + 'latin1': 'windows-1252', + 'latin10': 'iso8859-16', + 'latin2': 'iso8859-2', + 'latin3': 'iso8859-3', + 'latin4': 'iso8859-4', + 'latin5': 'windows-1254', + 'latin6': 'iso8859-10', + 'latin8': 'iso8859-14', + 'latin9': 'iso8859-15', + 'ms936': 'gbk', + 'mskanji': 'shift_jis', + 'pt154': 'ptcp154', + 'ptcp154': 'ptcp154', + 'r8': 'hp-roman8', + 'roman8': 'hp-roman8', + 'shiftjis': 'shift_jis', + 'tis620': 'cp874', + 'unicode11utf7': 'utf-7', + 'us': 'ascii', + 'usascii': 'ascii', + 'utf16': 'utf-16', + 'utf16be': 'utf-16-be', + 'utf16le': 'utf-16-le', + 'utf8': 'utf-8', + 'windows1250': 'cp1250', + 'windows1251': 'cp1251', + 'windows1252': 'cp1252', + 'windows1253': 'cp1253', + 'windows1254': 'cp1254', + 'windows1255': 'cp1255', + 'windows1256': 'cp1256', + 'windows1257': 'cp1257', + 'windows1258': 'cp1258', + 'windows936': 'gbk', + 'x-x-big5': 'big5'} + +tokenTypes = { + "Doctype": 0, + "Characters": 1, + "SpaceCharacters": 2, + "StartTag": 3, + "EndTag": 4, + "EmptyTag": 5, + "Comment": 6, + "ParseError": 7 +} + +tagTokenTypes = frozenset([tokenTypes["StartTag"], tokenTypes["EndTag"], + tokenTypes["EmptyTag"]]) + + +prefixes = dict([(v, k) for k, v in namespaces.items()]) +prefixes["http://www.w3.org/1998/Math/MathML"] = "math" + + +class DataLossWarning(UserWarning): + pass + + +class ReparseException(Exception): + pass diff --git a/catapult/third_party/httplib2/httplib2/test/__init__.py b/catapult/third_party/html5lib-python/html5lib/filters/__init__.py index e69de29b..e69de29b 100644 --- a/catapult/third_party/httplib2/httplib2/test/__init__.py +++ b/catapult/third_party/html5lib-python/html5lib/filters/__init__.py diff --git a/catapult/third_party/html5lib-python/html5lib/filters/_base.py b/catapult/third_party/html5lib-python/html5lib/filters/_base.py new file mode 100644 index 00000000..c7dbaed0 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/filters/_base.py @@ -0,0 +1,12 @@ +from __future__ import absolute_import, division, unicode_literals + + +class Filter(object): + def __init__(self, source): + self.source = source + + def __iter__(self): + return iter(self.source) + + def __getattr__(self, name): + return getattr(self.source, name) diff --git a/catapult/third_party/html5lib-python/html5lib/filters/alphabeticalattributes.py b/catapult/third_party/html5lib-python/html5lib/filters/alphabeticalattributes.py new file mode 100644 index 00000000..fed6996c --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/filters/alphabeticalattributes.py @@ -0,0 +1,20 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import _base + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict + + +class Filter(_base.Filter): + def __iter__(self): + for token in _base.Filter.__iter__(self): + if token["type"] in ("StartTag", "EmptyTag"): + attrs = OrderedDict() + for name, value in sorted(token["data"].items(), + key=lambda x: x[0]): + attrs[name] = value + token["data"] = attrs + yield token diff --git a/catapult/third_party/html5lib-python/html5lib/filters/inject_meta_charset.py b/catapult/third_party/html5lib-python/html5lib/filters/inject_meta_charset.py new file mode 100644 index 00000000..ca33b70b --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/filters/inject_meta_charset.py @@ -0,0 +1,65 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import _base + + +class Filter(_base.Filter): + def __init__(self, source, encoding): + _base.Filter.__init__(self, source) + self.encoding = encoding + + def __iter__(self): + state = "pre_head" + meta_found = (self.encoding is None) + pending = [] + + for token in _base.Filter.__iter__(self): + type = token["type"] + if type == "StartTag": + if token["name"].lower() == "head": + state = "in_head" + + elif type == "EmptyTag": + if token["name"].lower() == "meta": + # replace charset with actual encoding + has_http_equiv_content_type = False + for (namespace, name), value in token["data"].items(): + if namespace is not None: + continue + elif name.lower() == 'charset': + token["data"][(namespace, name)] = self.encoding + meta_found = True + break + elif name == 'http-equiv' and value.lower() == 'content-type': + has_http_equiv_content_type = True + else: + if has_http_equiv_content_type and (None, "content") in token["data"]: + token["data"][(None, "content")] = 'text/html; charset=%s' % self.encoding + meta_found = True + + elif token["name"].lower() == "head" and not meta_found: + # insert meta into empty head + yield {"type": "StartTag", "name": "head", + "data": token["data"]} + yield {"type": "EmptyTag", "name": "meta", + "data": {(None, "charset"): self.encoding}} + yield {"type": "EndTag", "name": "head"} + meta_found = True + continue + + elif type == "EndTag": + if token["name"].lower() == "head" and pending: + # insert meta into head (if necessary) and flush pending queue + yield pending.pop(0) + if not meta_found: + yield {"type": "EmptyTag", "name": "meta", + "data": {(None, "charset"): self.encoding}} + while pending: + yield pending.pop(0) + meta_found = True + state = "post_head" + + if state == "in_head": + pending.append(token) + else: + yield token diff --git a/catapult/third_party/html5lib-python/html5lib/filters/lint.py b/catapult/third_party/html5lib-python/html5lib/filters/lint.py new file mode 100644 index 00000000..8884696d --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/filters/lint.py @@ -0,0 +1,90 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import _base +from ..constants import cdataElements, rcdataElements, voidElements + +from ..constants import spaceCharacters +spaceCharacters = "".join(spaceCharacters) + + +class LintError(Exception): + pass + + +class Filter(_base.Filter): + def __iter__(self): + open_elements = [] + contentModelFlag = "PCDATA" + for token in _base.Filter.__iter__(self): + type = token["type"] + if type in ("StartTag", "EmptyTag"): + name = token["name"] + if contentModelFlag != "PCDATA": + raise LintError("StartTag not in PCDATA content model flag: %(tag)s" % {"tag": name}) + if not isinstance(name, str): + raise LintError("Tag name is not a string: %(tag)r" % {"tag": name}) + if not name: + raise LintError("Empty tag name") + if type == "StartTag" and name in voidElements: + raise LintError("Void element reported as StartTag token: %(tag)s" % {"tag": name}) + elif type == "EmptyTag" and name not in voidElements: + raise LintError("Non-void element reported as EmptyTag token: %(tag)s" % {"tag": token["name"]}) + if type == "StartTag": + open_elements.append(name) + for name, value in token["data"]: + if not isinstance(name, str): + raise LintError("Attribute name is not a string: %(name)r" % {"name": name}) + if not name: + raise LintError("Empty attribute name") + if not isinstance(value, str): + raise LintError("Attribute value is not a string: %(value)r" % {"value": value}) + if name in cdataElements: + contentModelFlag = "CDATA" + elif name in rcdataElements: + contentModelFlag = "RCDATA" + elif name == "plaintext": + contentModelFlag = "PLAINTEXT" + + elif type == "EndTag": + name = token["name"] + if not isinstance(name, str): + raise LintError("Tag name is not a string: %(tag)r" % {"tag": name}) + if not name: + raise LintError("Empty tag name") + if name in voidElements: + raise LintError("Void element reported as EndTag token: %(tag)s" % {"tag": name}) + start_name = open_elements.pop() + if start_name != name: + raise LintError("EndTag (%(end)s) does not match StartTag (%(start)s)" % {"end": name, "start": start_name}) + contentModelFlag = "PCDATA" + + elif type == "Comment": + if contentModelFlag != "PCDATA": + raise LintError("Comment not in PCDATA content model flag") + + elif type in ("Characters", "SpaceCharacters"): + data = token["data"] + if not isinstance(data, str): + raise LintError("Attribute name is not a string: %(name)r" % {"name": data}) + if not data: + raise LintError("%(type)s token with empty data" % {"type": type}) + if type == "SpaceCharacters": + data = data.strip(spaceCharacters) + if data: + raise LintError("Non-space character(s) found in SpaceCharacters token: %(token)r" % {"token": data}) + + elif type == "Doctype": + name = token["name"] + if contentModelFlag != "PCDATA": + raise LintError("Doctype not in PCDATA content model flag: %(name)s" % {"name": name}) + if not isinstance(name, str): + raise LintError("Tag name is not a string: %(tag)r" % {"tag": name}) + # XXX: what to do with token["data"] ? + + elif type in ("ParseError", "SerializeError"): + pass + + else: + raise LintError("Unknown token type: %(type)s" % {"type": type}) + + yield token diff --git a/catapult/third_party/html5lib-python/html5lib/filters/optionaltags.py b/catapult/third_party/html5lib-python/html5lib/filters/optionaltags.py new file mode 100644 index 00000000..fefe0b30 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/filters/optionaltags.py @@ -0,0 +1,205 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import _base + + +class Filter(_base.Filter): + def slider(self): + previous1 = previous2 = None + for token in self.source: + if previous1 is not None: + yield previous2, previous1, token + previous2 = previous1 + previous1 = token + yield previous2, previous1, None + + def __iter__(self): + for previous, token, next in self.slider(): + type = token["type"] + if type == "StartTag": + if (token["data"] or + not self.is_optional_start(token["name"], previous, next)): + yield token + elif type == "EndTag": + if not self.is_optional_end(token["name"], next): + yield token + else: + yield token + + def is_optional_start(self, tagname, previous, next): + type = next and next["type"] or None + if tagname in 'html': + # An html element's start tag may be omitted if the first thing + # inside the html element is not a space character or a comment. + return type not in ("Comment", "SpaceCharacters") + elif tagname == 'head': + # A head element's start tag may be omitted if the first thing + # inside the head element is an element. + # XXX: we also omit the start tag if the head element is empty + if type in ("StartTag", "EmptyTag"): + return True + elif type == "EndTag": + return next["name"] == "head" + elif tagname == 'body': + # A body element's start tag may be omitted if the first thing + # inside the body element is not a space character or a comment, + # except if the first thing inside the body element is a script + # or style element and the node immediately preceding the body + # element is a head element whose end tag has been omitted. + if type in ("Comment", "SpaceCharacters"): + return False + elif type == "StartTag": + # XXX: we do not look at the preceding event, so we never omit + # the body element's start tag if it's followed by a script or + # a style element. + return next["name"] not in ('script', 'style') + else: + return True + elif tagname == 'colgroup': + # A colgroup element's start tag may be omitted if the first thing + # inside the colgroup element is a col element, and if the element + # is not immediately preceeded by another colgroup element whose + # end tag has been omitted. + if type in ("StartTag", "EmptyTag"): + # XXX: we do not look at the preceding event, so instead we never + # omit the colgroup element's end tag when it is immediately + # followed by another colgroup element. See is_optional_end. + return next["name"] == "col" + else: + return False + elif tagname == 'tbody': + # A tbody element's start tag may be omitted if the first thing + # inside the tbody element is a tr element, and if the element is + # not immediately preceeded by a tbody, thead, or tfoot element + # whose end tag has been omitted. + if type == "StartTag": + # omit the thead and tfoot elements' end tag when they are + # immediately followed by a tbody element. See is_optional_end. + if previous and previous['type'] == 'EndTag' and \ + previous['name'] in ('tbody', 'thead', 'tfoot'): + return False + return next["name"] == 'tr' + else: + return False + return False + + def is_optional_end(self, tagname, next): + type = next and next["type"] or None + if tagname in ('html', 'head', 'body'): + # An html element's end tag may be omitted if the html element + # is not immediately followed by a space character or a comment. + return type not in ("Comment", "SpaceCharacters") + elif tagname in ('li', 'optgroup', 'tr'): + # A li element's end tag may be omitted if the li element is + # immediately followed by another li element or if there is + # no more content in the parent element. + # An optgroup element's end tag may be omitted if the optgroup + # element is immediately followed by another optgroup element, + # or if there is no more content in the parent element. + # A tr element's end tag may be omitted if the tr element is + # immediately followed by another tr element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] == tagname + else: + return type == "EndTag" or type is None + elif tagname in ('dt', 'dd'): + # A dt element's end tag may be omitted if the dt element is + # immediately followed by another dt element or a dd element. + # A dd element's end tag may be omitted if the dd element is + # immediately followed by another dd element or a dt element, + # or if there is no more content in the parent element. + if type == "StartTag": + return next["name"] in ('dt', 'dd') + elif tagname == 'dd': + return type == "EndTag" or type is None + else: + return False + elif tagname == 'p': + # A p element's end tag may be omitted if the p element is + # immediately followed by an address, article, aside, + # blockquote, datagrid, dialog, dir, div, dl, fieldset, + # footer, form, h1, h2, h3, h4, h5, h6, header, hr, menu, + # nav, ol, p, pre, section, table, or ul, element, or if + # there is no more content in the parent element. + if type in ("StartTag", "EmptyTag"): + return next["name"] in ('address', 'article', 'aside', + 'blockquote', 'datagrid', 'dialog', + 'dir', 'div', 'dl', 'fieldset', 'footer', + 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'header', 'hr', 'menu', 'nav', 'ol', + 'p', 'pre', 'section', 'table', 'ul') + else: + return type == "EndTag" or type is None + elif tagname == 'option': + # An option element's end tag may be omitted if the option + # element is immediately followed by another option element, + # or if it is immediately followed by an <code>optgroup</code> + # element, or if there is no more content in the parent + # element. + if type == "StartTag": + return next["name"] in ('option', 'optgroup') + else: + return type == "EndTag" or type is None + elif tagname in ('rt', 'rp'): + # An rt element's end tag may be omitted if the rt element is + # immediately followed by an rt or rp element, or if there is + # no more content in the parent element. + # An rp element's end tag may be omitted if the rp element is + # immediately followed by an rt or rp element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] in ('rt', 'rp') + else: + return type == "EndTag" or type is None + elif tagname == 'colgroup': + # A colgroup element's end tag may be omitted if the colgroup + # element is not immediately followed by a space character or + # a comment. + if type in ("Comment", "SpaceCharacters"): + return False + elif type == "StartTag": + # XXX: we also look for an immediately following colgroup + # element. See is_optional_start. + return next["name"] != 'colgroup' + else: + return True + elif tagname in ('thead', 'tbody'): + # A thead element's end tag may be omitted if the thead element + # is immediately followed by a tbody or tfoot element. + # A tbody element's end tag may be omitted if the tbody element + # is immediately followed by a tbody or tfoot element, or if + # there is no more content in the parent element. + # A tfoot element's end tag may be omitted if the tfoot element + # is immediately followed by a tbody element, or if there is no + # more content in the parent element. + # XXX: we never omit the end tag when the following element is + # a tbody. See is_optional_start. + if type == "StartTag": + return next["name"] in ['tbody', 'tfoot'] + elif tagname == 'tbody': + return type == "EndTag" or type is None + else: + return False + elif tagname == 'tfoot': + # A tfoot element's end tag may be omitted if the tfoot element + # is immediately followed by a tbody element, or if there is no + # more content in the parent element. + # XXX: we never omit the end tag when the following element is + # a tbody. See is_optional_start. + if type == "StartTag": + return next["name"] == 'tbody' + else: + return type == "EndTag" or type is None + elif tagname in ('td', 'th'): + # A td element's end tag may be omitted if the td element is + # immediately followed by a td or th element, or if there is + # no more content in the parent element. + # A th element's end tag may be omitted if the th element is + # immediately followed by a td or th element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] in ('td', 'th') + else: + return type == "EndTag" or type is None + return False diff --git a/catapult/third_party/html5lib-python/html5lib/filters/sanitizer.py b/catapult/third_party/html5lib-python/html5lib/filters/sanitizer.py new file mode 100644 index 00000000..b206b54e --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/filters/sanitizer.py @@ -0,0 +1,12 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import _base +from ..sanitizer import HTMLSanitizerMixin + + +class Filter(_base.Filter, HTMLSanitizerMixin): + def __iter__(self): + for token in _base.Filter.__iter__(self): + token = self.sanitize_token(token) + if token: + yield token diff --git a/catapult/third_party/html5lib-python/html5lib/filters/whitespace.py b/catapult/third_party/html5lib-python/html5lib/filters/whitespace.py new file mode 100644 index 00000000..dfc60eeb --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/filters/whitespace.py @@ -0,0 +1,38 @@ +from __future__ import absolute_import, division, unicode_literals + +import re + +from . import _base +from ..constants import rcdataElements, spaceCharacters +spaceCharacters = "".join(spaceCharacters) + +SPACES_REGEX = re.compile("[%s]+" % spaceCharacters) + + +class Filter(_base.Filter): + + spacePreserveElements = frozenset(["pre", "textarea"] + list(rcdataElements)) + + def __iter__(self): + preserve = 0 + for token in _base.Filter.__iter__(self): + type = token["type"] + if type == "StartTag" \ + and (preserve or token["name"] in self.spacePreserveElements): + preserve += 1 + + elif type == "EndTag" and preserve: + preserve -= 1 + + elif not preserve and type == "SpaceCharacters" and token["data"]: + # Test on token["data"] above to not introduce spaces where there were not + token["data"] = " " + + elif not preserve and type == "Characters": + token["data"] = collapse_spaces(token["data"]) + + yield token + + +def collapse_spaces(text): + return SPACES_REGEX.sub(' ', text) diff --git a/catapult/third_party/html5lib-python/html5lib/html5parser.py b/catapult/third_party/html5lib-python/html5lib/html5parser.py new file mode 100644 index 00000000..12aa6a35 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/html5parser.py @@ -0,0 +1,2724 @@ +from __future__ import absolute_import, division, unicode_literals +from six import with_metaclass + +import types + +from . import inputstream +from . import tokenizer + +from . import treebuilders +from .treebuilders._base import Marker + +from . import utils +from . import constants +from .constants import spaceCharacters, asciiUpper2Lower +from .constants import specialElements +from .constants import headingElements +from .constants import cdataElements, rcdataElements +from .constants import tokenTypes, ReparseException, namespaces +from .constants import htmlIntegrationPointElements, mathmlTextIntegrationPointElements +from .constants import adjustForeignAttributes as adjustForeignAttributesMap +from .constants import E + + +def parse(doc, treebuilder="etree", encoding=None, + namespaceHTMLElements=True): + """Parse a string or file-like object into a tree""" + tb = treebuilders.getTreeBuilder(treebuilder) + p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) + return p.parse(doc, encoding=encoding) + + +def parseFragment(doc, container="div", treebuilder="etree", encoding=None, + namespaceHTMLElements=True): + tb = treebuilders.getTreeBuilder(treebuilder) + p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) + return p.parseFragment(doc, container=container, encoding=encoding) + + +def method_decorator_metaclass(function): + class Decorated(type): + def __new__(meta, classname, bases, classDict): + for attributeName, attribute in classDict.items(): + if isinstance(attribute, types.FunctionType): + attribute = function(attribute) + + classDict[attributeName] = attribute + return type.__new__(meta, classname, bases, classDict) + return Decorated + + +class HTMLParser(object): + """HTML parser. Generates a tree structure from a stream of (possibly + malformed) HTML""" + + def __init__(self, tree=None, tokenizer=tokenizer.HTMLTokenizer, + strict=False, namespaceHTMLElements=True, debug=False): + """ + strict - raise an exception when a parse error is encountered + + tree - a treebuilder class controlling the type of tree that will be + returned. Built in treebuilders can be accessed through + html5lib.treebuilders.getTreeBuilder(treeType) + + tokenizer - a class that provides a stream of tokens to the treebuilder. + This may be replaced for e.g. a sanitizer which converts some tags to + text + """ + + # Raise an exception on the first error encountered + self.strict = strict + + if tree is None: + tree = treebuilders.getTreeBuilder("etree") + self.tree = tree(namespaceHTMLElements) + self.tokenizer_class = tokenizer + self.errors = [] + + self.phases = dict([(name, cls(self, self.tree)) for name, cls in + getPhases(debug).items()]) + + def _parse(self, stream, innerHTML=False, container="div", + encoding=None, parseMeta=True, useChardet=True, **kwargs): + + self.innerHTMLMode = innerHTML + self.container = container + self.tokenizer = self.tokenizer_class(stream, encoding=encoding, + parseMeta=parseMeta, + useChardet=useChardet, + parser=self, **kwargs) + self.reset() + + while True: + try: + self.mainLoop() + break + except ReparseException: + self.reset() + + def reset(self): + self.tree.reset() + self.firstStartTag = False + self.errors = [] + self.log = [] # only used with debug mode + # "quirks" / "limited quirks" / "no quirks" + self.compatMode = "no quirks" + + if self.innerHTMLMode: + self.innerHTML = self.container.lower() + + if self.innerHTML in cdataElements: + self.tokenizer.state = self.tokenizer.rcdataState + elif self.innerHTML in rcdataElements: + self.tokenizer.state = self.tokenizer.rawtextState + elif self.innerHTML == 'plaintext': + self.tokenizer.state = self.tokenizer.plaintextState + else: + # state already is data state + # self.tokenizer.state = self.tokenizer.dataState + pass + self.phase = self.phases["beforeHtml"] + self.phase.insertHtmlElement() + self.resetInsertionMode() + else: + self.innerHTML = False + self.phase = self.phases["initial"] + + self.lastPhase = None + + self.beforeRCDataPhase = None + + self.framesetOK = True + + @property + def documentEncoding(self): + """The name of the character encoding + that was used to decode the input stream, + or :obj:`None` if that is not determined yet. + + """ + if not hasattr(self, 'tokenizer'): + return None + return self.tokenizer.stream.charEncoding[0] + + def isHTMLIntegrationPoint(self, element): + if (element.name == "annotation-xml" and + element.namespace == namespaces["mathml"]): + return ("encoding" in element.attributes and + element.attributes["encoding"].translate( + asciiUpper2Lower) in + ("text/html", "application/xhtml+xml")) + else: + return (element.namespace, element.name) in htmlIntegrationPointElements + + def isMathMLTextIntegrationPoint(self, element): + return (element.namespace, element.name) in mathmlTextIntegrationPointElements + + def mainLoop(self): + CharactersToken = tokenTypes["Characters"] + SpaceCharactersToken = tokenTypes["SpaceCharacters"] + StartTagToken = tokenTypes["StartTag"] + EndTagToken = tokenTypes["EndTag"] + CommentToken = tokenTypes["Comment"] + DoctypeToken = tokenTypes["Doctype"] + ParseErrorToken = tokenTypes["ParseError"] + + for token in self.normalizedTokens(): + new_token = token + while new_token is not None: + currentNode = self.tree.openElements[-1] if self.tree.openElements else None + currentNodeNamespace = currentNode.namespace if currentNode else None + currentNodeName = currentNode.name if currentNode else None + + type = new_token["type"] + + if type == ParseErrorToken: + self.parseError(new_token["data"], new_token.get("datavars", {})) + new_token = None + else: + if (len(self.tree.openElements) == 0 or + currentNodeNamespace == self.tree.defaultNamespace or + (self.isMathMLTextIntegrationPoint(currentNode) and + ((type == StartTagToken and + token["name"] not in frozenset(["mglyph", "malignmark"])) or + type in (CharactersToken, SpaceCharactersToken))) or + (currentNodeNamespace == namespaces["mathml"] and + currentNodeName == "annotation-xml" and + token["name"] == "svg") or + (self.isHTMLIntegrationPoint(currentNode) and + type in (StartTagToken, CharactersToken, SpaceCharactersToken))): + phase = self.phase + else: + phase = self.phases["inForeignContent"] + + if type == CharactersToken: + new_token = phase.processCharacters(new_token) + elif type == SpaceCharactersToken: + new_token = phase.processSpaceCharacters(new_token) + elif type == StartTagToken: + new_token = phase.processStartTag(new_token) + elif type == EndTagToken: + new_token = phase.processEndTag(new_token) + elif type == CommentToken: + new_token = phase.processComment(new_token) + elif type == DoctypeToken: + new_token = phase.processDoctype(new_token) + + if (type == StartTagToken and token["selfClosing"] + and not token["selfClosingAcknowledged"]): + self.parseError("non-void-element-with-trailing-solidus", + {"name": token["name"]}) + + # When the loop finishes it's EOF + reprocess = True + phases = [] + while reprocess: + phases.append(self.phase) + reprocess = self.phase.processEOF() + if reprocess: + assert self.phase not in phases + + def normalizedTokens(self): + for token in self.tokenizer: + yield self.normalizeToken(token) + + def parse(self, stream, encoding=None, parseMeta=True, useChardet=True): + """Parse a HTML document into a well-formed tree + + stream - a filelike object or string containing the HTML to be parsed + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element) + """ + self._parse(stream, innerHTML=False, encoding=encoding, + parseMeta=parseMeta, useChardet=useChardet) + return self.tree.getDocument() + + def parseFragment(self, stream, container="div", encoding=None, + parseMeta=False, useChardet=True): + """Parse a HTML fragment into a well-formed tree fragment + + container - name of the element we're setting the innerHTML property + if set to None, default to 'div' + + stream - a filelike object or string containing the HTML to be parsed + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element) + """ + self._parse(stream, True, container=container, encoding=encoding) + return self.tree.getFragment() + + def parseError(self, errorcode="XXX-undefined-error", datavars={}): + # XXX The idea is to make errorcode mandatory. + self.errors.append((self.tokenizer.stream.position(), errorcode, datavars)) + if self.strict: + raise ParseError(E[errorcode] % datavars) + + def normalizeToken(self, token): + """ HTML5 specific normalizations to the token stream """ + + if token["type"] == tokenTypes["StartTag"]: + token["data"] = dict(token["data"][::-1]) + + return token + + def adjustMathMLAttributes(self, token): + replacements = {"definitionurl": "definitionURL"} + for k, v in replacements.items(): + if k in token["data"]: + token["data"][v] = token["data"][k] + del token["data"][k] + + def adjustSVGAttributes(self, token): + replacements = { + "attributename": "attributeName", + "attributetype": "attributeType", + "basefrequency": "baseFrequency", + "baseprofile": "baseProfile", + "calcmode": "calcMode", + "clippathunits": "clipPathUnits", + "contentscripttype": "contentScriptType", + "contentstyletype": "contentStyleType", + "diffuseconstant": "diffuseConstant", + "edgemode": "edgeMode", + "externalresourcesrequired": "externalResourcesRequired", + "filterres": "filterRes", + "filterunits": "filterUnits", + "glyphref": "glyphRef", + "gradienttransform": "gradientTransform", + "gradientunits": "gradientUnits", + "kernelmatrix": "kernelMatrix", + "kernelunitlength": "kernelUnitLength", + "keypoints": "keyPoints", + "keysplines": "keySplines", + "keytimes": "keyTimes", + "lengthadjust": "lengthAdjust", + "limitingconeangle": "limitingConeAngle", + "markerheight": "markerHeight", + "markerunits": "markerUnits", + "markerwidth": "markerWidth", + "maskcontentunits": "maskContentUnits", + "maskunits": "maskUnits", + "numoctaves": "numOctaves", + "pathlength": "pathLength", + "patterncontentunits": "patternContentUnits", + "patterntransform": "patternTransform", + "patternunits": "patternUnits", + "pointsatx": "pointsAtX", + "pointsaty": "pointsAtY", + "pointsatz": "pointsAtZ", + "preservealpha": "preserveAlpha", + "preserveaspectratio": "preserveAspectRatio", + "primitiveunits": "primitiveUnits", + "refx": "refX", + "refy": "refY", + "repeatcount": "repeatCount", + "repeatdur": "repeatDur", + "requiredextensions": "requiredExtensions", + "requiredfeatures": "requiredFeatures", + "specularconstant": "specularConstant", + "specularexponent": "specularExponent", + "spreadmethod": "spreadMethod", + "startoffset": "startOffset", + "stddeviation": "stdDeviation", + "stitchtiles": "stitchTiles", + "surfacescale": "surfaceScale", + "systemlanguage": "systemLanguage", + "tablevalues": "tableValues", + "targetx": "targetX", + "targety": "targetY", + "textlength": "textLength", + "viewbox": "viewBox", + "viewtarget": "viewTarget", + "xchannelselector": "xChannelSelector", + "ychannelselector": "yChannelSelector", + "zoomandpan": "zoomAndPan" + } + for originalName in list(token["data"].keys()): + if originalName in replacements: + svgName = replacements[originalName] + token["data"][svgName] = token["data"][originalName] + del token["data"][originalName] + + def adjustForeignAttributes(self, token): + replacements = adjustForeignAttributesMap + + for originalName in token["data"].keys(): + if originalName in replacements: + foreignName = replacements[originalName] + token["data"][foreignName] = token["data"][originalName] + del token["data"][originalName] + + def reparseTokenNormal(self, token): + self.parser.phase() + + def resetInsertionMode(self): + # The name of this method is mostly historical. (It's also used in the + # specification.) + last = False + newModes = { + "select": "inSelect", + "td": "inCell", + "th": "inCell", + "tr": "inRow", + "tbody": "inTableBody", + "thead": "inTableBody", + "tfoot": "inTableBody", + "caption": "inCaption", + "colgroup": "inColumnGroup", + "table": "inTable", + "head": "inBody", + "body": "inBody", + "frameset": "inFrameset", + "html": "beforeHead" + } + for node in self.tree.openElements[::-1]: + nodeName = node.name + new_phase = None + if node == self.tree.openElements[0]: + assert self.innerHTML + last = True + nodeName = self.innerHTML + # Check for conditions that should only happen in the innerHTML + # case + if nodeName in ("select", "colgroup", "head", "html"): + assert self.innerHTML + + if not last and node.namespace != self.tree.defaultNamespace: + continue + + if nodeName in newModes: + new_phase = self.phases[newModes[nodeName]] + break + elif last: + new_phase = self.phases["inBody"] + break + + self.phase = new_phase + + def parseRCDataRawtext(self, token, contentType): + """Generic RCDATA/RAWTEXT Parsing algorithm + contentType - RCDATA or RAWTEXT + """ + assert contentType in ("RAWTEXT", "RCDATA") + + self.tree.insertElement(token) + + if contentType == "RAWTEXT": + self.tokenizer.state = self.tokenizer.rawtextState + else: + self.tokenizer.state = self.tokenizer.rcdataState + + self.originalPhase = self.phase + + self.phase = self.phases["text"] + + +def getPhases(debug): + def log(function): + """Logger that records which phase processes each token""" + type_names = dict((value, key) for key, value in + constants.tokenTypes.items()) + + def wrapped(self, *args, **kwargs): + if function.__name__.startswith("process") and len(args) > 0: + token = args[0] + try: + info = {"type": type_names[token['type']]} + except: + raise + if token['type'] in constants.tagTokenTypes: + info["name"] = token['name'] + + self.parser.log.append((self.parser.tokenizer.state.__name__, + self.parser.phase.__class__.__name__, + self.__class__.__name__, + function.__name__, + info)) + return function(self, *args, **kwargs) + else: + return function(self, *args, **kwargs) + return wrapped + + def getMetaclass(use_metaclass, metaclass_func): + if use_metaclass: + return method_decorator_metaclass(metaclass_func) + else: + return type + + class Phase(with_metaclass(getMetaclass(debug, log))): + """Base class for helper object that implements each phase of processing + """ + + def __init__(self, parser, tree): + self.parser = parser + self.tree = tree + + def processEOF(self): + raise NotImplementedError + + def processComment(self, token): + # For most phases the following is correct. Where it's not it will be + # overridden. + self.tree.insertComment(token, self.tree.openElements[-1]) + + def processDoctype(self, token): + self.parser.parseError("unexpected-doctype") + + def processCharacters(self, token): + self.tree.insertText(token["data"]) + + def processSpaceCharacters(self, token): + self.tree.insertText(token["data"]) + + def processStartTag(self, token): + return self.startTagHandler[token["name"]](token) + + def startTagHtml(self, token): + if not self.parser.firstStartTag and token["name"] == "html": + self.parser.parseError("non-html-root") + # XXX Need a check here to see if the first start tag token emitted is + # this token... If it's not, invoke self.parser.parseError(). + for attr, value in token["data"].items(): + if attr not in self.tree.openElements[0].attributes: + self.tree.openElements[0].attributes[attr] = value + self.parser.firstStartTag = False + + def processEndTag(self, token): + return self.endTagHandler[token["name"]](token) + + class InitialPhase(Phase): + def processSpaceCharacters(self, token): + pass + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + correct = token["correct"] + + if (name != "html" or publicId is not None or + systemId is not None and systemId != "about:legacy-compat"): + self.parser.parseError("unknown-doctype") + + if publicId is None: + publicId = "" + + self.tree.insertDoctype(token) + + if publicId != "": + publicId = publicId.translate(asciiUpper2Lower) + + if (not correct or token["name"] != "html" + or publicId.startswith( + ("+//silmaril//dtd html pro v0r11 19970101//", + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", + "-//as//dtd html 3.0 aswedit + extensions//", + "-//ietf//dtd html 2.0 level 1//", + "-//ietf//dtd html 2.0 level 2//", + "-//ietf//dtd html 2.0 strict level 1//", + "-//ietf//dtd html 2.0 strict level 2//", + "-//ietf//dtd html 2.0 strict//", + "-//ietf//dtd html 2.0//", + "-//ietf//dtd html 2.1e//", + "-//ietf//dtd html 3.0//", + "-//ietf//dtd html 3.2 final//", + "-//ietf//dtd html 3.2//", + "-//ietf//dtd html 3//", + "-//ietf//dtd html level 0//", + "-//ietf//dtd html level 1//", + "-//ietf//dtd html level 2//", + "-//ietf//dtd html level 3//", + "-//ietf//dtd html strict level 0//", + "-//ietf//dtd html strict level 1//", + "-//ietf//dtd html strict level 2//", + "-//ietf//dtd html strict level 3//", + "-//ietf//dtd html strict//", + "-//ietf//dtd html//", + "-//metrius//dtd metrius presentational//", + "-//microsoft//dtd internet explorer 2.0 html strict//", + "-//microsoft//dtd internet explorer 2.0 html//", + "-//microsoft//dtd internet explorer 2.0 tables//", + "-//microsoft//dtd internet explorer 3.0 html strict//", + "-//microsoft//dtd internet explorer 3.0 html//", + "-//microsoft//dtd internet explorer 3.0 tables//", + "-//netscape comm. corp.//dtd html//", + "-//netscape comm. corp.//dtd strict html//", + "-//o'reilly and associates//dtd html 2.0//", + "-//o'reilly and associates//dtd html extended 1.0//", + "-//o'reilly and associates//dtd html extended relaxed 1.0//", + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", + "-//spyglass//dtd html 2.0 extended//", + "-//sq//dtd html 2.0 hotmetal + extensions//", + "-//sun microsystems corp.//dtd hotjava html//", + "-//sun microsystems corp.//dtd hotjava strict html//", + "-//w3c//dtd html 3 1995-03-24//", + "-//w3c//dtd html 3.2 draft//", + "-//w3c//dtd html 3.2 final//", + "-//w3c//dtd html 3.2//", + "-//w3c//dtd html 3.2s draft//", + "-//w3c//dtd html 4.0 frameset//", + "-//w3c//dtd html 4.0 transitional//", + "-//w3c//dtd html experimental 19960712//", + "-//w3c//dtd html experimental 970421//", + "-//w3c//dtd w3 html//", + "-//w3o//dtd w3 html 3.0//", + "-//webtechs//dtd mozilla html 2.0//", + "-//webtechs//dtd mozilla html//")) + or publicId in + ("-//w3o//dtd w3 html strict 3.0//en//", + "-/w3c/dtd html 4.0 transitional/en", + "html") + or publicId.startswith( + ("-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//")) and + systemId is None + or systemId and systemId.lower() == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"): + self.parser.compatMode = "quirks" + elif (publicId.startswith( + ("-//w3c//dtd xhtml 1.0 frameset//", + "-//w3c//dtd xhtml 1.0 transitional//")) + or publicId.startswith( + ("-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//")) and + systemId is not None): + self.parser.compatMode = "limited quirks" + + self.parser.phase = self.parser.phases["beforeHtml"] + + def anythingElse(self): + self.parser.compatMode = "quirks" + self.parser.phase = self.parser.phases["beforeHtml"] + + def processCharacters(self, token): + self.parser.parseError("expected-doctype-but-got-chars") + self.anythingElse() + return token + + def processStartTag(self, token): + self.parser.parseError("expected-doctype-but-got-start-tag", + {"name": token["name"]}) + self.anythingElse() + return token + + def processEndTag(self, token): + self.parser.parseError("expected-doctype-but-got-end-tag", + {"name": token["name"]}) + self.anythingElse() + return token + + def processEOF(self): + self.parser.parseError("expected-doctype-but-got-eof") + self.anythingElse() + return True + + class BeforeHtmlPhase(Phase): + # helper methods + def insertHtmlElement(self): + self.tree.insertRoot(impliedTagToken("html", "StartTag")) + self.parser.phase = self.parser.phases["beforeHead"] + + # other + def processEOF(self): + self.insertHtmlElement() + return True + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processSpaceCharacters(self, token): + pass + + def processCharacters(self, token): + self.insertHtmlElement() + return token + + def processStartTag(self, token): + if token["name"] == "html": + self.parser.firstStartTag = True + self.insertHtmlElement() + return token + + def processEndTag(self, token): + if token["name"] not in ("head", "body", "html", "br"): + self.parser.parseError("unexpected-end-tag-before-html", + {"name": token["name"]}) + else: + self.insertHtmlElement() + return token + + class BeforeHeadPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("head", self.startTagHead) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + (("head", "body", "html", "br"), self.endTagImplyHead) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.startTagHead(impliedTagToken("head", "StartTag")) + return True + + def processSpaceCharacters(self, token): + pass + + def processCharacters(self, token): + self.startTagHead(impliedTagToken("head", "StartTag")) + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagHead(self, token): + self.tree.insertElement(token) + self.tree.headPointer = self.tree.openElements[-1] + self.parser.phase = self.parser.phases["inHead"] + + def startTagOther(self, token): + self.startTagHead(impliedTagToken("head", "StartTag")) + return token + + def endTagImplyHead(self, token): + self.startTagHead(impliedTagToken("head", "StartTag")) + return token + + def endTagOther(self, token): + self.parser.parseError("end-tag-after-implied-root", + {"name": token["name"]}) + + class InHeadPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("title", self.startTagTitle), + (("noscript", "noframes", "style"), self.startTagNoScriptNoFramesStyle), + ("script", self.startTagScript), + (("base", "basefont", "bgsound", "command", "link"), + self.startTagBaseLinkCommand), + ("meta", self.startTagMeta), + ("head", self.startTagHead) + ]) + self.startTagHandler.default = self.startTagOther + + self. endTagHandler = utils.MethodDispatcher([ + ("head", self.endTagHead), + (("br", "html", "body"), self.endTagHtmlBodyBr) + ]) + self.endTagHandler.default = self.endTagOther + + # the real thing + def processEOF(self): + self.anythingElse() + return True + + def processCharacters(self, token): + self.anythingElse() + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagHead(self, token): + self.parser.parseError("two-heads-are-not-better-than-one") + + def startTagBaseLinkCommand(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagMeta(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + attributes = token["data"] + if self.parser.tokenizer.stream.charEncoding[1] == "tentative": + if "charset" in attributes: + self.parser.tokenizer.stream.changeEncoding(attributes["charset"]) + elif ("content" in attributes and + "http-equiv" in attributes and + attributes["http-equiv"].lower() == "content-type"): + # Encoding it as UTF-8 here is a hack, as really we should pass + # the abstract Unicode string, and just use the + # ContentAttrParser on that, but using UTF-8 allows all chars + # to be encoded and as a ASCII-superset works. + data = inputstream.EncodingBytes(attributes["content"].encode("utf-8")) + parser = inputstream.ContentAttrParser(data) + codec = parser.parse() + self.parser.tokenizer.stream.changeEncoding(codec) + + def startTagTitle(self, token): + self.parser.parseRCDataRawtext(token, "RCDATA") + + def startTagNoScriptNoFramesStyle(self, token): + # Need to decide whether to implement the scripting-disabled case + self.parser.parseRCDataRawtext(token, "RAWTEXT") + + def startTagScript(self, token): + self.tree.insertElement(token) + self.parser.tokenizer.state = self.parser.tokenizer.scriptDataState + self.parser.originalPhase = self.parser.phase + self.parser.phase = self.parser.phases["text"] + + def startTagOther(self, token): + self.anythingElse() + return token + + def endTagHead(self, token): + node = self.parser.tree.openElements.pop() + assert node.name == "head", "Expected head got %s" % node.name + self.parser.phase = self.parser.phases["afterHead"] + + def endTagHtmlBodyBr(self, token): + self.anythingElse() + return token + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def anythingElse(self): + self.endTagHead(impliedTagToken("head")) + + # XXX If we implement a parser for which scripting is disabled we need to + # implement this phase. + # + # class InHeadNoScriptPhase(Phase): + class AfterHeadPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("body", self.startTagBody), + ("frameset", self.startTagFrameset), + (("base", "basefont", "bgsound", "link", "meta", "noframes", "script", + "style", "title"), + self.startTagFromHead), + ("head", self.startTagHead) + ]) + self.startTagHandler.default = self.startTagOther + self.endTagHandler = utils.MethodDispatcher([(("body", "html", "br"), + self.endTagHtmlBodyBr)]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.anythingElse() + return True + + def processCharacters(self, token): + self.anythingElse() + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagBody(self, token): + self.parser.framesetOK = False + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inBody"] + + def startTagFrameset(self, token): + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inFrameset"] + + def startTagFromHead(self, token): + self.parser.parseError("unexpected-start-tag-out-of-my-head", + {"name": token["name"]}) + self.tree.openElements.append(self.tree.headPointer) + self.parser.phases["inHead"].processStartTag(token) + for node in self.tree.openElements[::-1]: + if node.name == "head": + self.tree.openElements.remove(node) + break + + def startTagHead(self, token): + self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) + + def startTagOther(self, token): + self.anythingElse() + return token + + def endTagHtmlBodyBr(self, token): + self.anythingElse() + return token + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def anythingElse(self): + self.tree.insertElement(impliedTagToken("body", "StartTag")) + self.parser.phase = self.parser.phases["inBody"] + self.parser.framesetOK = True + + class InBodyPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#parsing-main-inbody + # the really-really-really-very crazy mode + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + # Keep a ref to this for special handling of whitespace in <pre> + self.processSpaceCharactersNonPre = self.processSpaceCharacters + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("base", "basefont", "bgsound", "command", "link", "meta", + "script", "style", "title"), + self.startTagProcessInHead), + ("body", self.startTagBody), + ("frameset", self.startTagFrameset), + (("address", "article", "aside", "blockquote", "center", "details", + "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", + "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p", + "section", "summary", "ul"), + self.startTagCloseP), + (headingElements, self.startTagHeading), + (("pre", "listing"), self.startTagPreListing), + ("form", self.startTagForm), + (("li", "dd", "dt"), self.startTagListItem), + ("plaintext", self.startTagPlaintext), + ("a", self.startTagA), + (("b", "big", "code", "em", "font", "i", "s", "small", "strike", + "strong", "tt", "u"), self.startTagFormatting), + ("nobr", self.startTagNobr), + ("button", self.startTagButton), + (("applet", "marquee", "object"), self.startTagAppletMarqueeObject), + ("xmp", self.startTagXmp), + ("table", self.startTagTable), + (("area", "br", "embed", "img", "keygen", "wbr"), + self.startTagVoidFormatting), + (("param", "source", "track"), self.startTagParamSource), + ("input", self.startTagInput), + ("hr", self.startTagHr), + ("image", self.startTagImage), + ("isindex", self.startTagIsIndex), + ("textarea", self.startTagTextarea), + ("iframe", self.startTagIFrame), + (("noembed", "noframes", "noscript"), self.startTagRawtext), + ("select", self.startTagSelect), + (("rp", "rt"), self.startTagRpRt), + (("option", "optgroup"), self.startTagOpt), + (("math"), self.startTagMath), + (("svg"), self.startTagSvg), + (("caption", "col", "colgroup", "frame", "head", + "tbody", "td", "tfoot", "th", "thead", + "tr"), self.startTagMisplaced) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + ("body", self.endTagBody), + ("html", self.endTagHtml), + (("address", "article", "aside", "blockquote", "button", "center", + "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", + "footer", "header", "hgroup", "listing", "main", "menu", "nav", "ol", "pre", + "section", "summary", "ul"), self.endTagBlock), + ("form", self.endTagForm), + ("p", self.endTagP), + (("dd", "dt", "li"), self.endTagListItem), + (headingElements, self.endTagHeading), + (("a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", + "strike", "strong", "tt", "u"), self.endTagFormatting), + (("applet", "marquee", "object"), self.endTagAppletMarqueeObject), + ("br", self.endTagBr), + ]) + self.endTagHandler.default = self.endTagOther + + def isMatchingFormattingElement(self, node1, node2): + if node1.name != node2.name or node1.namespace != node2.namespace: + return False + elif len(node1.attributes) != len(node2.attributes): + return False + else: + attributes1 = sorted(node1.attributes.items()) + attributes2 = sorted(node2.attributes.items()) + for attr1, attr2 in zip(attributes1, attributes2): + if attr1 != attr2: + return False + return True + + # helper + def addFormattingElement(self, token): + self.tree.insertElement(token) + element = self.tree.openElements[-1] + + matchingElements = [] + for node in self.tree.activeFormattingElements[::-1]: + if node is Marker: + break + elif self.isMatchingFormattingElement(node, element): + matchingElements.append(node) + + assert len(matchingElements) <= 3 + if len(matchingElements) == 3: + self.tree.activeFormattingElements.remove(matchingElements[-1]) + self.tree.activeFormattingElements.append(element) + + # the real deal + def processEOF(self): + allowed_elements = frozenset(("dd", "dt", "li", "p", "tbody", "td", + "tfoot", "th", "thead", "tr", "body", + "html")) + for node in self.tree.openElements[::-1]: + if node.name not in allowed_elements: + self.parser.parseError("expected-closing-tag-but-got-eof") + break + # Stop parsing + + def processSpaceCharactersDropNewline(self, token): + # Sometimes (start of <pre>, <listing>, and <textarea> blocks) we + # want to drop leading newlines + data = token["data"] + self.processSpaceCharacters = self.processSpaceCharactersNonPre + if (data.startswith("\n") and + self.tree.openElements[-1].name in ("pre", "listing", "textarea") + and not self.tree.openElements[-1].hasContent()): + data = data[1:] + if data: + self.tree.reconstructActiveFormattingElements() + self.tree.insertText(data) + + def processCharacters(self, token): + if token["data"] == "\u0000": + # The tokenizer should always emit null on its own + return + self.tree.reconstructActiveFormattingElements() + self.tree.insertText(token["data"]) + # This must be bad for performance + if (self.parser.framesetOK and + any([char not in spaceCharacters + for char in token["data"]])): + self.parser.framesetOK = False + + def processSpaceCharacters(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertText(token["data"]) + + def startTagProcessInHead(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagBody(self, token): + self.parser.parseError("unexpected-start-tag", {"name": "body"}) + if (len(self.tree.openElements) == 1 + or self.tree.openElements[1].name != "body"): + assert self.parser.innerHTML + else: + self.parser.framesetOK = False + for attr, value in token["data"].items(): + if attr not in self.tree.openElements[1].attributes: + self.tree.openElements[1].attributes[attr] = value + + def startTagFrameset(self, token): + self.parser.parseError("unexpected-start-tag", {"name": "frameset"}) + if (len(self.tree.openElements) == 1 or self.tree.openElements[1].name != "body"): + assert self.parser.innerHTML + elif not self.parser.framesetOK: + pass + else: + if self.tree.openElements[1].parent: + self.tree.openElements[1].parent.removeChild(self.tree.openElements[1]) + while self.tree.openElements[-1].name != "html": + self.tree.openElements.pop() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inFrameset"] + + def startTagCloseP(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + + def startTagPreListing(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.parser.framesetOK = False + self.processSpaceCharacters = self.processSpaceCharactersDropNewline + + def startTagForm(self, token): + if self.tree.formPointer: + self.parser.parseError("unexpected-start-tag", {"name": "form"}) + else: + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.tree.formPointer = self.tree.openElements[-1] + + def startTagListItem(self, token): + self.parser.framesetOK = False + + stopNamesMap = {"li": ["li"], + "dt": ["dt", "dd"], + "dd": ["dt", "dd"]} + stopNames = stopNamesMap[token["name"]] + for node in reversed(self.tree.openElements): + if node.name in stopNames: + self.parser.phase.processEndTag( + impliedTagToken(node.name, "EndTag")) + break + if (node.nameTuple in specialElements and + node.name not in ("address", "div", "p")): + break + + if self.tree.elementInScope("p", variant="button"): + self.parser.phase.processEndTag( + impliedTagToken("p", "EndTag")) + + self.tree.insertElement(token) + + def startTagPlaintext(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.parser.tokenizer.state = self.parser.tokenizer.plaintextState + + def startTagHeading(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + if self.tree.openElements[-1].name in headingElements: + self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) + self.tree.openElements.pop() + self.tree.insertElement(token) + + def startTagA(self, token): + afeAElement = self.tree.elementInActiveFormattingElements("a") + if afeAElement: + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "a", "endName": "a"}) + self.endTagFormatting(impliedTagToken("a")) + if afeAElement in self.tree.openElements: + self.tree.openElements.remove(afeAElement) + if afeAElement in self.tree.activeFormattingElements: + self.tree.activeFormattingElements.remove(afeAElement) + self.tree.reconstructActiveFormattingElements() + self.addFormattingElement(token) + + def startTagFormatting(self, token): + self.tree.reconstructActiveFormattingElements() + self.addFormattingElement(token) + + def startTagNobr(self, token): + self.tree.reconstructActiveFormattingElements() + if self.tree.elementInScope("nobr"): + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "nobr", "endName": "nobr"}) + self.processEndTag(impliedTagToken("nobr")) + # XXX Need tests that trigger the following + self.tree.reconstructActiveFormattingElements() + self.addFormattingElement(token) + + def startTagButton(self, token): + if self.tree.elementInScope("button"): + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "button", "endName": "button"}) + self.processEndTag(impliedTagToken("button")) + return token + else: + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.parser.framesetOK = False + + def startTagAppletMarqueeObject(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.tree.activeFormattingElements.append(Marker) + self.parser.framesetOK = False + + def startTagXmp(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.reconstructActiveFormattingElements() + self.parser.framesetOK = False + self.parser.parseRCDataRawtext(token, "RAWTEXT") + + def startTagTable(self, token): + if self.parser.compatMode != "quirks": + if self.tree.elementInScope("p", variant="button"): + self.processEndTag(impliedTagToken("p")) + self.tree.insertElement(token) + self.parser.framesetOK = False + self.parser.phase = self.parser.phases["inTable"] + + def startTagVoidFormatting(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + self.parser.framesetOK = False + + def startTagInput(self, token): + framesetOK = self.parser.framesetOK + self.startTagVoidFormatting(token) + if ("type" in token["data"] and + token["data"]["type"].translate(asciiUpper2Lower) == "hidden"): + # input type=hidden doesn't change framesetOK + self.parser.framesetOK = framesetOK + + def startTagParamSource(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagHr(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + self.parser.framesetOK = False + + def startTagImage(self, token): + # No really... + self.parser.parseError("unexpected-start-tag-treated-as", + {"originalName": "image", "newName": "img"}) + self.processStartTag(impliedTagToken("img", "StartTag", + attributes=token["data"], + selfClosing=token["selfClosing"])) + + def startTagIsIndex(self, token): + self.parser.parseError("deprecated-tag", {"name": "isindex"}) + if self.tree.formPointer: + return + form_attrs = {} + if "action" in token["data"]: + form_attrs["action"] = token["data"]["action"] + self.processStartTag(impliedTagToken("form", "StartTag", + attributes=form_attrs)) + self.processStartTag(impliedTagToken("hr", "StartTag")) + self.processStartTag(impliedTagToken("label", "StartTag")) + # XXX Localization ... + if "prompt" in token["data"]: + prompt = token["data"]["prompt"] + else: + prompt = "This is a searchable index. Enter search keywords: " + self.processCharacters( + {"type": tokenTypes["Characters"], "data": prompt}) + attributes = token["data"].copy() + if "action" in attributes: + del attributes["action"] + if "prompt" in attributes: + del attributes["prompt"] + attributes["name"] = "isindex" + self.processStartTag(impliedTagToken("input", "StartTag", + attributes=attributes, + selfClosing=token["selfClosing"])) + self.processEndTag(impliedTagToken("label")) + self.processStartTag(impliedTagToken("hr", "StartTag")) + self.processEndTag(impliedTagToken("form")) + + def startTagTextarea(self, token): + self.tree.insertElement(token) + self.parser.tokenizer.state = self.parser.tokenizer.rcdataState + self.processSpaceCharacters = self.processSpaceCharactersDropNewline + self.parser.framesetOK = False + + def startTagIFrame(self, token): + self.parser.framesetOK = False + self.startTagRawtext(token) + + def startTagRawtext(self, token): + """iframe, noembed noframes, noscript(if scripting enabled)""" + self.parser.parseRCDataRawtext(token, "RAWTEXT") + + def startTagOpt(self, token): + if self.tree.openElements[-1].name == "option": + self.parser.phase.processEndTag(impliedTagToken("option")) + self.tree.reconstructActiveFormattingElements() + self.parser.tree.insertElement(token) + + def startTagSelect(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.parser.framesetOK = False + if self.parser.phase in (self.parser.phases["inTable"], + self.parser.phases["inCaption"], + self.parser.phases["inColumnGroup"], + self.parser.phases["inTableBody"], + self.parser.phases["inRow"], + self.parser.phases["inCell"]): + self.parser.phase = self.parser.phases["inSelectInTable"] + else: + self.parser.phase = self.parser.phases["inSelect"] + + def startTagRpRt(self, token): + if self.tree.elementInScope("ruby"): + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != "ruby": + self.parser.parseError() + self.tree.insertElement(token) + + def startTagMath(self, token): + self.tree.reconstructActiveFormattingElements() + self.parser.adjustMathMLAttributes(token) + self.parser.adjustForeignAttributes(token) + token["namespace"] = namespaces["mathml"] + self.tree.insertElement(token) + # Need to get the parse error right for the case where the token + # has a namespace not equal to the xmlns attribute + if token["selfClosing"]: + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagSvg(self, token): + self.tree.reconstructActiveFormattingElements() + self.parser.adjustSVGAttributes(token) + self.parser.adjustForeignAttributes(token) + token["namespace"] = namespaces["svg"] + self.tree.insertElement(token) + # Need to get the parse error right for the case where the token + # has a namespace not equal to the xmlns attribute + if token["selfClosing"]: + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagMisplaced(self, token): + """ Elements that should be children of other elements that have a + different insertion mode; here they are ignored + "caption", "col", "colgroup", "frame", "frameset", "head", + "option", "optgroup", "tbody", "td", "tfoot", "th", "thead", + "tr", "noscript" + """ + self.parser.parseError("unexpected-start-tag-ignored", {"name": token["name"]}) + + def startTagOther(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + + def endTagP(self, token): + if not self.tree.elementInScope("p", variant="button"): + self.startTagCloseP(impliedTagToken("p", "StartTag")) + self.parser.parseError("unexpected-end-tag", {"name": "p"}) + self.endTagP(impliedTagToken("p", "EndTag")) + else: + self.tree.generateImpliedEndTags("p") + if self.tree.openElements[-1].name != "p": + self.parser.parseError("unexpected-end-tag", {"name": "p"}) + node = self.tree.openElements.pop() + while node.name != "p": + node = self.tree.openElements.pop() + + def endTagBody(self, token): + if not self.tree.elementInScope("body"): + self.parser.parseError() + return + elif self.tree.openElements[-1].name != "body": + for node in self.tree.openElements[2:]: + if node.name not in frozenset(("dd", "dt", "li", "optgroup", + "option", "p", "rp", "rt", + "tbody", "td", "tfoot", + "th", "thead", "tr", "body", + "html")): + # Not sure this is the correct name for the parse error + self.parser.parseError( + "expected-one-end-tag-but-got-another", + {"expectedName": "body", "gotName": node.name}) + break + self.parser.phase = self.parser.phases["afterBody"] + + def endTagHtml(self, token): + # We repeat the test for the body end tag token being ignored here + if self.tree.elementInScope("body"): + self.endTagBody(impliedTagToken("body")) + return token + + def endTagBlock(self, token): + # Put us back in the right whitespace handling mode + if token["name"] == "pre": + self.processSpaceCharacters = self.processSpaceCharactersNonPre + inScope = self.tree.elementInScope(token["name"]) + if inScope: + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("end-tag-too-early", {"name": token["name"]}) + if inScope: + node = self.tree.openElements.pop() + while node.name != token["name"]: + node = self.tree.openElements.pop() + + def endTagForm(self, token): + node = self.tree.formPointer + self.tree.formPointer = None + if node is None or not self.tree.elementInScope(node): + self.parser.parseError("unexpected-end-tag", + {"name": "form"}) + else: + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1] != node: + self.parser.parseError("end-tag-too-early-ignored", + {"name": "form"}) + self.tree.openElements.remove(node) + + def endTagListItem(self, token): + if token["name"] == "li": + variant = "list" + else: + variant = None + if not self.tree.elementInScope(token["name"], variant=variant): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + else: + self.tree.generateImpliedEndTags(exclude=token["name"]) + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError( + "end-tag-too-early", + {"name": token["name"]}) + node = self.tree.openElements.pop() + while node.name != token["name"]: + node = self.tree.openElements.pop() + + def endTagHeading(self, token): + for item in headingElements: + if self.tree.elementInScope(item): + self.tree.generateImpliedEndTags() + break + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("end-tag-too-early", {"name": token["name"]}) + + for item in headingElements: + if self.tree.elementInScope(item): + item = self.tree.openElements.pop() + while item.name not in headingElements: + item = self.tree.openElements.pop() + break + + def endTagFormatting(self, token): + """The much-feared adoption agency algorithm""" + # http://svn.whatwg.org/webapps/complete.html#adoptionAgency revision 7867 + # XXX Better parseError messages appreciated. + + # Step 1 + outerLoopCounter = 0 + + # Step 2 + while outerLoopCounter < 8: + + # Step 3 + outerLoopCounter += 1 + + # Step 4: + + # Let the formatting element be the last element in + # the list of active formatting elements that: + # - is between the end of the list and the last scope + # marker in the list, if any, or the start of the list + # otherwise, and + # - has the same tag name as the token. + formattingElement = self.tree.elementInActiveFormattingElements( + token["name"]) + if (not formattingElement or + (formattingElement in self.tree.openElements and + not self.tree.elementInScope(formattingElement.name))): + # If there is no such node, then abort these steps + # and instead act as described in the "any other + # end tag" entry below. + self.endTagOther(token) + return + + # Otherwise, if there is such a node, but that node is + # not in the stack of open elements, then this is a + # parse error; remove the element from the list, and + # abort these steps. + elif formattingElement not in self.tree.openElements: + self.parser.parseError("adoption-agency-1.2", {"name": token["name"]}) + self.tree.activeFormattingElements.remove(formattingElement) + return + + # Otherwise, if there is such a node, and that node is + # also in the stack of open elements, but the element + # is not in scope, then this is a parse error; ignore + # the token, and abort these steps. + elif not self.tree.elementInScope(formattingElement.name): + self.parser.parseError("adoption-agency-4.4", {"name": token["name"]}) + return + + # Otherwise, there is a formatting element and that + # element is in the stack and is in scope. If the + # element is not the current node, this is a parse + # error. In any case, proceed with the algorithm as + # written in the following steps. + else: + if formattingElement != self.tree.openElements[-1]: + self.parser.parseError("adoption-agency-1.3", {"name": token["name"]}) + + # Step 5: + + # Let the furthest block be the topmost node in the + # stack of open elements that is lower in the stack + # than the formatting element, and is an element in + # the special category. There might not be one. + afeIndex = self.tree.openElements.index(formattingElement) + furthestBlock = None + for element in self.tree.openElements[afeIndex:]: + if element.nameTuple in specialElements: + furthestBlock = element + break + + # Step 6: + + # If there is no furthest block, then the UA must + # first pop all the nodes from the bottom of the stack + # of open elements, from the current node up to and + # including the formatting element, then remove the + # formatting element from the list of active + # formatting elements, and finally abort these steps. + if furthestBlock is None: + element = self.tree.openElements.pop() + while element != formattingElement: + element = self.tree.openElements.pop() + self.tree.activeFormattingElements.remove(element) + return + + # Step 7 + commonAncestor = self.tree.openElements[afeIndex - 1] + + # Step 8: + # The bookmark is supposed to help us identify where to reinsert + # nodes in step 15. We have to ensure that we reinsert nodes after + # the node before the active formatting element. Note the bookmark + # can move in step 9.7 + bookmark = self.tree.activeFormattingElements.index(formattingElement) + + # Step 9 + lastNode = node = furthestBlock + innerLoopCounter = 0 + + index = self.tree.openElements.index(node) + while innerLoopCounter < 3: + innerLoopCounter += 1 + # Node is element before node in open elements + index -= 1 + node = self.tree.openElements[index] + if node not in self.tree.activeFormattingElements: + self.tree.openElements.remove(node) + continue + # Step 9.6 + if node == formattingElement: + break + # Step 9.7 + if lastNode == furthestBlock: + bookmark = self.tree.activeFormattingElements.index(node) + 1 + # Step 9.8 + clone = node.cloneNode() + # Replace node with clone + self.tree.activeFormattingElements[ + self.tree.activeFormattingElements.index(node)] = clone + self.tree.openElements[ + self.tree.openElements.index(node)] = clone + node = clone + # Step 9.9 + # Remove lastNode from its parents, if any + if lastNode.parent: + lastNode.parent.removeChild(lastNode) + node.appendChild(lastNode) + # Step 9.10 + lastNode = node + + # Step 10 + # Foster parent lastNode if commonAncestor is a + # table, tbody, tfoot, thead, or tr we need to foster + # parent the lastNode + if lastNode.parent: + lastNode.parent.removeChild(lastNode) + + if commonAncestor.name in frozenset(("table", "tbody", "tfoot", "thead", "tr")): + parent, insertBefore = self.tree.getTableMisnestedNodePosition() + parent.insertBefore(lastNode, insertBefore) + else: + commonAncestor.appendChild(lastNode) + + # Step 11 + clone = formattingElement.cloneNode() + + # Step 12 + furthestBlock.reparentChildren(clone) + + # Step 13 + furthestBlock.appendChild(clone) + + # Step 14 + self.tree.activeFormattingElements.remove(formattingElement) + self.tree.activeFormattingElements.insert(bookmark, clone) + + # Step 15 + self.tree.openElements.remove(formattingElement) + self.tree.openElements.insert( + self.tree.openElements.index(furthestBlock) + 1, clone) + + def endTagAppletMarqueeObject(self, token): + if self.tree.elementInScope(token["name"]): + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("end-tag-too-early", {"name": token["name"]}) + + if self.tree.elementInScope(token["name"]): + element = self.tree.openElements.pop() + while element.name != token["name"]: + element = self.tree.openElements.pop() + self.tree.clearActiveFormattingElements() + + def endTagBr(self, token): + self.parser.parseError("unexpected-end-tag-treated-as", + {"originalName": "br", "newName": "br element"}) + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(impliedTagToken("br", "StartTag")) + self.tree.openElements.pop() + + def endTagOther(self, token): + for node in self.tree.openElements[::-1]: + if node.name == token["name"]: + self.tree.generateImpliedEndTags(exclude=token["name"]) + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + while self.tree.openElements.pop() != node: + pass + break + else: + if node.nameTuple in specialElements: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + break + + class TextPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = utils.MethodDispatcher([]) + self.startTagHandler.default = self.startTagOther + self.endTagHandler = utils.MethodDispatcher([ + ("script", self.endTagScript)]) + self.endTagHandler.default = self.endTagOther + + def processCharacters(self, token): + self.tree.insertText(token["data"]) + + def processEOF(self): + self.parser.parseError("expected-named-closing-tag-but-got-eof", + {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + self.parser.phase = self.parser.originalPhase + return True + + def startTagOther(self, token): + assert False, "Tried to process start tag %s in RCDATA/RAWTEXT mode" % token['name'] + + def endTagScript(self, token): + node = self.tree.openElements.pop() + assert node.name == "script" + self.parser.phase = self.parser.originalPhase + # The rest of this method is all stuff that only happens if + # document.write works + + def endTagOther(self, token): + self.tree.openElements.pop() + self.parser.phase = self.parser.originalPhase + + class InTablePhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-table + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("caption", self.startTagCaption), + ("colgroup", self.startTagColgroup), + ("col", self.startTagCol), + (("tbody", "tfoot", "thead"), self.startTagRowGroup), + (("td", "th", "tr"), self.startTagImplyTbody), + ("table", self.startTagTable), + (("style", "script"), self.startTagStyleScript), + ("input", self.startTagInput), + ("form", self.startTagForm) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + ("table", self.endTagTable), + (("body", "caption", "col", "colgroup", "html", "tbody", "td", + "tfoot", "th", "thead", "tr"), self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + # helper methods + def clearStackToTableContext(self): + # "clear the stack back to a table context" + while self.tree.openElements[-1].name not in ("table", "html"): + # self.parser.parseError("unexpected-implied-end-tag-in-table", + # {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + # When the current node is <html> it's an innerHTML case + + # processing methods + def processEOF(self): + if self.tree.openElements[-1].name != "html": + self.parser.parseError("eof-in-table") + else: + assert self.parser.innerHTML + # Stop parsing + + def processSpaceCharacters(self, token): + originalPhase = self.parser.phase + self.parser.phase = self.parser.phases["inTableText"] + self.parser.phase.originalPhase = originalPhase + self.parser.phase.processSpaceCharacters(token) + + def processCharacters(self, token): + originalPhase = self.parser.phase + self.parser.phase = self.parser.phases["inTableText"] + self.parser.phase.originalPhase = originalPhase + self.parser.phase.processCharacters(token) + + def insertText(self, token): + # If we get here there must be at least one non-whitespace character + # Do the table magic! + self.tree.insertFromTable = True + self.parser.phases["inBody"].processCharacters(token) + self.tree.insertFromTable = False + + def startTagCaption(self, token): + self.clearStackToTableContext() + self.tree.activeFormattingElements.append(Marker) + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inCaption"] + + def startTagColgroup(self, token): + self.clearStackToTableContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inColumnGroup"] + + def startTagCol(self, token): + self.startTagColgroup(impliedTagToken("colgroup", "StartTag")) + return token + + def startTagRowGroup(self, token): + self.clearStackToTableContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inTableBody"] + + def startTagImplyTbody(self, token): + self.startTagRowGroup(impliedTagToken("tbody", "StartTag")) + return token + + def startTagTable(self, token): + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "table", "endName": "table"}) + self.parser.phase.processEndTag(impliedTagToken("table")) + if not self.parser.innerHTML: + return token + + def startTagStyleScript(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagInput(self, token): + if ("type" in token["data"] and + token["data"]["type"].translate(asciiUpper2Lower) == "hidden"): + self.parser.parseError("unexpected-hidden-input-in-table") + self.tree.insertElement(token) + # XXX associate with form + self.tree.openElements.pop() + else: + self.startTagOther(token) + + def startTagForm(self, token): + self.parser.parseError("unexpected-form-in-table") + if self.tree.formPointer is None: + self.tree.insertElement(token) + self.tree.formPointer = self.tree.openElements[-1] + self.tree.openElements.pop() + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-implies-table-voodoo", {"name": token["name"]}) + # Do the table magic! + self.tree.insertFromTable = True + self.parser.phases["inBody"].processStartTag(token) + self.tree.insertFromTable = False + + def endTagTable(self, token): + if self.tree.elementInScope("table", variant="table"): + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != "table": + self.parser.parseError("end-tag-too-early-named", + {"gotName": "table", + "expectedName": self.tree.openElements[-1].name}) + while self.tree.openElements[-1].name != "table": + self.tree.openElements.pop() + self.tree.openElements.pop() + self.parser.resetInsertionMode() + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-implies-table-voodoo", {"name": token["name"]}) + # Do the table magic! + self.tree.insertFromTable = True + self.parser.phases["inBody"].processEndTag(token) + self.tree.insertFromTable = False + + class InTableTextPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.originalPhase = None + self.characterTokens = [] + + def flushCharacters(self): + data = "".join([item["data"] for item in self.characterTokens]) + if any([item not in spaceCharacters for item in data]): + token = {"type": tokenTypes["Characters"], "data": data} + self.parser.phases["inTable"].insertText(token) + elif data: + self.tree.insertText(data) + self.characterTokens = [] + + def processComment(self, token): + self.flushCharacters() + self.parser.phase = self.originalPhase + return token + + def processEOF(self): + self.flushCharacters() + self.parser.phase = self.originalPhase + return True + + def processCharacters(self, token): + if token["data"] == "\u0000": + return + self.characterTokens.append(token) + + def processSpaceCharacters(self, token): + # pretty sure we should never reach here + self.characterTokens.append(token) + # assert False + + def processStartTag(self, token): + self.flushCharacters() + self.parser.phase = self.originalPhase + return token + + def processEndTag(self, token): + self.flushCharacters() + self.parser.phase = self.originalPhase + return token + + class InCaptionPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-caption + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("caption", "col", "colgroup", "tbody", "td", "tfoot", "th", + "thead", "tr"), self.startTagTableElement) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + ("caption", self.endTagCaption), + ("table", self.endTagTable), + (("body", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", + "thead", "tr"), self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + def ignoreEndTagCaption(self): + return not self.tree.elementInScope("caption", variant="table") + + def processEOF(self): + self.parser.phases["inBody"].processEOF() + + def processCharacters(self, token): + return self.parser.phases["inBody"].processCharacters(token) + + def startTagTableElement(self, token): + self.parser.parseError() + # XXX Have to duplicate logic here to find out if the tag is ignored + ignoreEndTag = self.ignoreEndTagCaption() + self.parser.phase.processEndTag(impliedTagToken("caption")) + if not ignoreEndTag: + return token + + def startTagOther(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def endTagCaption(self, token): + if not self.ignoreEndTagCaption(): + # AT this code is quite similar to endTagTable in "InTable" + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != "caption": + self.parser.parseError("expected-one-end-tag-but-got-another", + {"gotName": "caption", + "expectedName": self.tree.openElements[-1].name}) + while self.tree.openElements[-1].name != "caption": + self.tree.openElements.pop() + self.tree.openElements.pop() + self.tree.clearActiveFormattingElements() + self.parser.phase = self.parser.phases["inTable"] + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagTable(self, token): + self.parser.parseError() + ignoreEndTag = self.ignoreEndTagCaption() + self.parser.phase.processEndTag(impliedTagToken("caption")) + if not ignoreEndTag: + return token + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagOther(self, token): + return self.parser.phases["inBody"].processEndTag(token) + + class InColumnGroupPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-column + + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("col", self.startTagCol) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + ("colgroup", self.endTagColgroup), + ("col", self.endTagCol) + ]) + self.endTagHandler.default = self.endTagOther + + def ignoreEndTagColgroup(self): + return self.tree.openElements[-1].name == "html" + + def processEOF(self): + if self.tree.openElements[-1].name == "html": + assert self.parser.innerHTML + return + else: + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return True + + def processCharacters(self, token): + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return token + + def startTagCol(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + + def startTagOther(self, token): + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return token + + def endTagColgroup(self, token): + if self.ignoreEndTagColgroup(): + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + else: + self.tree.openElements.pop() + self.parser.phase = self.parser.phases["inTable"] + + def endTagCol(self, token): + self.parser.parseError("no-end-tag", {"name": "col"}) + + def endTagOther(self, token): + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return token + + class InTableBodyPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-table0 + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("tr", self.startTagTr), + (("td", "th"), self.startTagTableCell), + (("caption", "col", "colgroup", "tbody", "tfoot", "thead"), + self.startTagTableOther) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + (("tbody", "tfoot", "thead"), self.endTagTableRowGroup), + ("table", self.endTagTable), + (("body", "caption", "col", "colgroup", "html", "td", "th", + "tr"), self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + # helper methods + def clearStackToTableBodyContext(self): + while self.tree.openElements[-1].name not in ("tbody", "tfoot", + "thead", "html"): + # self.parser.parseError("unexpected-implied-end-tag-in-table", + # {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + if self.tree.openElements[-1].name == "html": + assert self.parser.innerHTML + + # the rest + def processEOF(self): + self.parser.phases["inTable"].processEOF() + + def processSpaceCharacters(self, token): + return self.parser.phases["inTable"].processSpaceCharacters(token) + + def processCharacters(self, token): + return self.parser.phases["inTable"].processCharacters(token) + + def startTagTr(self, token): + self.clearStackToTableBodyContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inRow"] + + def startTagTableCell(self, token): + self.parser.parseError("unexpected-cell-in-table-body", + {"name": token["name"]}) + self.startTagTr(impliedTagToken("tr", "StartTag")) + return token + + def startTagTableOther(self, token): + # XXX AT Any ideas on how to share this with endTagTable? + if (self.tree.elementInScope("tbody", variant="table") or + self.tree.elementInScope("thead", variant="table") or + self.tree.elementInScope("tfoot", variant="table")): + self.clearStackToTableBodyContext() + self.endTagTableRowGroup( + impliedTagToken(self.tree.openElements[-1].name)) + return token + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def startTagOther(self, token): + return self.parser.phases["inTable"].processStartTag(token) + + def endTagTableRowGroup(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.clearStackToTableBodyContext() + self.tree.openElements.pop() + self.parser.phase = self.parser.phases["inTable"] + else: + self.parser.parseError("unexpected-end-tag-in-table-body", + {"name": token["name"]}) + + def endTagTable(self, token): + if (self.tree.elementInScope("tbody", variant="table") or + self.tree.elementInScope("thead", variant="table") or + self.tree.elementInScope("tfoot", variant="table")): + self.clearStackToTableBodyContext() + self.endTagTableRowGroup( + impliedTagToken(self.tree.openElements[-1].name)) + return token + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag-in-table-body", + {"name": token["name"]}) + + def endTagOther(self, token): + return self.parser.phases["inTable"].processEndTag(token) + + class InRowPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-row + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("td", "th"), self.startTagTableCell), + (("caption", "col", "colgroup", "tbody", "tfoot", "thead", + "tr"), self.startTagTableOther) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + ("tr", self.endTagTr), + ("table", self.endTagTable), + (("tbody", "tfoot", "thead"), self.endTagTableRowGroup), + (("body", "caption", "col", "colgroup", "html", "td", "th"), + self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + # helper methods (XXX unify this with other table helper methods) + def clearStackToTableRowContext(self): + while self.tree.openElements[-1].name not in ("tr", "html"): + self.parser.parseError("unexpected-implied-end-tag-in-table-row", + {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + + def ignoreEndTagTr(self): + return not self.tree.elementInScope("tr", variant="table") + + # the rest + def processEOF(self): + self.parser.phases["inTable"].processEOF() + + def processSpaceCharacters(self, token): + return self.parser.phases["inTable"].processSpaceCharacters(token) + + def processCharacters(self, token): + return self.parser.phases["inTable"].processCharacters(token) + + def startTagTableCell(self, token): + self.clearStackToTableRowContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inCell"] + self.tree.activeFormattingElements.append(Marker) + + def startTagTableOther(self, token): + ignoreEndTag = self.ignoreEndTagTr() + self.endTagTr(impliedTagToken("tr")) + # XXX how are we sure it's always ignored in the innerHTML case? + if not ignoreEndTag: + return token + + def startTagOther(self, token): + return self.parser.phases["inTable"].processStartTag(token) + + def endTagTr(self, token): + if not self.ignoreEndTagTr(): + self.clearStackToTableRowContext() + self.tree.openElements.pop() + self.parser.phase = self.parser.phases["inTableBody"] + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagTable(self, token): + ignoreEndTag = self.ignoreEndTagTr() + self.endTagTr(impliedTagToken("tr")) + # Reprocess the current tag if the tr end tag was not ignored + # XXX how are we sure it's always ignored in the innerHTML case? + if not ignoreEndTag: + return token + + def endTagTableRowGroup(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.endTagTr(impliedTagToken("tr")) + return token + else: + self.parser.parseError() + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag-in-table-row", + {"name": token["name"]}) + + def endTagOther(self, token): + return self.parser.phases["inTable"].processEndTag(token) + + class InCellPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-cell + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("caption", "col", "colgroup", "tbody", "td", "tfoot", "th", + "thead", "tr"), self.startTagTableOther) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + (("td", "th"), self.endTagTableCell), + (("body", "caption", "col", "colgroup", "html"), self.endTagIgnore), + (("table", "tbody", "tfoot", "thead", "tr"), self.endTagImply) + ]) + self.endTagHandler.default = self.endTagOther + + # helper + def closeCell(self): + if self.tree.elementInScope("td", variant="table"): + self.endTagTableCell(impliedTagToken("td")) + elif self.tree.elementInScope("th", variant="table"): + self.endTagTableCell(impliedTagToken("th")) + + # the rest + def processEOF(self): + self.parser.phases["inBody"].processEOF() + + def processCharacters(self, token): + return self.parser.phases["inBody"].processCharacters(token) + + def startTagTableOther(self, token): + if (self.tree.elementInScope("td", variant="table") or + self.tree.elementInScope("th", variant="table")): + self.closeCell() + return token + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def startTagOther(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def endTagTableCell(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.tree.generateImpliedEndTags(token["name"]) + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("unexpected-cell-end-tag", + {"name": token["name"]}) + while True: + node = self.tree.openElements.pop() + if node.name == token["name"]: + break + else: + self.tree.openElements.pop() + self.tree.clearActiveFormattingElements() + self.parser.phase = self.parser.phases["inRow"] + else: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagImply(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.closeCell() + return token + else: + # sometimes innerHTML case + self.parser.parseError() + + def endTagOther(self, token): + return self.parser.phases["inBody"].processEndTag(token) + + class InSelectPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("option", self.startTagOption), + ("optgroup", self.startTagOptgroup), + ("select", self.startTagSelect), + (("input", "keygen", "textarea"), self.startTagInput), + ("script", self.startTagScript) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + ("option", self.endTagOption), + ("optgroup", self.endTagOptgroup), + ("select", self.endTagSelect) + ]) + self.endTagHandler.default = self.endTagOther + + # http://www.whatwg.org/specs/web-apps/current-work/#in-select + def processEOF(self): + if self.tree.openElements[-1].name != "html": + self.parser.parseError("eof-in-select") + else: + assert self.parser.innerHTML + + def processCharacters(self, token): + if token["data"] == "\u0000": + return + self.tree.insertText(token["data"]) + + def startTagOption(self, token): + # We need to imply </option> if <option> is the current node. + if self.tree.openElements[-1].name == "option": + self.tree.openElements.pop() + self.tree.insertElement(token) + + def startTagOptgroup(self, token): + if self.tree.openElements[-1].name == "option": + self.tree.openElements.pop() + if self.tree.openElements[-1].name == "optgroup": + self.tree.openElements.pop() + self.tree.insertElement(token) + + def startTagSelect(self, token): + self.parser.parseError("unexpected-select-in-select") + self.endTagSelect(impliedTagToken("select")) + + def startTagInput(self, token): + self.parser.parseError("unexpected-input-in-select") + if self.tree.elementInScope("select", variant="select"): + self.endTagSelect(impliedTagToken("select")) + return token + else: + assert self.parser.innerHTML + + def startTagScript(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-in-select", + {"name": token["name"]}) + + def endTagOption(self, token): + if self.tree.openElements[-1].name == "option": + self.tree.openElements.pop() + else: + self.parser.parseError("unexpected-end-tag-in-select", + {"name": "option"}) + + def endTagOptgroup(self, token): + # </optgroup> implicitly closes <option> + if (self.tree.openElements[-1].name == "option" and + self.tree.openElements[-2].name == "optgroup"): + self.tree.openElements.pop() + # It also closes </optgroup> + if self.tree.openElements[-1].name == "optgroup": + self.tree.openElements.pop() + # But nothing else + else: + self.parser.parseError("unexpected-end-tag-in-select", + {"name": "optgroup"}) + + def endTagSelect(self, token): + if self.tree.elementInScope("select", variant="select"): + node = self.tree.openElements.pop() + while node.name != "select": + node = self.tree.openElements.pop() + self.parser.resetInsertionMode() + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-in-select", + {"name": token["name"]}) + + class InSelectInTablePhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + (("caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"), + self.startTagTable) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + (("caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"), + self.endTagTable) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.parser.phases["inSelect"].processEOF() + + def processCharacters(self, token): + return self.parser.phases["inSelect"].processCharacters(token) + + def startTagTable(self, token): + self.parser.parseError("unexpected-table-element-start-tag-in-select-in-table", {"name": token["name"]}) + self.endTagOther(impliedTagToken("select")) + return token + + def startTagOther(self, token): + return self.parser.phases["inSelect"].processStartTag(token) + + def endTagTable(self, token): + self.parser.parseError("unexpected-table-element-end-tag-in-select-in-table", {"name": token["name"]}) + if self.tree.elementInScope(token["name"], variant="table"): + self.endTagOther(impliedTagToken("select")) + return token + + def endTagOther(self, token): + return self.parser.phases["inSelect"].processEndTag(token) + + class InForeignContentPhase(Phase): + breakoutElements = frozenset(["b", "big", "blockquote", "body", "br", + "center", "code", "dd", "div", "dl", "dt", + "em", "embed", "h1", "h2", "h3", + "h4", "h5", "h6", "head", "hr", "i", "img", + "li", "listing", "menu", "meta", "nobr", + "ol", "p", "pre", "ruby", "s", "small", + "span", "strong", "strike", "sub", "sup", + "table", "tt", "u", "ul", "var"]) + + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + def adjustSVGTagNames(self, token): + replacements = {"altglyph": "altGlyph", + "altglyphdef": "altGlyphDef", + "altglyphitem": "altGlyphItem", + "animatecolor": "animateColor", + "animatemotion": "animateMotion", + "animatetransform": "animateTransform", + "clippath": "clipPath", + "feblend": "feBlend", + "fecolormatrix": "feColorMatrix", + "fecomponenttransfer": "feComponentTransfer", + "fecomposite": "feComposite", + "feconvolvematrix": "feConvolveMatrix", + "fediffuselighting": "feDiffuseLighting", + "fedisplacementmap": "feDisplacementMap", + "fedistantlight": "feDistantLight", + "feflood": "feFlood", + "fefunca": "feFuncA", + "fefuncb": "feFuncB", + "fefuncg": "feFuncG", + "fefuncr": "feFuncR", + "fegaussianblur": "feGaussianBlur", + "feimage": "feImage", + "femerge": "feMerge", + "femergenode": "feMergeNode", + "femorphology": "feMorphology", + "feoffset": "feOffset", + "fepointlight": "fePointLight", + "fespecularlighting": "feSpecularLighting", + "fespotlight": "feSpotLight", + "fetile": "feTile", + "feturbulence": "feTurbulence", + "foreignobject": "foreignObject", + "glyphref": "glyphRef", + "lineargradient": "linearGradient", + "radialgradient": "radialGradient", + "textpath": "textPath"} + + if token["name"] in replacements: + token["name"] = replacements[token["name"]] + + def processCharacters(self, token): + if token["data"] == "\u0000": + token["data"] = "\uFFFD" + elif (self.parser.framesetOK and + any(char not in spaceCharacters for char in token["data"])): + self.parser.framesetOK = False + Phase.processCharacters(self, token) + + def processStartTag(self, token): + currentNode = self.tree.openElements[-1] + if (token["name"] in self.breakoutElements or + (token["name"] == "font" and + set(token["data"].keys()) & set(["color", "face", "size"]))): + self.parser.parseError("unexpected-html-element-in-foreign-content", + {"name": token["name"]}) + while (self.tree.openElements[-1].namespace != + self.tree.defaultNamespace and + not self.parser.isHTMLIntegrationPoint(self.tree.openElements[-1]) and + not self.parser.isMathMLTextIntegrationPoint(self.tree.openElements[-1])): + self.tree.openElements.pop() + return token + + else: + if currentNode.namespace == namespaces["mathml"]: + self.parser.adjustMathMLAttributes(token) + elif currentNode.namespace == namespaces["svg"]: + self.adjustSVGTagNames(token) + self.parser.adjustSVGAttributes(token) + self.parser.adjustForeignAttributes(token) + token["namespace"] = currentNode.namespace + self.tree.insertElement(token) + if token["selfClosing"]: + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def processEndTag(self, token): + nodeIndex = len(self.tree.openElements) - 1 + node = self.tree.openElements[-1] + if node.name != token["name"]: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + while True: + if node.name.translate(asciiUpper2Lower) == token["name"]: + # XXX this isn't in the spec but it seems necessary + if self.parser.phase == self.parser.phases["inTableText"]: + self.parser.phase.flushCharacters() + self.parser.phase = self.parser.phase.originalPhase + while self.tree.openElements.pop() != node: + assert self.tree.openElements + new_token = None + break + nodeIndex -= 1 + + node = self.tree.openElements[nodeIndex] + if node.namespace != self.tree.defaultNamespace: + continue + else: + new_token = self.parser.phase.processEndTag(token) + break + return new_token + + class AfterBodyPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([("html", self.endTagHtml)]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + # Stop parsing + pass + + def processComment(self, token): + # This is needed because data is to be appended to the <html> element + # here and not to whatever is currently open. + self.tree.insertComment(token, self.tree.openElements[0]) + + def processCharacters(self, token): + self.parser.parseError("unexpected-char-after-body") + self.parser.phase = self.parser.phases["inBody"] + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-after-body", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + def endTagHtml(self, name): + if self.parser.innerHTML: + self.parser.parseError("unexpected-end-tag-after-body-innerhtml") + else: + self.parser.phase = self.parser.phases["afterAfterBody"] + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-after-body", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + class InFramesetPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-frameset + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("frameset", self.startTagFrameset), + ("frame", self.startTagFrame), + ("noframes", self.startTagNoframes) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + ("frameset", self.endTagFrameset) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + if self.tree.openElements[-1].name != "html": + self.parser.parseError("eof-in-frameset") + else: + assert self.parser.innerHTML + + def processCharacters(self, token): + self.parser.parseError("unexpected-char-in-frameset") + + def startTagFrameset(self, token): + self.tree.insertElement(token) + + def startTagFrame(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + + def startTagNoframes(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-in-frameset", + {"name": token["name"]}) + + def endTagFrameset(self, token): + if self.tree.openElements[-1].name == "html": + # innerHTML case + self.parser.parseError("unexpected-frameset-in-frameset-innerhtml") + else: + self.tree.openElements.pop() + if (not self.parser.innerHTML and + self.tree.openElements[-1].name != "frameset"): + # If we're not in innerHTML mode and the the current node is not a + # "frameset" element (anymore) then switch. + self.parser.phase = self.parser.phases["afterFrameset"] + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-in-frameset", + {"name": token["name"]}) + + class AfterFramesetPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#after3 + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("noframes", self.startTagNoframes) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = utils.MethodDispatcher([ + ("html", self.endTagHtml) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + # Stop parsing + pass + + def processCharacters(self, token): + self.parser.parseError("unexpected-char-after-frameset") + + def startTagNoframes(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-after-frameset", + {"name": token["name"]}) + + def endTagHtml(self, token): + self.parser.phase = self.parser.phases["afterAfterFrameset"] + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-after-frameset", + {"name": token["name"]}) + + class AfterAfterBodyPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml) + ]) + self.startTagHandler.default = self.startTagOther + + def processEOF(self): + pass + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processSpaceCharacters(self, token): + return self.parser.phases["inBody"].processSpaceCharacters(token) + + def processCharacters(self, token): + self.parser.parseError("expected-eof-but-got-char") + self.parser.phase = self.parser.phases["inBody"] + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("expected-eof-but-got-start-tag", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + def processEndTag(self, token): + self.parser.parseError("expected-eof-but-got-end-tag", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + class AfterAfterFramesetPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("noframes", self.startTagNoFrames) + ]) + self.startTagHandler.default = self.startTagOther + + def processEOF(self): + pass + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processSpaceCharacters(self, token): + return self.parser.phases["inBody"].processSpaceCharacters(token) + + def processCharacters(self, token): + self.parser.parseError("expected-eof-but-got-char") + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagNoFrames(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("expected-eof-but-got-start-tag", + {"name": token["name"]}) + + def processEndTag(self, token): + self.parser.parseError("expected-eof-but-got-end-tag", + {"name": token["name"]}) + + return { + "initial": InitialPhase, + "beforeHtml": BeforeHtmlPhase, + "beforeHead": BeforeHeadPhase, + "inHead": InHeadPhase, + # XXX "inHeadNoscript": InHeadNoScriptPhase, + "afterHead": AfterHeadPhase, + "inBody": InBodyPhase, + "text": TextPhase, + "inTable": InTablePhase, + "inTableText": InTableTextPhase, + "inCaption": InCaptionPhase, + "inColumnGroup": InColumnGroupPhase, + "inTableBody": InTableBodyPhase, + "inRow": InRowPhase, + "inCell": InCellPhase, + "inSelect": InSelectPhase, + "inSelectInTable": InSelectInTablePhase, + "inForeignContent": InForeignContentPhase, + "afterBody": AfterBodyPhase, + "inFrameset": InFramesetPhase, + "afterFrameset": AfterFramesetPhase, + "afterAfterBody": AfterAfterBodyPhase, + "afterAfterFrameset": AfterAfterFramesetPhase, + # XXX after after frameset + } + + +def impliedTagToken(name, type="EndTag", attributes=None, + selfClosing=False): + if attributes is None: + attributes = {} + return {"type": tokenTypes[type], "name": name, "data": attributes, + "selfClosing": selfClosing} + + +class ParseError(Exception): + """Error in parsed document""" + pass diff --git a/catapult/third_party/html5lib-python/html5lib/ihatexml.py b/catapult/third_party/html5lib-python/html5lib/ihatexml.py new file mode 100644 index 00000000..0fc79308 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/ihatexml.py @@ -0,0 +1,285 @@ +from __future__ import absolute_import, division, unicode_literals + +import re +import warnings + +from .constants import DataLossWarning + +baseChar = """ +[#x0041-#x005A] | [#x0061-#x007A] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | +[#x00F8-#x00FF] | [#x0100-#x0131] | [#x0134-#x013E] | [#x0141-#x0148] | +[#x014A-#x017E] | [#x0180-#x01C3] | [#x01CD-#x01F0] | [#x01F4-#x01F5] | +[#x01FA-#x0217] | [#x0250-#x02A8] | [#x02BB-#x02C1] | #x0386 | +[#x0388-#x038A] | #x038C | [#x038E-#x03A1] | [#x03A3-#x03CE] | +[#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0 | [#x03E2-#x03F3] | +[#x0401-#x040C] | [#x040E-#x044F] | [#x0451-#x045C] | [#x045E-#x0481] | +[#x0490-#x04C4] | [#x04C7-#x04C8] | [#x04CB-#x04CC] | [#x04D0-#x04EB] | +[#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | #x0559 | +[#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2] | [#x0621-#x063A] | +[#x0641-#x064A] | [#x0671-#x06B7] | [#x06BA-#x06BE] | [#x06C0-#x06CE] | +[#x06D0-#x06D3] | #x06D5 | [#x06E5-#x06E6] | [#x0905-#x0939] | #x093D | +[#x0958-#x0961] | [#x0985-#x098C] | [#x098F-#x0990] | [#x0993-#x09A8] | +[#x09AA-#x09B0] | #x09B2 | [#x09B6-#x09B9] | [#x09DC-#x09DD] | +[#x09DF-#x09E1] | [#x09F0-#x09F1] | [#x0A05-#x0A0A] | [#x0A0F-#x0A10] | +[#x0A13-#x0A28] | [#x0A2A-#x0A30] | [#x0A32-#x0A33] | [#x0A35-#x0A36] | +[#x0A38-#x0A39] | [#x0A59-#x0A5C] | #x0A5E | [#x0A72-#x0A74] | +[#x0A85-#x0A8B] | #x0A8D | [#x0A8F-#x0A91] | [#x0A93-#x0AA8] | +[#x0AAA-#x0AB0] | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | #x0ABD | #x0AE0 | +[#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28] | [#x0B2A-#x0B30] | +[#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D | [#x0B5C-#x0B5D] | +[#x0B5F-#x0B61] | [#x0B85-#x0B8A] | [#x0B8E-#x0B90] | [#x0B92-#x0B95] | +[#x0B99-#x0B9A] | #x0B9C | [#x0B9E-#x0B9F] | [#x0BA3-#x0BA4] | +[#x0BA8-#x0BAA] | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | [#x0C05-#x0C0C] | +[#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33] | [#x0C35-#x0C39] | +[#x0C60-#x0C61] | [#x0C85-#x0C8C] | [#x0C8E-#x0C90] | [#x0C92-#x0CA8] | +[#x0CAA-#x0CB3] | [#x0CB5-#x0CB9] | #x0CDE | [#x0CE0-#x0CE1] | +[#x0D05-#x0D0C] | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | [#x0D2A-#x0D39] | +[#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | [#x0E32-#x0E33] | +[#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | [#x0E87-#x0E88] | #x0E8A | +#x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F] | [#x0EA1-#x0EA3] | #x0EA5 | +#x0EA7 | [#x0EAA-#x0EAB] | [#x0EAD-#x0EAE] | #x0EB0 | [#x0EB2-#x0EB3] | +#x0EBD | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | [#x0F49-#x0F69] | +[#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | [#x1102-#x1103] | +[#x1105-#x1107] | #x1109 | [#x110B-#x110C] | [#x110E-#x1112] | #x113C | +#x113E | #x1140 | #x114C | #x114E | #x1150 | [#x1154-#x1155] | #x1159 | +[#x115F-#x1161] | #x1163 | #x1165 | #x1167 | #x1169 | [#x116D-#x116E] | +[#x1172-#x1173] | #x1175 | #x119E | #x11A8 | #x11AB | [#x11AE-#x11AF] | +[#x11B7-#x11B8] | #x11BA | [#x11BC-#x11C2] | #x11EB | #x11F0 | #x11F9 | +[#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | [#x1F00-#x1F15] | [#x1F18-#x1F1D] | +[#x1F20-#x1F45] | [#x1F48-#x1F4D] | [#x1F50-#x1F57] | #x1F59 | #x1F5B | +#x1F5D | [#x1F5F-#x1F7D] | [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE | +[#x1FC2-#x1FC4] | [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB] | +[#x1FE0-#x1FEC] | [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126 | +[#x212A-#x212B] | #x212E | [#x2180-#x2182] | [#x3041-#x3094] | +[#x30A1-#x30FA] | [#x3105-#x312C] | [#xAC00-#xD7A3]""" + +ideographic = """[#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029]""" + +combiningCharacter = """ +[#x0300-#x0345] | [#x0360-#x0361] | [#x0483-#x0486] | [#x0591-#x05A1] | +[#x05A3-#x05B9] | [#x05BB-#x05BD] | #x05BF | [#x05C1-#x05C2] | #x05C4 | +[#x064B-#x0652] | #x0670 | [#x06D6-#x06DC] | [#x06DD-#x06DF] | +[#x06E0-#x06E4] | [#x06E7-#x06E8] | [#x06EA-#x06ED] | [#x0901-#x0903] | +#x093C | [#x093E-#x094C] | #x094D | [#x0951-#x0954] | [#x0962-#x0963] | +[#x0981-#x0983] | #x09BC | #x09BE | #x09BF | [#x09C0-#x09C4] | +[#x09C7-#x09C8] | [#x09CB-#x09CD] | #x09D7 | [#x09E2-#x09E3] | #x0A02 | +#x0A3C | #x0A3E | #x0A3F | [#x0A40-#x0A42] | [#x0A47-#x0A48] | +[#x0A4B-#x0A4D] | [#x0A70-#x0A71] | [#x0A81-#x0A83] | #x0ABC | +[#x0ABE-#x0AC5] | [#x0AC7-#x0AC9] | [#x0ACB-#x0ACD] | [#x0B01-#x0B03] | +#x0B3C | [#x0B3E-#x0B43] | [#x0B47-#x0B48] | [#x0B4B-#x0B4D] | +[#x0B56-#x0B57] | [#x0B82-#x0B83] | [#x0BBE-#x0BC2] | [#x0BC6-#x0BC8] | +[#x0BCA-#x0BCD] | #x0BD7 | [#x0C01-#x0C03] | [#x0C3E-#x0C44] | +[#x0C46-#x0C48] | [#x0C4A-#x0C4D] | [#x0C55-#x0C56] | [#x0C82-#x0C83] | +[#x0CBE-#x0CC4] | [#x0CC6-#x0CC8] | [#x0CCA-#x0CCD] | [#x0CD5-#x0CD6] | +[#x0D02-#x0D03] | [#x0D3E-#x0D43] | [#x0D46-#x0D48] | [#x0D4A-#x0D4D] | +#x0D57 | #x0E31 | [#x0E34-#x0E3A] | [#x0E47-#x0E4E] | #x0EB1 | +[#x0EB4-#x0EB9] | [#x0EBB-#x0EBC] | [#x0EC8-#x0ECD] | [#x0F18-#x0F19] | +#x0F35 | #x0F37 | #x0F39 | #x0F3E | #x0F3F | [#x0F71-#x0F84] | +[#x0F86-#x0F8B] | [#x0F90-#x0F95] | #x0F97 | [#x0F99-#x0FAD] | +[#x0FB1-#x0FB7] | #x0FB9 | [#x20D0-#x20DC] | #x20E1 | [#x302A-#x302F] | +#x3099 | #x309A""" + +digit = """ +[#x0030-#x0039] | [#x0660-#x0669] | [#x06F0-#x06F9] | [#x0966-#x096F] | +[#x09E6-#x09EF] | [#x0A66-#x0A6F] | [#x0AE6-#x0AEF] | [#x0B66-#x0B6F] | +[#x0BE7-#x0BEF] | [#x0C66-#x0C6F] | [#x0CE6-#x0CEF] | [#x0D66-#x0D6F] | +[#x0E50-#x0E59] | [#x0ED0-#x0ED9] | [#x0F20-#x0F29]""" + +extender = """ +#x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 | #x0E46 | #x0EC6 | #x3005 | +#[#x3031-#x3035] | [#x309D-#x309E] | [#x30FC-#x30FE]""" + +letter = " | ".join([baseChar, ideographic]) + +# Without the +name = " | ".join([letter, digit, ".", "-", "_", combiningCharacter, + extender]) +nameFirst = " | ".join([letter, "_"]) + +reChar = re.compile(r"#x([\d|A-F]{4,4})") +reCharRange = re.compile(r"\[#x([\d|A-F]{4,4})-#x([\d|A-F]{4,4})\]") + + +def charStringToList(chars): + charRanges = [item.strip() for item in chars.split(" | ")] + rv = [] + for item in charRanges: + foundMatch = False + for regexp in (reChar, reCharRange): + match = regexp.match(item) + if match is not None: + rv.append([hexToInt(item) for item in match.groups()]) + if len(rv[-1]) == 1: + rv[-1] = rv[-1] * 2 + foundMatch = True + break + if not foundMatch: + assert len(item) == 1 + + rv.append([ord(item)] * 2) + rv = normaliseCharList(rv) + return rv + + +def normaliseCharList(charList): + charList = sorted(charList) + for item in charList: + assert item[1] >= item[0] + rv = [] + i = 0 + while i < len(charList): + j = 1 + rv.append(charList[i]) + while i + j < len(charList) and charList[i + j][0] <= rv[-1][1] + 1: + rv[-1][1] = charList[i + j][1] + j += 1 + i += j + return rv + +# We don't really support characters above the BMP :( +max_unicode = int("FFFF", 16) + + +def missingRanges(charList): + rv = [] + if charList[0] != 0: + rv.append([0, charList[0][0] - 1]) + for i, item in enumerate(charList[:-1]): + rv.append([item[1] + 1, charList[i + 1][0] - 1]) + if charList[-1][1] != max_unicode: + rv.append([charList[-1][1] + 1, max_unicode]) + return rv + + +def listToRegexpStr(charList): + rv = [] + for item in charList: + if item[0] == item[1]: + rv.append(escapeRegexp(chr(item[0]))) + else: + rv.append(escapeRegexp(chr(item[0])) + "-" + + escapeRegexp(chr(item[1]))) + return "[%s]" % "".join(rv) + + +def hexToInt(hex_str): + return int(hex_str, 16) + + +def escapeRegexp(string): + specialCharacters = (".", "^", "$", "*", "+", "?", "{", "}", + "[", "]", "|", "(", ")", "-") + for char in specialCharacters: + string = string.replace(char, "\\" + char) + + return string + +# output from the above +nonXmlNameBMPRegexp = re.compile('[\x00-,/:-@\\[-\\^`\\{-\xb6\xb8-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u02cf\u02d2-\u02ff\u0346-\u035f\u0362-\u0385\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482\u0487-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u0590\u05a2\u05ba\u05be\u05c0\u05c3\u05c5-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u063f\u0653-\u065f\u066a-\u066f\u06b8-\u06b9\u06bf\u06cf\u06d4\u06e9\u06ee-\u06ef\u06fa-\u0900\u0904\u093a-\u093b\u094e-\u0950\u0955-\u0957\u0964-\u0965\u0970-\u0980\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09bb\u09bd\u09c5-\u09c6\u09c9-\u09ca\u09ce-\u09d6\u09d8-\u09db\u09de\u09e4-\u09e5\u09f2-\u0a01\u0a03-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a3b\u0a3d\u0a43-\u0a46\u0a49-\u0a4a\u0a4e-\u0a58\u0a5d\u0a5f-\u0a65\u0a75-\u0a80\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abb\u0ac6\u0aca\u0ace-\u0adf\u0ae1-\u0ae5\u0af0-\u0b00\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3b\u0b44-\u0b46\u0b49-\u0b4a\u0b4e-\u0b55\u0b58-\u0b5b\u0b5e\u0b62-\u0b65\u0b70-\u0b81\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0bbd\u0bc3-\u0bc5\u0bc9\u0bce-\u0bd6\u0bd8-\u0be6\u0bf0-\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c3d\u0c45\u0c49\u0c4e-\u0c54\u0c57-\u0c5f\u0c62-\u0c65\u0c70-\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cbd\u0cc5\u0cc9\u0cce-\u0cd4\u0cd7-\u0cdd\u0cdf\u0ce2-\u0ce5\u0cf0-\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d3d\u0d44-\u0d45\u0d49\u0d4e-\u0d56\u0d58-\u0d5f\u0d62-\u0d65\u0d70-\u0e00\u0e2f\u0e3b-\u0e3f\u0e4f\u0e5a-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eba\u0ebe-\u0ebf\u0ec5\u0ec7\u0ece-\u0ecf\u0eda-\u0f17\u0f1a-\u0f1f\u0f2a-\u0f34\u0f36\u0f38\u0f3a-\u0f3d\u0f48\u0f6a-\u0f70\u0f85\u0f8c-\u0f8f\u0f96\u0f98\u0fae-\u0fb0\u0fb8\u0fba-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u20cf\u20dd-\u20e0\u20e2-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3004\u3006\u3008-\u3020\u3030\u3036-\u3040\u3095-\u3098\u309b-\u309c\u309f-\u30a0\u30fb\u30ff-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]') + +nonXmlNameFirstBMPRegexp = re.compile('[\x00-@\\[-\\^`\\{-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u0385\u0387\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u0640\u064b-\u0670\u06b8-\u06b9\u06bf\u06cf\u06d4\u06d6-\u06e4\u06e7-\u0904\u093a-\u093c\u093e-\u0957\u0962-\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09db\u09de\u09e2-\u09ef\u09f2-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a58\u0a5d\u0a5f-\u0a71\u0a75-\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abc\u0abe-\u0adf\u0ae1-\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3c\u0b3e-\u0b5b\u0b5e\u0b62-\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c5f\u0c62-\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cdd\u0cdf\u0ce2-\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d5f\u0d62-\u0e00\u0e2f\u0e31\u0e34-\u0e3f\u0e46-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eb1\u0eb4-\u0ebc\u0ebe-\u0ebf\u0ec5-\u0f3f\u0f48\u0f6a-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3006\u3008-\u3020\u302a-\u3040\u3095-\u30a0\u30fb-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]') + +# Simpler things +nonPubidCharRegexp = re.compile("[^\x20\x0D\x0Aa-zA-Z0-9\-\'()+,./:=?;!*#@$_%]") + + +class InfosetFilter(object): + replacementRegexp = re.compile(r"U[\dA-F]{5,5}") + + def __init__(self, replaceChars=None, + dropXmlnsLocalName=False, + dropXmlnsAttrNs=False, + preventDoubleDashComments=False, + preventDashAtCommentEnd=False, + replaceFormFeedCharacters=True, + preventSingleQuotePubid=False): + + self.dropXmlnsLocalName = dropXmlnsLocalName + self.dropXmlnsAttrNs = dropXmlnsAttrNs + + self.preventDoubleDashComments = preventDoubleDashComments + self.preventDashAtCommentEnd = preventDashAtCommentEnd + + self.replaceFormFeedCharacters = replaceFormFeedCharacters + + self.preventSingleQuotePubid = preventSingleQuotePubid + + self.replaceCache = {} + + def coerceAttribute(self, name, namespace=None): + if self.dropXmlnsLocalName and name.startswith("xmlns:"): + warnings.warn("Attributes cannot begin with xmlns", DataLossWarning) + return None + elif (self.dropXmlnsAttrNs and + namespace == "http://www.w3.org/2000/xmlns/"): + warnings.warn("Attributes cannot be in the xml namespace", DataLossWarning) + return None + else: + return self.toXmlName(name) + + def coerceElement(self, name, namespace=None): + return self.toXmlName(name) + + def coerceComment(self, data): + if self.preventDoubleDashComments: + while "--" in data: + warnings.warn("Comments cannot contain adjacent dashes", DataLossWarning) + data = data.replace("--", "- -") + return data + + def coerceCharacters(self, data): + if self.replaceFormFeedCharacters: + for i in range(data.count("\x0C")): + warnings.warn("Text cannot contain U+000C", DataLossWarning) + data = data.replace("\x0C", " ") + # Other non-xml characters + return data + + def coercePubid(self, data): + dataOutput = data + for char in nonPubidCharRegexp.findall(data): + warnings.warn("Coercing non-XML pubid", DataLossWarning) + replacement = self.getReplacementCharacter(char) + dataOutput = dataOutput.replace(char, replacement) + if self.preventSingleQuotePubid and dataOutput.find("'") >= 0: + warnings.warn("Pubid cannot contain single quote", DataLossWarning) + dataOutput = dataOutput.replace("'", self.getReplacementCharacter("'")) + return dataOutput + + def toXmlName(self, name): + nameFirst = name[0] + nameRest = name[1:] + m = nonXmlNameFirstBMPRegexp.match(nameFirst) + if m: + warnings.warn("Coercing non-XML name", DataLossWarning) + nameFirstOutput = self.getReplacementCharacter(nameFirst) + else: + nameFirstOutput = nameFirst + + nameRestOutput = nameRest + replaceChars = set(nonXmlNameBMPRegexp.findall(nameRest)) + for char in replaceChars: + warnings.warn("Coercing non-XML name", DataLossWarning) + replacement = self.getReplacementCharacter(char) + nameRestOutput = nameRestOutput.replace(char, replacement) + return nameFirstOutput + nameRestOutput + + def getReplacementCharacter(self, char): + if char in self.replaceCache: + replacement = self.replaceCache[char] + else: + replacement = self.escapeChar(char) + return replacement + + def fromXmlName(self, name): + for item in set(self.replacementRegexp.findall(name)): + name = name.replace(item, self.unescapeChar(item)) + return name + + def escapeChar(self, char): + replacement = "U%05X" % ord(char) + self.replaceCache[char] = replacement + return replacement + + def unescapeChar(self, charcode): + return chr(int(charcode[1:], 16)) diff --git a/catapult/third_party/html5lib-python/html5lib/inputstream.py b/catapult/third_party/html5lib-python/html5lib/inputstream.py new file mode 100644 index 00000000..7020aa60 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/inputstream.py @@ -0,0 +1,903 @@ +from __future__ import absolute_import, division, unicode_literals +from six import text_type +from six.moves import http_client + +import codecs +import re + +from .constants import EOF, spaceCharacters, asciiLetters, asciiUppercase +from .constants import encodings, ReparseException +from . import utils + +from io import StringIO + +try: + from io import BytesIO +except ImportError: + BytesIO = StringIO + +try: + from io import BufferedIOBase +except ImportError: + class BufferedIOBase(object): + pass + +# Non-unicode versions of constants for use in the pre-parser +spaceCharactersBytes = frozenset([item.encode("ascii") for item in spaceCharacters]) +asciiLettersBytes = frozenset([item.encode("ascii") for item in asciiLetters]) +asciiUppercaseBytes = frozenset([item.encode("ascii") for item in asciiUppercase]) +spacesAngleBrackets = spaceCharactersBytes | frozenset([b">", b"<"]) + + +invalid_unicode_no_surrogate = "[\u0001-\u0008\u000B\u000E-\u001F\u007F-\u009F\uFDD0-\uFDEF\uFFFE\uFFFF\U0001FFFE\U0001FFFF\U0002FFFE\U0002FFFF\U0003FFFE\U0003FFFF\U0004FFFE\U0004FFFF\U0005FFFE\U0005FFFF\U0006FFFE\U0006FFFF\U0007FFFE\U0007FFFF\U0008FFFE\U0008FFFF\U0009FFFE\U0009FFFF\U000AFFFE\U000AFFFF\U000BFFFE\U000BFFFF\U000CFFFE\U000CFFFF\U000DFFFE\U000DFFFF\U000EFFFE\U000EFFFF\U000FFFFE\U000FFFFF\U0010FFFE\U0010FFFF]" + +if utils.supports_lone_surrogates: + # Use one extra step of indirection and create surrogates with + # unichr. Not using this indirection would introduce an illegal + # unicode literal on platforms not supporting such lone + # surrogates. + invalid_unicode_re = re.compile(invalid_unicode_no_surrogate + + eval('"\\uD800-\\uDFFF"')) +else: + invalid_unicode_re = re.compile(invalid_unicode_no_surrogate) + +non_bmp_invalid_codepoints = set([0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, + 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, + 0x6FFFE, 0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, + 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, + 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, + 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, + 0x10FFFE, 0x10FFFF]) + +ascii_punctuation_re = re.compile("[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]") + +# Cache for charsUntil() +charsUntilRegEx = {} + + +class BufferedStream(object): + """Buffering for streams that do not have buffering of their own + + The buffer is implemented as a list of chunks on the assumption that + joining many strings will be slow since it is O(n**2) + """ + + def __init__(self, stream): + self.stream = stream + self.buffer = [] + self.position = [-1, 0] # chunk number, offset + + def tell(self): + pos = 0 + for chunk in self.buffer[:self.position[0]]: + pos += len(chunk) + pos += self.position[1] + return pos + + def seek(self, pos): + assert pos <= self._bufferedBytes() + offset = pos + i = 0 + while len(self.buffer[i]) < offset: + offset -= len(self.buffer[i]) + i += 1 + self.position = [i, offset] + + def read(self, bytes): + if not self.buffer: + return self._readStream(bytes) + elif (self.position[0] == len(self.buffer) and + self.position[1] == len(self.buffer[-1])): + return self._readStream(bytes) + else: + return self._readFromBuffer(bytes) + + def _bufferedBytes(self): + return sum([len(item) for item in self.buffer]) + + def _readStream(self, bytes): + data = self.stream.read(bytes) + self.buffer.append(data) + self.position[0] += 1 + self.position[1] = len(data) + return data + + def _readFromBuffer(self, bytes): + remainingBytes = bytes + rv = [] + bufferIndex = self.position[0] + bufferOffset = self.position[1] + while bufferIndex < len(self.buffer) and remainingBytes != 0: + assert remainingBytes > 0 + bufferedData = self.buffer[bufferIndex] + + if remainingBytes <= len(bufferedData) - bufferOffset: + bytesToRead = remainingBytes + self.position = [bufferIndex, bufferOffset + bytesToRead] + else: + bytesToRead = len(bufferedData) - bufferOffset + self.position = [bufferIndex, len(bufferedData)] + bufferIndex += 1 + rv.append(bufferedData[bufferOffset:bufferOffset + bytesToRead]) + remainingBytes -= bytesToRead + + bufferOffset = 0 + + if remainingBytes: + rv.append(self._readStream(remainingBytes)) + + return b"".join(rv) + + +def HTMLInputStream(source, encoding=None, parseMeta=True, chardet=True): + if isinstance(source, http_client.HTTPResponse): + # Work around Python bug #20007: read(0) closes the connection. + # http://bugs.python.org/issue20007 + isUnicode = False + elif hasattr(source, "read"): + isUnicode = isinstance(source.read(0), text_type) + else: + isUnicode = isinstance(source, text_type) + + if isUnicode: + if encoding is not None: + raise TypeError("Cannot explicitly set an encoding with a unicode string") + + return HTMLUnicodeInputStream(source) + else: + return HTMLBinaryInputStream(source, encoding, parseMeta, chardet) + + +class HTMLUnicodeInputStream(object): + """Provides a unicode stream of characters to the HTMLTokenizer. + + This class takes care of character encoding and removing or replacing + incorrect byte-sequences and also provides column and line tracking. + + """ + + _defaultChunkSize = 10240 + + def __init__(self, source): + """Initialises the HTMLInputStream. + + HTMLInputStream(source, [encoding]) -> Normalized stream from source + for use by html5lib. + + source can be either a file-object, local filename or a string. + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element) + + parseMeta - Look for a <meta> element containing encoding information + + """ + + if not utils.supports_lone_surrogates: + # Such platforms will have already checked for such + # surrogate errors, so no need to do this checking. + self.reportCharacterErrors = None + self.replaceCharactersRegexp = None + elif len("\U0010FFFF") == 1: + self.reportCharacterErrors = self.characterErrorsUCS4 + self.replaceCharactersRegexp = re.compile(eval('"[\\uD800-\\uDFFF]"')) + else: + self.reportCharacterErrors = self.characterErrorsUCS2 + self.replaceCharactersRegexp = re.compile( + eval('"([\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF])"')) + + # List of where new lines occur + self.newLines = [0] + + self.charEncoding = ("utf-8", "certain") + self.dataStream = self.openStream(source) + + self.reset() + + def reset(self): + self.chunk = "" + self.chunkSize = 0 + self.chunkOffset = 0 + self.errors = [] + + # number of (complete) lines in previous chunks + self.prevNumLines = 0 + # number of columns in the last line of the previous chunk + self.prevNumCols = 0 + + # Deal with CR LF and surrogates split over chunk boundaries + self._bufferedCharacter = None + + def openStream(self, source): + """Produces a file object from source. + + source can be either a file object, local filename or a string. + + """ + # Already a file object + if hasattr(source, 'read'): + stream = source + else: + stream = StringIO(source) + + return stream + + def _position(self, offset): + chunk = self.chunk + nLines = chunk.count('\n', 0, offset) + positionLine = self.prevNumLines + nLines + lastLinePos = chunk.rfind('\n', 0, offset) + if lastLinePos == -1: + positionColumn = self.prevNumCols + offset + else: + positionColumn = offset - (lastLinePos + 1) + return (positionLine, positionColumn) + + def position(self): + """Returns (line, col) of the current position in the stream.""" + line, col = self._position(self.chunkOffset) + return (line + 1, col) + + def char(self): + """ Read one character from the stream or queue if available. Return + EOF when EOF is reached. + """ + # Read a new chunk from the input stream if necessary + if self.chunkOffset >= self.chunkSize: + if not self.readChunk(): + return EOF + + chunkOffset = self.chunkOffset + char = self.chunk[chunkOffset] + self.chunkOffset = chunkOffset + 1 + + return char + + def readChunk(self, chunkSize=None): + if chunkSize is None: + chunkSize = self._defaultChunkSize + + self.prevNumLines, self.prevNumCols = self._position(self.chunkSize) + + self.chunk = "" + self.chunkSize = 0 + self.chunkOffset = 0 + + data = self.dataStream.read(chunkSize) + + # Deal with CR LF and surrogates broken across chunks + if self._bufferedCharacter: + data = self._bufferedCharacter + data + self._bufferedCharacter = None + elif not data: + # We have no more data, bye-bye stream + return False + + if len(data) > 1: + lastv = ord(data[-1]) + if lastv == 0x0D or 0xD800 <= lastv <= 0xDBFF: + self._bufferedCharacter = data[-1] + data = data[:-1] + + if self.reportCharacterErrors: + self.reportCharacterErrors(data) + + # Replace invalid characters + # Note U+0000 is dealt with in the tokenizer + data = self.replaceCharactersRegexp.sub("\ufffd", data) + + data = data.replace("\r\n", "\n") + data = data.replace("\r", "\n") + + self.chunk = data + self.chunkSize = len(data) + + return True + + def characterErrorsUCS4(self, data): + for i in range(len(invalid_unicode_re.findall(data))): + self.errors.append("invalid-codepoint") + + def characterErrorsUCS2(self, data): + # Someone picked the wrong compile option + # You lose + skip = False + for match in invalid_unicode_re.finditer(data): + if skip: + continue + codepoint = ord(match.group()) + pos = match.start() + # Pretty sure there should be endianness issues here + if utils.isSurrogatePair(data[pos:pos + 2]): + # We have a surrogate pair! + char_val = utils.surrogatePairToCodepoint(data[pos:pos + 2]) + if char_val in non_bmp_invalid_codepoints: + self.errors.append("invalid-codepoint") + skip = True + elif (codepoint >= 0xD800 and codepoint <= 0xDFFF and + pos == len(data) - 1): + self.errors.append("invalid-codepoint") + else: + skip = False + self.errors.append("invalid-codepoint") + + def charsUntil(self, characters, opposite=False): + """ Returns a string of characters from the stream up to but not + including any character in 'characters' or EOF. 'characters' must be + a container that supports the 'in' method and iteration over its + characters. + """ + + # Use a cache of regexps to find the required characters + try: + chars = charsUntilRegEx[(characters, opposite)] + except KeyError: + if __debug__: + for c in characters: + assert(ord(c) < 128) + regex = "".join(["\\x%02x" % ord(c) for c in characters]) + if not opposite: + regex = "^%s" % regex + chars = charsUntilRegEx[(characters, opposite)] = re.compile("[%s]+" % regex) + + rv = [] + + while True: + # Find the longest matching prefix + m = chars.match(self.chunk, self.chunkOffset) + if m is None: + # If nothing matched, and it wasn't because we ran out of chunk, + # then stop + if self.chunkOffset != self.chunkSize: + break + else: + end = m.end() + # If not the whole chunk matched, return everything + # up to the part that didn't match + if end != self.chunkSize: + rv.append(self.chunk[self.chunkOffset:end]) + self.chunkOffset = end + break + # If the whole remainder of the chunk matched, + # use it all and read the next chunk + rv.append(self.chunk[self.chunkOffset:]) + if not self.readChunk(): + # Reached EOF + break + + r = "".join(rv) + return r + + def unget(self, char): + # Only one character is allowed to be ungotten at once - it must + # be consumed again before any further call to unget + if char is not None: + if self.chunkOffset == 0: + # unget is called quite rarely, so it's a good idea to do + # more work here if it saves a bit of work in the frequently + # called char and charsUntil. + # So, just prepend the ungotten character onto the current + # chunk: + self.chunk = char + self.chunk + self.chunkSize += 1 + else: + self.chunkOffset -= 1 + assert self.chunk[self.chunkOffset] == char + + +class HTMLBinaryInputStream(HTMLUnicodeInputStream): + """Provides a unicode stream of characters to the HTMLTokenizer. + + This class takes care of character encoding and removing or replacing + incorrect byte-sequences and also provides column and line tracking. + + """ + + def __init__(self, source, encoding=None, parseMeta=True, chardet=True): + """Initialises the HTMLInputStream. + + HTMLInputStream(source, [encoding]) -> Normalized stream from source + for use by html5lib. + + source can be either a file-object, local filename or a string. + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element) + + parseMeta - Look for a <meta> element containing encoding information + + """ + # Raw Stream - for unicode objects this will encode to utf-8 and set + # self.charEncoding as appropriate + self.rawStream = self.openStream(source) + + HTMLUnicodeInputStream.__init__(self, self.rawStream) + + self.charEncoding = (codecName(encoding), "certain") + + # Encoding Information + # Number of bytes to use when looking for a meta element with + # encoding information + self.numBytesMeta = 512 + # Number of bytes to use when using detecting encoding using chardet + self.numBytesChardet = 100 + # Encoding to use if no other information can be found + self.defaultEncoding = "windows-1252" + + # Detect encoding iff no explicit "transport level" encoding is supplied + if (self.charEncoding[0] is None): + self.charEncoding = self.detectEncoding(parseMeta, chardet) + + # Call superclass + self.reset() + + def reset(self): + self.dataStream = codecs.getreader(self.charEncoding[0])(self.rawStream, + 'replace') + HTMLUnicodeInputStream.reset(self) + + def openStream(self, source): + """Produces a file object from source. + + source can be either a file object, local filename or a string. + + """ + # Already a file object + if hasattr(source, 'read'): + stream = source + else: + stream = BytesIO(source) + + try: + stream.seek(stream.tell()) + except: + stream = BufferedStream(stream) + + return stream + + def detectEncoding(self, parseMeta=True, chardet=True): + # First look for a BOM + # This will also read past the BOM if present + encoding = self.detectBOM() + confidence = "certain" + # If there is no BOM need to look for meta elements with encoding + # information + if encoding is None and parseMeta: + encoding = self.detectEncodingMeta() + confidence = "tentative" + # Guess with chardet, if avaliable + if encoding is None and chardet: + confidence = "tentative" + try: + try: + from charade.universaldetector import UniversalDetector + except ImportError: + from chardet.universaldetector import UniversalDetector + buffers = [] + detector = UniversalDetector() + while not detector.done: + buffer = self.rawStream.read(self.numBytesChardet) + assert isinstance(buffer, bytes) + if not buffer: + break + buffers.append(buffer) + detector.feed(buffer) + detector.close() + encoding = detector.result['encoding'] + self.rawStream.seek(0) + except ImportError: + pass + # If all else fails use the default encoding + if encoding is None: + confidence = "tentative" + encoding = self.defaultEncoding + + # Substitute for equivalent encodings: + encodingSub = {"iso-8859-1": "windows-1252"} + + if encoding.lower() in encodingSub: + encoding = encodingSub[encoding.lower()] + + return encoding, confidence + + def changeEncoding(self, newEncoding): + assert self.charEncoding[1] != "certain" + newEncoding = codecName(newEncoding) + if newEncoding in ("utf-16", "utf-16-be", "utf-16-le"): + newEncoding = "utf-8" + if newEncoding is None: + return + elif newEncoding == self.charEncoding[0]: + self.charEncoding = (self.charEncoding[0], "certain") + else: + self.rawStream.seek(0) + self.reset() + self.charEncoding = (newEncoding, "certain") + raise ReparseException("Encoding changed from %s to %s" % (self.charEncoding[0], newEncoding)) + + def detectBOM(self): + """Attempts to detect at BOM at the start of the stream. If + an encoding can be determined from the BOM return the name of the + encoding otherwise return None""" + bomDict = { + codecs.BOM_UTF8: 'utf-8', + codecs.BOM_UTF16_LE: 'utf-16-le', codecs.BOM_UTF16_BE: 'utf-16-be', + codecs.BOM_UTF32_LE: 'utf-32-le', codecs.BOM_UTF32_BE: 'utf-32-be' + } + + # Go to beginning of file and read in 4 bytes + string = self.rawStream.read(4) + assert isinstance(string, bytes) + + # Try detecting the BOM using bytes from the string + encoding = bomDict.get(string[:3]) # UTF-8 + seek = 3 + if not encoding: + # Need to detect UTF-32 before UTF-16 + encoding = bomDict.get(string) # UTF-32 + seek = 4 + if not encoding: + encoding = bomDict.get(string[:2]) # UTF-16 + seek = 2 + + # Set the read position past the BOM if one was found, otherwise + # set it to the start of the stream + self.rawStream.seek(encoding and seek or 0) + + return encoding + + def detectEncodingMeta(self): + """Report the encoding declared by the meta element + """ + buffer = self.rawStream.read(self.numBytesMeta) + assert isinstance(buffer, bytes) + parser = EncodingParser(buffer) + self.rawStream.seek(0) + encoding = parser.getEncoding() + + if encoding in ("utf-16", "utf-16-be", "utf-16-le"): + encoding = "utf-8" + + return encoding + + +class EncodingBytes(bytes): + """String-like object with an associated position and various extra methods + If the position is ever greater than the string length then an exception is + raised""" + def __new__(self, value): + assert isinstance(value, bytes) + return bytes.__new__(self, value.lower()) + + def __init__(self, value): + self._position = -1 + + def __iter__(self): + return self + + def __next__(self): + p = self._position = self._position + 1 + if p >= len(self): + raise StopIteration + elif p < 0: + raise TypeError + return self[p:p + 1] + + def next(self): + # Py2 compat + return self.__next__() + + def previous(self): + p = self._position + if p >= len(self): + raise StopIteration + elif p < 0: + raise TypeError + self._position = p = p - 1 + return self[p:p + 1] + + def setPosition(self, position): + if self._position >= len(self): + raise StopIteration + self._position = position + + def getPosition(self): + if self._position >= len(self): + raise StopIteration + if self._position >= 0: + return self._position + else: + return None + + position = property(getPosition, setPosition) + + def getCurrentByte(self): + return self[self.position:self.position + 1] + + currentByte = property(getCurrentByte) + + def skip(self, chars=spaceCharactersBytes): + """Skip past a list of characters""" + p = self.position # use property for the error-checking + while p < len(self): + c = self[p:p + 1] + if c not in chars: + self._position = p + return c + p += 1 + self._position = p + return None + + def skipUntil(self, chars): + p = self.position + while p < len(self): + c = self[p:p + 1] + if c in chars: + self._position = p + return c + p += 1 + self._position = p + return None + + def matchBytes(self, bytes): + """Look for a sequence of bytes at the start of a string. If the bytes + are found return True and advance the position to the byte after the + match. Otherwise return False and leave the position alone""" + p = self.position + data = self[p:p + len(bytes)] + rv = data.startswith(bytes) + if rv: + self.position += len(bytes) + return rv + + def jumpTo(self, bytes): + """Look for the next sequence of bytes matching a given sequence. If + a match is found advance the position to the last byte of the match""" + newPosition = self[self.position:].find(bytes) + if newPosition > -1: + # XXX: This is ugly, but I can't see a nicer way to fix this. + if self._position == -1: + self._position = 0 + self._position += (newPosition + len(bytes) - 1) + return True + else: + raise StopIteration + + +class EncodingParser(object): + """Mini parser for detecting character encoding from meta elements""" + + def __init__(self, data): + """string - the data to work on for encoding detection""" + self.data = EncodingBytes(data) + self.encoding = None + + def getEncoding(self): + methodDispatch = ( + (b"<!--", self.handleComment), + (b"<meta", self.handleMeta), + (b"</", self.handlePossibleEndTag), + (b"<!", self.handleOther), + (b"<?", self.handleOther), + (b"<", self.handlePossibleStartTag)) + for byte in self.data: + keepParsing = True + for key, method in methodDispatch: + if self.data.matchBytes(key): + try: + keepParsing = method() + break + except StopIteration: + keepParsing = False + break + if not keepParsing: + break + + return self.encoding + + def handleComment(self): + """Skip over comments""" + return self.data.jumpTo(b"-->") + + def handleMeta(self): + if self.data.currentByte not in spaceCharactersBytes: + # if we have <meta not followed by a space so just keep going + return True + # We have a valid meta element we want to search for attributes + hasPragma = False + pendingEncoding = None + while True: + # Try to find the next attribute after the current position + attr = self.getAttribute() + if attr is None: + return True + else: + if attr[0] == b"http-equiv": + hasPragma = attr[1] == b"content-type" + if hasPragma and pendingEncoding is not None: + self.encoding = pendingEncoding + return False + elif attr[0] == b"charset": + tentativeEncoding = attr[1] + codec = codecName(tentativeEncoding) + if codec is not None: + self.encoding = codec + return False + elif attr[0] == b"content": + contentParser = ContentAttrParser(EncodingBytes(attr[1])) + tentativeEncoding = contentParser.parse() + if tentativeEncoding is not None: + codec = codecName(tentativeEncoding) + if codec is not None: + if hasPragma: + self.encoding = codec + return False + else: + pendingEncoding = codec + + def handlePossibleStartTag(self): + return self.handlePossibleTag(False) + + def handlePossibleEndTag(self): + next(self.data) + return self.handlePossibleTag(True) + + def handlePossibleTag(self, endTag): + data = self.data + if data.currentByte not in asciiLettersBytes: + # If the next byte is not an ascii letter either ignore this + # fragment (possible start tag case) or treat it according to + # handleOther + if endTag: + data.previous() + self.handleOther() + return True + + c = data.skipUntil(spacesAngleBrackets) + if c == b"<": + # return to the first step in the overall "two step" algorithm + # reprocessing the < byte + data.previous() + else: + # Read all attributes + attr = self.getAttribute() + while attr is not None: + attr = self.getAttribute() + return True + + def handleOther(self): + return self.data.jumpTo(b">") + + def getAttribute(self): + """Return a name,value pair for the next attribute in the stream, + if one is found, or None""" + data = self.data + # Step 1 (skip chars) + c = data.skip(spaceCharactersBytes | frozenset([b"/"])) + assert c is None or len(c) == 1 + # Step 2 + if c in (b">", None): + return None + # Step 3 + attrName = [] + attrValue = [] + # Step 4 attribute name + while True: + if c == b"=" and attrName: + break + elif c in spaceCharactersBytes: + # Step 6! + c = data.skip() + break + elif c in (b"/", b">"): + return b"".join(attrName), b"" + elif c in asciiUppercaseBytes: + attrName.append(c.lower()) + elif c is None: + return None + else: + attrName.append(c) + # Step 5 + c = next(data) + # Step 7 + if c != b"=": + data.previous() + return b"".join(attrName), b"" + # Step 8 + next(data) + # Step 9 + c = data.skip() + # Step 10 + if c in (b"'", b'"'): + # 10.1 + quoteChar = c + while True: + # 10.2 + c = next(data) + # 10.3 + if c == quoteChar: + next(data) + return b"".join(attrName), b"".join(attrValue) + # 10.4 + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + # 10.5 + else: + attrValue.append(c) + elif c == b">": + return b"".join(attrName), b"" + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + elif c is None: + return None + else: + attrValue.append(c) + # Step 11 + while True: + c = next(data) + if c in spacesAngleBrackets: + return b"".join(attrName), b"".join(attrValue) + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + elif c is None: + return None + else: + attrValue.append(c) + + +class ContentAttrParser(object): + def __init__(self, data): + assert isinstance(data, bytes) + self.data = data + + def parse(self): + try: + # Check if the attr name is charset + # otherwise return + self.data.jumpTo(b"charset") + self.data.position += 1 + self.data.skip() + if not self.data.currentByte == b"=": + # If there is no = sign keep looking for attrs + return None + self.data.position += 1 + self.data.skip() + # Look for an encoding between matching quote marks + if self.data.currentByte in (b'"', b"'"): + quoteMark = self.data.currentByte + self.data.position += 1 + oldPosition = self.data.position + if self.data.jumpTo(quoteMark): + return self.data[oldPosition:self.data.position] + else: + return None + else: + # Unquoted value + oldPosition = self.data.position + try: + self.data.skipUntil(spaceCharactersBytes) + return self.data[oldPosition:self.data.position] + except StopIteration: + # Return the whole remaining value + return self.data[oldPosition:] + except StopIteration: + return None + + +def codecName(encoding): + """Return the python codec name corresponding to an encoding or None if the + string doesn't correspond to a valid encoding.""" + if isinstance(encoding, bytes): + try: + encoding = encoding.decode("ascii") + except UnicodeDecodeError: + return None + if encoding: + canonicalName = ascii_punctuation_re.sub("", encoding).lower() + return encodings.get(canonicalName, None) + else: + return None diff --git a/catapult/third_party/html5lib-python/html5lib/sanitizer.py b/catapult/third_party/html5lib-python/html5lib/sanitizer.py new file mode 100644 index 00000000..2cef2655 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/sanitizer.py @@ -0,0 +1,296 @@ +from __future__ import absolute_import, division, unicode_literals + +import re +from xml.sax.saxutils import escape, unescape +from six.moves import urllib_parse as urlparse + +from .tokenizer import HTMLTokenizer +from .constants import tokenTypes + + +content_type_rgx = re.compile(r''' + ^ + # Match a content type <application>/<type> + (?P<content_type>[-a-zA-Z0-9.]+/[-a-zA-Z0-9.]+) + # Match any character set and encoding + (?:(?:;charset=(?:[-a-zA-Z0-9]+)(?:;(?:base64))?) + |(?:;(?:base64))?(?:;charset=(?:[-a-zA-Z0-9]+))?) + # Assume the rest is data + ,.* + $ + ''', + re.VERBOSE) + + +class HTMLSanitizerMixin(object): + """ sanitization of XHTML+MathML+SVG and of inline style attributes.""" + + acceptable_elements = ['a', 'abbr', 'acronym', 'address', 'area', + 'article', 'aside', 'audio', 'b', 'big', 'blockquote', 'br', 'button', + 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', + 'command', 'datagrid', 'datalist', 'dd', 'del', 'details', 'dfn', + 'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'event-source', 'fieldset', + 'figcaption', 'figure', 'footer', 'font', 'form', 'header', 'h1', + 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'input', 'ins', + 'keygen', 'kbd', 'label', 'legend', 'li', 'm', 'map', 'menu', 'meter', + 'multicol', 'nav', 'nextid', 'ol', 'output', 'optgroup', 'option', + 'p', 'pre', 'progress', 'q', 's', 'samp', 'section', 'select', + 'small', 'sound', 'source', 'spacer', 'span', 'strike', 'strong', + 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'time', 'tfoot', + 'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var', 'video'] + + mathml_elements = ['maction', 'math', 'merror', 'mfrac', 'mi', + 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', + 'mprescripts', 'mroot', 'mrow', 'mspace', 'msqrt', 'mstyle', 'msub', + 'msubsup', 'msup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', + 'munderover', 'none'] + + svg_elements = ['a', 'animate', 'animateColor', 'animateMotion', + 'animateTransform', 'clipPath', 'circle', 'defs', 'desc', 'ellipse', + 'font-face', 'font-face-name', 'font-face-src', 'g', 'glyph', 'hkern', + 'linearGradient', 'line', 'marker', 'metadata', 'missing-glyph', + 'mpath', 'path', 'polygon', 'polyline', 'radialGradient', 'rect', + 'set', 'stop', 'svg', 'switch', 'text', 'title', 'tspan', 'use'] + + acceptable_attributes = ['abbr', 'accept', 'accept-charset', 'accesskey', + 'action', 'align', 'alt', 'autocomplete', 'autofocus', 'axis', + 'background', 'balance', 'bgcolor', 'bgproperties', 'border', + 'bordercolor', 'bordercolordark', 'bordercolorlight', 'bottompadding', + 'cellpadding', 'cellspacing', 'ch', 'challenge', 'char', 'charoff', + 'choff', 'charset', 'checked', 'cite', 'class', 'clear', 'color', + 'cols', 'colspan', 'compact', 'contenteditable', 'controls', 'coords', + 'data', 'datafld', 'datapagesize', 'datasrc', 'datetime', 'default', + 'delay', 'dir', 'disabled', 'draggable', 'dynsrc', 'enctype', 'end', + 'face', 'for', 'form', 'frame', 'galleryimg', 'gutter', 'headers', + 'height', 'hidefocus', 'hidden', 'high', 'href', 'hreflang', 'hspace', + 'icon', 'id', 'inputmode', 'ismap', 'keytype', 'label', 'leftspacing', + 'lang', 'list', 'longdesc', 'loop', 'loopcount', 'loopend', + 'loopstart', 'low', 'lowsrc', 'max', 'maxlength', 'media', 'method', + 'min', 'multiple', 'name', 'nohref', 'noshade', 'nowrap', 'open', + 'optimum', 'pattern', 'ping', 'point-size', 'poster', 'pqg', 'preload', + 'prompt', 'radiogroup', 'readonly', 'rel', 'repeat-max', 'repeat-min', + 'replace', 'required', 'rev', 'rightspacing', 'rows', 'rowspan', + 'rules', 'scope', 'selected', 'shape', 'size', 'span', 'src', 'start', + 'step', 'style', 'summary', 'suppress', 'tabindex', 'target', + 'template', 'title', 'toppadding', 'type', 'unselectable', 'usemap', + 'urn', 'valign', 'value', 'variable', 'volume', 'vspace', 'vrml', + 'width', 'wrap', 'xml:lang'] + + mathml_attributes = ['actiontype', 'align', 'columnalign', 'columnalign', + 'columnalign', 'columnlines', 'columnspacing', 'columnspan', 'depth', + 'display', 'displaystyle', 'equalcolumns', 'equalrows', 'fence', + 'fontstyle', 'fontweight', 'frame', 'height', 'linethickness', 'lspace', + 'mathbackground', 'mathcolor', 'mathvariant', 'mathvariant', 'maxsize', + 'minsize', 'other', 'rowalign', 'rowalign', 'rowalign', 'rowlines', + 'rowspacing', 'rowspan', 'rspace', 'scriptlevel', 'selection', + 'separator', 'stretchy', 'width', 'width', 'xlink:href', 'xlink:show', + 'xlink:type', 'xmlns', 'xmlns:xlink'] + + svg_attributes = ['accent-height', 'accumulate', 'additive', 'alphabetic', + 'arabic-form', 'ascent', 'attributeName', 'attributeType', + 'baseProfile', 'bbox', 'begin', 'by', 'calcMode', 'cap-height', + 'class', 'clip-path', 'color', 'color-rendering', 'content', 'cx', + 'cy', 'd', 'dx', 'dy', 'descent', 'display', 'dur', 'end', 'fill', + 'fill-opacity', 'fill-rule', 'font-family', 'font-size', + 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'from', + 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'gradientUnits', 'hanging', + 'height', 'horiz-adv-x', 'horiz-origin-x', 'id', 'ideographic', 'k', + 'keyPoints', 'keySplines', 'keyTimes', 'lang', 'marker-end', + 'marker-mid', 'marker-start', 'markerHeight', 'markerUnits', + 'markerWidth', 'mathematical', 'max', 'min', 'name', 'offset', + 'opacity', 'orient', 'origin', 'overline-position', + 'overline-thickness', 'panose-1', 'path', 'pathLength', 'points', + 'preserveAspectRatio', 'r', 'refX', 'refY', 'repeatCount', + 'repeatDur', 'requiredExtensions', 'requiredFeatures', 'restart', + 'rotate', 'rx', 'ry', 'slope', 'stemh', 'stemv', 'stop-color', + 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness', + 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', + 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', + 'stroke-width', 'systemLanguage', 'target', 'text-anchor', 'to', + 'transform', 'type', 'u1', 'u2', 'underline-position', + 'underline-thickness', 'unicode', 'unicode-range', 'units-per-em', + 'values', 'version', 'viewBox', 'visibility', 'width', 'widths', 'x', + 'x-height', 'x1', 'x2', 'xlink:actuate', 'xlink:arcrole', + 'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type', + 'xml:base', 'xml:lang', 'xml:space', 'xmlns', 'xmlns:xlink', 'y', + 'y1', 'y2', 'zoomAndPan'] + + attr_val_is_uri = ['href', 'src', 'cite', 'action', 'longdesc', 'poster', 'background', 'datasrc', + 'dynsrc', 'lowsrc', 'ping', 'poster', 'xlink:href', 'xml:base'] + + svg_attr_val_allows_ref = ['clip-path', 'color-profile', 'cursor', 'fill', + 'filter', 'marker', 'marker-start', 'marker-mid', 'marker-end', + 'mask', 'stroke'] + + svg_allow_local_href = ['altGlyph', 'animate', 'animateColor', + 'animateMotion', 'animateTransform', 'cursor', 'feImage', 'filter', + 'linearGradient', 'pattern', 'radialGradient', 'textpath', 'tref', + 'set', 'use'] + + acceptable_css_properties = ['azimuth', 'background-color', + 'border-bottom-color', 'border-collapse', 'border-color', + 'border-left-color', 'border-right-color', 'border-top-color', 'clear', + 'color', 'cursor', 'direction', 'display', 'elevation', 'float', 'font', + 'font-family', 'font-size', 'font-style', 'font-variant', 'font-weight', + 'height', 'letter-spacing', 'line-height', 'overflow', 'pause', + 'pause-after', 'pause-before', 'pitch', 'pitch-range', 'richness', + 'speak', 'speak-header', 'speak-numeral', 'speak-punctuation', + 'speech-rate', 'stress', 'text-align', 'text-decoration', 'text-indent', + 'unicode-bidi', 'vertical-align', 'voice-family', 'volume', + 'white-space', 'width'] + + acceptable_css_keywords = ['auto', 'aqua', 'black', 'block', 'blue', + 'bold', 'both', 'bottom', 'brown', 'center', 'collapse', 'dashed', + 'dotted', 'fuchsia', 'gray', 'green', '!important', 'italic', 'left', + 'lime', 'maroon', 'medium', 'none', 'navy', 'normal', 'nowrap', 'olive', + 'pointer', 'purple', 'red', 'right', 'solid', 'silver', 'teal', 'top', + 'transparent', 'underline', 'white', 'yellow'] + + acceptable_svg_properties = ['fill', 'fill-opacity', 'fill-rule', + 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin', + 'stroke-opacity'] + + acceptable_protocols = ['ed2k', 'ftp', 'http', 'https', 'irc', + 'mailto', 'news', 'gopher', 'nntp', 'telnet', 'webcal', + 'xmpp', 'callto', 'feed', 'urn', 'aim', 'rsync', 'tag', + 'ssh', 'sftp', 'rtsp', 'afs', 'data'] + + acceptable_content_types = ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/bmp', 'text/plain'] + + # subclasses may define their own versions of these constants + allowed_elements = acceptable_elements + mathml_elements + svg_elements + allowed_attributes = acceptable_attributes + mathml_attributes + svg_attributes + allowed_css_properties = acceptable_css_properties + allowed_css_keywords = acceptable_css_keywords + allowed_svg_properties = acceptable_svg_properties + allowed_protocols = acceptable_protocols + allowed_content_types = acceptable_content_types + + # Sanitize the +html+, escaping all elements not in ALLOWED_ELEMENTS, and + # stripping out all # attributes not in ALLOWED_ATTRIBUTES. Style + # attributes are parsed, and a restricted set, # specified by + # ALLOWED_CSS_PROPERTIES and ALLOWED_CSS_KEYWORDS, are allowed through. + # attributes in ATTR_VAL_IS_URI are scanned, and only URI schemes specified + # in ALLOWED_PROTOCOLS are allowed. + # + # sanitize_html('<script> do_nasty_stuff() </script>') + # => <script> do_nasty_stuff() </script> + # sanitize_html('<a href="javascript: sucker();">Click here for $100</a>') + # => <a>Click here for $100</a> + def sanitize_token(self, token): + + # accommodate filters which use token_type differently + token_type = token["type"] + if token_type in list(tokenTypes.keys()): + token_type = tokenTypes[token_type] + + if token_type in (tokenTypes["StartTag"], tokenTypes["EndTag"], + tokenTypes["EmptyTag"]): + if token["name"] in self.allowed_elements: + return self.allowed_token(token, token_type) + else: + return self.disallowed_token(token, token_type) + elif token_type == tokenTypes["Comment"]: + pass + else: + return token + + def allowed_token(self, token, token_type): + if "data" in token: + attrs = dict([(name, val) for name, val in + token["data"][::-1] + if name in self.allowed_attributes]) + for attr in self.attr_val_is_uri: + if attr not in attrs: + continue + val_unescaped = re.sub("[`\000-\040\177-\240\s]+", '', + unescape(attrs[attr])).lower() + # remove replacement characters from unescaped characters + val_unescaped = val_unescaped.replace("\ufffd", "") + uri = urlparse.urlparse(val_unescaped) + if uri and uri.scheme: + if uri.scheme not in self.allowed_protocols: + del attrs[attr] + if uri.scheme == 'data': + m = content_type_rgx.match(uri.path) + if not m: + del attrs[attr] + elif m.group('content_type') not in self.allowed_content_types: + del attrs[attr] + + for attr in self.svg_attr_val_allows_ref: + if attr in attrs: + attrs[attr] = re.sub(r'url\s*\(\s*[^#\s][^)]+?\)', + ' ', + unescape(attrs[attr])) + if (token["name"] in self.svg_allow_local_href and + 'xlink:href' in attrs and re.search('^\s*[^#\s].*', + attrs['xlink:href'])): + del attrs['xlink:href'] + if 'style' in attrs: + attrs['style'] = self.sanitize_css(attrs['style']) + token["data"] = [[name, val] for name, val in list(attrs.items())] + return token + + def disallowed_token(self, token, token_type): + if token_type == tokenTypes["EndTag"]: + token["data"] = "</%s>" % token["name"] + elif token["data"]: + attrs = ''.join([' %s="%s"' % (k, escape(v)) for k, v in token["data"]]) + token["data"] = "<%s%s>" % (token["name"], attrs) + else: + token["data"] = "<%s>" % token["name"] + if token.get("selfClosing"): + token["data"] = token["data"][:-1] + "/>" + + if token["type"] in list(tokenTypes.keys()): + token["type"] = "Characters" + else: + token["type"] = tokenTypes["Characters"] + + del token["name"] + return token + + def sanitize_css(self, style): + # disallow urls + style = re.compile('url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ', style) + + # gauntlet + if not re.match("""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): + return '' + if not re.match("^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$", style): + return '' + + clean = [] + for prop, value in re.findall("([-\w]+)\s*:\s*([^:;]*)", style): + if not value: + continue + if prop.lower() in self.allowed_css_properties: + clean.append(prop + ': ' + value + ';') + elif prop.split('-')[0].lower() in ['background', 'border', 'margin', + 'padding']: + for keyword in value.split(): + if keyword not in self.acceptable_css_keywords and \ + not re.match("^(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$", keyword): + break + else: + clean.append(prop + ': ' + value + ';') + elif prop.lower() in self.allowed_svg_properties: + clean.append(prop + ': ' + value + ';') + + return ' '.join(clean) + + +class HTMLSanitizer(HTMLTokenizer, HTMLSanitizerMixin): + def __init__(self, stream, encoding=None, parseMeta=True, useChardet=True, + lowercaseElementName=False, lowercaseAttrName=False, parser=None): + # Change case matching defaults as we only output lowercase html anyway + # This solution doesn't seem ideal... + HTMLTokenizer.__init__(self, stream, encoding, parseMeta, useChardet, + lowercaseElementName, lowercaseAttrName, parser=parser) + + def __iter__(self): + for token in HTMLTokenizer.__iter__(self): + token = self.sanitize_token(token) + if token: + yield token diff --git a/catapult/third_party/html5lib-python/html5lib/serializer/__init__.py b/catapult/third_party/html5lib-python/html5lib/serializer/__init__.py new file mode 100644 index 00000000..8380839a --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/serializer/__init__.py @@ -0,0 +1,16 @@ +from __future__ import absolute_import, division, unicode_literals + +from .. import treewalkers + +from .htmlserializer import HTMLSerializer + + +def serialize(input, tree="etree", format="html", encoding=None, + **serializer_opts): + # XXX: Should we cache this? + walker = treewalkers.getTreeWalker(tree) + if format == "html": + s = HTMLSerializer(**serializer_opts) + else: + raise ValueError("type must be html") + return s.render(walker(input), encoding) diff --git a/catapult/third_party/html5lib-python/html5lib/serializer/htmlserializer.py b/catapult/third_party/html5lib-python/html5lib/serializer/htmlserializer.py new file mode 100644 index 00000000..be4d6344 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/serializer/htmlserializer.py @@ -0,0 +1,317 @@ +from __future__ import absolute_import, division, unicode_literals +from six import text_type + +try: + from functools import reduce +except ImportError: + pass + +from ..constants import voidElements, booleanAttributes, spaceCharacters +from ..constants import rcdataElements, entities, xmlEntities +from .. import utils +from xml.sax.saxutils import escape + +spaceCharacters = "".join(spaceCharacters) + +try: + from codecs import register_error, xmlcharrefreplace_errors +except ImportError: + unicode_encode_errors = "strict" +else: + unicode_encode_errors = "htmlentityreplace" + + encode_entity_map = {} + is_ucs4 = len("\U0010FFFF") == 1 + for k, v in list(entities.items()): + # skip multi-character entities + if ((is_ucs4 and len(v) > 1) or + (not is_ucs4 and len(v) > 2)): + continue + if v != "&": + if len(v) == 2: + v = utils.surrogatePairToCodepoint(v) + else: + v = ord(v) + if v not in encode_entity_map or k.islower(): + # prefer < over < and similarly for &, >, etc. + encode_entity_map[v] = k + + def htmlentityreplace_errors(exc): + if isinstance(exc, (UnicodeEncodeError, UnicodeTranslateError)): + res = [] + codepoints = [] + skip = False + for i, c in enumerate(exc.object[exc.start:exc.end]): + if skip: + skip = False + continue + index = i + exc.start + if utils.isSurrogatePair(exc.object[index:min([exc.end, index + 2])]): + codepoint = utils.surrogatePairToCodepoint(exc.object[index:index + 2]) + skip = True + else: + codepoint = ord(c) + codepoints.append(codepoint) + for cp in codepoints: + e = encode_entity_map.get(cp) + if e: + res.append("&") + res.append(e) + if not e.endswith(";"): + res.append(";") + else: + res.append("&#x%s;" % (hex(cp)[2:])) + return ("".join(res), exc.end) + else: + return xmlcharrefreplace_errors(exc) + + register_error(unicode_encode_errors, htmlentityreplace_errors) + + del register_error + + +class HTMLSerializer(object): + + # attribute quoting options + quote_attr_values = False + quote_char = '"' + use_best_quote_char = True + + # tag syntax options + omit_optional_tags = True + minimize_boolean_attributes = True + use_trailing_solidus = False + space_before_trailing_solidus = True + + # escaping options + escape_lt_in_attrs = False + escape_rcdata = False + resolve_entities = True + + # miscellaneous options + alphabetical_attributes = False + inject_meta_charset = True + strip_whitespace = False + sanitize = False + + options = ("quote_attr_values", "quote_char", "use_best_quote_char", + "omit_optional_tags", "minimize_boolean_attributes", + "use_trailing_solidus", "space_before_trailing_solidus", + "escape_lt_in_attrs", "escape_rcdata", "resolve_entities", + "alphabetical_attributes", "inject_meta_charset", + "strip_whitespace", "sanitize") + + def __init__(self, **kwargs): + """Initialize HTMLSerializer. + + Keyword options (default given first unless specified) include: + + inject_meta_charset=True|False + Whether it insert a meta element to define the character set of the + document. + quote_attr_values=True|False + Whether to quote attribute values that don't require quoting + per HTML5 parsing rules. + quote_char=u'"'|u"'" + Use given quote character for attribute quoting. Default is to + use double quote unless attribute value contains a double quote, + in which case single quotes are used instead. + escape_lt_in_attrs=False|True + Whether to escape < in attribute values. + escape_rcdata=False|True + Whether to escape characters that need to be escaped within normal + elements within rcdata elements such as style. + resolve_entities=True|False + Whether to resolve named character entities that appear in the + source tree. The XML predefined entities < > & " ' + are unaffected by this setting. + strip_whitespace=False|True + Whether to remove semantically meaningless whitespace. (This + compresses all whitespace to a single space except within pre.) + minimize_boolean_attributes=True|False + Shortens boolean attributes to give just the attribute value, + for example <input disabled="disabled"> becomes <input disabled>. + use_trailing_solidus=False|True + Includes a close-tag slash at the end of the start tag of void + elements (empty elements whose end tag is forbidden). E.g. <hr/>. + space_before_trailing_solidus=True|False + Places a space immediately before the closing slash in a tag + using a trailing solidus. E.g. <hr />. Requires use_trailing_solidus. + sanitize=False|True + Strip all unsafe or unknown constructs from output. + See `html5lib user documentation`_ + omit_optional_tags=True|False + Omit start/end tags that are optional. + alphabetical_attributes=False|True + Reorder attributes to be in alphabetical order. + + .. _html5lib user documentation: http://code.google.com/p/html5lib/wiki/UserDocumentation + """ + if 'quote_char' in kwargs: + self.use_best_quote_char = False + for attr in self.options: + setattr(self, attr, kwargs.get(attr, getattr(self, attr))) + self.errors = [] + self.strict = False + + def encode(self, string): + assert(isinstance(string, text_type)) + if self.encoding: + return string.encode(self.encoding, unicode_encode_errors) + else: + return string + + def encodeStrict(self, string): + assert(isinstance(string, text_type)) + if self.encoding: + return string.encode(self.encoding, "strict") + else: + return string + + def serialize(self, treewalker, encoding=None): + self.encoding = encoding + in_cdata = False + self.errors = [] + + if encoding and self.inject_meta_charset: + from ..filters.inject_meta_charset import Filter + treewalker = Filter(treewalker, encoding) + # WhitespaceFilter should be used before OptionalTagFilter + # for maximum efficiently of this latter filter + if self.strip_whitespace: + from ..filters.whitespace import Filter + treewalker = Filter(treewalker) + if self.sanitize: + from ..filters.sanitizer import Filter + treewalker = Filter(treewalker) + if self.omit_optional_tags: + from ..filters.optionaltags import Filter + treewalker = Filter(treewalker) + # Alphabetical attributes must be last, as other filters + # could add attributes and alter the order + if self.alphabetical_attributes: + from ..filters.alphabeticalattributes import Filter + treewalker = Filter(treewalker) + + for token in treewalker: + type = token["type"] + if type == "Doctype": + doctype = "<!DOCTYPE %s" % token["name"] + + if token["publicId"]: + doctype += ' PUBLIC "%s"' % token["publicId"] + elif token["systemId"]: + doctype += " SYSTEM" + if token["systemId"]: + if token["systemId"].find('"') >= 0: + if token["systemId"].find("'") >= 0: + self.serializeError("System identifer contains both single and double quote characters") + quote_char = "'" + else: + quote_char = '"' + doctype += " %s%s%s" % (quote_char, token["systemId"], quote_char) + + doctype += ">" + yield self.encodeStrict(doctype) + + elif type in ("Characters", "SpaceCharacters"): + if type == "SpaceCharacters" or in_cdata: + if in_cdata and token["data"].find("</") >= 0: + self.serializeError("Unexpected </ in CDATA") + yield self.encode(token["data"]) + else: + yield self.encode(escape(token["data"])) + + elif type in ("StartTag", "EmptyTag"): + name = token["name"] + yield self.encodeStrict("<%s" % name) + if name in rcdataElements and not self.escape_rcdata: + in_cdata = True + elif in_cdata: + self.serializeError("Unexpected child element of a CDATA element") + for (attr_namespace, attr_name), attr_value in token["data"].items(): + # TODO: Add namespace support here + k = attr_name + v = attr_value + yield self.encodeStrict(' ') + + yield self.encodeStrict(k) + if not self.minimize_boolean_attributes or \ + (k not in booleanAttributes.get(name, tuple()) + and k not in booleanAttributes.get("", tuple())): + yield self.encodeStrict("=") + if self.quote_attr_values or not v: + quote_attr = True + else: + quote_attr = reduce(lambda x, y: x or (y in v), + spaceCharacters + ">\"'=", False) + v = v.replace("&", "&") + if self.escape_lt_in_attrs: + v = v.replace("<", "<") + if quote_attr: + quote_char = self.quote_char + if self.use_best_quote_char: + if "'" in v and '"' not in v: + quote_char = '"' + elif '"' in v and "'" not in v: + quote_char = "'" + if quote_char == "'": + v = v.replace("'", "'") + else: + v = v.replace('"', """) + yield self.encodeStrict(quote_char) + yield self.encode(v) + yield self.encodeStrict(quote_char) + else: + yield self.encode(v) + if name in voidElements and self.use_trailing_solidus: + if self.space_before_trailing_solidus: + yield self.encodeStrict(" /") + else: + yield self.encodeStrict("/") + yield self.encode(">") + + elif type == "EndTag": + name = token["name"] + if name in rcdataElements: + in_cdata = False + elif in_cdata: + self.serializeError("Unexpected child element of a CDATA element") + yield self.encodeStrict("</%s>" % name) + + elif type == "Comment": + data = token["data"] + if data.find("--") >= 0: + self.serializeError("Comment contains --") + yield self.encodeStrict("<!--%s-->" % token["data"]) + + elif type == "Entity": + name = token["name"] + key = name + ";" + if key not in entities: + self.serializeError("Entity %s not recognized" % name) + if self.resolve_entities and key not in xmlEntities: + data = entities[key] + else: + data = "&%s;" % name + yield self.encodeStrict(data) + + else: + self.serializeError(token["data"]) + + def render(self, treewalker, encoding=None): + if encoding: + return b"".join(list(self.serialize(treewalker, encoding))) + else: + return "".join(list(self.serialize(treewalker))) + + def serializeError(self, data="XXX ERROR MESSAGE NEEDED"): + # XXX The idea is to make data mandatory. + self.errors.append(data) + if self.strict: + raise SerializeError + + +def SerializeError(Exception): + """Error in serialized tree""" + pass diff --git a/catapult/third_party/html5lib-python/html5lib/tests/README b/catapult/third_party/html5lib-python/html5lib/tests/README new file mode 100644 index 00000000..c564b683 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/README @@ -0,0 +1 @@ +Each testcase file can be run through nose (using ``nosetests``).
\ No newline at end of file diff --git a/catapult/third_party/html5lib-python/html5lib/tests/__init__.py b/catapult/third_party/html5lib-python/html5lib/tests/__init__.py new file mode 100644 index 00000000..b8ce2de3 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/__init__.py @@ -0,0 +1 @@ +from __future__ import absolute_import, division, unicode_literals diff --git a/catapult/third_party/html5lib-python/html5lib/tests/mockParser.py b/catapult/third_party/html5lib-python/html5lib/tests/mockParser.py new file mode 100644 index 00000000..ef31527e --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/mockParser.py @@ -0,0 +1,41 @@ +from __future__ import absolute_import, division, unicode_literals + +import sys +import os + +if __name__ == '__main__': + # Allow us to import from the src directory + os.chdir(os.path.split(os.path.abspath(__file__))[0]) + sys.path.insert(0, os.path.abspath(os.path.join(os.pardir, "src"))) + +from html5lib.tokenizer import HTMLTokenizer + + +class HTMLParser(object): + """ Fake parser to test tokenizer output """ + def parse(self, stream, output=True): + tokenizer = HTMLTokenizer(stream) + for token in tokenizer: + if output: + print(token) + +if __name__ == "__main__": + x = HTMLParser() + if len(sys.argv) > 1: + if len(sys.argv) > 2: + import hotshot + import hotshot.stats + prof = hotshot.Profile('stats.prof') + prof.runcall(x.parse, sys.argv[1], False) + prof.close() + stats = hotshot.stats.load('stats.prof') + stats.strip_dirs() + stats.sort_stats('time') + stats.print_stats() + else: + x.parse(sys.argv[1]) + else: + print("""Usage: python mockParser.py filename [stats] + If stats is specified the hotshots profiler will run and output the + stats instead. + """) diff --git a/catapult/third_party/html5lib-python/html5lib/tests/performance/concatenation.py b/catapult/third_party/html5lib-python/html5lib/tests/performance/concatenation.py new file mode 100644 index 00000000..a1465036 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/performance/concatenation.py @@ -0,0 +1,36 @@ +from __future__ import absolute_import, division, unicode_literals + + +def f1(): + x = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + y = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + z = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + x += y + z + + +def f2(): + x = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + y = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + z = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + x = x + y + z + + +def f3(): + x = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + y = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + z = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + x = "".join((x, y, z)) + + +def f4(): + x = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + y = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + z = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + x = "%s%s%s" % (x, y, z) + +import timeit +for x in range(4): + statement = "f%s" % (x + 1) + t = timeit.Timer(statement, "from __main__ import " + statement) + r = t.repeat(3, 1000000) + print(r, min(r)) diff --git a/catapult/third_party/html5lib-python/html5lib/tests/support.py b/catapult/third_party/html5lib-python/html5lib/tests/support.py new file mode 100644 index 00000000..41f2d2a0 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/support.py @@ -0,0 +1,177 @@ +from __future__ import absolute_import, division, unicode_literals + +import os +import sys +import codecs +import glob +import xml.sax.handler + +base_path = os.path.split(__file__)[0] + +test_dir = os.path.join(base_path, 'testdata') +sys.path.insert(0, os.path.abspath(os.path.join(base_path, + os.path.pardir, + os.path.pardir))) + +from html5lib import treebuilders +del base_path + +# Build a dict of avaliable trees +treeTypes = {"DOM": treebuilders.getTreeBuilder("dom")} + +# Try whatever etree implementations are avaliable from a list that are +#"supposed" to work +try: + import xml.etree.ElementTree as ElementTree + treeTypes['ElementTree'] = treebuilders.getTreeBuilder("etree", ElementTree, fullTree=True) +except ImportError: + try: + import elementtree.ElementTree as ElementTree + treeTypes['ElementTree'] = treebuilders.getTreeBuilder("etree", ElementTree, fullTree=True) + except ImportError: + pass + +try: + import xml.etree.cElementTree as cElementTree + treeTypes['cElementTree'] = treebuilders.getTreeBuilder("etree", cElementTree, fullTree=True) +except ImportError: + try: + import cElementTree + treeTypes['cElementTree'] = treebuilders.getTreeBuilder("etree", cElementTree, fullTree=True) + except ImportError: + pass + +try: + import lxml.etree as lxml # flake8: noqa +except ImportError: + pass +else: + treeTypes['lxml'] = treebuilders.getTreeBuilder("lxml") + + +def get_data_files(subdirectory, files='*.dat'): + return glob.glob(os.path.join(test_dir, subdirectory, files)) + + +class DefaultDict(dict): + def __init__(self, default, *args, **kwargs): + self.default = default + dict.__init__(self, *args, **kwargs) + + def __getitem__(self, key): + return dict.get(self, key, self.default) + + +class TestData(object): + def __init__(self, filename, newTestHeading="data", encoding="utf8"): + if encoding is None: + self.f = open(filename, mode="rb") + else: + self.f = codecs.open(filename, encoding=encoding) + self.encoding = encoding + self.newTestHeading = newTestHeading + + def __del__(self): + self.f.close() + + def __iter__(self): + data = DefaultDict(None) + key = None + for line in self.f: + heading = self.isSectionHeading(line) + if heading: + if data and heading == self.newTestHeading: + # Remove trailing newline + data[key] = data[key][:-1] + yield self.normaliseOutput(data) + data = DefaultDict(None) + key = heading + data[key] = "" if self.encoding else b"" + elif key is not None: + data[key] += line + if data: + yield self.normaliseOutput(data) + + def isSectionHeading(self, line): + """If the current heading is a test section heading return the heading, + otherwise return False""" + # print(line) + if line.startswith("#" if self.encoding else b"#"): + return line[1:].strip() + else: + return False + + def normaliseOutput(self, data): + # Remove trailing newlines + for key, value in data.items(): + if value.endswith("\n" if self.encoding else b"\n"): + data[key] = value[:-1] + return data + + +def convert(stripChars): + def convertData(data): + """convert the output of str(document) to the format used in the testcases""" + data = data.split("\n") + rv = [] + for line in data: + if line.startswith("|"): + rv.append(line[stripChars:]) + else: + rv.append(line) + return "\n".join(rv) + return convertData + +convertExpected = convert(2) + + +def errorMessage(input, expected, actual): + msg = ("Input:\n%s\nExpected:\n%s\nRecieved\n%s\n" % + (repr(input), repr(expected), repr(actual))) + if sys.version_info.major == 2: + msg = msg.encode("ascii", "backslashreplace") + return msg + + +class TracingSaxHandler(xml.sax.handler.ContentHandler): + def __init__(self): + xml.sax.handler.ContentHandler.__init__(self) + self.visited = [] + + def startDocument(self): + self.visited.append('startDocument') + + def endDocument(self): + self.visited.append('endDocument') + + def startPrefixMapping(self, prefix, uri): + # These are ignored as their order is not guaranteed + pass + + def endPrefixMapping(self, prefix): + # These are ignored as their order is not guaranteed + pass + + def startElement(self, name, attrs): + self.visited.append(('startElement', name, attrs)) + + def endElement(self, name): + self.visited.append(('endElement', name)) + + def startElementNS(self, name, qname, attrs): + self.visited.append(('startElementNS', name, qname, dict(attrs))) + + def endElementNS(self, name, qname): + self.visited.append(('endElementNS', name, qname)) + + def characters(self, content): + self.visited.append(('characters', content)) + + def ignorableWhitespace(self, whitespace): + self.visited.append(('ignorableWhitespace', whitespace)) + + def processingInstruction(self, target, data): + self.visited.append(('processingInstruction', target, data)) + + def skippedEntity(self, name): + self.visited.append(('skippedEntity', name)) diff --git a/catapult/third_party/html5lib-python/html5lib/tests/test_encoding.py b/catapult/third_party/html5lib-python/html5lib/tests/test_encoding.py new file mode 100644 index 00000000..d774ce0f --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/test_encoding.py @@ -0,0 +1,67 @@ +from __future__ import absolute_import, division, unicode_literals + +import os +import unittest + +try: + unittest.TestCase.assertEqual +except AttributeError: + unittest.TestCase.assertEqual = unittest.TestCase.assertEquals + +from .support import get_data_files, TestData, test_dir, errorMessage +from html5lib import HTMLParser, inputstream + + +class Html5EncodingTestCase(unittest.TestCase): + def test_codec_name_a(self): + self.assertEqual(inputstream.codecName("utf-8"), "utf-8") + + def test_codec_name_b(self): + self.assertEqual(inputstream.codecName("utf8"), "utf-8") + + def test_codec_name_c(self): + self.assertEqual(inputstream.codecName(" utf8 "), "utf-8") + + def test_codec_name_d(self): + self.assertEqual(inputstream.codecName("ISO_8859--1"), "windows-1252") + + +def runParserEncodingTest(data, encoding): + p = HTMLParser() + assert p.documentEncoding is None + p.parse(data, useChardet=False) + encoding = encoding.lower().decode("ascii") + + assert encoding == p.documentEncoding, errorMessage(data, encoding, p.documentEncoding) + + +def runPreScanEncodingTest(data, encoding): + stream = inputstream.HTMLBinaryInputStream(data, chardet=False) + encoding = encoding.lower().decode("ascii") + + # Very crude way to ignore irrelevant tests + if len(data) > stream.numBytesMeta: + return + + assert encoding == stream.charEncoding[0], errorMessage(data, encoding, stream.charEncoding[0]) + + +def test_encoding(): + for filename in get_data_files("encoding"): + tests = TestData(filename, b"data", encoding=None) + for idx, test in enumerate(tests): + yield (runParserEncodingTest, test[b'data'], test[b'encoding']) + yield (runPreScanEncodingTest, test[b'data'], test[b'encoding']) + +try: + try: + import charade # flake8: noqa + except ImportError: + import chardet # flake8: noqa +except ImportError: + print("charade/chardet not found, skipping chardet tests") +else: + def test_chardet(): + with open(os.path.join(test_dir, "encoding" , "chardet", "test_big5.txt"), "rb") as fp: + encoding = inputstream.HTMLInputStream(fp.read()).charEncoding + assert encoding[0].lower() == "big5" diff --git a/catapult/third_party/html5lib-python/html5lib/tests/test_parser.py b/catapult/third_party/html5lib-python/html5lib/tests/test_parser.py new file mode 100644 index 00000000..230cdb42 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/test_parser.py @@ -0,0 +1,96 @@ +from __future__ import absolute_import, division, unicode_literals + +import os +import sys +import traceback +import warnings +import re + +warnings.simplefilter("error") + +from .support import get_data_files +from .support import TestData, convert, convertExpected, treeTypes +from html5lib import html5parser, constants + +# Run the parse error checks +checkParseErrors = False + +# XXX - There should just be one function here but for some reason the testcase +# format differs from the treedump format by a single space character + + +def convertTreeDump(data): + return "\n".join(convert(3)(data).split("\n")[1:]) + +namespaceExpected = re.compile(r"^(\s*)<(\S+)>", re.M).sub + + +def runParserTest(innerHTML, input, expected, errors, treeClass, + namespaceHTMLElements): + with warnings.catch_warnings(record=True) as caughtWarnings: + warnings.simplefilter("always") + p = html5parser.HTMLParser(tree=treeClass, + namespaceHTMLElements=namespaceHTMLElements) + + try: + if innerHTML: + document = p.parseFragment(input, innerHTML) + else: + document = p.parse(input) + except: + errorMsg = "\n".join(["\n\nInput:", input, "\nExpected:", expected, + "\nTraceback:", traceback.format_exc()]) + assert False, errorMsg + + otherWarnings = [x for x in caughtWarnings + if not issubclass(x.category, constants.DataLossWarning)] + assert len(otherWarnings) == 0, [(x.category, x.message) for x in otherWarnings] + if len(caughtWarnings): + return + + output = convertTreeDump(p.tree.testSerializer(document)) + + expected = convertExpected(expected) + if namespaceHTMLElements: + expected = namespaceExpected(r"\1<html \2>", expected) + + errorMsg = "\n".join(["\n\nInput:", input, "\nExpected:", expected, + "\nReceived:", output]) + assert expected == output, errorMsg + + errStr = [] + for (line, col), errorcode, datavars in p.errors: + assert isinstance(datavars, dict), "%s, %s" % (errorcode, repr(datavars)) + errStr.append("Line: %i Col: %i %s" % (line, col, + constants.E[errorcode] % datavars)) + + errorMsg2 = "\n".join(["\n\nInput:", input, + "\nExpected errors (" + str(len(errors)) + "):\n" + "\n".join(errors), + "\nActual errors (" + str(len(p.errors)) + "):\n" + "\n".join(errStr)]) + if checkParseErrors: + assert len(p.errors) == len(errors), errorMsg2 + + +def test_parser(): + sys.stderr.write('Testing tree builders ' + " ".join(list(treeTypes.keys())) + "\n") + files = get_data_files('tree-construction') + + for filename in files: + testName = os.path.basename(filename).replace(".dat", "") + if testName in ("template",): + continue + + tests = TestData(filename, "data") + + for index, test in enumerate(tests): + input, errors, innerHTML, expected = [test[key] for key in + ('data', 'errors', + 'document-fragment', + 'document')] + if errors: + errors = errors.split("\n") + + for treeName, treeCls in treeTypes.items(): + for namespaceHTMLElements in (True, False): + yield (runParserTest, innerHTML, input, expected, errors, treeCls, + namespaceHTMLElements) diff --git a/catapult/third_party/html5lib-python/html5lib/tests/test_parser2.py b/catapult/third_party/html5lib-python/html5lib/tests/test_parser2.py new file mode 100644 index 00000000..20bbdf31 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/test_parser2.py @@ -0,0 +1,64 @@ +from __future__ import absolute_import, division, unicode_literals + +import io + +from . import support # flake8: noqa +from html5lib import html5parser +from html5lib.constants import namespaces +from html5lib import treebuilders + +import unittest + +# tests that aren't autogenerated from text files + + +class MoreParserTests(unittest.TestCase): + + def setUp(self): + self.dom_tree = treebuilders.getTreeBuilder("dom") + + def test_assertDoctypeCloneable(self): + parser = html5parser.HTMLParser(tree=self.dom_tree) + doc = parser.parse('<!DOCTYPE HTML>') + self.assertTrue(doc.cloneNode(True)) + + def test_line_counter(self): + # http://groups.google.com/group/html5lib-discuss/browse_frm/thread/f4f00e4a2f26d5c0 + parser = html5parser.HTMLParser(tree=self.dom_tree) + parser.parse("<pre>\nx\n>\n</pre>") + + def test_namespace_html_elements_0_dom(self): + parser = html5parser.HTMLParser(tree=self.dom_tree, namespaceHTMLElements=True) + doc = parser.parse("<html></html>") + self.assertTrue(doc.childNodes[0].namespaceURI == namespaces["html"]) + + def test_namespace_html_elements_1_dom(self): + parser = html5parser.HTMLParser(tree=self.dom_tree, namespaceHTMLElements=False) + doc = parser.parse("<html></html>") + self.assertTrue(doc.childNodes[0].namespaceURI is None) + + def test_namespace_html_elements_0_etree(self): + parser = html5parser.HTMLParser(namespaceHTMLElements=True) + doc = parser.parse("<html></html>") + self.assertTrue(list(doc)[0].tag == "{%s}html" % (namespaces["html"],)) + + def test_namespace_html_elements_1_etree(self): + parser = html5parser.HTMLParser(namespaceHTMLElements=False) + doc = parser.parse("<html></html>") + self.assertTrue(list(doc)[0].tag == "html") + + def test_unicode_file(self): + parser = html5parser.HTMLParser() + parser.parse(io.StringIO("a")) + + +def buildTestSuite(): + return unittest.defaultTestLoader.loadTestsFromName(__name__) + + +def main(): + buildTestSuite() + unittest.main() + +if __name__ == '__main__': + main() diff --git a/catapult/third_party/html5lib-python/html5lib/tests/test_sanitizer.py b/catapult/third_party/html5lib-python/html5lib/tests/test_sanitizer.py new file mode 100644 index 00000000..0507d86b --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/test_sanitizer.py @@ -0,0 +1,129 @@ +from __future__ import absolute_import, division, unicode_literals + +try: + import json +except ImportError: + import simplejson as json + +from html5lib import html5parser, sanitizer, constants, treebuilders + + +def toxmlFactory(): + tree = treebuilders.getTreeBuilder("etree") + + def toxml(element): + # encode/decode roundtrip required for Python 2.6 compatibility + result_bytes = tree.implementation.tostring(element, encoding="utf-8") + return result_bytes.decode("utf-8") + + return toxml + + +def runSanitizerTest(name, expected, input, toxml=None): + if toxml is None: + toxml = toxmlFactory() + expected = ''.join([toxml(token) for token in html5parser.HTMLParser(). + parseFragment(expected)]) + expected = json.loads(json.dumps(expected)) + assert expected == sanitize_html(input) + + +def sanitize_html(stream, toxml=None): + if toxml is None: + toxml = toxmlFactory() + return ''.join([toxml(token) for token in + html5parser.HTMLParser(tokenizer=sanitizer.HTMLSanitizer). + parseFragment(stream)]) + + +def test_should_handle_astral_plane_characters(): + assert '<html:p xmlns:html="http://www.w3.org/1999/xhtml">\U0001d4b5 \U0001d538</html:p>' == sanitize_html("<p>𝒵 𝔸</p>") + + +def test_should_allow_relative_uris(): + assert '<html:p xmlns:html="http://www.w3.org/1999/xhtml"><html:a href="/example.com" /></html:p>' == sanitize_html('<p><a href="/example.com"></a></p>') + + +def test_sanitizer(): + toxml = toxmlFactory() + for tag_name in sanitizer.HTMLSanitizer.allowed_elements: + if tag_name in ['caption', 'col', 'colgroup', 'optgroup', 'option', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr']: + continue # TODO + if tag_name != tag_name.lower(): + continue # TODO + if tag_name == 'image': + yield (runSanitizerTest, "test_should_allow_%s_tag" % tag_name, + "<img title=\"1\"/>foo <bad>bar</bad> baz", + "<%s title='1'>foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name), + toxml) + elif tag_name == 'br': + yield (runSanitizerTest, "test_should_allow_%s_tag" % tag_name, + "<br title=\"1\"/>foo <bad>bar</bad> baz<br/>", + "<%s title='1'>foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name), + toxml) + elif tag_name in constants.voidElements: + yield (runSanitizerTest, "test_should_allow_%s_tag" % tag_name, + "<%s title=\"1\"/>foo <bad>bar</bad> baz" % tag_name, + "<%s title='1'>foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name), + toxml) + else: + yield (runSanitizerTest, "test_should_allow_%s_tag" % tag_name, + "<%s title=\"1\">foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name), + "<%s title='1'>foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name), + toxml) + + for tag_name in sanitizer.HTMLSanitizer.allowed_elements: + tag_name = tag_name.upper() + yield (runSanitizerTest, "test_should_forbid_%s_tag" % tag_name, + "<%s title=\"1\">foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name), + "<%s title='1'>foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name), + toxml) + + for attribute_name in sanitizer.HTMLSanitizer.allowed_attributes: + if attribute_name != attribute_name.lower(): + continue # TODO + if attribute_name == 'style': + continue + attribute_value = 'foo' + if attribute_name in sanitizer.HTMLSanitizer.attr_val_is_uri: + attribute_value = '%s://sub.domain.tld/path/object.ext' % sanitizer.HTMLSanitizer.allowed_protocols[0] + yield (runSanitizerTest, "test_should_allow_%s_attribute" % attribute_name, + "<p %s=\"%s\">foo <bad>bar</bad> baz</p>" % (attribute_name, attribute_value), + "<p %s='%s'>foo <bad>bar</bad> baz</p>" % (attribute_name, attribute_value), + toxml) + + for attribute_name in sanitizer.HTMLSanitizer.allowed_attributes: + attribute_name = attribute_name.upper() + yield (runSanitizerTest, "test_should_forbid_%s_attribute" % attribute_name, + "<p>foo <bad>bar</bad> baz</p>", + "<p %s='display: none;'>foo <bad>bar</bad> baz</p>" % attribute_name, + toxml) + + for protocol in sanitizer.HTMLSanitizer.allowed_protocols: + rest_of_uri = '//sub.domain.tld/path/object.ext' + if protocol == 'data': + rest_of_uri = 'image/png;base64,aGVsbG8gd29ybGQ=' + yield (runSanitizerTest, "test_should_allow_uppercase_%s_uris" % protocol, + "<img src=\"%s:%s\">foo</a>" % (protocol, rest_of_uri), + """<img src="%s:%s">foo</a>""" % (protocol, rest_of_uri), + toxml) + + yield (runSanitizerTest, "test_invalid_data_uri", + "<audio controls=\"\"></audio>", + "<audio controls=\"\" src=\"data:foobar\"></audio>", + toxml) + + yield (runSanitizerTest, "test_data_uri_disallowed_type", + "<audio controls=\"\"></audio>", + "<audio controls=\"\" src=\"data:text/html,<html>\"></audio>", + toxml) + + for protocol in sanitizer.HTMLSanitizer.allowed_protocols: + rest_of_uri = '//sub.domain.tld/path/object.ext' + if protocol == 'data': + rest_of_uri = 'image/png;base64,aGVsbG8gd29ybGQ=' + protocol = protocol.upper() + yield (runSanitizerTest, "test_should_allow_uppercase_%s_uris" % protocol, + "<img src=\"%s:%s\">foo</a>" % (protocol, rest_of_uri), + """<img src="%s:%s">foo</a>""" % (protocol, rest_of_uri), + toxml) diff --git a/catapult/third_party/html5lib-python/html5lib/tests/test_serializer.py b/catapult/third_party/html5lib-python/html5lib/tests/test_serializer.py new file mode 100644 index 00000000..3c37feff --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/test_serializer.py @@ -0,0 +1,178 @@ +from __future__ import absolute_import, division, unicode_literals + +import json +import unittest + +from .support import get_data_files + +try: + unittest.TestCase.assertEqual +except AttributeError: + unittest.TestCase.assertEqual = unittest.TestCase.assertEquals + +import html5lib +from html5lib import constants +from html5lib.serializer import HTMLSerializer, serialize +from html5lib.treewalkers._base import TreeWalker + +optionals_loaded = [] + +try: + from lxml import etree + optionals_loaded.append("lxml") +except ImportError: + pass + +default_namespace = constants.namespaces["html"] + + +class JsonWalker(TreeWalker): + def __iter__(self): + for token in self.tree: + type = token[0] + if type == "StartTag": + if len(token) == 4: + namespace, name, attrib = token[1:4] + else: + namespace = default_namespace + name, attrib = token[1:3] + yield self.startTag(namespace, name, self._convertAttrib(attrib)) + elif type == "EndTag": + if len(token) == 3: + namespace, name = token[1:3] + else: + namespace = default_namespace + name = token[1] + yield self.endTag(namespace, name) + elif type == "EmptyTag": + if len(token) == 4: + namespace, name, attrib = token[1:] + else: + namespace = default_namespace + name, attrib = token[1:] + for token in self.emptyTag(namespace, name, self._convertAttrib(attrib)): + yield token + elif type == "Comment": + yield self.comment(token[1]) + elif type in ("Characters", "SpaceCharacters"): + for token in self.text(token[1]): + yield token + elif type == "Doctype": + if len(token) == 4: + yield self.doctype(token[1], token[2], token[3]) + elif len(token) == 3: + yield self.doctype(token[1], token[2]) + else: + yield self.doctype(token[1]) + else: + raise ValueError("Unknown token type: " + type) + + def _convertAttrib(self, attribs): + """html5lib tree-walkers use a dict of (namespace, name): value for + attributes, but JSON cannot represent this. Convert from the format + in the serializer tests (a list of dicts with "namespace", "name", + and "value" as keys) to html5lib's tree-walker format.""" + attrs = {} + for attrib in attribs: + name = (attrib["namespace"], attrib["name"]) + assert(name not in attrs) + attrs[name] = attrib["value"] + return attrs + + +def serialize_html(input, options): + options = dict([(str(k), v) for k, v in options.items()]) + stream = JsonWalker(input) + serializer = HTMLSerializer(alphabetical_attributes=True, **options) + return serializer.render(stream, options.get("encoding", None)) + + +def runSerializerTest(input, expected, options): + encoding = options.get("encoding", None) + + if encoding: + encode = lambda x: x.encode(encoding) + expected = list(map(encode, expected)) + + result = serialize_html(input, options) + if len(expected) == 1: + assert expected[0] == result, "Expected:\n%s\nActual:\n%s\nOptions:\n%s" % (expected[0], result, str(options)) + elif result not in expected: + assert False, "Expected: %s, Received: %s" % (expected, result) + + +class EncodingTestCase(unittest.TestCase): + def throwsWithLatin1(self, input): + self.assertRaises(UnicodeEncodeError, serialize_html, input, {"encoding": "iso-8859-1"}) + + def testDoctypeName(self): + self.throwsWithLatin1([["Doctype", "\u0101"]]) + + def testDoctypePublicId(self): + self.throwsWithLatin1([["Doctype", "potato", "\u0101"]]) + + def testDoctypeSystemId(self): + self.throwsWithLatin1([["Doctype", "potato", "potato", "\u0101"]]) + + def testCdataCharacters(self): + runSerializerTest([["StartTag", "http://www.w3.org/1999/xhtml", "style", {}], ["Characters", "\u0101"]], + ["<style>ā"], {"encoding": "iso-8859-1"}) + + def testCharacters(self): + runSerializerTest([["Characters", "\u0101"]], + ["ā"], {"encoding": "iso-8859-1"}) + + def testStartTagName(self): + self.throwsWithLatin1([["StartTag", "http://www.w3.org/1999/xhtml", "\u0101", []]]) + + def testEmptyTagName(self): + self.throwsWithLatin1([["EmptyTag", "http://www.w3.org/1999/xhtml", "\u0101", []]]) + + def testAttributeName(self): + self.throwsWithLatin1([["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": None, "name": "\u0101", "value": "potato"}]]]) + + def testAttributeValue(self): + runSerializerTest([["StartTag", "http://www.w3.org/1999/xhtml", "span", + [{"namespace": None, "name": "potato", "value": "\u0101"}]]], + ["<span potato=ā>"], {"encoding": "iso-8859-1"}) + + def testEndTagName(self): + self.throwsWithLatin1([["EndTag", "http://www.w3.org/1999/xhtml", "\u0101"]]) + + def testComment(self): + self.throwsWithLatin1([["Comment", "\u0101"]]) + + +if "lxml" in optionals_loaded: + class LxmlTestCase(unittest.TestCase): + def setUp(self): + self.parser = etree.XMLParser(resolve_entities=False) + self.treewalker = html5lib.getTreeWalker("lxml") + self.serializer = HTMLSerializer() + + def testEntityReplacement(self): + doc = """<!DOCTYPE html SYSTEM "about:legacy-compat"><html>β</html>""" + tree = etree.fromstring(doc, parser=self.parser).getroottree() + result = serialize(tree, tree="lxml", omit_optional_tags=False) + self.assertEqual("""<!DOCTYPE html SYSTEM "about:legacy-compat"><html>\u03B2</html>""", result) + + def testEntityXML(self): + doc = """<!DOCTYPE html SYSTEM "about:legacy-compat"><html>></html>""" + tree = etree.fromstring(doc, parser=self.parser).getroottree() + result = serialize(tree, tree="lxml", omit_optional_tags=False) + self.assertEqual("""<!DOCTYPE html SYSTEM "about:legacy-compat"><html>></html>""", result) + + def testEntityNoResolve(self): + doc = """<!DOCTYPE html SYSTEM "about:legacy-compat"><html>β</html>""" + tree = etree.fromstring(doc, parser=self.parser).getroottree() + result = serialize(tree, tree="lxml", omit_optional_tags=False, + resolve_entities=False) + self.assertEqual("""<!DOCTYPE html SYSTEM "about:legacy-compat"><html>β</html>""", result) + + +def test_serializer(): + for filename in get_data_files('serializer', '*.test'): + with open(filename) as fp: + tests = json.load(fp) + for index, test in enumerate(tests['tests']): + yield runSerializerTest, test["input"], test["expected"], test.get("options", {}) diff --git a/catapult/third_party/html5lib-python/html5lib/tests/test_stream.py b/catapult/third_party/html5lib-python/html5lib/tests/test_stream.py new file mode 100644 index 00000000..2a876c1d --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/test_stream.py @@ -0,0 +1,183 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import support # flake8: noqa +import unittest +import codecs +from io import BytesIO + +from six.moves import http_client + +from html5lib.inputstream import (BufferedStream, HTMLInputStream, + HTMLUnicodeInputStream, HTMLBinaryInputStream) + +class BufferedStreamTest(unittest.TestCase): + def test_basic(self): + s = b"abc" + fp = BufferedStream(BytesIO(s)) + read = fp.read(10) + assert read == s + + def test_read_length(self): + fp = BufferedStream(BytesIO(b"abcdef")) + read1 = fp.read(1) + assert read1 == b"a" + read2 = fp.read(2) + assert read2 == b"bc" + read3 = fp.read(3) + assert read3 == b"def" + read4 = fp.read(4) + assert read4 == b"" + + def test_tell(self): + fp = BufferedStream(BytesIO(b"abcdef")) + read1 = fp.read(1) + assert fp.tell() == 1 + read2 = fp.read(2) + assert fp.tell() == 3 + read3 = fp.read(3) + assert fp.tell() == 6 + read4 = fp.read(4) + assert fp.tell() == 6 + + def test_seek(self): + fp = BufferedStream(BytesIO(b"abcdef")) + read1 = fp.read(1) + assert read1 == b"a" + fp.seek(0) + read2 = fp.read(1) + assert read2 == b"a" + read3 = fp.read(2) + assert read3 == b"bc" + fp.seek(2) + read4 = fp.read(2) + assert read4 == b"cd" + fp.seek(4) + read5 = fp.read(2) + assert read5 == b"ef" + + def test_seek_tell(self): + fp = BufferedStream(BytesIO(b"abcdef")) + read1 = fp.read(1) + assert fp.tell() == 1 + fp.seek(0) + read2 = fp.read(1) + assert fp.tell() == 1 + read3 = fp.read(2) + assert fp.tell() == 3 + fp.seek(2) + read4 = fp.read(2) + assert fp.tell() == 4 + fp.seek(4) + read5 = fp.read(2) + assert fp.tell() == 6 + + +class HTMLUnicodeInputStreamShortChunk(HTMLUnicodeInputStream): + _defaultChunkSize = 2 + + +class HTMLBinaryInputStreamShortChunk(HTMLBinaryInputStream): + _defaultChunkSize = 2 + + +class HTMLInputStreamTest(unittest.TestCase): + + def test_char_ascii(self): + stream = HTMLInputStream(b"'", encoding='ascii') + self.assertEqual(stream.charEncoding[0], 'ascii') + self.assertEqual(stream.char(), "'") + + def test_char_utf8(self): + stream = HTMLInputStream('\u2018'.encode('utf-8'), encoding='utf-8') + self.assertEqual(stream.charEncoding[0], 'utf-8') + self.assertEqual(stream.char(), '\u2018') + + def test_char_win1252(self): + stream = HTMLInputStream("\xa9\xf1\u2019".encode('windows-1252')) + self.assertEqual(stream.charEncoding[0], 'windows-1252') + self.assertEqual(stream.char(), "\xa9") + self.assertEqual(stream.char(), "\xf1") + self.assertEqual(stream.char(), "\u2019") + + def test_bom(self): + stream = HTMLInputStream(codecs.BOM_UTF8 + b"'") + self.assertEqual(stream.charEncoding[0], 'utf-8') + self.assertEqual(stream.char(), "'") + + def test_utf_16(self): + stream = HTMLInputStream((' ' * 1025).encode('utf-16')) + self.assertTrue(stream.charEncoding[0] in ['utf-16-le', 'utf-16-be'], stream.charEncoding) + self.assertEqual(len(stream.charsUntil(' ', True)), 1025) + + def test_newlines(self): + stream = HTMLBinaryInputStreamShortChunk(codecs.BOM_UTF8 + b"a\nbb\r\nccc\rddddxe") + self.assertEqual(stream.position(), (1, 0)) + self.assertEqual(stream.charsUntil('c'), "a\nbb\n") + self.assertEqual(stream.position(), (3, 0)) + self.assertEqual(stream.charsUntil('x'), "ccc\ndddd") + self.assertEqual(stream.position(), (4, 4)) + self.assertEqual(stream.charsUntil('e'), "x") + self.assertEqual(stream.position(), (4, 5)) + + def test_newlines2(self): + size = HTMLUnicodeInputStream._defaultChunkSize + stream = HTMLInputStream("\r" * size + "\n") + self.assertEqual(stream.charsUntil('x'), "\n" * size) + + def test_position(self): + stream = HTMLBinaryInputStreamShortChunk(codecs.BOM_UTF8 + b"a\nbb\nccc\nddde\nf\ngh") + self.assertEqual(stream.position(), (1, 0)) + self.assertEqual(stream.charsUntil('c'), "a\nbb\n") + self.assertEqual(stream.position(), (3, 0)) + stream.unget("\n") + self.assertEqual(stream.position(), (2, 2)) + self.assertEqual(stream.charsUntil('c'), "\n") + self.assertEqual(stream.position(), (3, 0)) + stream.unget("\n") + self.assertEqual(stream.position(), (2, 2)) + self.assertEqual(stream.char(), "\n") + self.assertEqual(stream.position(), (3, 0)) + self.assertEqual(stream.charsUntil('e'), "ccc\nddd") + self.assertEqual(stream.position(), (4, 3)) + self.assertEqual(stream.charsUntil('h'), "e\nf\ng") + self.assertEqual(stream.position(), (6, 1)) + + def test_position2(self): + stream = HTMLUnicodeInputStreamShortChunk("abc\nd") + self.assertEqual(stream.position(), (1, 0)) + self.assertEqual(stream.char(), "a") + self.assertEqual(stream.position(), (1, 1)) + self.assertEqual(stream.char(), "b") + self.assertEqual(stream.position(), (1, 2)) + self.assertEqual(stream.char(), "c") + self.assertEqual(stream.position(), (1, 3)) + self.assertEqual(stream.char(), "\n") + self.assertEqual(stream.position(), (2, 0)) + self.assertEqual(stream.char(), "d") + self.assertEqual(stream.position(), (2, 1)) + + def test_python_issue_20007(self): + """ + Make sure we have a work-around for Python bug #20007 + http://bugs.python.org/issue20007 + """ + class FakeSocket(object): + def makefile(self, _mode, _bufsize=None): + return BytesIO(b"HTTP/1.1 200 Ok\r\n\r\nText") + + source = http_client.HTTPResponse(FakeSocket()) + source.begin() + stream = HTMLInputStream(source) + self.assertEqual(stream.charsUntil(" "), "Text") + + +def buildTestSuite(): + return unittest.defaultTestLoader.loadTestsFromName(__name__) + + +def main(): + buildTestSuite() + unittest.main() + +if __name__ == '__main__': + main() diff --git a/catapult/third_party/html5lib-python/html5lib/tests/test_tokenizer.py b/catapult/third_party/html5lib-python/html5lib/tests/test_tokenizer.py new file mode 100644 index 00000000..6a563c32 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/test_tokenizer.py @@ -0,0 +1,221 @@ +from __future__ import absolute_import, division, unicode_literals + +import json +import warnings +import re + +from six import unichr + +from .support import get_data_files + +from html5lib.tokenizer import HTMLTokenizer +from html5lib import constants, utils + + +class TokenizerTestParser(object): + def __init__(self, initialState, lastStartTag=None): + self.tokenizer = HTMLTokenizer + self._state = initialState + self._lastStartTag = lastStartTag + + def parse(self, stream, encoding=None, innerHTML=False): + tokenizer = self.tokenizer(stream, encoding) + self.outputTokens = [] + + tokenizer.state = getattr(tokenizer, self._state) + if self._lastStartTag is not None: + tokenizer.currentToken = {"type": "startTag", + "name": self._lastStartTag} + + types = dict((v, k) for k, v in constants.tokenTypes.items()) + for token in tokenizer: + getattr(self, 'process%s' % types[token["type"]])(token) + + return self.outputTokens + + def processDoctype(self, token): + self.outputTokens.append(["DOCTYPE", token["name"], token["publicId"], + token["systemId"], token["correct"]]) + + def processStartTag(self, token): + self.outputTokens.append(["StartTag", token["name"], + dict(token["data"][::-1]), token["selfClosing"]]) + + def processEmptyTag(self, token): + if token["name"] not in constants.voidElements: + self.outputTokens.append("ParseError") + self.outputTokens.append(["StartTag", token["name"], dict(token["data"][::-1])]) + + def processEndTag(self, token): + self.outputTokens.append(["EndTag", token["name"], + token["selfClosing"]]) + + def processComment(self, token): + self.outputTokens.append(["Comment", token["data"]]) + + def processSpaceCharacters(self, token): + self.outputTokens.append(["Character", token["data"]]) + self.processSpaceCharacters = self.processCharacters + + def processCharacters(self, token): + self.outputTokens.append(["Character", token["data"]]) + + def processEOF(self, token): + pass + + def processParseError(self, token): + self.outputTokens.append(["ParseError", token["data"]]) + + +def concatenateCharacterTokens(tokens): + outputTokens = [] + for token in tokens: + if "ParseError" not in token and token[0] == "Character": + if (outputTokens and "ParseError" not in outputTokens[-1] and + outputTokens[-1][0] == "Character"): + outputTokens[-1][1] += token[1] + else: + outputTokens.append(token) + else: + outputTokens.append(token) + return outputTokens + + +def normalizeTokens(tokens): + # TODO: convert tests to reflect arrays + for i, token in enumerate(tokens): + if token[0] == 'ParseError': + tokens[i] = token[0] + return tokens + + +def tokensMatch(expectedTokens, receivedTokens, ignoreErrorOrder, + ignoreErrors=False): + """Test whether the test has passed or failed + + If the ignoreErrorOrder flag is set to true we don't test the relative + positions of parse errors and non parse errors + """ + checkSelfClosing = False + for token in expectedTokens: + if (token[0] == "StartTag" and len(token) == 4 + or token[0] == "EndTag" and len(token) == 3): + checkSelfClosing = True + break + + if not checkSelfClosing: + for token in receivedTokens: + if token[0] == "StartTag" or token[0] == "EndTag": + token.pop() + + if not ignoreErrorOrder and not ignoreErrors: + return expectedTokens == receivedTokens + else: + # Sort the tokens into two groups; non-parse errors and parse errors + tokens = {"expected": [[], []], "received": [[], []]} + for tokenType, tokenList in zip(list(tokens.keys()), + (expectedTokens, receivedTokens)): + for token in tokenList: + if token != "ParseError": + tokens[tokenType][0].append(token) + else: + if not ignoreErrors: + tokens[tokenType][1].append(token) + return tokens["expected"] == tokens["received"] + + +_surrogateRe = re.compile(r"\\u([0-9A-Fa-f]{4})(?:\\u([0-9A-Fa-f]{4}))?") + + +def unescape(test): + def decode(inp): + """Decode \\uXXXX escapes + + This decodes \\uXXXX escapes, possibly into non-BMP characters when + two surrogate character escapes are adjacent to each other. + """ + # This cannot be implemented using the unicode_escape codec + # because that requires its input be ISO-8859-1, and we need + # arbitrary unicode as input. + def repl(m): + if m.group(2) is not None: + high = int(m.group(1), 16) + low = int(m.group(2), 16) + if 0xD800 <= high <= 0xDBFF and 0xDC00 <= low <= 0xDFFF: + cp = ((high - 0xD800) << 10) + (low - 0xDC00) + 0x10000 + return unichr(cp) + else: + return unichr(high) + unichr(low) + else: + return unichr(int(m.group(1), 16)) + try: + return _surrogateRe.sub(repl, inp) + except ValueError: + # This occurs when unichr throws ValueError, which should + # only be for a lone-surrogate. + if utils.supports_lone_surrogates: + raise + return None + + test["input"] = decode(test["input"]) + for token in test["output"]: + if token == "ParseError": + continue + else: + token[1] = decode(token[1]) + if len(token) > 2: + for key, value in token[2]: + del token[2][key] + token[2][decode(key)] = decode(value) + return test + + +def runTokenizerTest(test): + warnings.resetwarnings() + warnings.simplefilter("error") + + expected = concatenateCharacterTokens(test['output']) + if 'lastStartTag' not in test: + test['lastStartTag'] = None + parser = TokenizerTestParser(test['initialState'], + test['lastStartTag']) + tokens = parser.parse(test['input']) + tokens = concatenateCharacterTokens(tokens) + received = normalizeTokens(tokens) + errorMsg = "\n".join(["\n\nInitial state:", + test['initialState'], + "\nInput:", test['input'], + "\nExpected:", repr(expected), + "\nreceived:", repr(tokens)]) + errorMsg = errorMsg + ignoreErrorOrder = test.get('ignoreErrorOrder', False) + assert tokensMatch(expected, received, ignoreErrorOrder, True), errorMsg + + +def _doCapitalize(match): + return match.group(1).upper() + +_capitalizeRe = re.compile(r"\W+(\w)").sub + + +def capitalize(s): + s = s.lower() + s = _capitalizeRe(_doCapitalize, s) + return s + + +def testTokenizer(): + for filename in get_data_files('tokenizer', '*.test'): + with open(filename) as fp: + tests = json.load(fp) + if 'tests' in tests: + for index, test in enumerate(tests['tests']): + if 'initialStates' not in test: + test["initialStates"] = ["Data state"] + if 'doubleEscaped' in test: + test = unescape(test) + if test["input"] is None: + continue # Not valid input for this platform + for initialState in test["initialStates"]: + test["initialState"] = capitalize(initialState) + yield runTokenizerTest, test diff --git a/catapult/third_party/html5lib-python/html5lib/tests/test_treeadapters.py b/catapult/third_party/html5lib-python/html5lib/tests/test_treeadapters.py new file mode 100644 index 00000000..5f38b6c3 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/test_treeadapters.py @@ -0,0 +1,40 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import support # flake8: noqa + +import html5lib +from html5lib.treeadapters import sax +from html5lib.treewalkers import getTreeWalker + + +def test_to_sax(): + handler = support.TracingSaxHandler() + tree = html5lib.parse("""<html xml:lang="en"> + <title>Directory Listing</title> + <a href="/"><b/></p> + """, treebuilder="etree") + walker = getTreeWalker("etree") + sax.to_sax(walker(tree), handler) + expected = [ + 'startDocument', + ('startElementNS', ('http://www.w3.org/1999/xhtml', 'html'), + 'html', {(None, 'xml:lang'): 'en'}), + ('startElementNS', ('http://www.w3.org/1999/xhtml', 'head'), 'head', {}), + ('startElementNS', ('http://www.w3.org/1999/xhtml', 'title'), 'title', {}), + ('characters', 'Directory Listing'), + ('endElementNS', ('http://www.w3.org/1999/xhtml', 'title'), 'title'), + ('characters', '\n '), + ('endElementNS', ('http://www.w3.org/1999/xhtml', 'head'), 'head'), + ('startElementNS', ('http://www.w3.org/1999/xhtml', 'body'), 'body', {}), + ('startElementNS', ('http://www.w3.org/1999/xhtml', 'a'), 'a', {(None, 'href'): '/'}), + ('startElementNS', ('http://www.w3.org/1999/xhtml', 'b'), 'b', {}), + ('startElementNS', ('http://www.w3.org/1999/xhtml', 'p'), 'p', {}), + ('endElementNS', ('http://www.w3.org/1999/xhtml', 'p'), 'p'), + ('characters', '\n '), + ('endElementNS', ('http://www.w3.org/1999/xhtml', 'b'), 'b'), + ('endElementNS', ('http://www.w3.org/1999/xhtml', 'a'), 'a'), + ('endElementNS', ('http://www.w3.org/1999/xhtml', 'body'), 'body'), + ('endElementNS', ('http://www.w3.org/1999/xhtml', 'html'), 'html'), + 'endDocument', + ] + assert expected == handler.visited diff --git a/catapult/third_party/html5lib-python/html5lib/tests/test_treewalkers.py b/catapult/third_party/html5lib-python/html5lib/tests/test_treewalkers.py new file mode 100644 index 00000000..3be12327 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/test_treewalkers.py @@ -0,0 +1,276 @@ +from __future__ import absolute_import, division, unicode_literals + +import os +import sys +import unittest +import warnings +from difflib import unified_diff + +try: + unittest.TestCase.assertEqual +except AttributeError: + unittest.TestCase.assertEqual = unittest.TestCase.assertEquals + +from .support import get_data_files, TestData, convertExpected + +from html5lib import html5parser, treewalkers, treebuilders, constants + + +def PullDOMAdapter(node): + from xml.dom import Node + from xml.dom.pulldom import START_ELEMENT, END_ELEMENT, COMMENT, CHARACTERS + + if node.nodeType in (Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE): + for childNode in node.childNodes: + for event in PullDOMAdapter(childNode): + yield event + + elif node.nodeType == Node.DOCUMENT_TYPE_NODE: + raise NotImplementedError("DOCTYPE nodes are not supported by PullDOM") + + elif node.nodeType == Node.COMMENT_NODE: + yield COMMENT, node + + elif node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): + yield CHARACTERS, node + + elif node.nodeType == Node.ELEMENT_NODE: + yield START_ELEMENT, node + for childNode in node.childNodes: + for event in PullDOMAdapter(childNode): + yield event + yield END_ELEMENT, node + + else: + raise NotImplementedError("Node type not supported: " + str(node.nodeType)) + +treeTypes = { + "DOM": {"builder": treebuilders.getTreeBuilder("dom"), + "walker": treewalkers.getTreeWalker("dom")}, + "PullDOM": {"builder": treebuilders.getTreeBuilder("dom"), + "adapter": PullDOMAdapter, + "walker": treewalkers.getTreeWalker("pulldom")}, +} + +# Try whatever etree implementations are available from a list that are +#"supposed" to work +try: + import xml.etree.ElementTree as ElementTree +except ImportError: + pass +else: + treeTypes['ElementTree'] = \ + {"builder": treebuilders.getTreeBuilder("etree", ElementTree), + "walker": treewalkers.getTreeWalker("etree", ElementTree)} + +try: + import xml.etree.cElementTree as ElementTree +except ImportError: + pass +else: + treeTypes['cElementTree'] = \ + {"builder": treebuilders.getTreeBuilder("etree", ElementTree), + "walker": treewalkers.getTreeWalker("etree", ElementTree)} + + +try: + import lxml.etree as ElementTree # flake8: noqa +except ImportError: + pass +else: + treeTypes['lxml_native'] = \ + {"builder": treebuilders.getTreeBuilder("lxml"), + "walker": treewalkers.getTreeWalker("lxml")} + + +try: + from genshi.core import QName, Attrs + from genshi.core import START, END, TEXT, COMMENT, DOCTYPE +except ImportError: + pass +else: + def GenshiAdapter(tree): + text = None + for token in treewalkers.getTreeWalker("dom")(tree): + type = token["type"] + if type in ("Characters", "SpaceCharacters"): + if text is None: + text = token["data"] + else: + text += token["data"] + elif text is not None: + yield TEXT, text, (None, -1, -1) + text = None + + if type in ("StartTag", "EmptyTag"): + if token["namespace"]: + name = "{%s}%s" % (token["namespace"], token["name"]) + else: + name = token["name"] + attrs = Attrs([(QName("{%s}%s" % attr if attr[0] is not None else attr[1]), value) + for attr, value in token["data"].items()]) + yield (START, (QName(name), attrs), (None, -1, -1)) + if type == "EmptyTag": + type = "EndTag" + + if type == "EndTag": + if token["namespace"]: + name = "{%s}%s" % (token["namespace"], token["name"]) + else: + name = token["name"] + + yield END, QName(name), (None, -1, -1) + + elif type == "Comment": + yield COMMENT, token["data"], (None, -1, -1) + + elif type == "Doctype": + yield DOCTYPE, (token["name"], token["publicId"], + token["systemId"]), (None, -1, -1) + + else: + pass # FIXME: What to do? + + if text is not None: + yield TEXT, text, (None, -1, -1) + + treeTypes["genshi"] = \ + {"builder": treebuilders.getTreeBuilder("dom"), + "adapter": GenshiAdapter, + "walker": treewalkers.getTreeWalker("genshi")} + +import re +attrlist = re.compile(r"^(\s+)\w+=.*(\n\1\w+=.*)+", re.M) + + +def sortattrs(x): + lines = x.group(0).split("\n") + lines.sort() + return "\n".join(lines) + + +class TokenTestCase(unittest.TestCase): + def test_all_tokens(self): + expected = [ + {'data': {}, 'type': 'StartTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'html'}, + {'data': {}, 'type': 'StartTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'head'}, + {'data': {}, 'type': 'EndTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'head'}, + {'data': {}, 'type': 'StartTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'body'}, + {'data': 'a', 'type': 'Characters'}, + {'data': {}, 'type': 'StartTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'div'}, + {'data': 'b', 'type': 'Characters'}, + {'data': {}, 'type': 'EndTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'div'}, + {'data': 'c', 'type': 'Characters'}, + {'data': {}, 'type': 'EndTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'body'}, + {'data': {}, 'type': 'EndTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'html'} + ] + for treeName, treeCls in treeTypes.items(): + p = html5parser.HTMLParser(tree=treeCls["builder"]) + document = p.parse("<html><head></head><body>a<div>b</div>c</body></html>") + document = treeCls.get("adapter", lambda x: x)(document) + output = treeCls["walker"](document) + for expectedToken, outputToken in zip(expected, output): + self.assertEqual(expectedToken, outputToken) + + +def runTreewalkerTest(innerHTML, input, expected, errors, treeClass): + warnings.resetwarnings() + warnings.simplefilter("error") + try: + p = html5parser.HTMLParser(tree=treeClass["builder"]) + if innerHTML: + document = p.parseFragment(input, innerHTML) + else: + document = p.parse(input) + except constants.DataLossWarning: + # Ignore testcases we know we don't pass + return + + document = treeClass.get("adapter", lambda x: x)(document) + try: + output = treewalkers.pprint(treeClass["walker"](document)) + output = attrlist.sub(sortattrs, output) + expected = attrlist.sub(sortattrs, convertExpected(expected)) + diff = "".join(unified_diff([line + "\n" for line in expected.splitlines()], + [line + "\n" for line in output.splitlines()], + "Expected", "Received")) + assert expected == output, "\n".join([ + "", "Input:", input, + "", "Expected:", expected, + "", "Received:", output, + "", "Diff:", diff, + ]) + except NotImplementedError: + pass # Amnesty for those that confess... + + +def test_treewalker(): + sys.stdout.write('Testing tree walkers ' + " ".join(list(treeTypes.keys())) + "\n") + + for treeName, treeCls in treeTypes.items(): + files = get_data_files('tree-construction') + for filename in files: + testName = os.path.basename(filename).replace(".dat", "") + if testName in ("template",): + continue + + tests = TestData(filename, "data") + + for index, test in enumerate(tests): + (input, errors, + innerHTML, expected) = [test[key] for key in ("data", "errors", + "document-fragment", + "document")] + errors = errors.split("\n") + yield runTreewalkerTest, innerHTML, input, expected, errors, treeCls + + +def set_attribute_on_first_child(docfrag, name, value, treeName): + """naively sets an attribute on the first child of the document + fragment passed in""" + setter = {'ElementTree': lambda d: d[0].set, + 'DOM': lambda d: d.firstChild.setAttribute} + setter['cElementTree'] = setter['ElementTree'] + try: + setter.get(treeName, setter['DOM'])(docfrag)(name, value) + except AttributeError: + setter['ElementTree'](docfrag)(name, value) + + +def runTreewalkerEditTest(intext, expected, attrs_to_add, tree): + """tests what happens when we add attributes to the intext""" + treeName, treeClass = tree + parser = html5parser.HTMLParser(tree=treeClass["builder"]) + document = parser.parseFragment(intext) + for nom, val in attrs_to_add: + set_attribute_on_first_child(document, nom, val, treeName) + + document = treeClass.get("adapter", lambda x: x)(document) + output = treewalkers.pprint(treeClass["walker"](document)) + output = attrlist.sub(sortattrs, output) + if not output in expected: + raise AssertionError("TreewalkerEditTest: %s\nExpected:\n%s\nReceived:\n%s" % (treeName, expected, output)) + + +def test_treewalker_six_mix(): + """Str/Unicode mix. If str attrs added to tree""" + + # On Python 2.x string literals are of type str. Unless, like this + # file, the programmer imports unicode_literals from __future__. + # In that case, string literals become objects of type unicode. + + # This test simulates a Py2 user, modifying attributes on a document + # fragment but not using the u'' syntax nor importing unicode_literals + sm_tests = [ + ('<a href="http://example.com">Example</a>', + [(str('class'), str('test123'))], + '<a>\n class="test123"\n href="http://example.com"\n "Example"'), + + ('<link href="http://example.com/cow">', + [(str('rel'), str('alternate'))], + '<link>\n href="http://example.com/cow"\n rel="alternate"\n "Example"') + ] + + for tree in treeTypes.items(): + for intext, attrs, expected in sm_tests: + yield runTreewalkerEditTest, intext, expected, attrs, tree diff --git a/catapult/third_party/html5lib-python/html5lib/tests/test_whitespace_filter.py b/catapult/third_party/html5lib-python/html5lib/tests/test_whitespace_filter.py new file mode 100644 index 00000000..9ed27fd6 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/test_whitespace_filter.py @@ -0,0 +1,133 @@ +from __future__ import absolute_import, division, unicode_literals + +import unittest + +from html5lib.filters.whitespace import Filter +from html5lib.constants import spaceCharacters +spaceCharacters = "".join(spaceCharacters) + +try: + unittest.TestCase.assertEqual +except AttributeError: + unittest.TestCase.assertEqual = unittest.TestCase.assertEquals + + +class TestCase(unittest.TestCase): + def runTest(self, input, expected): + output = list(Filter(input)) + errorMsg = "\n".join(["\n\nInput:", str(input), + "\nExpected:", str(expected), + "\nReceived:", str(output)]) + self.assertEqual(output, expected, errorMsg) + + def runTestUnmodifiedOutput(self, input): + self.runTest(input, input) + + def testPhrasingElements(self): + self.runTestUnmodifiedOutput( + [{"type": "Characters", "data": "This is a "}, + {"type": "StartTag", "name": "span", "data": []}, + {"type": "Characters", "data": "phrase"}, + {"type": "EndTag", "name": "span", "data": []}, + {"type": "SpaceCharacters", "data": " "}, + {"type": "Characters", "data": "with"}, + {"type": "SpaceCharacters", "data": " "}, + {"type": "StartTag", "name": "em", "data": []}, + {"type": "Characters", "data": "emphasised text"}, + {"type": "EndTag", "name": "em", "data": []}, + {"type": "Characters", "data": " and an "}, + {"type": "StartTag", "name": "img", "data": [["alt", "image"]]}, + {"type": "Characters", "data": "."}]) + + def testLeadingWhitespace(self): + self.runTest( + [{"type": "StartTag", "name": "p", "data": []}, + {"type": "SpaceCharacters", "data": spaceCharacters}, + {"type": "Characters", "data": "foo"}, + {"type": "EndTag", "name": "p", "data": []}], + [{"type": "StartTag", "name": "p", "data": []}, + {"type": "SpaceCharacters", "data": " "}, + {"type": "Characters", "data": "foo"}, + {"type": "EndTag", "name": "p", "data": []}]) + + def testLeadingWhitespaceAsCharacters(self): + self.runTest( + [{"type": "StartTag", "name": "p", "data": []}, + {"type": "Characters", "data": spaceCharacters + "foo"}, + {"type": "EndTag", "name": "p", "data": []}], + [{"type": "StartTag", "name": "p", "data": []}, + {"type": "Characters", "data": " foo"}, + {"type": "EndTag", "name": "p", "data": []}]) + + def testTrailingWhitespace(self): + self.runTest( + [{"type": "StartTag", "name": "p", "data": []}, + {"type": "Characters", "data": "foo"}, + {"type": "SpaceCharacters", "data": spaceCharacters}, + {"type": "EndTag", "name": "p", "data": []}], + [{"type": "StartTag", "name": "p", "data": []}, + {"type": "Characters", "data": "foo"}, + {"type": "SpaceCharacters", "data": " "}, + {"type": "EndTag", "name": "p", "data": []}]) + + def testTrailingWhitespaceAsCharacters(self): + self.runTest( + [{"type": "StartTag", "name": "p", "data": []}, + {"type": "Characters", "data": "foo" + spaceCharacters}, + {"type": "EndTag", "name": "p", "data": []}], + [{"type": "StartTag", "name": "p", "data": []}, + {"type": "Characters", "data": "foo "}, + {"type": "EndTag", "name": "p", "data": []}]) + + def testWhitespace(self): + self.runTest( + [{"type": "StartTag", "name": "p", "data": []}, + {"type": "Characters", "data": "foo" + spaceCharacters + "bar"}, + {"type": "EndTag", "name": "p", "data": []}], + [{"type": "StartTag", "name": "p", "data": []}, + {"type": "Characters", "data": "foo bar"}, + {"type": "EndTag", "name": "p", "data": []}]) + + def testLeadingWhitespaceInPre(self): + self.runTestUnmodifiedOutput( + [{"type": "StartTag", "name": "pre", "data": []}, + {"type": "SpaceCharacters", "data": spaceCharacters}, + {"type": "Characters", "data": "foo"}, + {"type": "EndTag", "name": "pre", "data": []}]) + + def testLeadingWhitespaceAsCharactersInPre(self): + self.runTestUnmodifiedOutput( + [{"type": "StartTag", "name": "pre", "data": []}, + {"type": "Characters", "data": spaceCharacters + "foo"}, + {"type": "EndTag", "name": "pre", "data": []}]) + + def testTrailingWhitespaceInPre(self): + self.runTestUnmodifiedOutput( + [{"type": "StartTag", "name": "pre", "data": []}, + {"type": "Characters", "data": "foo"}, + {"type": "SpaceCharacters", "data": spaceCharacters}, + {"type": "EndTag", "name": "pre", "data": []}]) + + def testTrailingWhitespaceAsCharactersInPre(self): + self.runTestUnmodifiedOutput( + [{"type": "StartTag", "name": "pre", "data": []}, + {"type": "Characters", "data": "foo" + spaceCharacters}, + {"type": "EndTag", "name": "pre", "data": []}]) + + def testWhitespaceInPre(self): + self.runTestUnmodifiedOutput( + [{"type": "StartTag", "name": "pre", "data": []}, + {"type": "Characters", "data": "foo" + spaceCharacters + "bar"}, + {"type": "EndTag", "name": "pre", "data": []}]) + + +def buildTestSuite(): + return unittest.defaultTestLoader.loadTestsFromName(__name__) + + +def main(): + buildTestSuite() + unittest.main() + +if __name__ == "__main__": + main() diff --git a/catapult/third_party/html5lib-python/html5lib/tests/tokenizertotree.py b/catapult/third_party/html5lib-python/html5lib/tests/tokenizertotree.py new file mode 100644 index 00000000..b841c76c --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/tokenizertotree.py @@ -0,0 +1,68 @@ +from __future__ import absolute_import, division, unicode_literals + +import sys +import os +import json +import re + +import html5lib +from . import support +from . import test_tokenizer + +p = html5lib.HTMLParser() + +unnamespaceExpected = re.compile(r"^(\|\s*)<html ([^>]+)>", re.M).sub + + +def main(out_path): + if not os.path.exists(out_path): + sys.stderr.write("Path %s does not exist" % out_path) + sys.exit(1) + + for filename in support.get_data_files('tokenizer', '*.test'): + run_file(filename, out_path) + + +def run_file(filename, out_path): + try: + tests_data = json.load(open(filename, "r")) + except ValueError: + sys.stderr.write("Failed to load %s\n" % filename) + return + name = os.path.splitext(os.path.split(filename)[1])[0] + output_file = open(os.path.join(out_path, "tokenizer_%s.dat" % name), "w") + + if 'tests' in tests_data: + for test_data in tests_data['tests']: + if 'initialStates' not in test_data: + test_data["initialStates"] = ["Data state"] + + for initial_state in test_data["initialStates"]: + if initial_state != "Data state": + # don't support this yet + continue + test = make_test(test_data) + output_file.write(test) + + output_file.close() + + +def make_test(test_data): + if 'doubleEscaped' in test_data: + test_data = test_tokenizer.unescape_test(test_data) + + rv = [] + rv.append("#data") + rv.append(test_data["input"].encode("utf8")) + rv.append("#errors") + tree = p.parse(test_data["input"]) + output = p.tree.testSerializer(tree) + output = "\n".join(("| " + line[3:]) if line.startswith("| ") else line + for line in output.split("\n")) + output = unnamespaceExpected(r"\1<\2>", output) + rv.append(output.encode("utf8")) + rv.append("") + return "\n".join(rv) + +if __name__ == "__main__": + main(sys.argv[1]) diff --git a/catapult/third_party/html5lib-python/html5lib/tests/us-ascii.html b/catapult/third_party/html5lib-python/html5lib/tests/us-ascii.html new file mode 100644 index 00000000..bf8fb576 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/us-ascii.html @@ -0,0 +1,3 @@ +<!doctype html> +<title>Test</title> +<p>Hello World!
\ No newline at end of file diff --git a/catapult/third_party/html5lib-python/html5lib/tests/utf-8-bom.html b/catapult/third_party/html5lib-python/html5lib/tests/utf-8-bom.html new file mode 100644 index 00000000..0f03b8da --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tests/utf-8-bom.html @@ -0,0 +1,3 @@ +<!doctype html> +<title>Test</title> +<p>Hello World! ©
\ No newline at end of file diff --git a/catapult/third_party/html5lib-python/html5lib/tokenizer.py b/catapult/third_party/html5lib-python/html5lib/tokenizer.py new file mode 100644 index 00000000..79774578 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/tokenizer.py @@ -0,0 +1,1731 @@ +from __future__ import absolute_import, division, unicode_literals + +try: + chr = unichr # flake8: noqa +except NameError: + pass + +from collections import deque + +from .constants import spaceCharacters +from .constants import entities +from .constants import asciiLetters, asciiUpper2Lower +from .constants import digits, hexDigits, EOF +from .constants import tokenTypes, tagTokenTypes +from .constants import replacementCharacters + +from .inputstream import HTMLInputStream + +from .trie import Trie + +entitiesTrie = Trie(entities) + + +class HTMLTokenizer(object): + """ This class takes care of tokenizing HTML. + + * self.currentToken + Holds the token that is currently being processed. + + * self.state + Holds a reference to the method to be invoked... XXX + + * self.stream + Points to HTMLInputStream object. + """ + + def __init__(self, stream, encoding=None, parseMeta=True, useChardet=True, + lowercaseElementName=True, lowercaseAttrName=True, parser=None): + + self.stream = HTMLInputStream(stream, encoding, parseMeta, useChardet) + self.parser = parser + + # Perform case conversions? + self.lowercaseElementName = lowercaseElementName + self.lowercaseAttrName = lowercaseAttrName + + # Setup the initial tokenizer state + self.escapeFlag = False + self.lastFourChars = [] + self.state = self.dataState + self.escape = False + + # The current token being created + self.currentToken = None + super(HTMLTokenizer, self).__init__() + + def __iter__(self): + """ This is where the magic happens. + + We do our usually processing through the states and when we have a token + to return we yield the token which pauses processing until the next token + is requested. + """ + self.tokenQueue = deque([]) + # Start processing. When EOF is reached self.state will return False + # instead of True and the loop will terminate. + while self.state(): + while self.stream.errors: + yield {"type": tokenTypes["ParseError"], "data": self.stream.errors.pop(0)} + while self.tokenQueue: + yield self.tokenQueue.popleft() + + def consumeNumberEntity(self, isHex): + """This function returns either U+FFFD or the character based on the + decimal or hexadecimal representation. It also discards ";" if present. + If not present self.tokenQueue.append({"type": tokenTypes["ParseError"]}) is invoked. + """ + + allowed = digits + radix = 10 + if isHex: + allowed = hexDigits + radix = 16 + + charStack = [] + + # Consume all the characters that are in range while making sure we + # don't hit an EOF. + c = self.stream.char() + while c in allowed and c is not EOF: + charStack.append(c) + c = self.stream.char() + + # Convert the set of characters consumed to an int. + charAsInt = int("".join(charStack), radix) + + # Certain characters get replaced with others + if charAsInt in replacementCharacters: + char = replacementCharacters[charAsInt] + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + elif ((0xD800 <= charAsInt <= 0xDFFF) or + (charAsInt > 0x10FFFF)): + char = "\uFFFD" + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + else: + # Should speed up this check somehow (e.g. move the set to a constant) + if ((0x0001 <= charAsInt <= 0x0008) or + (0x000E <= charAsInt <= 0x001F) or + (0x007F <= charAsInt <= 0x009F) or + (0xFDD0 <= charAsInt <= 0xFDEF) or + charAsInt in frozenset([0x000B, 0xFFFE, 0xFFFF, 0x1FFFE, + 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, + 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, + 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, + 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, + 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, + 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, + 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, + 0xFFFFF, 0x10FFFE, 0x10FFFF])): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + try: + # Try/except needed as UCS-2 Python builds' unichar only works + # within the BMP. + char = chr(charAsInt) + except ValueError: + v = charAsInt - 0x10000 + char = chr(0xD800 | (v >> 10)) + chr(0xDC00 | (v & 0x3FF)) + + # Discard the ; if present. Otherwise, put it back on the queue and + # invoke parseError on parser. + if c != ";": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "numeric-entity-without-semicolon"}) + self.stream.unget(c) + + return char + + def consumeEntity(self, allowedChar=None, fromAttribute=False): + # Initialise to the default output for when no entity is matched + output = "&" + + charStack = [self.stream.char()] + if (charStack[0] in spaceCharacters or charStack[0] in (EOF, "<", "&") + or (allowedChar is not None and allowedChar == charStack[0])): + self.stream.unget(charStack[0]) + + elif charStack[0] == "#": + # Read the next character to see if it's hex or decimal + hex = False + charStack.append(self.stream.char()) + if charStack[-1] in ("x", "X"): + hex = True + charStack.append(self.stream.char()) + + # charStack[-1] should be the first digit + if (hex and charStack[-1] in hexDigits) \ + or (not hex and charStack[-1] in digits): + # At least one digit found, so consume the whole number + self.stream.unget(charStack[-1]) + output = self.consumeNumberEntity(hex) + else: + # No digits found + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "expected-numeric-entity"}) + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + + else: + # At this point in the process might have named entity. Entities + # are stored in the global variable "entities". + # + # Consume characters and compare to these to a substring of the + # entity names in the list until the substring no longer matches. + while (charStack[-1] is not EOF): + if not entitiesTrie.has_keys_with_prefix("".join(charStack)): + break + charStack.append(self.stream.char()) + + # At this point we have a string that starts with some characters + # that may match an entity + # Try to find the longest entity the string will match to take care + # of ¬i for instance. + try: + entityName = entitiesTrie.longest_prefix("".join(charStack[:-1])) + entityLength = len(entityName) + except KeyError: + entityName = None + + if entityName is not None: + if entityName[-1] != ";": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "named-entity-without-semicolon"}) + if (entityName[-1] != ";" and fromAttribute and + (charStack[entityLength] in asciiLetters or + charStack[entityLength] in digits or + charStack[entityLength] == "=")): + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + else: + output = entities[entityName] + self.stream.unget(charStack.pop()) + output += "".join(charStack[entityLength:]) + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-named-entity"}) + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + + if fromAttribute: + self.currentToken["data"][-1][1] += output + else: + if output in spaceCharacters: + tokenType = "SpaceCharacters" + else: + tokenType = "Characters" + self.tokenQueue.append({"type": tokenTypes[tokenType], "data": output}) + + def processEntityInAttribute(self, allowedChar): + """This method replaces the need for "entityInAttributeValueState". + """ + self.consumeEntity(allowedChar=allowedChar, fromAttribute=True) + + def emitCurrentToken(self): + """This method is a generic handler for emitting the tags. It also sets + the state to "data" because that's what's needed after a token has been + emitted. + """ + token = self.currentToken + # Add token to the queue to be yielded + if (token["type"] in tagTokenTypes): + if self.lowercaseElementName: + token["name"] = token["name"].translate(asciiUpper2Lower) + if token["type"] == tokenTypes["EndTag"]: + if token["data"]: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "attributes-in-end-tag"}) + if token["selfClosing"]: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "self-closing-flag-on-end-tag"}) + self.tokenQueue.append(token) + self.state = self.dataState + + # Below are the various tokenizer states worked out. + def dataState(self): + data = self.stream.char() + if data == "&": + self.state = self.entityDataState + elif data == "<": + self.state = self.tagOpenState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\u0000"}) + elif data is EOF: + # Tokenization ends. + return False + elif data in spaceCharacters: + # Directly after emitting a token you switch back to the "data + # state". At that point spaceCharacters are important so they are + # emitted separately. + self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data": + data + self.stream.charsUntil(spaceCharacters, True)}) + # No need to update lastFourChars here, since the first space will + # have already been appended to lastFourChars and will have broken + # any <!-- or --> sequences + else: + chars = self.stream.charsUntil(("&", "<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def entityDataState(self): + self.consumeEntity() + self.state = self.dataState + return True + + def rcdataState(self): + data = self.stream.char() + if data == "&": + self.state = self.characterReferenceInRcdata + elif data == "<": + self.state = self.rcdataLessThanSignState + elif data == EOF: + # Tokenization ends. + return False + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data in spaceCharacters: + # Directly after emitting a token you switch back to the "data + # state". At that point spaceCharacters are important so they are + # emitted separately. + self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data": + data + self.stream.charsUntil(spaceCharacters, True)}) + # No need to update lastFourChars here, since the first space will + # have already been appended to lastFourChars and will have broken + # any <!-- or --> sequences + else: + chars = self.stream.charsUntil(("&", "<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def characterReferenceInRcdata(self): + self.consumeEntity() + self.state = self.rcdataState + return True + + def rawtextState(self): + data = self.stream.char() + if data == "<": + self.state = self.rawtextLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + # Tokenization ends. + return False + else: + chars = self.stream.charsUntil(("<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def scriptDataState(self): + data = self.stream.char() + if data == "<": + self.state = self.scriptDataLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + # Tokenization ends. + return False + else: + chars = self.stream.charsUntil(("<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def plaintextState(self): + data = self.stream.char() + if data == EOF: + # Tokenization ends. + return False + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + self.stream.charsUntil("\u0000")}) + return True + + def tagOpenState(self): + data = self.stream.char() + if data == "!": + self.state = self.markupDeclarationOpenState + elif data == "/": + self.state = self.closeTagOpenState + elif data in asciiLetters: + self.currentToken = {"type": tokenTypes["StartTag"], + "name": data, "data": [], + "selfClosing": False, + "selfClosingAcknowledged": False} + self.state = self.tagNameState + elif data == ">": + # XXX In theory it could be something besides a tag name. But + # do we really care? + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name-but-got-right-bracket"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<>"}) + self.state = self.dataState + elif data == "?": + # XXX In theory it could be something besides a tag name. But + # do we really care? + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name-but-got-question-mark"}) + self.stream.unget(data) + self.state = self.bogusCommentState + else: + # XXX + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.dataState + return True + + def closeTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.currentToken = {"type": tokenTypes["EndTag"], "name": data, + "data": [], "selfClosing": False} + self.state = self.tagNameState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-right-bracket"}) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-eof"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.state = self.dataState + else: + # XXX data can be _'_... + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-char", + "datavars": {"data": data}}) + self.stream.unget(data) + self.state = self.bogusCommentState + return True + + def tagNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == ">": + self.emitCurrentToken() + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-tag-name"}) + self.state = self.dataState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] += "\uFFFD" + else: + self.currentToken["name"] += data + # (Don't use charsUntil here, because tag names are + # very short and it's faster to not do anything fancy) + return True + + def rcdataLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.rcdataEndTagOpenState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.rcdataState + return True + + def rcdataEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer += data + self.state = self.rcdataEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.rcdataState + return True + + def rcdataEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.rcdataState + return True + + def rawtextLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.rawtextEndTagOpenState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.rawtextState + return True + + def rawtextEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer += data + self.state = self.rawtextEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.rawtextState + return True + + def rawtextEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.rawtextState + return True + + def scriptDataLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.scriptDataEndTagOpenState + elif data == "!": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<!"}) + self.state = self.scriptDataEscapeStartState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer += data + self.state = self.scriptDataEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEscapeStartState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapeStartDashState + else: + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEscapeStartDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapedDashDashState + else: + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEscapedState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapedDashState + elif data == "<": + self.state = self.scriptDataEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + self.state = self.dataState + else: + chars = self.stream.charsUntil(("<", "-", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def scriptDataEscapedDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapedDashDashState + elif data == "<": + self.state = self.scriptDataEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataEscapedState + elif data == EOF: + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedDashDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + elif data == "<": + self.state = self.scriptDataEscapedLessThanSignState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"}) + self.state = self.scriptDataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataEscapedState + elif data == EOF: + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.scriptDataEscapedEndTagOpenState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<" + data}) + self.temporaryBuffer = data + self.state = self.scriptDataDoubleEscapeStartState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer = data + self.state = self.scriptDataEscapedEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataDoubleEscapeStartState(self): + data = self.stream.char() + if data in (spaceCharacters | frozenset(("/", ">"))): + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + if self.temporaryBuffer.lower() == "script": + self.state = self.scriptDataDoubleEscapedState + else: + self.state = self.scriptDataEscapedState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.temporaryBuffer += data + else: + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataDoubleEscapedState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataDoubleEscapedDashState + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + return True + + def scriptDataDoubleEscapedDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataDoubleEscapedDashDashState + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataDoubleEscapedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapedDashDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"}) + self.state = self.scriptDataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataDoubleEscapedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapedLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "/"}) + self.temporaryBuffer = "" + self.state = self.scriptDataDoubleEscapeEndState + else: + self.stream.unget(data) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapeEndState(self): + data = self.stream.char() + if data in (spaceCharacters | frozenset(("/", ">"))): + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + if self.temporaryBuffer.lower() == "script": + self.state = self.scriptDataEscapedState + else: + self.state = self.scriptDataDoubleEscapedState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.temporaryBuffer += data + else: + self.stream.unget(data) + self.state = self.scriptDataDoubleEscapedState + return True + + def beforeAttributeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data in asciiLetters: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == ">": + self.emitCurrentToken() + elif data == "/": + self.state = self.selfClosingStartTagState + elif data in ("'", '"', "=", "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "invalid-character-in-attribute-name"}) + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"].append(["\uFFFD", ""]) + self.state = self.attributeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-name-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + return True + + def attributeNameState(self): + data = self.stream.char() + leavingThisState = True + emitToken = False + if data == "=": + self.state = self.beforeAttributeValueState + elif data in asciiLetters: + self.currentToken["data"][-1][0] += data +\ + self.stream.charsUntil(asciiLetters, True) + leavingThisState = False + elif data == ">": + # XXX If we emit here the attributes are converted to a dict + # without being checked and when the code below runs we error + # because data is a dict not a list + emitToken = True + elif data in spaceCharacters: + self.state = self.afterAttributeNameState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][0] += "\uFFFD" + leavingThisState = False + elif data in ("'", '"', "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "invalid-character-in-attribute-name"}) + self.currentToken["data"][-1][0] += data + leavingThisState = False + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "eof-in-attribute-name"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][0] += data + leavingThisState = False + + if leavingThisState: + # Attributes are not dropped at this stage. That happens when the + # start tag token is emitted so values can still be safely appended + # to attributes, but we do want to report the parse error in time. + if self.lowercaseAttrName: + self.currentToken["data"][-1][0] = ( + self.currentToken["data"][-1][0].translate(asciiUpper2Lower)) + for name, value in self.currentToken["data"][:-1]: + if self.currentToken["data"][-1][0] == name: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "duplicate-attribute"}) + break + # XXX Fix for above XXX + if emitToken: + self.emitCurrentToken() + return True + + def afterAttributeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data == "=": + self.state = self.beforeAttributeValueState + elif data == ">": + self.emitCurrentToken() + elif data in asciiLetters: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"].append(["\uFFFD", ""]) + self.state = self.attributeNameState + elif data in ("'", '"', "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "invalid-character-after-attribute-name"}) + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-end-of-tag-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + return True + + def beforeAttributeValueState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data == "\"": + self.state = self.attributeValueDoubleQuotedState + elif data == "&": + self.state = self.attributeValueUnQuotedState + self.stream.unget(data) + elif data == "'": + self.state = self.attributeValueSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-value-but-got-right-bracket"}) + self.emitCurrentToken() + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + self.state = self.attributeValueUnQuotedState + elif data in ("=", "<", "`"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "equals-in-unquoted-attribute-value"}) + self.currentToken["data"][-1][1] += data + self.state = self.attributeValueUnQuotedState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-value-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data + self.state = self.attributeValueUnQuotedState + return True + + def attributeValueDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterAttributeValueState + elif data == "&": + self.processEntityInAttribute('"') + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-double-quote"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data +\ + self.stream.charsUntil(("\"", "&", "\u0000")) + return True + + def attributeValueSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterAttributeValueState + elif data == "&": + self.processEntityInAttribute("'") + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-single-quote"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data +\ + self.stream.charsUntil(("'", "&", "\u0000")) + return True + + def attributeValueUnQuotedState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == "&": + self.processEntityInAttribute(">") + elif data == ">": + self.emitCurrentToken() + elif data in ('"', "'", "=", "<", "`"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-in-unquoted-attribute-value"}) + self.currentToken["data"][-1][1] += data + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-no-quotes"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data + self.stream.charsUntil( + frozenset(("&", ">", '"', "'", "=", "<", "`", "\u0000")) | spaceCharacters) + return True + + def afterAttributeValueState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == ">": + self.emitCurrentToken() + elif data == "/": + self.state = self.selfClosingStartTagState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-EOF-after-attribute-value"}) + self.stream.unget(data) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-after-attribute-value"}) + self.stream.unget(data) + self.state = self.beforeAttributeNameState + return True + + def selfClosingStartTagState(self): + data = self.stream.char() + if data == ">": + self.currentToken["selfClosing"] = True + self.emitCurrentToken() + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "unexpected-EOF-after-solidus-in-tag"}) + self.stream.unget(data) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-after-solidus-in-tag"}) + self.stream.unget(data) + self.state = self.beforeAttributeNameState + return True + + def bogusCommentState(self): + # Make a new comment token and give it as value all the characters + # until the first > or EOF (charsUntil checks for EOF automatically) + # and emit it. + data = self.stream.charsUntil(">") + data = data.replace("\u0000", "\uFFFD") + self.tokenQueue.append( + {"type": tokenTypes["Comment"], "data": data}) + + # Eat the character directly after the bogus comment which is either a + # ">" or an EOF. + self.stream.char() + self.state = self.dataState + return True + + def markupDeclarationOpenState(self): + charStack = [self.stream.char()] + if charStack[-1] == "-": + charStack.append(self.stream.char()) + if charStack[-1] == "-": + self.currentToken = {"type": tokenTypes["Comment"], "data": ""} + self.state = self.commentStartState + return True + elif charStack[-1] in ('d', 'D'): + matched = True + for expected in (('o', 'O'), ('c', 'C'), ('t', 'T'), + ('y', 'Y'), ('p', 'P'), ('e', 'E')): + charStack.append(self.stream.char()) + if charStack[-1] not in expected: + matched = False + break + if matched: + self.currentToken = {"type": tokenTypes["Doctype"], + "name": "", + "publicId": None, "systemId": None, + "correct": True} + self.state = self.doctypeState + return True + elif (charStack[-1] == "[" and + self.parser is not None and + self.parser.tree.openElements and + self.parser.tree.openElements[-1].namespace != self.parser.tree.defaultNamespace): + matched = True + for expected in ["C", "D", "A", "T", "A", "["]: + charStack.append(self.stream.char()) + if charStack[-1] != expected: + matched = False + break + if matched: + self.state = self.cdataSectionState + return True + + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-dashes-or-doctype"}) + + while charStack: + self.stream.unget(charStack.pop()) + self.state = self.bogusCommentState + return True + + def commentStartState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentStartDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "incorrect-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += data + self.state = self.commentState + return True + + def commentStartDashState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "-\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "incorrect-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "-" + data + self.state = self.commentState + return True + + def commentState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += data + \ + self.stream.charsUntil(("-", "\u0000")) + return True + + def commentEndDashState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "-\uFFFD" + self.state = self.commentState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-end-dash"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "-" + data + self.state = self.commentState + return True + + def commentEndState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "--\uFFFD" + self.state = self.commentState + elif data == "!": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-bang-after-double-dash-in-comment"}) + self.state = self.commentEndBangState + elif data == "-": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-dash-after-double-dash-in-comment"}) + self.currentToken["data"] += data + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-double-dash"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + # XXX + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-comment"}) + self.currentToken["data"] += "--" + data + self.state = self.commentState + return True + + def commentEndBangState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "-": + self.currentToken["data"] += "--!" + self.state = self.commentEndDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "--!\uFFFD" + self.state = self.commentState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-end-bang-state"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "--!" + data + self.state = self.commentState + return True + + def doctypeState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-eof"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "need-space-after-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypeNameState + return True + + def beforeDoctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-right-bracket"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] = "\uFFFD" + self.state = self.doctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-eof"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["name"] = data + self.state = self.doctypeNameState + return True + + def doctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.state = self.afterDoctypeNameState + elif data == ">": + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] += "\uFFFD" + self.state = self.doctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype-name"}) + self.currentToken["correct"] = False + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["name"] += data + return True + + def afterDoctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.currentToken["correct"] = False + self.stream.unget(data) + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + if data in ("p", "P"): + matched = True + for expected in (("u", "U"), ("b", "B"), ("l", "L"), + ("i", "I"), ("c", "C")): + data = self.stream.char() + if data not in expected: + matched = False + break + if matched: + self.state = self.afterDoctypePublicKeywordState + return True + elif data in ("s", "S"): + matched = True + for expected in (("y", "Y"), ("s", "S"), ("t", "T"), + ("e", "E"), ("m", "M")): + data = self.stream.char() + if data not in expected: + matched = False + break + if matched: + self.state = self.afterDoctypeSystemKeywordState + return True + + # All the characters read before the current 'data' will be + # [a-zA-Z], so they're garbage in the bogus doctype and can be + # discarded; only the latest character might be '>' or EOF + # and needs to be ungetted + self.stream.unget(data) + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-space-or-right-bracket-in-doctype", "datavars": + {"data": data}}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + + return True + + def afterDoctypePublicKeywordState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypePublicIdentifierState + elif data in ("'", '"'): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypePublicIdentifierState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.stream.unget(data) + self.state = self.beforeDoctypePublicIdentifierState + return True + + def beforeDoctypePublicIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == "\"": + self.currentToken["publicId"] = "" + self.state = self.doctypePublicIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["publicId"] = "" + self.state = self.doctypePublicIdentifierSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def doctypePublicIdentifierDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterDoctypePublicIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["publicId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["publicId"] += data + return True + + def doctypePublicIdentifierSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterDoctypePublicIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["publicId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["publicId"] += data + return True + + def afterDoctypePublicIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.betweenDoctypePublicAndSystemIdentifiersState + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == '"': + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def betweenDoctypePublicAndSystemIdentifiersState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == '"': + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def afterDoctypeSystemKeywordState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypeSystemIdentifierState + elif data in ("'", '"'): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypeSystemIdentifierState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.stream.unget(data) + self.state = self.beforeDoctypeSystemIdentifierState + return True + + def beforeDoctypeSystemIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == "\"": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def doctypeSystemIdentifierDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterDoctypeSystemIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["systemId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["systemId"] += data + return True + + def doctypeSystemIdentifierSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterDoctypeSystemIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["systemId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["systemId"] += data + return True + + def afterDoctypeSystemIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.state = self.bogusDoctypeState + return True + + def bogusDoctypeState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + # XXX EMIT + self.stream.unget(data) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + pass + return True + + def cdataSectionState(self): + data = [] + while True: + data.append(self.stream.charsUntil("]")) + data.append(self.stream.charsUntil(">")) + char = self.stream.char() + if char == EOF: + break + else: + assert char == ">" + if data[-1][-2:] == "]]": + data[-1] = data[-1][:-2] + break + else: + data.append(char) + + data = "".join(data) + # Deal with null here rather than in the parser + nullCount = data.count("\u0000") + if nullCount > 0: + for i in range(nullCount): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + data = data.replace("\u0000", "\uFFFD") + if data: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": data}) + self.state = self.dataState + return True diff --git a/catapult/third_party/html5lib-python/html5lib/treeadapters/__init__.py b/catapult/third_party/html5lib-python/html5lib/treeadapters/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treeadapters/__init__.py diff --git a/catapult/third_party/html5lib-python/html5lib/treeadapters/sax.py b/catapult/third_party/html5lib-python/html5lib/treeadapters/sax.py new file mode 100644 index 00000000..ad47df95 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treeadapters/sax.py @@ -0,0 +1,44 @@ +from __future__ import absolute_import, division, unicode_literals + +from xml.sax.xmlreader import AttributesNSImpl + +from ..constants import adjustForeignAttributes, unadjustForeignAttributes + +prefix_mapping = {} +for prefix, localName, namespace in adjustForeignAttributes.values(): + if prefix is not None: + prefix_mapping[prefix] = namespace + + +def to_sax(walker, handler): + """Call SAX-like content handler based on treewalker walker""" + handler.startDocument() + for prefix, namespace in prefix_mapping.items(): + handler.startPrefixMapping(prefix, namespace) + + for token in walker: + type = token["type"] + if type == "Doctype": + continue + elif type in ("StartTag", "EmptyTag"): + attrs = AttributesNSImpl(token["data"], + unadjustForeignAttributes) + handler.startElementNS((token["namespace"], token["name"]), + token["name"], + attrs) + if type == "EmptyTag": + handler.endElementNS((token["namespace"], token["name"]), + token["name"]) + elif type == "EndTag": + handler.endElementNS((token["namespace"], token["name"]), + token["name"]) + elif type in ("Characters", "SpaceCharacters"): + handler.characters(token["data"]) + elif type == "Comment": + pass + else: + assert False, "Unknown token type" + + for prefix, namespace in prefix_mapping.items(): + handler.endPrefixMapping(prefix) + handler.endDocument() diff --git a/catapult/third_party/html5lib-python/html5lib/treebuilders/__init__.py b/catapult/third_party/html5lib-python/html5lib/treebuilders/__init__.py new file mode 100644 index 00000000..6a6b2a4c --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treebuilders/__init__.py @@ -0,0 +1,76 @@ +"""A collection of modules for building different kinds of tree from +HTML documents. + +To create a treebuilder for a new type of tree, you need to do +implement several things: + +1) A set of classes for various types of elements: Document, Doctype, +Comment, Element. These must implement the interface of +_base.treebuilders.Node (although comment nodes have a different +signature for their constructor, see treebuilders.etree.Comment) +Textual content may also be implemented as another node type, or not, as +your tree implementation requires. + +2) A treebuilder object (called TreeBuilder by convention) that +inherits from treebuilders._base.TreeBuilder. This has 4 required attributes: +documentClass - the class to use for the bottommost node of a document +elementClass - the class to use for HTML Elements +commentClass - the class to use for comments +doctypeClass - the class to use for doctypes +It also has one required method: +getDocument - Returns the root node of the complete document tree + +3) If you wish to run the unit tests, you must also create a +testSerializer method on your treebuilder which accepts a node and +returns a string containing Node and its children serialized according +to the format used in the unittests +""" + +from __future__ import absolute_import, division, unicode_literals + +from ..utils import default_etree + +treeBuilderCache = {} + + +def getTreeBuilder(treeType, implementation=None, **kwargs): + """Get a TreeBuilder class for various types of tree with built-in support + + treeType - the name of the tree type required (case-insensitive). Supported + values are: + + "dom" - A generic builder for DOM implementations, defaulting to + a xml.dom.minidom based implementation. + "etree" - A generic builder for tree implementations exposing an + ElementTree-like interface, defaulting to + xml.etree.cElementTree if available and + xml.etree.ElementTree if not. + "lxml" - A etree-based builder for lxml.etree, handling + limitations of lxml's implementation. + + implementation - (Currently applies to the "etree" and "dom" tree types). A + module implementing the tree type e.g. + xml.etree.ElementTree or xml.etree.cElementTree.""" + + treeType = treeType.lower() + if treeType not in treeBuilderCache: + if treeType == "dom": + from . import dom + # Come up with a sane default (pref. from the stdlib) + if implementation is None: + from xml.dom import minidom + implementation = minidom + # NEVER cache here, caching is done in the dom submodule + return dom.getDomModule(implementation, **kwargs).TreeBuilder + elif treeType == "lxml": + from . import etree_lxml + treeBuilderCache[treeType] = etree_lxml.TreeBuilder + elif treeType == "etree": + from . import etree + if implementation is None: + implementation = default_etree + # NEVER cache here, caching is done in the etree submodule + return etree.getETreeModule(implementation, **kwargs).TreeBuilder + else: + raise ValueError("""Unrecognised treebuilder "%s" """ % treeType) + return treeBuilderCache.get(treeType) diff --git a/catapult/third_party/html5lib-python/html5lib/treebuilders/_base.py b/catapult/third_party/html5lib-python/html5lib/treebuilders/_base.py new file mode 100644 index 00000000..8b97cc11 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treebuilders/_base.py @@ -0,0 +1,377 @@ +from __future__ import absolute_import, division, unicode_literals +from six import text_type + +from ..constants import scopingElements, tableInsertModeElements, namespaces + +# The scope markers are inserted when entering object elements, +# marquees, table cells, and table captions, and are used to prevent formatting +# from "leaking" into tables, object elements, and marquees. +Marker = None + +listElementsMap = { + None: (frozenset(scopingElements), False), + "button": (frozenset(scopingElements | set([(namespaces["html"], "button")])), False), + "list": (frozenset(scopingElements | set([(namespaces["html"], "ol"), + (namespaces["html"], "ul")])), False), + "table": (frozenset([(namespaces["html"], "html"), + (namespaces["html"], "table")]), False), + "select": (frozenset([(namespaces["html"], "optgroup"), + (namespaces["html"], "option")]), True) +} + + +class Node(object): + def __init__(self, name): + """Node representing an item in the tree. + name - The tag name associated with the node + parent - The parent of the current node (or None for the document node) + value - The value of the current node (applies to text nodes and + comments + attributes - a dict holding name, value pairs for attributes of the node + childNodes - a list of child nodes of the current node. This must + include all elements but not necessarily other node types + _flags - A list of miscellaneous flags that can be set on the node + """ + self.name = name + self.parent = None + self.value = None + self.attributes = {} + self.childNodes = [] + self._flags = [] + + def __str__(self): + attributesStr = " ".join(["%s=\"%s\"" % (name, value) + for name, value in + self.attributes.items()]) + if attributesStr: + return "<%s %s>" % (self.name, attributesStr) + else: + return "<%s>" % (self.name) + + def __repr__(self): + return "<%s>" % (self.name) + + def appendChild(self, node): + """Insert node as a child of the current node + """ + raise NotImplementedError + + def insertText(self, data, insertBefore=None): + """Insert data as text in the current node, positioned before the + start of node insertBefore or to the end of the node's text. + """ + raise NotImplementedError + + def insertBefore(self, node, refNode): + """Insert node as a child of the current node, before refNode in the + list of child nodes. Raises ValueError if refNode is not a child of + the current node""" + raise NotImplementedError + + def removeChild(self, node): + """Remove node from the children of the current node + """ + raise NotImplementedError + + def reparentChildren(self, newParent): + """Move all the children of the current node to newParent. + This is needed so that trees that don't store text as nodes move the + text in the correct way + """ + # XXX - should this method be made more general? + for child in self.childNodes: + newParent.appendChild(child) + self.childNodes = [] + + def cloneNode(self): + """Return a shallow copy of the current node i.e. a node with the same + name and attributes but with no parent or child nodes + """ + raise NotImplementedError + + def hasContent(self): + """Return true if the node has children or text, false otherwise + """ + raise NotImplementedError + + +class ActiveFormattingElements(list): + def append(self, node): + equalCount = 0 + if node != Marker: + for element in self[::-1]: + if element == Marker: + break + if self.nodesEqual(element, node): + equalCount += 1 + if equalCount == 3: + self.remove(element) + break + list.append(self, node) + + def nodesEqual(self, node1, node2): + if not node1.nameTuple == node2.nameTuple: + return False + + if not node1.attributes == node2.attributes: + return False + + return True + + +class TreeBuilder(object): + """Base treebuilder implementation + documentClass - the class to use for the bottommost node of a document + elementClass - the class to use for HTML Elements + commentClass - the class to use for comments + doctypeClass - the class to use for doctypes + """ + + # Document class + documentClass = None + + # The class to use for creating a node + elementClass = None + + # The class to use for creating comments + commentClass = None + + # The class to use for creating doctypes + doctypeClass = None + + # Fragment class + fragmentClass = None + + def __init__(self, namespaceHTMLElements): + if namespaceHTMLElements: + self.defaultNamespace = "http://www.w3.org/1999/xhtml" + else: + self.defaultNamespace = None + self.reset() + + def reset(self): + self.openElements = [] + self.activeFormattingElements = ActiveFormattingElements() + + # XXX - rename these to headElement, formElement + self.headPointer = None + self.formPointer = None + + self.insertFromTable = False + + self.document = self.documentClass() + + def elementInScope(self, target, variant=None): + + # If we pass a node in we match that. if we pass a string + # match any node with that name + exactNode = hasattr(target, "nameTuple") + + listElements, invert = listElementsMap[variant] + + for node in reversed(self.openElements): + if (node.name == target and not exactNode or + node == target and exactNode): + return True + elif (invert ^ (node.nameTuple in listElements)): + return False + + assert False # We should never reach this point + + def reconstructActiveFormattingElements(self): + # Within this algorithm the order of steps described in the + # specification is not quite the same as the order of steps in the + # code. It should still do the same though. + + # Step 1: stop the algorithm when there's nothing to do. + if not self.activeFormattingElements: + return + + # Step 2 and step 3: we start with the last element. So i is -1. + i = len(self.activeFormattingElements) - 1 + entry = self.activeFormattingElements[i] + if entry == Marker or entry in self.openElements: + return + + # Step 6 + while entry != Marker and entry not in self.openElements: + if i == 0: + # This will be reset to 0 below + i = -1 + break + i -= 1 + # Step 5: let entry be one earlier in the list. + entry = self.activeFormattingElements[i] + + while True: + # Step 7 + i += 1 + + # Step 8 + entry = self.activeFormattingElements[i] + clone = entry.cloneNode() # Mainly to get a new copy of the attributes + + # Step 9 + element = self.insertElement({"type": "StartTag", + "name": clone.name, + "namespace": clone.namespace, + "data": clone.attributes}) + + # Step 10 + self.activeFormattingElements[i] = element + + # Step 11 + if element == self.activeFormattingElements[-1]: + break + + def clearActiveFormattingElements(self): + entry = self.activeFormattingElements.pop() + while self.activeFormattingElements and entry != Marker: + entry = self.activeFormattingElements.pop() + + def elementInActiveFormattingElements(self, name): + """Check if an element exists between the end of the active + formatting elements and the last marker. If it does, return it, else + return false""" + + for item in self.activeFormattingElements[::-1]: + # Check for Marker first because if it's a Marker it doesn't have a + # name attribute. + if item == Marker: + break + elif item.name == name: + return item + return False + + def insertRoot(self, token): + element = self.createElement(token) + self.openElements.append(element) + self.document.appendChild(element) + + def insertDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + + doctype = self.doctypeClass(name, publicId, systemId) + self.document.appendChild(doctype) + + def insertComment(self, token, parent=None): + if parent is None: + parent = self.openElements[-1] + parent.appendChild(self.commentClass(token["data"])) + + def createElement(self, token): + """Create an element but don't insert it anywhere""" + name = token["name"] + namespace = token.get("namespace", self.defaultNamespace) + element = self.elementClass(name, namespace) + element.attributes = token["data"] + return element + + def _getInsertFromTable(self): + return self._insertFromTable + + def _setInsertFromTable(self, value): + """Switch the function used to insert an element from the + normal one to the misnested table one and back again""" + self._insertFromTable = value + if value: + self.insertElement = self.insertElementTable + else: + self.insertElement = self.insertElementNormal + + insertFromTable = property(_getInsertFromTable, _setInsertFromTable) + + def insertElementNormal(self, token): + name = token["name"] + assert isinstance(name, text_type), "Element %s not unicode" % name + namespace = token.get("namespace", self.defaultNamespace) + element = self.elementClass(name, namespace) + element.attributes = token["data"] + self.openElements[-1].appendChild(element) + self.openElements.append(element) + return element + + def insertElementTable(self, token): + """Create an element and insert it into the tree""" + element = self.createElement(token) + if self.openElements[-1].name not in tableInsertModeElements: + return self.insertElementNormal(token) + else: + # We should be in the InTable mode. This means we want to do + # special magic element rearranging + parent, insertBefore = self.getTableMisnestedNodePosition() + if insertBefore is None: + parent.appendChild(element) + else: + parent.insertBefore(element, insertBefore) + self.openElements.append(element) + return element + + def insertText(self, data, parent=None): + """Insert text data.""" + if parent is None: + parent = self.openElements[-1] + + if (not self.insertFromTable or (self.insertFromTable and + self.openElements[-1].name + not in tableInsertModeElements)): + parent.insertText(data) + else: + # We should be in the InTable mode. This means we want to do + # special magic element rearranging + parent, insertBefore = self.getTableMisnestedNodePosition() + parent.insertText(data, insertBefore) + + def getTableMisnestedNodePosition(self): + """Get the foster parent element, and sibling to insert before + (or None) when inserting a misnested table node""" + # The foster parent element is the one which comes before the most + # recently opened table element + # XXX - this is really inelegant + lastTable = None + fosterParent = None + insertBefore = None + for elm in self.openElements[::-1]: + if elm.name == "table": + lastTable = elm + break + if lastTable: + # XXX - we should really check that this parent is actually a + # node here + if lastTable.parent: + fosterParent = lastTable.parent + insertBefore = lastTable + else: + fosterParent = self.openElements[ + self.openElements.index(lastTable) - 1] + else: + fosterParent = self.openElements[0] + return fosterParent, insertBefore + + def generateImpliedEndTags(self, exclude=None): + name = self.openElements[-1].name + # XXX td, th and tr are not actually needed + if (name in frozenset(("dd", "dt", "li", "option", "optgroup", "p", "rp", "rt")) + and name != exclude): + self.openElements.pop() + # XXX This is not entirely what the specification says. We should + # investigate it more closely. + self.generateImpliedEndTags(exclude) + + def getDocument(self): + "Return the final tree" + return self.document + + def getFragment(self): + "Return the final fragment" + # assert self.innerHTML + fragment = self.fragmentClass() + self.openElements[0].reparentChildren(fragment) + return fragment + + def testSerializer(self, node): + """Serialize the subtree of node in the format required by unit tests + node - the node from which to start serializing""" + raise NotImplementedError diff --git a/catapult/third_party/html5lib-python/html5lib/treebuilders/dom.py b/catapult/third_party/html5lib-python/html5lib/treebuilders/dom.py new file mode 100644 index 00000000..234233b7 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treebuilders/dom.py @@ -0,0 +1,227 @@ +from __future__ import absolute_import, division, unicode_literals + + +from xml.dom import minidom, Node +import weakref + +from . import _base +from .. import constants +from ..constants import namespaces +from ..utils import moduleFactoryFactory + + +def getDomBuilder(DomImplementation): + Dom = DomImplementation + + class AttrList(object): + def __init__(self, element): + self.element = element + + def __iter__(self): + return list(self.element.attributes.items()).__iter__() + + def __setitem__(self, name, value): + self.element.setAttribute(name, value) + + def __len__(self): + return len(list(self.element.attributes.items())) + + def items(self): + return [(item[0], item[1]) for item in + list(self.element.attributes.items())] + + def keys(self): + return list(self.element.attributes.keys()) + + def __getitem__(self, name): + return self.element.getAttribute(name) + + def __contains__(self, name): + if isinstance(name, tuple): + raise NotImplementedError + else: + return self.element.hasAttribute(name) + + class NodeBuilder(_base.Node): + def __init__(self, element): + _base.Node.__init__(self, element.nodeName) + self.element = element + + namespace = property(lambda self: hasattr(self.element, "namespaceURI") + and self.element.namespaceURI or None) + + def appendChild(self, node): + node.parent = self + self.element.appendChild(node.element) + + def insertText(self, data, insertBefore=None): + text = self.element.ownerDocument.createTextNode(data) + if insertBefore: + self.element.insertBefore(text, insertBefore.element) + else: + self.element.appendChild(text) + + def insertBefore(self, node, refNode): + self.element.insertBefore(node.element, refNode.element) + node.parent = self + + def removeChild(self, node): + if node.element.parentNode == self.element: + self.element.removeChild(node.element) + node.parent = None + + def reparentChildren(self, newParent): + while self.element.hasChildNodes(): + child = self.element.firstChild + self.element.removeChild(child) + newParent.element.appendChild(child) + self.childNodes = [] + + def getAttributes(self): + return AttrList(self.element) + + def setAttributes(self, attributes): + if attributes: + for name, value in list(attributes.items()): + if isinstance(name, tuple): + if name[0] is not None: + qualifiedName = (name[0] + ":" + name[1]) + else: + qualifiedName = name[1] + self.element.setAttributeNS(name[2], qualifiedName, + value) + else: + self.element.setAttribute( + name, value) + attributes = property(getAttributes, setAttributes) + + def cloneNode(self): + return NodeBuilder(self.element.cloneNode(False)) + + def hasContent(self): + return self.element.hasChildNodes() + + def getNameTuple(self): + if self.namespace is None: + return namespaces["html"], self.name + else: + return self.namespace, self.name + + nameTuple = property(getNameTuple) + + class TreeBuilder(_base.TreeBuilder): + def documentClass(self): + self.dom = Dom.getDOMImplementation().createDocument(None, None, None) + return weakref.proxy(self) + + def insertDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + + domimpl = Dom.getDOMImplementation() + doctype = domimpl.createDocumentType(name, publicId, systemId) + self.document.appendChild(NodeBuilder(doctype)) + if Dom == minidom: + doctype.ownerDocument = self.dom + + def elementClass(self, name, namespace=None): + if namespace is None and self.defaultNamespace is None: + node = self.dom.createElement(name) + else: + node = self.dom.createElementNS(namespace, name) + + return NodeBuilder(node) + + def commentClass(self, data): + return NodeBuilder(self.dom.createComment(data)) + + def fragmentClass(self): + return NodeBuilder(self.dom.createDocumentFragment()) + + def appendChild(self, node): + self.dom.appendChild(node.element) + + def testSerializer(self, element): + return testSerializer(element) + + def getDocument(self): + return self.dom + + def getFragment(self): + return _base.TreeBuilder.getFragment(self).element + + def insertText(self, data, parent=None): + data = data + if parent != self: + _base.TreeBuilder.insertText(self, data, parent) + else: + # HACK: allow text nodes as children of the document node + if hasattr(self.dom, '_child_node_types'): + if Node.TEXT_NODE not in self.dom._child_node_types: + self.dom._child_node_types = list(self.dom._child_node_types) + self.dom._child_node_types.append(Node.TEXT_NODE) + self.dom.appendChild(self.dom.createTextNode(data)) + + implementation = DomImplementation + name = None + + def testSerializer(element): + element.normalize() + rv = [] + + def serializeElement(element, indent=0): + if element.nodeType == Node.DOCUMENT_TYPE_NODE: + if element.name: + if element.publicId or element.systemId: + publicId = element.publicId or "" + systemId = element.systemId or "" + rv.append("""|%s<!DOCTYPE %s "%s" "%s">""" % + (' ' * indent, element.name, publicId, systemId)) + else: + rv.append("|%s<!DOCTYPE %s>" % (' ' * indent, element.name)) + else: + rv.append("|%s<!DOCTYPE >" % (' ' * indent,)) + elif element.nodeType == Node.DOCUMENT_NODE: + rv.append("#document") + elif element.nodeType == Node.DOCUMENT_FRAGMENT_NODE: + rv.append("#document-fragment") + elif element.nodeType == Node.COMMENT_NODE: + rv.append("|%s<!-- %s -->" % (' ' * indent, element.nodeValue)) + elif element.nodeType == Node.TEXT_NODE: + rv.append("|%s\"%s\"" % (' ' * indent, element.nodeValue)) + else: + if (hasattr(element, "namespaceURI") and + element.namespaceURI is not None): + name = "%s %s" % (constants.prefixes[element.namespaceURI], + element.nodeName) + else: + name = element.nodeName + rv.append("|%s<%s>" % (' ' * indent, name)) + if element.hasAttributes(): + attributes = [] + for i in range(len(element.attributes)): + attr = element.attributes.item(i) + name = attr.nodeName + value = attr.value + ns = attr.namespaceURI + if ns: + name = "%s %s" % (constants.prefixes[ns], attr.localName) + else: + name = attr.nodeName + attributes.append((name, value)) + + for name, value in sorted(attributes): + rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) + indent += 2 + for child in element.childNodes: + serializeElement(child, indent) + serializeElement(element, 0) + + return "\n".join(rv) + + return locals() + + +# The actual means to get a module! +getDomModule = moduleFactoryFactory(getDomBuilder) diff --git a/catapult/third_party/html5lib-python/html5lib/treebuilders/etree.py b/catapult/third_party/html5lib-python/html5lib/treebuilders/etree.py new file mode 100644 index 00000000..2c8ed19f --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treebuilders/etree.py @@ -0,0 +1,337 @@ +from __future__ import absolute_import, division, unicode_literals +from six import text_type + +import re + +from . import _base +from .. import ihatexml +from .. import constants +from ..constants import namespaces +from ..utils import moduleFactoryFactory + +tag_regexp = re.compile("{([^}]*)}(.*)") + + +def getETreeBuilder(ElementTreeImplementation, fullTree=False): + ElementTree = ElementTreeImplementation + ElementTreeCommentType = ElementTree.Comment("asd").tag + + class Element(_base.Node): + def __init__(self, name, namespace=None): + self._name = name + self._namespace = namespace + self._element = ElementTree.Element(self._getETreeTag(name, + namespace)) + if namespace is None: + self.nameTuple = namespaces["html"], self._name + else: + self.nameTuple = self._namespace, self._name + self.parent = None + self._childNodes = [] + self._flags = [] + + def _getETreeTag(self, name, namespace): + if namespace is None: + etree_tag = name + else: + etree_tag = "{%s}%s" % (namespace, name) + return etree_tag + + def _setName(self, name): + self._name = name + self._element.tag = self._getETreeTag(self._name, self._namespace) + + def _getName(self): + return self._name + + name = property(_getName, _setName) + + def _setNamespace(self, namespace): + self._namespace = namespace + self._element.tag = self._getETreeTag(self._name, self._namespace) + + def _getNamespace(self): + return self._namespace + + namespace = property(_getNamespace, _setNamespace) + + def _getAttributes(self): + return self._element.attrib + + def _setAttributes(self, attributes): + # Delete existing attributes first + # XXX - there may be a better way to do this... + for key in list(self._element.attrib.keys()): + del self._element.attrib[key] + for key, value in attributes.items(): + if isinstance(key, tuple): + name = "{%s}%s" % (key[2], key[1]) + else: + name = key + self._element.set(name, value) + + attributes = property(_getAttributes, _setAttributes) + + def _getChildNodes(self): + return self._childNodes + + def _setChildNodes(self, value): + del self._element[:] + self._childNodes = [] + for element in value: + self.insertChild(element) + + childNodes = property(_getChildNodes, _setChildNodes) + + def hasContent(self): + """Return true if the node has children or text""" + return bool(self._element.text or len(self._element)) + + def appendChild(self, node): + self._childNodes.append(node) + self._element.append(node._element) + node.parent = self + + def insertBefore(self, node, refNode): + index = list(self._element).index(refNode._element) + self._element.insert(index, node._element) + node.parent = self + + def removeChild(self, node): + self._element.remove(node._element) + node.parent = None + + def insertText(self, data, insertBefore=None): + if not(len(self._element)): + if not self._element.text: + self._element.text = "" + self._element.text += data + elif insertBefore is None: + # Insert the text as the tail of the last child element + if not self._element[-1].tail: + self._element[-1].tail = "" + self._element[-1].tail += data + else: + # Insert the text before the specified node + children = list(self._element) + index = children.index(insertBefore._element) + if index > 0: + if not self._element[index - 1].tail: + self._element[index - 1].tail = "" + self._element[index - 1].tail += data + else: + if not self._element.text: + self._element.text = "" + self._element.text += data + + def cloneNode(self): + element = type(self)(self.name, self.namespace) + for name, value in self.attributes.items(): + element.attributes[name] = value + return element + + def reparentChildren(self, newParent): + if newParent.childNodes: + newParent.childNodes[-1]._element.tail += self._element.text + else: + if not newParent._element.text: + newParent._element.text = "" + if self._element.text is not None: + newParent._element.text += self._element.text + self._element.text = "" + _base.Node.reparentChildren(self, newParent) + + class Comment(Element): + def __init__(self, data): + # Use the superclass constructor to set all properties on the + # wrapper element + self._element = ElementTree.Comment(data) + self.parent = None + self._childNodes = [] + self._flags = [] + + def _getData(self): + return self._element.text + + def _setData(self, value): + self._element.text = value + + data = property(_getData, _setData) + + class DocumentType(Element): + def __init__(self, name, publicId, systemId): + Element.__init__(self, "<!DOCTYPE>") + self._element.text = name + self.publicId = publicId + self.systemId = systemId + + def _getPublicId(self): + return self._element.get("publicId", "") + + def _setPublicId(self, value): + if value is not None: + self._element.set("publicId", value) + + publicId = property(_getPublicId, _setPublicId) + + def _getSystemId(self): + return self._element.get("systemId", "") + + def _setSystemId(self, value): + if value is not None: + self._element.set("systemId", value) + + systemId = property(_getSystemId, _setSystemId) + + class Document(Element): + def __init__(self): + Element.__init__(self, "DOCUMENT_ROOT") + + class DocumentFragment(Element): + def __init__(self): + Element.__init__(self, "DOCUMENT_FRAGMENT") + + def testSerializer(element): + rv = [] + + def serializeElement(element, indent=0): + if not(hasattr(element, "tag")): + element = element.getroot() + if element.tag == "<!DOCTYPE>": + if element.get("publicId") or element.get("systemId"): + publicId = element.get("publicId") or "" + systemId = element.get("systemId") or "" + rv.append("""<!DOCTYPE %s "%s" "%s">""" % + (element.text, publicId, systemId)) + else: + rv.append("<!DOCTYPE %s>" % (element.text,)) + elif element.tag == "DOCUMENT_ROOT": + rv.append("#document") + if element.text is not None: + rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) + if element.tail is not None: + raise TypeError("Document node cannot have tail") + if hasattr(element, "attrib") and len(element.attrib): + raise TypeError("Document node cannot have attributes") + elif element.tag == ElementTreeCommentType: + rv.append("|%s<!-- %s -->" % (' ' * indent, element.text)) + else: + assert isinstance(element.tag, text_type), \ + "Expected unicode, got %s, %s" % (type(element.tag), element.tag) + nsmatch = tag_regexp.match(element.tag) + + if nsmatch is None: + name = element.tag + else: + ns, name = nsmatch.groups() + prefix = constants.prefixes[ns] + name = "%s %s" % (prefix, name) + rv.append("|%s<%s>" % (' ' * indent, name)) + + if hasattr(element, "attrib"): + attributes = [] + for name, value in element.attrib.items(): + nsmatch = tag_regexp.match(name) + if nsmatch is not None: + ns, name = nsmatch.groups() + prefix = constants.prefixes[ns] + attr_string = "%s %s" % (prefix, name) + else: + attr_string = name + attributes.append((attr_string, value)) + + for name, value in sorted(attributes): + rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) + if element.text: + rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) + indent += 2 + for child in element: + serializeElement(child, indent) + if element.tail: + rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail)) + serializeElement(element, 0) + + return "\n".join(rv) + + def tostring(element): + """Serialize an element and its child nodes to a string""" + rv = [] + filter = ihatexml.InfosetFilter() + + def serializeElement(element): + if isinstance(element, ElementTree.ElementTree): + element = element.getroot() + + if element.tag == "<!DOCTYPE>": + if element.get("publicId") or element.get("systemId"): + publicId = element.get("publicId") or "" + systemId = element.get("systemId") or "" + rv.append("""<!DOCTYPE %s PUBLIC "%s" "%s">""" % + (element.text, publicId, systemId)) + else: + rv.append("<!DOCTYPE %s>" % (element.text,)) + elif element.tag == "DOCUMENT_ROOT": + if element.text is not None: + rv.append(element.text) + if element.tail is not None: + raise TypeError("Document node cannot have tail") + if hasattr(element, "attrib") and len(element.attrib): + raise TypeError("Document node cannot have attributes") + + for child in element: + serializeElement(child) + + elif element.tag == ElementTreeCommentType: + rv.append("<!--%s-->" % (element.text,)) + else: + # This is assumed to be an ordinary element + if not element.attrib: + rv.append("<%s>" % (filter.fromXmlName(element.tag),)) + else: + attr = " ".join(["%s=\"%s\"" % ( + filter.fromXmlName(name), value) + for name, value in element.attrib.items()]) + rv.append("<%s %s>" % (element.tag, attr)) + if element.text: + rv.append(element.text) + + for child in element: + serializeElement(child) + + rv.append("</%s>" % (element.tag,)) + + if element.tail: + rv.append(element.tail) + + serializeElement(element) + + return "".join(rv) + + class TreeBuilder(_base.TreeBuilder): + documentClass = Document + doctypeClass = DocumentType + elementClass = Element + commentClass = Comment + fragmentClass = DocumentFragment + implementation = ElementTreeImplementation + + def testSerializer(self, element): + return testSerializer(element) + + def getDocument(self): + if fullTree: + return self.document._element + else: + if self.defaultNamespace is not None: + return self.document._element.find( + "{%s}html" % self.defaultNamespace) + else: + return self.document._element.find("html") + + def getFragment(self): + return _base.TreeBuilder.getFragment(self)._element + + return locals() + + +getETreeModule = moduleFactoryFactory(getETreeBuilder) diff --git a/catapult/third_party/html5lib-python/html5lib/treebuilders/etree_lxml.py b/catapult/third_party/html5lib-python/html5lib/treebuilders/etree_lxml.py new file mode 100644 index 00000000..35d08efa --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treebuilders/etree_lxml.py @@ -0,0 +1,369 @@ +"""Module for supporting the lxml.etree library. The idea here is to use as much +of the native library as possible, without using fragile hacks like custom element +names that break between releases. The downside of this is that we cannot represent +all possible trees; specifically the following are known to cause problems: + +Text or comments as siblings of the root element +Docypes with no name + +When any of these things occur, we emit a DataLossWarning +""" + +from __future__ import absolute_import, division, unicode_literals + +import warnings +import re +import sys + +from . import _base +from ..constants import DataLossWarning +from .. import constants +from . import etree as etree_builders +from .. import ihatexml + +import lxml.etree as etree + + +fullTree = True +tag_regexp = re.compile("{([^}]*)}(.*)") + +comment_type = etree.Comment("asd").tag + + +class DocumentType(object): + def __init__(self, name, publicId, systemId): + self.name = name + self.publicId = publicId + self.systemId = systemId + + +class Document(object): + def __init__(self): + self._elementTree = None + self._childNodes = [] + + def appendChild(self, element): + self._elementTree.getroot().addnext(element._element) + + def _getChildNodes(self): + return self._childNodes + + childNodes = property(_getChildNodes) + + +def testSerializer(element): + rv = [] + finalText = None + infosetFilter = ihatexml.InfosetFilter() + + def serializeElement(element, indent=0): + if not hasattr(element, "tag"): + if hasattr(element, "getroot"): + # Full tree case + rv.append("#document") + if element.docinfo.internalDTD: + if not (element.docinfo.public_id or + element.docinfo.system_url): + dtd_str = "<!DOCTYPE %s>" % element.docinfo.root_name + else: + dtd_str = """<!DOCTYPE %s "%s" "%s">""" % ( + element.docinfo.root_name, + element.docinfo.public_id, + element.docinfo.system_url) + rv.append("|%s%s" % (' ' * (indent + 2), dtd_str)) + next_element = element.getroot() + while next_element.getprevious() is not None: + next_element = next_element.getprevious() + while next_element is not None: + serializeElement(next_element, indent + 2) + next_element = next_element.getnext() + elif isinstance(element, str) or isinstance(element, bytes): + # Text in a fragment + assert isinstance(element, str) or sys.version_info.major == 2 + rv.append("|%s\"%s\"" % (' ' * indent, element)) + else: + # Fragment case + rv.append("#document-fragment") + for next_element in element: + serializeElement(next_element, indent + 2) + elif element.tag == comment_type: + rv.append("|%s<!-- %s -->" % (' ' * indent, element.text)) + if hasattr(element, "tail") and element.tail: + rv.append("|%s\"%s\"" % (' ' * indent, element.tail)) + else: + assert isinstance(element, etree._Element) + nsmatch = etree_builders.tag_regexp.match(element.tag) + if nsmatch is not None: + ns = nsmatch.group(1) + tag = nsmatch.group(2) + prefix = constants.prefixes[ns] + rv.append("|%s<%s %s>" % (' ' * indent, prefix, + infosetFilter.fromXmlName(tag))) + else: + rv.append("|%s<%s>" % (' ' * indent, + infosetFilter.fromXmlName(element.tag))) + + if hasattr(element, "attrib"): + attributes = [] + for name, value in element.attrib.items(): + nsmatch = tag_regexp.match(name) + if nsmatch is not None: + ns, name = nsmatch.groups() + name = infosetFilter.fromXmlName(name) + prefix = constants.prefixes[ns] + attr_string = "%s %s" % (prefix, name) + else: + attr_string = infosetFilter.fromXmlName(name) + attributes.append((attr_string, value)) + + for name, value in sorted(attributes): + rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) + + if element.text: + rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) + indent += 2 + for child in element: + serializeElement(child, indent) + if hasattr(element, "tail") and element.tail: + rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail)) + serializeElement(element, 0) + + if finalText is not None: + rv.append("|%s\"%s\"" % (' ' * 2, finalText)) + + return "\n".join(rv) + + +def tostring(element): + """Serialize an element and its child nodes to a string""" + rv = [] + finalText = None + + def serializeElement(element): + if not hasattr(element, "tag"): + if element.docinfo.internalDTD: + if element.docinfo.doctype: + dtd_str = element.docinfo.doctype + else: + dtd_str = "<!DOCTYPE %s>" % element.docinfo.root_name + rv.append(dtd_str) + serializeElement(element.getroot()) + + elif element.tag == comment_type: + rv.append("<!--%s-->" % (element.text,)) + + else: + # This is assumed to be an ordinary element + if not element.attrib: + rv.append("<%s>" % (element.tag,)) + else: + attr = " ".join(["%s=\"%s\"" % (name, value) + for name, value in element.attrib.items()]) + rv.append("<%s %s>" % (element.tag, attr)) + if element.text: + rv.append(element.text) + + for child in element: + serializeElement(child) + + rv.append("</%s>" % (element.tag,)) + + if hasattr(element, "tail") and element.tail: + rv.append(element.tail) + + serializeElement(element) + + if finalText is not None: + rv.append("%s\"" % (' ' * 2, finalText)) + + return "".join(rv) + + +class TreeBuilder(_base.TreeBuilder): + documentClass = Document + doctypeClass = DocumentType + elementClass = None + commentClass = None + fragmentClass = Document + implementation = etree + + def __init__(self, namespaceHTMLElements, fullTree=False): + builder = etree_builders.getETreeModule(etree, fullTree=fullTree) + infosetFilter = self.infosetFilter = ihatexml.InfosetFilter() + self.namespaceHTMLElements = namespaceHTMLElements + + class Attributes(dict): + def __init__(self, element, value={}): + self._element = element + dict.__init__(self, value) + for key, value in self.items(): + if isinstance(key, tuple): + name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1])) + else: + name = infosetFilter.coerceAttribute(key) + self._element._element.attrib[name] = value + + def __setitem__(self, key, value): + dict.__setitem__(self, key, value) + if isinstance(key, tuple): + name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1])) + else: + name = infosetFilter.coerceAttribute(key) + self._element._element.attrib[name] = value + + class Element(builder.Element): + def __init__(self, name, namespace): + name = infosetFilter.coerceElement(name) + builder.Element.__init__(self, name, namespace=namespace) + self._attributes = Attributes(self) + + def _setName(self, name): + self._name = infosetFilter.coerceElement(name) + self._element.tag = self._getETreeTag( + self._name, self._namespace) + + def _getName(self): + return infosetFilter.fromXmlName(self._name) + + name = property(_getName, _setName) + + def _getAttributes(self): + return self._attributes + + def _setAttributes(self, attributes): + self._attributes = Attributes(self, attributes) + + attributes = property(_getAttributes, _setAttributes) + + def insertText(self, data, insertBefore=None): + data = infosetFilter.coerceCharacters(data) + builder.Element.insertText(self, data, insertBefore) + + def appendChild(self, child): + builder.Element.appendChild(self, child) + + class Comment(builder.Comment): + def __init__(self, data): + data = infosetFilter.coerceComment(data) + builder.Comment.__init__(self, data) + + def _setData(self, data): + data = infosetFilter.coerceComment(data) + self._element.text = data + + def _getData(self): + return self._element.text + + data = property(_getData, _setData) + + self.elementClass = Element + self.commentClass = builder.Comment + # self.fragmentClass = builder.DocumentFragment + _base.TreeBuilder.__init__(self, namespaceHTMLElements) + + def reset(self): + _base.TreeBuilder.reset(self) + self.insertComment = self.insertCommentInitial + self.initial_comments = [] + self.doctype = None + + def testSerializer(self, element): + return testSerializer(element) + + def getDocument(self): + if fullTree: + return self.document._elementTree + else: + return self.document._elementTree.getroot() + + def getFragment(self): + fragment = [] + element = self.openElements[0]._element + if element.text: + fragment.append(element.text) + fragment.extend(list(element)) + if element.tail: + fragment.append(element.tail) + return fragment + + def insertDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + + if not name: + warnings.warn("lxml cannot represent empty doctype", DataLossWarning) + self.doctype = None + else: + coercedName = self.infosetFilter.coerceElement(name) + if coercedName != name: + warnings.warn("lxml cannot represent non-xml doctype", DataLossWarning) + + doctype = self.doctypeClass(coercedName, publicId, systemId) + self.doctype = doctype + + def insertCommentInitial(self, data, parent=None): + self.initial_comments.append(data) + + def insertCommentMain(self, data, parent=None): + if (parent == self.document and + self.document._elementTree.getroot()[-1].tag == comment_type): + warnings.warn("lxml cannot represent adjacent comments beyond the root elements", DataLossWarning) + super(TreeBuilder, self).insertComment(data, parent) + + def insertRoot(self, token): + """Create the document root""" + # Because of the way libxml2 works, it doesn't seem to be possible to + # alter information like the doctype after the tree has been parsed. + # Therefore we need to use the built-in parser to create our iniial + # tree, after which we can add elements like normal + docStr = "" + if self.doctype: + assert self.doctype.name + docStr += "<!DOCTYPE %s" % self.doctype.name + if (self.doctype.publicId is not None or + self.doctype.systemId is not None): + docStr += (' PUBLIC "%s" ' % + (self.infosetFilter.coercePubid(self.doctype.publicId or ""))) + if self.doctype.systemId: + sysid = self.doctype.systemId + if sysid.find("'") >= 0 and sysid.find('"') >= 0: + warnings.warn("DOCTYPE system cannot contain single and double quotes", DataLossWarning) + sysid = sysid.replace("'", 'U00027') + if sysid.find("'") >= 0: + docStr += '"%s"' % sysid + else: + docStr += "'%s'" % sysid + else: + docStr += "''" + docStr += ">" + if self.doctype.name != token["name"]: + warnings.warn("lxml cannot represent doctype with a different name to the root element", DataLossWarning) + docStr += "<THIS_SHOULD_NEVER_APPEAR_PUBLICLY/>" + root = etree.fromstring(docStr) + + # Append the initial comments: + for comment_token in self.initial_comments: + root.addprevious(etree.Comment(comment_token["data"])) + + # Create the root document and add the ElementTree to it + self.document = self.documentClass() + self.document._elementTree = root.getroottree() + + # Give the root element the right name + name = token["name"] + namespace = token.get("namespace", self.defaultNamespace) + if namespace is None: + etree_tag = name + else: + etree_tag = "{%s}%s" % (namespace, name) + root.tag = etree_tag + + # Add the root element to the internal child/open data structures + root_element = self.elementClass(name, namespace) + root_element._element = root + self.document._childNodes.append(root_element) + self.openElements.append(root_element) + + # Reset to the default insert comment function + self.insertComment = self.insertCommentMain diff --git a/catapult/third_party/html5lib-python/html5lib/treewalkers/__init__.py b/catapult/third_party/html5lib-python/html5lib/treewalkers/__init__.py new file mode 100644 index 00000000..20b91b11 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treewalkers/__init__.py @@ -0,0 +1,147 @@ +"""A collection of modules for iterating through different kinds of +tree, generating tokens identical to those produced by the tokenizer +module. + +To create a tree walker for a new type of tree, you need to do +implement a tree walker object (called TreeWalker by convention) that +implements a 'serialize' method taking a tree as sole argument and +returning an iterator generating tokens. +""" + +from __future__ import absolute_import, division, unicode_literals + +__all__ = ["getTreeWalker", "pprint", "dom", "etree", "genshistream", "lxmletree", + "pulldom"] + +import sys + +from .. import constants +from ..utils import default_etree + +treeWalkerCache = {} + + +def getTreeWalker(treeType, implementation=None, **kwargs): + """Get a TreeWalker class for various types of tree with built-in support + + treeType - the name of the tree type required (case-insensitive). Supported + values are: + + "dom" - The xml.dom.minidom DOM implementation + "pulldom" - The xml.dom.pulldom event stream + "etree" - A generic walker for tree implementations exposing an + elementtree-like interface (known to work with + ElementTree, cElementTree and lxml.etree). + "lxml" - Optimized walker for lxml.etree + "genshi" - a Genshi stream + + implementation - (Currently applies to the "etree" tree type only). A module + implementing the tree type e.g. xml.etree.ElementTree or + cElementTree.""" + + treeType = treeType.lower() + if treeType not in treeWalkerCache: + if treeType in ("dom", "pulldom"): + name = "%s.%s" % (__name__, treeType) + __import__(name) + mod = sys.modules[name] + treeWalkerCache[treeType] = mod.TreeWalker + elif treeType == "genshi": + from . import genshistream + treeWalkerCache[treeType] = genshistream.TreeWalker + elif treeType == "lxml": + from . import lxmletree + treeWalkerCache[treeType] = lxmletree.TreeWalker + elif treeType == "etree": + from . import etree + if implementation is None: + implementation = default_etree + # XXX: NEVER cache here, caching is done in the etree submodule + return etree.getETreeModule(implementation, **kwargs).TreeWalker + return treeWalkerCache.get(treeType) + + +def concatenateCharacterTokens(tokens): + pendingCharacters = [] + for token in tokens: + type = token["type"] + if type in ("Characters", "SpaceCharacters"): + pendingCharacters.append(token["data"]) + else: + if pendingCharacters: + yield {"type": "Characters", "data": "".join(pendingCharacters)} + pendingCharacters = [] + yield token + if pendingCharacters: + yield {"type": "Characters", "data": "".join(pendingCharacters)} + + +def pprint(walker): + """Pretty printer for tree walkers""" + output = [] + indent = 0 + for token in concatenateCharacterTokens(walker): + type = token["type"] + if type in ("StartTag", "EmptyTag"): + # tag name + if token["namespace"] and token["namespace"] != constants.namespaces["html"]: + if token["namespace"] in constants.prefixes: + ns = constants.prefixes[token["namespace"]] + else: + ns = token["namespace"] + name = "%s %s" % (ns, token["name"]) + else: + name = token["name"] + output.append("%s<%s>" % (" " * indent, name)) + indent += 2 + # attributes (sorted for consistent ordering) + attrs = token["data"] + for (namespace, localname), value in sorted(attrs.items()): + if namespace: + if namespace in constants.prefixes: + ns = constants.prefixes[namespace] + else: + ns = namespace + name = "%s %s" % (ns, localname) + else: + name = localname + output.append("%s%s=\"%s\"" % (" " * indent, name, value)) + # self-closing + if type == "EmptyTag": + indent -= 2 + + elif type == "EndTag": + indent -= 2 + + elif type == "Comment": + output.append("%s<!-- %s -->" % (" " * indent, token["data"])) + + elif type == "Doctype": + if token["name"]: + if token["publicId"]: + output.append("""%s<!DOCTYPE %s "%s" "%s">""" % + (" " * indent, + token["name"], + token["publicId"], + token["systemId"] if token["systemId"] else "")) + elif token["systemId"]: + output.append("""%s<!DOCTYPE %s "" "%s">""" % + (" " * indent, + token["name"], + token["systemId"])) + else: + output.append("%s<!DOCTYPE %s>" % (" " * indent, + token["name"])) + else: + output.append("%s<!DOCTYPE >" % (" " * indent,)) + + elif type == "Characters": + output.append("%s\"%s\"" % (" " * indent, token["data"])) + + elif type == "SpaceCharacters": + assert False, "concatenateCharacterTokens should have got rid of all Space tokens" + + else: + raise ValueError("Unknown token type, %s" % type) + + return "\n".join(output) diff --git a/catapult/third_party/html5lib-python/html5lib/treewalkers/_base.py b/catapult/third_party/html5lib-python/html5lib/treewalkers/_base.py new file mode 100644 index 00000000..4e11cd02 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treewalkers/_base.py @@ -0,0 +1,200 @@ +from __future__ import absolute_import, division, unicode_literals +from six import text_type, string_types + +__all__ = ["DOCUMENT", "DOCTYPE", "TEXT", "ELEMENT", "COMMENT", "ENTITY", "UNKNOWN", + "TreeWalker", "NonRecursiveTreeWalker"] + +from xml.dom import Node + +DOCUMENT = Node.DOCUMENT_NODE +DOCTYPE = Node.DOCUMENT_TYPE_NODE +TEXT = Node.TEXT_NODE +ELEMENT = Node.ELEMENT_NODE +COMMENT = Node.COMMENT_NODE +ENTITY = Node.ENTITY_NODE +UNKNOWN = "<#UNKNOWN#>" + +from ..constants import voidElements, spaceCharacters +spaceCharacters = "".join(spaceCharacters) + + +def to_text(s, blank_if_none=True): + """Wrapper around six.text_type to convert None to empty string""" + if s is None: + if blank_if_none: + return "" + else: + return None + elif isinstance(s, text_type): + return s + else: + return text_type(s) + + +def is_text_or_none(string): + """Wrapper around isinstance(string_types) or is None""" + return string is None or isinstance(string, string_types) + + +class TreeWalker(object): + def __init__(self, tree): + self.tree = tree + + def __iter__(self): + raise NotImplementedError + + def error(self, msg): + return {"type": "SerializeError", "data": msg} + + def emptyTag(self, namespace, name, attrs, hasChildren=False): + assert namespace is None or isinstance(namespace, string_types), type(namespace) + assert isinstance(name, string_types), type(name) + assert all((namespace is None or isinstance(namespace, string_types)) and + isinstance(name, string_types) and + isinstance(value, string_types) + for (namespace, name), value in attrs.items()) + + yield {"type": "EmptyTag", "name": to_text(name, False), + "namespace": to_text(namespace), + "data": attrs} + if hasChildren: + yield self.error("Void element has children") + + def startTag(self, namespace, name, attrs): + assert namespace is None or isinstance(namespace, string_types), type(namespace) + assert isinstance(name, string_types), type(name) + assert all((namespace is None or isinstance(namespace, string_types)) and + isinstance(name, string_types) and + isinstance(value, string_types) + for (namespace, name), value in attrs.items()) + + return {"type": "StartTag", + "name": text_type(name), + "namespace": to_text(namespace), + "data": dict(((to_text(namespace, False), to_text(name)), + to_text(value, False)) + for (namespace, name), value in attrs.items())} + + def endTag(self, namespace, name): + assert namespace is None or isinstance(namespace, string_types), type(namespace) + assert isinstance(name, string_types), type(namespace) + + return {"type": "EndTag", + "name": to_text(name, False), + "namespace": to_text(namespace), + "data": {}} + + def text(self, data): + assert isinstance(data, string_types), type(data) + + data = to_text(data) + middle = data.lstrip(spaceCharacters) + left = data[:len(data) - len(middle)] + if left: + yield {"type": "SpaceCharacters", "data": left} + data = middle + middle = data.rstrip(spaceCharacters) + right = data[len(middle):] + if middle: + yield {"type": "Characters", "data": middle} + if right: + yield {"type": "SpaceCharacters", "data": right} + + def comment(self, data): + assert isinstance(data, string_types), type(data) + + return {"type": "Comment", "data": text_type(data)} + + def doctype(self, name, publicId=None, systemId=None, correct=True): + assert is_text_or_none(name), type(name) + assert is_text_or_none(publicId), type(publicId) + assert is_text_or_none(systemId), type(systemId) + + return {"type": "Doctype", + "name": to_text(name), + "publicId": to_text(publicId), + "systemId": to_text(systemId), + "correct": to_text(correct)} + + def entity(self, name): + assert isinstance(name, string_types), type(name) + + return {"type": "Entity", "name": text_type(name)} + + def unknown(self, nodeType): + return self.error("Unknown node type: " + nodeType) + + +class NonRecursiveTreeWalker(TreeWalker): + def getNodeDetails(self, node): + raise NotImplementedError + + def getFirstChild(self, node): + raise NotImplementedError + + def getNextSibling(self, node): + raise NotImplementedError + + def getParentNode(self, node): + raise NotImplementedError + + def __iter__(self): + currentNode = self.tree + while currentNode is not None: + details = self.getNodeDetails(currentNode) + type, details = details[0], details[1:] + hasChildren = False + + if type == DOCTYPE: + yield self.doctype(*details) + + elif type == TEXT: + for token in self.text(*details): + yield token + + elif type == ELEMENT: + namespace, name, attributes, hasChildren = details + if name in voidElements: + for token in self.emptyTag(namespace, name, attributes, + hasChildren): + yield token + hasChildren = False + else: + yield self.startTag(namespace, name, attributes) + + elif type == COMMENT: + yield self.comment(details[0]) + + elif type == ENTITY: + yield self.entity(details[0]) + + elif type == DOCUMENT: + hasChildren = True + + else: + yield self.unknown(details[0]) + + if hasChildren: + firstChild = self.getFirstChild(currentNode) + else: + firstChild = None + + if firstChild is not None: + currentNode = firstChild + else: + while currentNode is not None: + details = self.getNodeDetails(currentNode) + type, details = details[0], details[1:] + if type == ELEMENT: + namespace, name, attributes, hasChildren = details + if name not in voidElements: + yield self.endTag(namespace, name) + if self.tree is currentNode: + currentNode = None + break + nextSibling = self.getNextSibling(currentNode) + if nextSibling is not None: + currentNode = nextSibling + break + else: + currentNode = self.getParentNode(currentNode) diff --git a/catapult/third_party/html5lib-python/html5lib/treewalkers/dom.py b/catapult/third_party/html5lib-python/html5lib/treewalkers/dom.py new file mode 100644 index 00000000..ac4dcf31 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treewalkers/dom.py @@ -0,0 +1,43 @@ +from __future__ import absolute_import, division, unicode_literals + +from xml.dom import Node + +from . import _base + + +class TreeWalker(_base.NonRecursiveTreeWalker): + def getNodeDetails(self, node): + if node.nodeType == Node.DOCUMENT_TYPE_NODE: + return _base.DOCTYPE, node.name, node.publicId, node.systemId + + elif node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): + return _base.TEXT, node.nodeValue + + elif node.nodeType == Node.ELEMENT_NODE: + attrs = {} + for attr in list(node.attributes.keys()): + attr = node.getAttributeNode(attr) + if attr.namespaceURI: + attrs[(attr.namespaceURI, attr.localName)] = attr.value + else: + attrs[(None, attr.name)] = attr.value + return (_base.ELEMENT, node.namespaceURI, node.nodeName, + attrs, node.hasChildNodes()) + + elif node.nodeType == Node.COMMENT_NODE: + return _base.COMMENT, node.nodeValue + + elif node.nodeType in (Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE): + return (_base.DOCUMENT,) + + else: + return _base.UNKNOWN, node.nodeType + + def getFirstChild(self, node): + return node.firstChild + + def getNextSibling(self, node): + return node.nextSibling + + def getParentNode(self, node): + return node.parentNode diff --git a/catapult/third_party/html5lib-python/html5lib/treewalkers/etree.py b/catapult/third_party/html5lib-python/html5lib/treewalkers/etree.py new file mode 100644 index 00000000..69840c21 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treewalkers/etree.py @@ -0,0 +1,136 @@ +from __future__ import absolute_import, division, unicode_literals + +try: + from collections import OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict + except ImportError: + OrderedDict = dict + +import re + +from six import string_types + +from . import _base +from ..utils import moduleFactoryFactory + +tag_regexp = re.compile("{([^}]*)}(.*)") + + +def getETreeBuilder(ElementTreeImplementation): + ElementTree = ElementTreeImplementation + ElementTreeCommentType = ElementTree.Comment("asd").tag + + class TreeWalker(_base.NonRecursiveTreeWalker): + """Given the particular ElementTree representation, this implementation, + to avoid using recursion, returns "nodes" as tuples with the following + content: + + 1. The current element + + 2. The index of the element relative to its parent + + 3. A stack of ancestor elements + + 4. A flag "text", "tail" or None to indicate if the current node is a + text node; either the text or tail of the current element (1) + """ + def getNodeDetails(self, node): + if isinstance(node, tuple): # It might be the root Element + elt, key, parents, flag = node + if flag in ("text", "tail"): + return _base.TEXT, getattr(elt, flag) + else: + node = elt + + if not(hasattr(node, "tag")): + node = node.getroot() + + if node.tag in ("DOCUMENT_ROOT", "DOCUMENT_FRAGMENT"): + return (_base.DOCUMENT,) + + elif node.tag == "<!DOCTYPE>": + return (_base.DOCTYPE, node.text, + node.get("publicId"), node.get("systemId")) + + elif node.tag == ElementTreeCommentType: + return _base.COMMENT, node.text + + else: + assert isinstance(node.tag, string_types), type(node.tag) + # This is assumed to be an ordinary element + match = tag_regexp.match(node.tag) + if match: + namespace, tag = match.groups() + else: + namespace = None + tag = node.tag + attrs = OrderedDict() + for name, value in list(node.attrib.items()): + match = tag_regexp.match(name) + if match: + attrs[(match.group(1), match.group(2))] = value + else: + attrs[(None, name)] = value + return (_base.ELEMENT, namespace, tag, + attrs, len(node) or node.text) + + def getFirstChild(self, node): + if isinstance(node, tuple): + element, key, parents, flag = node + else: + element, key, parents, flag = node, None, [], None + + if flag in ("text", "tail"): + return None + else: + if element.text: + return element, key, parents, "text" + elif len(element): + parents.append(element) + return element[0], 0, parents, None + else: + return None + + def getNextSibling(self, node): + if isinstance(node, tuple): + element, key, parents, flag = node + else: + return None + + if flag == "text": + if len(element): + parents.append(element) + return element[0], 0, parents, None + else: + return None + else: + if element.tail and flag != "tail": + return element, key, parents, "tail" + elif key < len(parents[-1]) - 1: + return parents[-1][key + 1], key + 1, parents, None + else: + return None + + def getParentNode(self, node): + if isinstance(node, tuple): + element, key, parents, flag = node + else: + return None + + if flag == "text": + if not parents: + return element + else: + return element, key, parents, None + else: + parent = parents.pop() + if not parents: + return parent + else: + return parent, list(parents[-1]).index(parent), parents, None + + return locals() + +getETreeModule = moduleFactoryFactory(getETreeBuilder) diff --git a/catapult/third_party/html5lib-python/html5lib/treewalkers/genshistream.py b/catapult/third_party/html5lib-python/html5lib/treewalkers/genshistream.py new file mode 100644 index 00000000..f559c45d --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treewalkers/genshistream.py @@ -0,0 +1,69 @@ +from __future__ import absolute_import, division, unicode_literals + +from genshi.core import QName +from genshi.core import START, END, XML_NAMESPACE, DOCTYPE, TEXT +from genshi.core import START_NS, END_NS, START_CDATA, END_CDATA, PI, COMMENT + +from . import _base + +from ..constants import voidElements, namespaces + + +class TreeWalker(_base.TreeWalker): + def __iter__(self): + # Buffer the events so we can pass in the following one + previous = None + for event in self.tree: + if previous is not None: + for token in self.tokens(previous, event): + yield token + previous = event + + # Don't forget the final event! + if previous is not None: + for token in self.tokens(previous, None): + yield token + + def tokens(self, event, next): + kind, data, pos = event + if kind == START: + tag, attribs = data + name = tag.localname + namespace = tag.namespace + converted_attribs = {} + for k, v in attribs: + if isinstance(k, QName): + converted_attribs[(k.namespace, k.localname)] = v + else: + converted_attribs[(None, k)] = v + + if namespace == namespaces["html"] and name in voidElements: + for token in self.emptyTag(namespace, name, converted_attribs, + not next or next[0] != END + or next[1] != tag): + yield token + else: + yield self.startTag(namespace, name, converted_attribs) + + elif kind == END: + name = data.localname + namespace = data.namespace + if name not in voidElements: + yield self.endTag(namespace, name) + + elif kind == COMMENT: + yield self.comment(data) + + elif kind == TEXT: + for token in self.text(data): + yield token + + elif kind == DOCTYPE: + yield self.doctype(*data) + + elif kind in (XML_NAMESPACE, DOCTYPE, START_NS, END_NS, + START_CDATA, END_CDATA, PI): + pass + + else: + yield self.unknown(kind) diff --git a/catapult/third_party/html5lib-python/html5lib/treewalkers/lxmletree.py b/catapult/third_party/html5lib-python/html5lib/treewalkers/lxmletree.py new file mode 100644 index 00000000..90e116d3 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treewalkers/lxmletree.py @@ -0,0 +1,201 @@ +from __future__ import absolute_import, division, unicode_literals +from six import text_type + +from lxml import etree +from ..treebuilders.etree import tag_regexp + +from . import _base + +from .. import ihatexml + + +def ensure_str(s): + if s is None: + return None + elif isinstance(s, text_type): + return s + else: + return s.decode("utf-8", "strict") + + +class Root(object): + def __init__(self, et): + self.elementtree = et + self.children = [] + if et.docinfo.internalDTD: + self.children.append(Doctype(self, + ensure_str(et.docinfo.root_name), + ensure_str(et.docinfo.public_id), + ensure_str(et.docinfo.system_url))) + root = et.getroot() + node = root + + while node.getprevious() is not None: + node = node.getprevious() + while node is not None: + self.children.append(node) + node = node.getnext() + + self.text = None + self.tail = None + + def __getitem__(self, key): + return self.children[key] + + def getnext(self): + return None + + def __len__(self): + return 1 + + +class Doctype(object): + def __init__(self, root_node, name, public_id, system_id): + self.root_node = root_node + self.name = name + self.public_id = public_id + self.system_id = system_id + + self.text = None + self.tail = None + + def getnext(self): + return self.root_node.children[1] + + +class FragmentRoot(Root): + def __init__(self, children): + self.children = [FragmentWrapper(self, child) for child in children] + self.text = self.tail = None + + def getnext(self): + return None + + +class FragmentWrapper(object): + def __init__(self, fragment_root, obj): + self.root_node = fragment_root + self.obj = obj + if hasattr(self.obj, 'text'): + self.text = ensure_str(self.obj.text) + else: + self.text = None + if hasattr(self.obj, 'tail'): + self.tail = ensure_str(self.obj.tail) + else: + self.tail = None + + def __getattr__(self, name): + return getattr(self.obj, name) + + def getnext(self): + siblings = self.root_node.children + idx = siblings.index(self) + if idx < len(siblings) - 1: + return siblings[idx + 1] + else: + return None + + def __getitem__(self, key): + return self.obj[key] + + def __bool__(self): + return bool(self.obj) + + def getparent(self): + return None + + def __str__(self): + return str(self.obj) + + def __unicode__(self): + return str(self.obj) + + def __len__(self): + return len(self.obj) + + +class TreeWalker(_base.NonRecursiveTreeWalker): + def __init__(self, tree): + if hasattr(tree, "getroot"): + tree = Root(tree) + elif isinstance(tree, list): + tree = FragmentRoot(tree) + _base.NonRecursiveTreeWalker.__init__(self, tree) + self.filter = ihatexml.InfosetFilter() + + def getNodeDetails(self, node): + if isinstance(node, tuple): # Text node + node, key = node + assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key + return _base.TEXT, ensure_str(getattr(node, key)) + + elif isinstance(node, Root): + return (_base.DOCUMENT,) + + elif isinstance(node, Doctype): + return _base.DOCTYPE, node.name, node.public_id, node.system_id + + elif isinstance(node, FragmentWrapper) and not hasattr(node, "tag"): + return _base.TEXT, node.obj + + elif node.tag == etree.Comment: + return _base.COMMENT, ensure_str(node.text) + + elif node.tag == etree.Entity: + return _base.ENTITY, ensure_str(node.text)[1:-1] # strip &; + + else: + # This is assumed to be an ordinary element + match = tag_regexp.match(ensure_str(node.tag)) + if match: + namespace, tag = match.groups() + else: + namespace = None + tag = ensure_str(node.tag) + attrs = {} + for name, value in list(node.attrib.items()): + name = ensure_str(name) + value = ensure_str(value) + match = tag_regexp.match(name) + if match: + attrs[(match.group(1), match.group(2))] = value + else: + attrs[(None, name)] = value + return (_base.ELEMENT, namespace, self.filter.fromXmlName(tag), + attrs, len(node) > 0 or node.text) + + def getFirstChild(self, node): + assert not isinstance(node, tuple), "Text nodes have no children" + + assert len(node) or node.text, "Node has no children" + if node.text: + return (node, "text") + else: + return node[0] + + def getNextSibling(self, node): + if isinstance(node, tuple): # Text node + node, key = node + assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key + if key == "text": + # XXX: we cannot use a "bool(node) and node[0] or None" construct here + # because node[0] might evaluate to False if it has no child element + if len(node): + return node[0] + else: + return None + else: # tail + return node.getnext() + + return (node, "tail") if node.tail else node.getnext() + + def getParentNode(self, node): + if isinstance(node, tuple): # Text node + node, key = node + assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key + if key == "text": + return node + # else: fallback to "normal" processing + + return node.getparent() diff --git a/catapult/third_party/html5lib-python/html5lib/treewalkers/pulldom.py b/catapult/third_party/html5lib-python/html5lib/treewalkers/pulldom.py new file mode 100644 index 00000000..0b0f515f --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/treewalkers/pulldom.py @@ -0,0 +1,63 @@ +from __future__ import absolute_import, division, unicode_literals + +from xml.dom.pulldom import START_ELEMENT, END_ELEMENT, \ + COMMENT, IGNORABLE_WHITESPACE, CHARACTERS + +from . import _base + +from ..constants import voidElements + + +class TreeWalker(_base.TreeWalker): + def __iter__(self): + ignore_until = None + previous = None + for event in self.tree: + if previous is not None and \ + (ignore_until is None or previous[1] is ignore_until): + if previous[1] is ignore_until: + ignore_until = None + for token in self.tokens(previous, event): + yield token + if token["type"] == "EmptyTag": + ignore_until = previous[1] + previous = event + if ignore_until is None or previous[1] is ignore_until: + for token in self.tokens(previous, None): + yield token + elif ignore_until is not None: + raise ValueError("Illformed DOM event stream: void element without END_ELEMENT") + + def tokens(self, event, next): + type, node = event + if type == START_ELEMENT: + name = node.nodeName + namespace = node.namespaceURI + attrs = {} + for attr in list(node.attributes.keys()): + attr = node.getAttributeNode(attr) + attrs[(attr.namespaceURI, attr.localName)] = attr.value + if name in voidElements: + for token in self.emptyTag(namespace, + name, + attrs, + not next or next[1] is not node): + yield token + else: + yield self.startTag(namespace, name, attrs) + + elif type == END_ELEMENT: + name = node.nodeName + namespace = node.namespaceURI + if name not in voidElements: + yield self.endTag(namespace, name) + + elif type == COMMENT: + yield self.comment(node.nodeValue) + + elif type in (IGNORABLE_WHITESPACE, CHARACTERS): + for token in self.text(node.nodeValue): + yield token + + else: + yield self.unknown(type) diff --git a/catapult/third_party/html5lib-python/html5lib/trie/__init__.py b/catapult/third_party/html5lib-python/html5lib/trie/__init__.py new file mode 100644 index 00000000..a8cca8a9 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/trie/__init__.py @@ -0,0 +1,12 @@ +from __future__ import absolute_import, division, unicode_literals + +from .py import Trie as PyTrie + +Trie = PyTrie + +try: + from .datrie import Trie as DATrie +except ImportError: + pass +else: + Trie = DATrie diff --git a/catapult/third_party/html5lib-python/html5lib/trie/_base.py b/catapult/third_party/html5lib-python/html5lib/trie/_base.py new file mode 100644 index 00000000..724486b1 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/trie/_base.py @@ -0,0 +1,37 @@ +from __future__ import absolute_import, division, unicode_literals + +from collections import Mapping + + +class Trie(Mapping): + """Abstract base class for tries""" + + def keys(self, prefix=None): + keys = super().keys() + + if prefix is None: + return set(keys) + + # Python 2.6: no set comprehensions + return set([x for x in keys if x.startswith(prefix)]) + + def has_keys_with_prefix(self, prefix): + for key in self.keys(): + if key.startswith(prefix): + return True + + return False + + def longest_prefix(self, prefix): + if prefix in self: + return prefix + + for i in range(1, len(prefix) + 1): + if prefix[:-i] in self: + return prefix[:-i] + + raise KeyError(prefix) + + def longest_prefix_item(self, prefix): + lprefix = self.longest_prefix(prefix) + return (lprefix, self[lprefix]) diff --git a/catapult/third_party/html5lib-python/html5lib/trie/datrie.py b/catapult/third_party/html5lib-python/html5lib/trie/datrie.py new file mode 100644 index 00000000..51f3d046 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/trie/datrie.py @@ -0,0 +1,44 @@ +from __future__ import absolute_import, division, unicode_literals + +from datrie import Trie as DATrie +from six import text_type + +from ._base import Trie as ABCTrie + + +class Trie(ABCTrie): + def __init__(self, data): + chars = set() + for key in data.keys(): + if not isinstance(key, text_type): + raise TypeError("All keys must be strings") + for char in key: + chars.add(char) + + self._data = DATrie("".join(chars)) + for key, value in data.items(): + self._data[key] = value + + def __contains__(self, key): + return key in self._data + + def __len__(self): + return len(self._data) + + def __iter__(self): + raise NotImplementedError() + + def __getitem__(self, key): + return self._data[key] + + def keys(self, prefix=None): + return self._data.keys(prefix) + + def has_keys_with_prefix(self, prefix): + return self._data.has_keys_with_prefix(prefix) + + def longest_prefix(self, prefix): + return self._data.longest_prefix(prefix) + + def longest_prefix_item(self, prefix): + return self._data.longest_prefix_item(prefix) diff --git a/catapult/third_party/html5lib-python/html5lib/trie/py.py b/catapult/third_party/html5lib-python/html5lib/trie/py.py new file mode 100644 index 00000000..c2ba3da7 --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/trie/py.py @@ -0,0 +1,67 @@ +from __future__ import absolute_import, division, unicode_literals +from six import text_type + +from bisect import bisect_left + +from ._base import Trie as ABCTrie + + +class Trie(ABCTrie): + def __init__(self, data): + if not all(isinstance(x, text_type) for x in data.keys()): + raise TypeError("All keys must be strings") + + self._data = data + self._keys = sorted(data.keys()) + self._cachestr = "" + self._cachepoints = (0, len(data)) + + def __contains__(self, key): + return key in self._data + + def __len__(self): + return len(self._data) + + def __iter__(self): + return iter(self._data) + + def __getitem__(self, key): + return self._data[key] + + def keys(self, prefix=None): + if prefix is None or prefix == "" or not self._keys: + return set(self._keys) + + if prefix.startswith(self._cachestr): + lo, hi = self._cachepoints + start = i = bisect_left(self._keys, prefix, lo, hi) + else: + start = i = bisect_left(self._keys, prefix) + + keys = set() + if start == len(self._keys): + return keys + + while self._keys[i].startswith(prefix): + keys.add(self._keys[i]) + i += 1 + + self._cachestr = prefix + self._cachepoints = (start, i) + + return keys + + def has_keys_with_prefix(self, prefix): + if prefix in self._data: + return True + + if prefix.startswith(self._cachestr): + lo, hi = self._cachepoints + i = bisect_left(self._keys, prefix, lo, hi) + else: + i = bisect_left(self._keys, prefix) + + if i == len(self._keys): + return False + + return self._keys[i].startswith(prefix) diff --git a/catapult/third_party/html5lib-python/html5lib/utils.py b/catapult/third_party/html5lib-python/html5lib/utils.py new file mode 100644 index 00000000..fdc18feb --- /dev/null +++ b/catapult/third_party/html5lib-python/html5lib/utils.py @@ -0,0 +1,103 @@ +from __future__ import absolute_import, division, unicode_literals + +from types import ModuleType + +from six import text_type + +try: + import xml.etree.cElementTree as default_etree +except ImportError: + import xml.etree.ElementTree as default_etree + + +__all__ = ["default_etree", "MethodDispatcher", "isSurrogatePair", + "surrogatePairToCodepoint", "moduleFactoryFactory", + "supports_lone_surrogates"] + + +# Platforms not supporting lone surrogates (\uD800-\uDFFF) should be +# caught by the below test. In general this would be any platform +# using UTF-16 as its encoding of unicode strings, such as +# Jython. This is because UTF-16 itself is based on the use of such +# surrogates, and there is no mechanism to further escape such +# escapes. +try: + _x = eval('"\\uD800"') + if not isinstance(_x, text_type): + # We need this with u"" because of http://bugs.jython.org/issue2039 + _x = eval('u"\\uD800"') + assert isinstance(_x, text_type) +except: + supports_lone_surrogates = False +else: + supports_lone_surrogates = True + + +class MethodDispatcher(dict): + """Dict with 2 special properties: + + On initiation, keys that are lists, sets or tuples are converted to + multiple keys so accessing any one of the items in the original + list-like object returns the matching value + + md = MethodDispatcher({("foo", "bar"):"baz"}) + md["foo"] == "baz" + + A default value which can be set through the default attribute. + """ + + def __init__(self, items=()): + # Using _dictEntries instead of directly assigning to self is about + # twice as fast. Please do careful performance testing before changing + # anything here. + _dictEntries = [] + for name, value in items: + if type(name) in (list, tuple, frozenset, set): + for item in name: + _dictEntries.append((item, value)) + else: + _dictEntries.append((name, value)) + dict.__init__(self, _dictEntries) + self.default = None + + def __getitem__(self, key): + return dict.get(self, key, self.default) + + +# Some utility functions to dal with weirdness around UCS2 vs UCS4 +# python builds + +def isSurrogatePair(data): + return (len(data) == 2 and + ord(data[0]) >= 0xD800 and ord(data[0]) <= 0xDBFF and + ord(data[1]) >= 0xDC00 and ord(data[1]) <= 0xDFFF) + + +def surrogatePairToCodepoint(data): + char_val = (0x10000 + (ord(data[0]) - 0xD800) * 0x400 + + (ord(data[1]) - 0xDC00)) + return char_val + +# Module Factory Factory (no, this isn't Java, I know) +# Here to stop this being duplicated all over the place. + + +def moduleFactoryFactory(factory): + moduleCache = {} + + def moduleFactory(baseModule, *args, **kwargs): + if isinstance(ModuleType.__name__, type("")): + name = "_%s_factory" % baseModule.__name__ + else: + name = b"_%s_factory" % baseModule.__name__ + + if name in moduleCache: + return moduleCache[name] + else: + mod = ModuleType(name) + objs = factory(baseModule, *args, **kwargs) + mod.__dict__.update(objs) + moduleCache[name] = mod + return mod + + return moduleFactory diff --git a/catapult/third_party/html5lib-python/parse.py b/catapult/third_party/html5lib-python/parse.py new file mode 100755 index 00000000..b9bea288 --- /dev/null +++ b/catapult/third_party/html5lib-python/parse.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +"""usage: %prog [options] filename + +Parse a document to a tree, with optional profiling +""" + +import sys +import os +import traceback +from optparse import OptionParser + +from html5lib import html5parser, sanitizer +from html5lib.tokenizer import HTMLTokenizer +from html5lib import treebuilders, serializer, treewalkers +from html5lib import constants +from html5lib import utils + +def parse(): + optParser = getOptParser() + opts,args = optParser.parse_args() + encoding = "utf8" + + try: + f = args[-1] + # Try opening from the internet + if f.startswith('http://'): + try: + import urllib.request, urllib.parse, urllib.error, cgi + f = urllib.request.urlopen(f) + contentType = f.headers.get('content-type') + if contentType: + (mediaType, params) = cgi.parse_header(contentType) + encoding = params.get('charset') + except: + pass + elif f == '-': + f = sys.stdin + if sys.version_info[0] >= 3: + encoding = None + else: + try: + # Try opening from file system + f = open(f, "rb") + except IOError as e: + sys.stderr.write("Unable to open file: %s\n" % e) + sys.exit(1) + except IndexError: + sys.stderr.write("No filename provided. Use -h for help\n") + sys.exit(1) + + treebuilder = treebuilders.getTreeBuilder(opts.treebuilder) + + if opts.sanitize: + tokenizer = sanitizer.HTMLSanitizer + else: + tokenizer = HTMLTokenizer + + p = html5parser.HTMLParser(tree=treebuilder, tokenizer=tokenizer, debug=opts.log) + + if opts.fragment: + parseMethod = p.parseFragment + else: + parseMethod = p.parse + + if opts.profile: + import cProfile + import pstats + cProfile.runctx("run(parseMethod, f, encoding)", None, + {"run": run, + "parseMethod": parseMethod, + "f": f, + "encoding": encoding}, + "stats.prof") + # XXX - We should use a temp file here + stats = pstats.Stats('stats.prof') + stats.strip_dirs() + stats.sort_stats('time') + stats.print_stats() + elif opts.time: + import time + t0 = time.time() + document = run(parseMethod, f, encoding) + t1 = time.time() + if document: + printOutput(p, document, opts) + t2 = time.time() + sys.stderr.write("\n\nRun took: %fs (plus %fs to print the output)"%(t1-t0, t2-t1)) + else: + sys.stderr.write("\n\nRun took: %fs"%(t1-t0)) + else: + document = run(parseMethod, f, encoding) + if document: + printOutput(p, document, opts) + +def run(parseMethod, f, encoding): + try: + document = parseMethod(f, encoding=encoding) + except: + document = None + traceback.print_exc() + return document + +def printOutput(parser, document, opts): + if opts.encoding: + print("Encoding:", parser.tokenizer.stream.charEncoding) + + for item in parser.log: + print(item) + + if document is not None: + if opts.xml: + tb = opts.treebuilder.lower() + if tb == "dom": + document.writexml(sys.stdout, encoding="utf-8") + elif tb == "lxml": + import lxml.etree + sys.stdout.write(lxml.etree.tostring(document)) + elif tb == "etree": + sys.stdout.write(utils.default_etree.tostring(document)) + elif opts.tree: + if not hasattr(document,'__getitem__'): + document = [document] + for fragment in document: + print(parser.tree.testSerializer(fragment)) + elif opts.hilite: + sys.stdout.write(document.hilite("utf-8")) + elif opts.html: + kwargs = {} + for opt in serializer.HTMLSerializer.options: + try: + kwargs[opt] = getattr(opts,opt) + except: + pass + if not kwargs['quote_char']: + del kwargs['quote_char'] + + tokens = treewalkers.getTreeWalker(opts.treebuilder)(document) + if sys.version_info[0] >= 3: + encoding = None + else: + encoding = "utf-8" + for text in serializer.HTMLSerializer(**kwargs).serialize(tokens, encoding=encoding): + sys.stdout.write(text) + if not text.endswith('\n'): sys.stdout.write('\n') + if opts.error: + errList=[] + for pos, errorcode, datavars in parser.errors: + errList.append("Line %i Col %i"%pos + " " + constants.E.get(errorcode, 'Unknown error "%s"' % errorcode) % datavars) + sys.stdout.write("\nParse errors:\n" + "\n".join(errList)+"\n") + +def getOptParser(): + parser = OptionParser(usage=__doc__) + + parser.add_option("-p", "--profile", action="store_true", default=False, + dest="profile", help="Use the hotshot profiler to " + "produce a detailed log of the run") + + parser.add_option("-t", "--time", + action="store_true", default=False, dest="time", + help="Time the run using time.time (may not be accurate on all platforms, especially for short runs)") + + parser.add_option("-b", "--treebuilder", action="store", type="string", + dest="treebuilder", default="etree") + + parser.add_option("-e", "--error", action="store_true", default=False, + dest="error", help="Print a list of parse errors") + + parser.add_option("-f", "--fragment", action="store_true", default=False, + dest="fragment", help="Parse as a fragment") + + parser.add_option("", "--tree", action="store_true", default=False, + dest="tree", help="Output as debug tree") + + parser.add_option("-x", "--xml", action="store_true", default=False, + dest="xml", help="Output as xml") + + parser.add_option("", "--no-html", action="store_false", default=True, + dest="html", help="Don't output html") + + parser.add_option("", "--hilite", action="store_true", default=False, + dest="hilite", help="Output as formatted highlighted code.") + + parser.add_option("-c", "--encoding", action="store_true", default=False, + dest="encoding", help="Print character encoding used") + + parser.add_option("", "--inject-meta-charset", action="store_true", + default=False, dest="inject_meta_charset", + help="inject <meta charset>") + + parser.add_option("", "--strip-whitespace", action="store_true", + default=False, dest="strip_whitespace", + help="strip whitespace") + + parser.add_option("", "--omit-optional-tags", action="store_true", + default=False, dest="omit_optional_tags", + help="omit optional tags") + + parser.add_option("", "--quote-attr-values", action="store_true", + default=False, dest="quote_attr_values", + help="quote attribute values") + + parser.add_option("", "--use-best-quote-char", action="store_true", + default=False, dest="use_best_quote_char", + help="use best quote character") + + parser.add_option("", "--quote-char", action="store", + default=None, dest="quote_char", + help="quote character") + + parser.add_option("", "--no-minimize-boolean-attributes", + action="store_false", default=True, + dest="minimize_boolean_attributes", + help="minimize boolean attributes") + + parser.add_option("", "--use-trailing-solidus", action="store_true", + default=False, dest="use_trailing_solidus", + help="use trailing solidus") + + parser.add_option("", "--space-before-trailing-solidus", + action="store_true", default=False, + dest="space_before_trailing_solidus", + help="add space before trailing solidus") + + parser.add_option("", "--escape-lt-in-attrs", action="store_true", + default=False, dest="escape_lt_in_attrs", + help="escape less than signs in attribute values") + + parser.add_option("", "--escape-rcdata", action="store_true", + default=False, dest="escape_rcdata", + help="escape rcdata element values") + + parser.add_option("", "--sanitize", action="store_true", default=False, + dest="sanitize", help="sanitize") + + parser.add_option("-l", "--log", action="store_true", default=False, + dest="log", help="log state transitions") + + return parser + +if __name__ == "__main__": + parse() diff --git a/catapult/third_party/html5lib-python/requirements-install.sh b/catapult/third_party/html5lib-python/requirements-install.sh new file mode 100755 index 00000000..5f8ba506 --- /dev/null +++ b/catapult/third_party/html5lib-python/requirements-install.sh @@ -0,0 +1,16 @@ +#!/bin/bash -e + +if [[ $USE_OPTIONAL != "true" && $USE_OPTIONAL != "false" ]]; then + echo "fatal: \$USE_OPTIONAL not set to true or false. Exiting." + exit 1 +fi + +pip install -r requirements-test.txt + +if [[ $USE_OPTIONAL == "true" && $TRAVIS_PYTHON_VERSION != "pypy" ]]; then + if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then + pip install --allow-external Genshi --allow-insecure Genshi -r requirements-optional-2.6.txt + else + pip install --allow-external Genshi --allow-insecure Genshi -r requirements-optional-cpython.txt + fi +fi diff --git a/catapult/third_party/html5lib-python/requirements-optional-2.6.txt b/catapult/third_party/html5lib-python/requirements-optional-2.6.txt new file mode 100644 index 00000000..37557ac4 --- /dev/null +++ b/catapult/third_party/html5lib-python/requirements-optional-2.6.txt @@ -0,0 +1,5 @@ +-r requirements-optional-cpython.txt + +# Can be used to force attributes to be serialized in alphabetical +# order. +ordereddict diff --git a/catapult/third_party/html5lib-python/requirements-optional-cpython.txt b/catapult/third_party/html5lib-python/requirements-optional-cpython.txt new file mode 100644 index 00000000..35ed3529 --- /dev/null +++ b/catapult/third_party/html5lib-python/requirements-optional-cpython.txt @@ -0,0 +1,5 @@ +-r requirements-optional.txt + +# lxml is supported with its own treebuilder ("lxml") and otherwise +# uses the standard ElementTree support +lxml diff --git a/catapult/third_party/html5lib-python/requirements-optional.txt b/catapult/third_party/html5lib-python/requirements-optional.txt new file mode 100644 index 00000000..c6355270 --- /dev/null +++ b/catapult/third_party/html5lib-python/requirements-optional.txt @@ -0,0 +1,13 @@ +-r requirements.txt + +# We support a Genshi treewalker that can be used to serialize Genshi +# streams. +genshi + +# DATrie can be used in place of our Python trie implementation for +# slightly better parsing performance. +datrie + +# charade can be used as a fallback in case we are unable to determine +# the encoding of a document. +charade diff --git a/catapult/third_party/html5lib-python/requirements-test.txt b/catapult/third_party/html5lib-python/requirements-test.txt new file mode 100644 index 00000000..d5f8088c --- /dev/null +++ b/catapult/third_party/html5lib-python/requirements-test.txt @@ -0,0 +1,5 @@ +-r requirements.txt + +flake8 +nose +ordereddict # Python 2.6 diff --git a/catapult/third_party/html5lib-python/requirements.txt b/catapult/third_party/html5lib-python/requirements.txt new file mode 100644 index 00000000..ffe2fce4 --- /dev/null +++ b/catapult/third_party/html5lib-python/requirements.txt @@ -0,0 +1 @@ +six diff --git a/catapult/third_party/html5lib-python/setup.py b/catapult/third_party/html5lib-python/setup.py new file mode 100644 index 00000000..34474724 --- /dev/null +++ b/catapult/third_party/html5lib-python/setup.py @@ -0,0 +1,58 @@ +from distutils.core import setup +import ast +import os +import codecs + +classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: Text Processing :: Markup :: HTML' + ] + +packages = ['html5lib'] + ['html5lib.'+name + for name in os.listdir(os.path.join('html5lib')) + if os.path.isdir(os.path.join('html5lib', name)) and + not name.startswith('.') and name != 'tests'] + +current_dir = os.path.dirname(__file__) +with codecs.open(os.path.join(current_dir, 'README.rst'), 'r', 'utf8') as readme_file: + with codecs.open(os.path.join(current_dir, 'CHANGES.rst'), 'r', 'utf8') as changes_file: + long_description = readme_file.read() + '\n' + changes_file.read() + +version = None +with open(os.path.join("html5lib", "__init__.py"), "rb") as init_file: + t = ast.parse(init_file.read(), filename="__init__.py", mode="exec") + assert isinstance(t, ast.Module) + assignments = filter(lambda x: isinstance(x, ast.Assign), t.body) + for a in assignments: + if (len(a.targets) == 1 and + isinstance(a.targets[0], ast.Name) and + a.targets[0].id == "__version__" and + isinstance(a.value, ast.Str)): + version = a.value.s + +setup(name='html5lib', + version=version, + url='https://github.com/html5lib/html5lib-python', + license="MIT License", + description='HTML parser based on the WHATWG HTML specification', + long_description=long_description, + classifiers=classifiers, + maintainer='James Graham', + maintainer_email='james@hoppipolla.co.uk', + packages=packages, + install_requires=[ + 'six', + ], + ) diff --git a/catapult/third_party/html5lib-python/tox.ini b/catapult/third_party/html5lib-python/tox.ini new file mode 100644 index 00000000..479f9e1f --- /dev/null +++ b/catapult/third_party/html5lib-python/tox.ini @@ -0,0 +1,30 @@ +[tox] +envlist = py26,py27,py32,py33,py34,pypy + +[testenv] +deps = + -r{toxinidir}/requirements-optional-cpython.txt + flake8 + nose +commands = + {envbindir}/nosetests -q + {toxinidir}/flake8-run.sh +install_command = + pip install {opts} {packages} + +[testenv:pypy] +# lxml doesn't work and datrie doesn't make sense +# (it's slower than the pure-python version) +deps = + charade + flake8 + Genshi + nose + six + +[testenv:py26] +basepython = python2.6 +deps = + -r{toxinidir}/requirements-optional-2.6.txt + flake8 + nose diff --git a/catapult/third_party/html5lib-python/utils/entities.py b/catapult/third_party/html5lib-python/utils/entities.py new file mode 100644 index 00000000..116a27cb --- /dev/null +++ b/catapult/third_party/html5lib-python/utils/entities.py @@ -0,0 +1,88 @@ +import json + +import html5lib + +def parse(path="html5ents.xml"): + return html5lib.parse(open(path), treebuilder="lxml") + +def entity_table(tree): + return dict((entity_name("".join(tr[0].xpath(".//text()"))), + entity_characters(tr[1].text)) + for tr in tree.xpath("//h:tbody/h:tr", + namespaces={"h":"http://www.w3.org/1999/xhtml"})) + +def entity_name(inp): + return inp.strip() + +def entity_characters(inp): + return "".join(codepoint_to_character(item) + for item in inp.split() + if item) + +def codepoint_to_character(inp): + return ("\U000"+inp[2:]).decode("unicode-escape") + +def make_tests_json(entities): + test_list = make_test_list(entities) + tests_json = {"tests": + [make_test(*item) for item in test_list] + } + return tests_json + +def make_test(name, characters, good): + return { + "description":test_description(name, good), + "input":"&%s"%name, + "output":test_expected(name, characters, good) + } + +def test_description(name, good): + with_semicolon = name.endswith(";") + semicolon_text = {True:"with a semi-colon", + False:"without a semi-colon"}[with_semicolon] + if good: + text = "Named entity: %s %s"%(name, semicolon_text) + else: + text = "Bad named entity: %s %s"%(name, semicolon_text) + return text + +def test_expected(name, characters, good): + rv = [] + if not good or not name.endswith(";"): + rv.append("ParseError") + rv.append(["Character", characters]) + return rv + +def make_test_list(entities): + tests = [] + for entity_name, characters in entities.items(): + if entity_name.endswith(";") and not subentity_exists(entity_name, entities): + tests.append((entity_name[:-1], "&" + entity_name[:-1], False)) + tests.append((entity_name, characters, True)) + return sorted(tests) + +def subentity_exists(entity_name, entities): + for i in range(1, len(entity_name)): + if entity_name[:-i] in entities: + return True + return False + +def make_entities_code(entities): + entities_text = "\n".join(" \"%s\": u\"%s\","%( + name, entities[name].encode( + "unicode-escape").replace("\"", "\\\"")) + for name in sorted(entities.keys())) + return """entities = { +%s +}"""%entities_text + +def main(): + entities = entity_table(parse()) + tests_json = make_tests_json(entities) + json.dump(tests_json, open("namedEntities.test", "w"), indent=4) + code = make_entities_code(entities) + open("entities_constants.py", "w").write(code) + +if __name__ == "__main__": + main() + diff --git a/catapult/third_party/html5lib-python/utils/iana_parse.py b/catapult/third_party/html5lib-python/utils/iana_parse.py new file mode 100644 index 00000000..6dde94c2 --- /dev/null +++ b/catapult/third_party/html5lib-python/utils/iana_parse.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +import sys +import urllib.request, urllib.error, urllib.parse +import codecs + +def main(): + encodings = [] + f = urllib.request.urlopen(sys.argv[1]) + for line in f: + if line.startswith("Name: ") or line.startswith("Alias: "): + enc = line.split()[1] + try: + codecs.lookup(enc) + if enc.lower not in encodings: + encodings.append(enc.lower()) + except LookupError: + pass + sys.stdout.write("encodings = frozenset((\n") + for enc in encodings: + sys.stdout.write(' "%s",\n'%enc) + sys.stdout.write(' ))') + +if __name__ == "__main__": + main()
\ No newline at end of file diff --git a/catapult/third_party/html5lib-python/utils/spider.py b/catapult/third_party/html5lib-python/utils/spider.py new file mode 100644 index 00000000..a7b80319 --- /dev/null +++ b/catapult/third_party/html5lib-python/utils/spider.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +"""Spider to try and find bugs in the parser. Requires httplib2 and elementtree + +usage: +import spider +s = spider.Spider() +s.spider("http://www.google.com", maxURLs=100) +""" + +import urllib.request, urllib.error, urllib.parse +import urllib.robotparser +import md5 + +import httplib2 + +import html5lib +from html5lib.treebuilders import etree + +class Spider(object): + def __init__(self): + self.unvisitedURLs = set() + self.visitedURLs = set() + self.buggyURLs=set() + self.robotParser = urllib.robotparser.RobotFileParser() + self.contentDigest = {} + self.http = httplib2.Http(".cache") + + def run(self, initialURL, maxURLs=1000): + urlNumber = 0 + self.visitedURLs.add(initialURL) + content = self.loadURL(initialURL) + while maxURLs is None or urlNumber < maxURLs: + if content is not None: + self.parse(content) + urlNumber += 1 + if not self.unvisitedURLs: + break + content = self.loadURL(self.unvisitedURLs.pop()) + + def parse(self, content): + failed = False + p = html5lib.HTMLParser(tree=etree.TreeBuilder) + try: + tree = p.parse(content) + except: + self.buggyURLs.add(self.currentURL) + failed = True + print("BUGGY:", self.currentURL) + self.visitedURLs.add(self.currentURL) + if not failed: + self.updateURLs(tree) + + def loadURL(self, url): + resp, content = self.http.request(url, "GET") + self.currentURL = url + digest = md5.md5(content).hexdigest() + if digest in self.contentDigest: + content = None + self.visitedURLs.add(url) + else: + self.contentDigest[digest] = url + + if resp['status'] != "200": + content = None + + return content + + def updateURLs(self, tree): + """Take all the links in the current document, extract the URLs and + update the list of visited and unvisited URLs according to whether we + have seen them before or not""" + urls = set() + #Remove all links we have already visited + for link in tree.findall(".//a"): + try: + url = urllib.parse.urldefrag(link.attrib['href'])[0] + if (url and url not in self.unvisitedURLs and url + not in self.visitedURLs): + urls.add(url) + except KeyError: + pass + + #Remove all non-http URLs and a dd a sutiable base URL where that is + #missing + newUrls = set() + for url in urls: + splitURL = list(urllib.parse.urlsplit(url)) + if splitURL[0] != "http": + continue + if splitURL[1] == "": + splitURL[1] = urllib.parse.urlsplit(self.currentURL)[1] + newUrls.add(urllib.parse.urlunsplit(splitURL)) + urls = newUrls + + responseHeaders = {} + #Now we want to find the content types of the links we haven't visited + for url in urls: + try: + resp, content = self.http.request(url, "HEAD") + responseHeaders[url] = resp + except AttributeError as KeyError: + #Don't know why this happens + pass + + + #Remove links not of content-type html or pages not found + #XXX - need to deal with other status codes? + toVisit = set([url for url in urls if url in responseHeaders and + "html" in responseHeaders[url]['content-type'] and + responseHeaders[url]['status'] == "200"]) + + #Now check we are allowed to spider the page + for url in toVisit: + robotURL = list(urllib.parse.urlsplit(url)[:2]) + robotURL.extend(["robots.txt", "", ""]) + robotURL = urllib.parse.urlunsplit(robotURL) + self.robotParser.set_url(robotURL) + if not self.robotParser.can_fetch("*", url): + toVisit.remove(url) + + self.visitedURLs.update(urls) + self.unvisitedURLs.update(toVisit) diff --git a/catapult/third_party/httplib2/httplib2/README.chromium b/catapult/third_party/httplib2/httplib2/README.chromium deleted file mode 100644 index 5ddca400..00000000 --- a/catapult/third_party/httplib2/httplib2/README.chromium +++ /dev/null @@ -1,11 +0,0 @@ -Name: httplib2 -URL: https://github.com/jcgregorio/httplib2 -Version: 0.9.1 -License: MIT - -Description: -httplib2 is a HTTP library used by oauth2client and apiclient. - -Local Modifications: -Took only the contents of the python2/ directory. - diff --git a/catapult/third_party/httplib2/httplib2/__init__.py b/catapult/third_party/httplib2/httplib2/__init__.py deleted file mode 100644 index 19e7cff1..00000000 --- a/catapult/third_party/httplib2/httplib2/__init__.py +++ /dev/null @@ -1,1695 +0,0 @@ -from __future__ import generators -""" -httplib2 - -A caching http interface that supports ETags and gzip -to conserve bandwidth. - -Requires Python 2.3 or later - -Changelog: -2007-08-18, Rick: Modified so it's able to use a socks proxy if needed. - -""" - -__author__ = "Joe Gregorio (joe@bitworking.org)" -__copyright__ = "Copyright 2006, Joe Gregorio" -__contributors__ = ["Thomas Broyer (t.broyer@ltgt.net)", - "James Antill", - "Xavier Verges Farrero", - "Jonathan Feinberg", - "Blair Zajac", - "Sam Ruby", - "Louis Nyffenegger"] -__license__ = "MIT" -__version__ = "0.9.1" - -import re -import sys -import email -import email.Utils -import email.Message -import email.FeedParser -import StringIO -import gzip -import zlib -import httplib -import urlparse -import urllib -import base64 -import os -import copy -import calendar -import time -import random -import errno -try: - from hashlib import sha1 as _sha, md5 as _md5 -except ImportError: - # prior to Python 2.5, these were separate modules - import sha - import md5 - _sha = sha.new - _md5 = md5.new -import hmac -from gettext import gettext as _ -import socket - -try: - from httplib2 import socks -except ImportError: - try: - import socks - except (ImportError, AttributeError): - socks = None - -# Build the appropriate socket wrapper for ssl -try: - import ssl # python 2.6 - ssl_SSLError = ssl.SSLError - def _ssl_wrap_socket(sock, key_file, cert_file, - disable_validation, ca_certs): - if disable_validation: - cert_reqs = ssl.CERT_NONE - else: - cert_reqs = ssl.CERT_REQUIRED - # We should be specifying SSL version 3 or TLS v1, but the ssl module - # doesn't expose the necessary knobs. So we need to go with the default - # of SSLv23. - return ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file, - cert_reqs=cert_reqs, ca_certs=ca_certs) -except (AttributeError, ImportError): - ssl_SSLError = None - def _ssl_wrap_socket(sock, key_file, cert_file, - disable_validation, ca_certs): - if not disable_validation: - raise CertificateValidationUnsupported( - "SSL certificate validation is not supported without " - "the ssl module installed. To avoid this error, install " - "the ssl module, or explicity disable validation.") - ssl_sock = socket.ssl(sock, key_file, cert_file) - return httplib.FakeSocket(sock, ssl_sock) - - -if sys.version_info >= (2,3): - from iri2uri import iri2uri -else: - def iri2uri(uri): - return uri - -def has_timeout(timeout): # python 2.6 - if hasattr(socket, '_GLOBAL_DEFAULT_TIMEOUT'): - return (timeout is not None and timeout is not socket._GLOBAL_DEFAULT_TIMEOUT) - return (timeout is not None) - -__all__ = [ - 'Http', 'Response', 'ProxyInfo', 'HttpLib2Error', 'RedirectMissingLocation', - 'RedirectLimit', 'FailedToDecompressContent', - 'UnimplementedDigestAuthOptionError', - 'UnimplementedHmacDigestAuthOptionError', - 'debuglevel', 'ProxiesUnavailableError'] - - -# The httplib debug level, set to a non-zero value to get debug output -debuglevel = 0 - -# A request will be tried 'RETRIES' times if it fails at the socket/connection level. -RETRIES = 2 - -# Python 2.3 support -if sys.version_info < (2,4): - def sorted(seq): - seq.sort() - return seq - -# Python 2.3 support -def HTTPResponse__getheaders(self): - """Return list of (header, value) tuples.""" - if self.msg is None: - raise httplib.ResponseNotReady() - return self.msg.items() - -if not hasattr(httplib.HTTPResponse, 'getheaders'): - httplib.HTTPResponse.getheaders = HTTPResponse__getheaders - -# All exceptions raised here derive from HttpLib2Error -class HttpLib2Error(Exception): pass - -# Some exceptions can be caught and optionally -# be turned back into responses. -class HttpLib2ErrorWithResponse(HttpLib2Error): - def __init__(self, desc, response, content): - self.response = response - self.content = content - HttpLib2Error.__init__(self, desc) - -class RedirectMissingLocation(HttpLib2ErrorWithResponse): pass -class RedirectLimit(HttpLib2ErrorWithResponse): pass -class FailedToDecompressContent(HttpLib2ErrorWithResponse): pass -class UnimplementedDigestAuthOptionError(HttpLib2ErrorWithResponse): pass -class UnimplementedHmacDigestAuthOptionError(HttpLib2ErrorWithResponse): pass - -class MalformedHeader(HttpLib2Error): pass -class RelativeURIError(HttpLib2Error): pass -class ServerNotFoundError(HttpLib2Error): pass -class ProxiesUnavailableError(HttpLib2Error): pass -class CertificateValidationUnsupported(HttpLib2Error): pass -class SSLHandshakeError(HttpLib2Error): pass -class NotSupportedOnThisPlatform(HttpLib2Error): pass -class CertificateHostnameMismatch(SSLHandshakeError): - def __init__(self, desc, host, cert): - HttpLib2Error.__init__(self, desc) - self.host = host - self.cert = cert - -# Open Items: -# ----------- -# Proxy support - -# Are we removing the cached content too soon on PUT (only delete on 200 Maybe?) - -# Pluggable cache storage (supports storing the cache in -# flat files by default. We need a plug-in architecture -# that can support Berkeley DB and Squid) - -# == Known Issues == -# Does not handle a resource that uses conneg and Last-Modified but no ETag as a cache validator. -# Does not handle Cache-Control: max-stale -# Does not use Age: headers when calculating cache freshness. - - -# The number of redirections to follow before giving up. -# Note that only GET redirects are automatically followed. -# Will also honor 301 requests by saving that info and never -# requesting that URI again. -DEFAULT_MAX_REDIRECTS = 5 - -try: - # Users can optionally provide a module that tells us where the CA_CERTS - # are located. - import ca_certs_locater - CA_CERTS = ca_certs_locater.get() -except ImportError: - # Default CA certificates file bundled with httplib2. - CA_CERTS = os.path.join( - os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt") - -# Which headers are hop-by-hop headers by default -HOP_BY_HOP = ['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'transfer-encoding', 'upgrade'] - -def _get_end2end_headers(response): - hopbyhop = list(HOP_BY_HOP) - hopbyhop.extend([x.strip() for x in response.get('connection', '').split(',')]) - return [header for header in response.keys() if header not in hopbyhop] - -URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") - -def parse_uri(uri): - """Parses a URI using the regex given in Appendix B of RFC 3986. - - (scheme, authority, path, query, fragment) = parse_uri(uri) - """ - groups = URI.match(uri).groups() - return (groups[1], groups[3], groups[4], groups[6], groups[8]) - -def urlnorm(uri): - (scheme, authority, path, query, fragment) = parse_uri(uri) - if not scheme or not authority: - raise RelativeURIError("Only absolute URIs are allowed. uri = %s" % uri) - authority = authority.lower() - scheme = scheme.lower() - if not path: - path = "/" - # Could do syntax based normalization of the URI before - # computing the digest. See Section 6.2.2 of Std 66. - request_uri = query and "?".join([path, query]) or path - scheme = scheme.lower() - defrag_uri = scheme + "://" + authority + request_uri - return scheme, authority, request_uri, defrag_uri - - -# Cache filename construction (original borrowed from Venus http://intertwingly.net/code/venus/) -re_url_scheme = re.compile(r'^\w+://') -re_slash = re.compile(r'[?/:|]+') - -def safename(filename): - """Return a filename suitable for the cache. - - Strips dangerous and common characters to create a filename we - can use to store the cache in. - """ - - try: - if re_url_scheme.match(filename): - if isinstance(filename,str): - filename = filename.decode('utf-8') - filename = filename.encode('idna') - else: - filename = filename.encode('idna') - except UnicodeError: - pass - if isinstance(filename,unicode): - filename=filename.encode('utf-8') - filemd5 = _md5(filename).hexdigest() - filename = re_url_scheme.sub("", filename) - filename = re_slash.sub(",", filename) - - # limit length of filename - if len(filename)>200: - filename=filename[:200] - return ",".join((filename, filemd5)) - -NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+') -def _normalize_headers(headers): - return dict([ (key.lower(), NORMALIZE_SPACE.sub(value, ' ').strip()) for (key, value) in headers.iteritems()]) - -def _parse_cache_control(headers): - retval = {} - if headers.has_key('cache-control'): - parts = headers['cache-control'].split(',') - parts_with_args = [tuple([x.strip().lower() for x in part.split("=", 1)]) for part in parts if -1 != part.find("=")] - parts_wo_args = [(name.strip().lower(), 1) for name in parts if -1 == name.find("=")] - retval = dict(parts_with_args + parts_wo_args) - return retval - -# Whether to use a strict mode to parse WWW-Authenticate headers -# Might lead to bad results in case of ill-formed header value, -# so disabled by default, falling back to relaxed parsing. -# Set to true to turn on, usefull for testing servers. -USE_WWW_AUTH_STRICT_PARSING = 0 - -# In regex below: -# [^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+ matches a "token" as defined by HTTP -# "(?:[^\0-\x08\x0A-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?" matches a "quoted-string" as defined by HTTP, when LWS have already been replaced by a single space -# Actually, as an auth-param value can be either a token or a quoted-string, they are combined in a single pattern which matches both: -# \"?((?<=\")(?:[^\0-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?(?=\")|(?<!\")[^\0-\x08\x0A-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+(?!\"))\"? -WWW_AUTH_STRICT = re.compile(r"^(?:\s*(?:,\s*)?([^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+)\s*=\s*\"?((?<=\")(?:[^\0-\x08\x0A-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?(?=\")|(?<!\")[^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+(?!\"))\"?)(.*)$") -WWW_AUTH_RELAXED = re.compile(r"^(?:\s*(?:,\s*)?([^ \t\r\n=]+)\s*=\s*\"?((?<=\")(?:[^\\\"]|\\.)*?(?=\")|(?<!\")[^ \t\r\n,]+(?!\"))\"?)(.*)$") -UNQUOTE_PAIRS = re.compile(r'\\(.)') -def _parse_www_authenticate(headers, headername='www-authenticate'): - """Returns a dictionary of dictionaries, one dict - per auth_scheme.""" - retval = {} - if headers.has_key(headername): - try: - - authenticate = headers[headername].strip() - www_auth = USE_WWW_AUTH_STRICT_PARSING and WWW_AUTH_STRICT or WWW_AUTH_RELAXED - while authenticate: - # Break off the scheme at the beginning of the line - if headername == 'authentication-info': - (auth_scheme, the_rest) = ('digest', authenticate) - else: - (auth_scheme, the_rest) = authenticate.split(" ", 1) - # Now loop over all the key value pairs that come after the scheme, - # being careful not to roll into the next scheme - match = www_auth.search(the_rest) - auth_params = {} - while match: - if match and len(match.groups()) == 3: - (key, value, the_rest) = match.groups() - auth_params[key.lower()] = UNQUOTE_PAIRS.sub(r'\1', value) # '\\'.join([x.replace('\\', '') for x in value.split('\\\\')]) - match = www_auth.search(the_rest) - retval[auth_scheme.lower()] = auth_params - authenticate = the_rest.strip() - - except ValueError: - raise MalformedHeader("WWW-Authenticate") - return retval - - -def _entry_disposition(response_headers, request_headers): - """Determine freshness from the Date, Expires and Cache-Control headers. - - We don't handle the following: - - 1. Cache-Control: max-stale - 2. Age: headers are not used in the calculations. - - Not that this algorithm is simpler than you might think - because we are operating as a private (non-shared) cache. - This lets us ignore 's-maxage'. We can also ignore - 'proxy-invalidate' since we aren't a proxy. - We will never return a stale document as - fresh as a design decision, and thus the non-implementation - of 'max-stale'. This also lets us safely ignore 'must-revalidate' - since we operate as if every server has sent 'must-revalidate'. - Since we are private we get to ignore both 'public' and - 'private' parameters. We also ignore 'no-transform' since - we don't do any transformations. - The 'no-store' parameter is handled at a higher level. - So the only Cache-Control parameters we look at are: - - no-cache - only-if-cached - max-age - min-fresh - """ - - retval = "STALE" - cc = _parse_cache_control(request_headers) - cc_response = _parse_cache_control(response_headers) - - if request_headers.has_key('pragma') and request_headers['pragma'].lower().find('no-cache') != -1: - retval = "TRANSPARENT" - if 'cache-control' not in request_headers: - request_headers['cache-control'] = 'no-cache' - elif cc.has_key('no-cache'): - retval = "TRANSPARENT" - elif cc_response.has_key('no-cache'): - retval = "STALE" - elif cc.has_key('only-if-cached'): - retval = "FRESH" - elif response_headers.has_key('date'): - date = calendar.timegm(email.Utils.parsedate_tz(response_headers['date'])) - now = time.time() - current_age = max(0, now - date) - if cc_response.has_key('max-age'): - try: - freshness_lifetime = int(cc_response['max-age']) - except ValueError: - freshness_lifetime = 0 - elif response_headers.has_key('expires'): - expires = email.Utils.parsedate_tz(response_headers['expires']) - if None == expires: - freshness_lifetime = 0 - else: - freshness_lifetime = max(0, calendar.timegm(expires) - date) - else: - freshness_lifetime = 0 - if cc.has_key('max-age'): - try: - freshness_lifetime = int(cc['max-age']) - except ValueError: - freshness_lifetime = 0 - if cc.has_key('min-fresh'): - try: - min_fresh = int(cc['min-fresh']) - except ValueError: - min_fresh = 0 - current_age += min_fresh - if freshness_lifetime > current_age: - retval = "FRESH" - return retval - -def _decompressContent(response, new_content): - content = new_content - try: - encoding = response.get('content-encoding', None) - if encoding in ['gzip', 'deflate']: - if encoding == 'gzip': - content = gzip.GzipFile(fileobj=StringIO.StringIO(new_content)).read() - if encoding == 'deflate': - content = zlib.decompress(content) - response['content-length'] = str(len(content)) - # Record the historical presence of the encoding in a way the won't interfere. - response['-content-encoding'] = response['content-encoding'] - del response['content-encoding'] - except IOError: - content = "" - raise FailedToDecompressContent(_("Content purported to be compressed with %s but failed to decompress.") % response.get('content-encoding'), response, content) - return content - -def _updateCache(request_headers, response_headers, content, cache, cachekey): - if cachekey: - cc = _parse_cache_control(request_headers) - cc_response = _parse_cache_control(response_headers) - if cc.has_key('no-store') or cc_response.has_key('no-store'): - cache.delete(cachekey) - else: - info = email.Message.Message() - for key, value in response_headers.iteritems(): - if key not in ['status','content-encoding','transfer-encoding']: - info[key] = value - - # Add annotations to the cache to indicate what headers - # are variant for this request. - vary = response_headers.get('vary', None) - if vary: - vary_headers = vary.lower().replace(' ', '').split(',') - for header in vary_headers: - key = '-varied-%s' % header - try: - info[key] = request_headers[header] - except KeyError: - pass - - status = response_headers.status - if status == 304: - status = 200 - - status_header = 'status: %d\r\n' % status - - header_str = info.as_string() - - header_str = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", header_str) - text = "".join([status_header, header_str, content]) - - cache.set(cachekey, text) - -def _cnonce(): - dig = _md5("%s:%s" % (time.ctime(), ["0123456789"[random.randrange(0, 9)] for i in range(20)])).hexdigest() - return dig[:16] - -def _wsse_username_token(cnonce, iso_now, password): - return base64.b64encode(_sha("%s%s%s" % (cnonce, iso_now, password)).digest()).strip() - - -# For credentials we need two things, first -# a pool of credential to try (not necesarily tied to BAsic, Digest, etc.) -# Then we also need a list of URIs that have already demanded authentication -# That list is tricky since sub-URIs can take the same auth, or the -# auth scheme may change as you descend the tree. -# So we also need each Auth instance to be able to tell us -# how close to the 'top' it is. - -class Authentication(object): - def __init__(self, credentials, host, request_uri, headers, response, content, http): - (scheme, authority, path, query, fragment) = parse_uri(request_uri) - self.path = path - self.host = host - self.credentials = credentials - self.http = http - - def depth(self, request_uri): - (scheme, authority, path, query, fragment) = parse_uri(request_uri) - return request_uri[len(self.path):].count("/") - - def inscope(self, host, request_uri): - # XXX Should we normalize the request_uri? - (scheme, authority, path, query, fragment) = parse_uri(request_uri) - return (host == self.host) and path.startswith(self.path) - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header. Over-ride this in sub-classes.""" - pass - - def response(self, response, content): - """Gives us a chance to update with new nonces - or such returned from the last authorized response. - Over-rise this in sub-classes if necessary. - - Return TRUE is the request is to be retried, for - example Digest may return stale=true. - """ - return False - - - -class BasicAuthentication(Authentication): - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header.""" - headers['authorization'] = 'Basic ' + base64.b64encode("%s:%s" % self.credentials).strip() - - -class DigestAuthentication(Authentication): - """Only do qop='auth' and MD5, since that - is all Apache currently implements""" - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - challenge = _parse_www_authenticate(response, 'www-authenticate') - self.challenge = challenge['digest'] - qop = self.challenge.get('qop', 'auth') - self.challenge['qop'] = ('auth' in [x.strip() for x in qop.split()]) and 'auth' or None - if self.challenge['qop'] is None: - raise UnimplementedDigestAuthOptionError( _("Unsupported value for qop: %s." % qop)) - self.challenge['algorithm'] = self.challenge.get('algorithm', 'MD5').upper() - if self.challenge['algorithm'] != 'MD5': - raise UnimplementedDigestAuthOptionError( _("Unsupported value for algorithm: %s." % self.challenge['algorithm'])) - self.A1 = "".join([self.credentials[0], ":", self.challenge['realm'], ":", self.credentials[1]]) - self.challenge['nc'] = 1 - - def request(self, method, request_uri, headers, content, cnonce = None): - """Modify the request headers""" - H = lambda x: _md5(x).hexdigest() - KD = lambda s, d: H("%s:%s" % (s, d)) - A2 = "".join([method, ":", request_uri]) - self.challenge['cnonce'] = cnonce or _cnonce() - request_digest = '"%s"' % KD(H(self.A1), "%s:%s:%s:%s:%s" % ( - self.challenge['nonce'], - '%08x' % self.challenge['nc'], - self.challenge['cnonce'], - self.challenge['qop'], H(A2))) - headers['authorization'] = 'Digest username="%s", realm="%s", nonce="%s", uri="%s", algorithm=%s, response=%s, qop=%s, nc=%08x, cnonce="%s"' % ( - self.credentials[0], - self.challenge['realm'], - self.challenge['nonce'], - request_uri, - self.challenge['algorithm'], - request_digest, - self.challenge['qop'], - self.challenge['nc'], - self.challenge['cnonce']) - if self.challenge.get('opaque'): - headers['authorization'] += ', opaque="%s"' % self.challenge['opaque'] - self.challenge['nc'] += 1 - - def response(self, response, content): - if not response.has_key('authentication-info'): - challenge = _parse_www_authenticate(response, 'www-authenticate').get('digest', {}) - if 'true' == challenge.get('stale'): - self.challenge['nonce'] = challenge['nonce'] - self.challenge['nc'] = 1 - return True - else: - updated_challenge = _parse_www_authenticate(response, 'authentication-info').get('digest', {}) - - if updated_challenge.has_key('nextnonce'): - self.challenge['nonce'] = updated_challenge['nextnonce'] - self.challenge['nc'] = 1 - return False - - -class HmacDigestAuthentication(Authentication): - """Adapted from Robert Sayre's code and DigestAuthentication above.""" - __author__ = "Thomas Broyer (t.broyer@ltgt.net)" - - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - challenge = _parse_www_authenticate(response, 'www-authenticate') - self.challenge = challenge['hmacdigest'] - # TODO: self.challenge['domain'] - self.challenge['reason'] = self.challenge.get('reason', 'unauthorized') - if self.challenge['reason'] not in ['unauthorized', 'integrity']: - self.challenge['reason'] = 'unauthorized' - self.challenge['salt'] = self.challenge.get('salt', '') - if not self.challenge.get('snonce'): - raise UnimplementedHmacDigestAuthOptionError( _("The challenge doesn't contain a server nonce, or this one is empty.")) - self.challenge['algorithm'] = self.challenge.get('algorithm', 'HMAC-SHA-1') - if self.challenge['algorithm'] not in ['HMAC-SHA-1', 'HMAC-MD5']: - raise UnimplementedHmacDigestAuthOptionError( _("Unsupported value for algorithm: %s." % self.challenge['algorithm'])) - self.challenge['pw-algorithm'] = self.challenge.get('pw-algorithm', 'SHA-1') - if self.challenge['pw-algorithm'] not in ['SHA-1', 'MD5']: - raise UnimplementedHmacDigestAuthOptionError( _("Unsupported value for pw-algorithm: %s." % self.challenge['pw-algorithm'])) - if self.challenge['algorithm'] == 'HMAC-MD5': - self.hashmod = _md5 - else: - self.hashmod = _sha - if self.challenge['pw-algorithm'] == 'MD5': - self.pwhashmod = _md5 - else: - self.pwhashmod = _sha - self.key = "".join([self.credentials[0], ":", - self.pwhashmod.new("".join([self.credentials[1], self.challenge['salt']])).hexdigest().lower(), - ":", self.challenge['realm']]) - self.key = self.pwhashmod.new(self.key).hexdigest().lower() - - def request(self, method, request_uri, headers, content): - """Modify the request headers""" - keys = _get_end2end_headers(headers) - keylist = "".join(["%s " % k for k in keys]) - headers_val = "".join([headers[k] for k in keys]) - created = time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime()) - cnonce = _cnonce() - request_digest = "%s:%s:%s:%s:%s" % (method, request_uri, cnonce, self.challenge['snonce'], headers_val) - request_digest = hmac.new(self.key, request_digest, self.hashmod).hexdigest().lower() - headers['authorization'] = 'HMACDigest username="%s", realm="%s", snonce="%s", cnonce="%s", uri="%s", created="%s", response="%s", headers="%s"' % ( - self.credentials[0], - self.challenge['realm'], - self.challenge['snonce'], - cnonce, - request_uri, - created, - request_digest, - keylist) - - def response(self, response, content): - challenge = _parse_www_authenticate(response, 'www-authenticate').get('hmacdigest', {}) - if challenge.get('reason') in ['integrity', 'stale']: - return True - return False - - -class WsseAuthentication(Authentication): - """This is thinly tested and should not be relied upon. - At this time there isn't any third party server to test against. - Blogger and TypePad implemented this algorithm at one point - but Blogger has since switched to Basic over HTTPS and - TypePad has implemented it wrong, by never issuing a 401 - challenge but instead requiring your client to telepathically know that - their endpoint is expecting WSSE profile="UsernameToken".""" - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header.""" - headers['authorization'] = 'WSSE profile="UsernameToken"' - iso_now = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) - cnonce = _cnonce() - password_digest = _wsse_username_token(cnonce, iso_now, self.credentials[1]) - headers['X-WSSE'] = 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"' % ( - self.credentials[0], - password_digest, - cnonce, - iso_now) - -class GoogleLoginAuthentication(Authentication): - def __init__(self, credentials, host, request_uri, headers, response, content, http): - from urllib import urlencode - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - challenge = _parse_www_authenticate(response, 'www-authenticate') - service = challenge['googlelogin'].get('service', 'xapi') - # Bloggger actually returns the service in the challenge - # For the rest we guess based on the URI - if service == 'xapi' and request_uri.find("calendar") > 0: - service = "cl" - # No point in guessing Base or Spreadsheet - #elif request_uri.find("spreadsheets") > 0: - # service = "wise" - - auth = dict(Email=credentials[0], Passwd=credentials[1], service=service, source=headers['user-agent']) - resp, content = self.http.request("https://www.google.com/accounts/ClientLogin", method="POST", body=urlencode(auth), headers={'Content-Type': 'application/x-www-form-urlencoded'}) - lines = content.split('\n') - d = dict([tuple(line.split("=", 1)) for line in lines if line]) - if resp.status == 403: - self.Auth = "" - else: - self.Auth = d['Auth'] - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header.""" - headers['authorization'] = 'GoogleLogin Auth=' + self.Auth - - -AUTH_SCHEME_CLASSES = { - "basic": BasicAuthentication, - "wsse": WsseAuthentication, - "digest": DigestAuthentication, - "hmacdigest": HmacDigestAuthentication, - "googlelogin": GoogleLoginAuthentication -} - -AUTH_SCHEME_ORDER = ["hmacdigest", "googlelogin", "digest", "wsse", "basic"] - -class FileCache(object): - """Uses a local directory as a store for cached files. - Not really safe to use if multiple threads or processes are going to - be running on the same cache. - """ - def __init__(self, cache, safe=safename): # use safe=lambda x: md5.new(x).hexdigest() for the old behavior - self.cache = cache - self.safe = safe - if not os.path.exists(cache): - os.makedirs(self.cache) - - def get(self, key): - retval = None - cacheFullPath = os.path.join(self.cache, self.safe(key)) - try: - f = file(cacheFullPath, "rb") - retval = f.read() - f.close() - except IOError: - pass - return retval - - def set(self, key, value): - cacheFullPath = os.path.join(self.cache, self.safe(key)) - f = file(cacheFullPath, "wb") - f.write(value) - f.close() - - def delete(self, key): - cacheFullPath = os.path.join(self.cache, self.safe(key)) - if os.path.exists(cacheFullPath): - os.remove(cacheFullPath) - -class Credentials(object): - def __init__(self): - self.credentials = [] - - def add(self, name, password, domain=""): - self.credentials.append((domain.lower(), name, password)) - - def clear(self): - self.credentials = [] - - def iter(self, domain): - for (cdomain, name, password) in self.credentials: - if cdomain == "" or domain == cdomain: - yield (name, password) - -class KeyCerts(Credentials): - """Identical to Credentials except that - name/password are mapped to key/cert.""" - pass - -class AllHosts(object): - pass - -class ProxyInfo(object): - """Collect information required to use a proxy.""" - bypass_hosts = () - - def __init__(self, proxy_type, proxy_host, proxy_port, - proxy_rdns=True, proxy_user=None, proxy_pass=None): - """ - Args: - proxy_type: The type of proxy server. This must be set to one of - socks.PROXY_TYPE_XXX constants. For example: - - p = ProxyInfo(proxy_type=socks.PROXY_TYPE_HTTP, - proxy_host='localhost', proxy_port=8000) - - proxy_host: The hostname or IP address of the proxy server. - - proxy_port: The port that the proxy server is running on. - - proxy_rdns: If True (default), DNS queries will not be performed - locally, and instead, handed to the proxy to resolve. This is useful - if the network does not allow resolution of non-local names. In - httplib2 0.9 and earlier, this defaulted to False. - - proxy_user: The username used to authenticate with the proxy server. - - proxy_pass: The password used to authenticate with the proxy server. - """ - self.proxy_type = proxy_type - self.proxy_host = proxy_host - self.proxy_port = proxy_port - self.proxy_rdns = proxy_rdns - self.proxy_user = proxy_user - self.proxy_pass = proxy_pass - - def astuple(self): - return (self.proxy_type, self.proxy_host, self.proxy_port, - self.proxy_rdns, self.proxy_user, self.proxy_pass) - - def isgood(self): - return (self.proxy_host != None) and (self.proxy_port != None) - - def applies_to(self, hostname): - return not self.bypass_host(hostname) - - def bypass_host(self, hostname): - """Has this host been excluded from the proxy config""" - if self.bypass_hosts is AllHosts: - return True - - bypass = False - for domain in self.bypass_hosts: - if hostname.endswith(domain): - bypass = True - - return bypass - - -def proxy_info_from_environment(method='http'): - """ - Read proxy info from the environment variables. - """ - if method not in ['http', 'https']: - return - - env_var = method + '_proxy' - url = os.environ.get(env_var, os.environ.get(env_var.upper())) - if not url: - return - pi = proxy_info_from_url(url, method) - - no_proxy = os.environ.get('no_proxy', os.environ.get('NO_PROXY', '')) - bypass_hosts = [] - if no_proxy: - bypass_hosts = no_proxy.split(',') - # special case, no_proxy=* means all hosts bypassed - if no_proxy == '*': - bypass_hosts = AllHosts - - pi.bypass_hosts = bypass_hosts - return pi - -def proxy_info_from_url(url, method='http'): - """ - Construct a ProxyInfo from a URL (such as http_proxy env var) - """ - url = urlparse.urlparse(url) - username = None - password = None - port = None - if '@' in url[1]: - ident, host_port = url[1].split('@', 1) - if ':' in ident: - username, password = ident.split(':', 1) - else: - password = ident - else: - host_port = url[1] - if ':' in host_port: - host, port = host_port.split(':', 1) - else: - host = host_port - - if port: - port = int(port) - else: - port = dict(https=443, http=80)[method] - - proxy_type = 3 # socks.PROXY_TYPE_HTTP - return ProxyInfo( - proxy_type = proxy_type, - proxy_host = host, - proxy_port = port, - proxy_user = username or None, - proxy_pass = password or None, - ) - - -class HTTPConnectionWithTimeout(httplib.HTTPConnection): - """ - HTTPConnection subclass that supports timeouts - - All timeouts are in seconds. If None is passed for timeout then - Python's default timeout for sockets will be used. See for example - the docs of socket.setdefaulttimeout(): - http://docs.python.org/library/socket.html#socket.setdefaulttimeout - """ - - def __init__(self, host, port=None, strict=None, timeout=None, proxy_info=None): - httplib.HTTPConnection.__init__(self, host, port, strict) - self.timeout = timeout - self.proxy_info = proxy_info - - def connect(self): - """Connect to the host and port specified in __init__.""" - # Mostly verbatim from httplib.py. - if self.proxy_info and socks is None: - raise ProxiesUnavailableError( - 'Proxy support missing but proxy use was requested!') - msg = "getaddrinfo returns an empty list" - if self.proxy_info and self.proxy_info.isgood(): - use_proxy = True - proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass = self.proxy_info.astuple() - - host = proxy_host - port = proxy_port - else: - use_proxy = False - - host = self.host - port = self.port - - for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - if use_proxy: - self.sock = socks.socksocket(af, socktype, proto) - self.sock.setproxy(proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass) - else: - self.sock = socket.socket(af, socktype, proto) - self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - # Different from httplib: support timeouts. - if has_timeout(self.timeout): - self.sock.settimeout(self.timeout) - # End of difference from httplib. - if self.debuglevel > 0: - print "connect: (%s, %s) ************" % (self.host, self.port) - if use_proxy: - print "proxy: %s ************" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass)) - - self.sock.connect((self.host, self.port) + sa[2:]) - except socket.error, msg: - if self.debuglevel > 0: - print "connect fail: (%s, %s)" % (self.host, self.port) - if use_proxy: - print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass)) - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg - -class HTTPSConnectionWithTimeout(httplib.HTTPSConnection): - """ - This class allows communication via SSL. - - All timeouts are in seconds. If None is passed for timeout then - Python's default timeout for sockets will be used. See for example - the docs of socket.setdefaulttimeout(): - http://docs.python.org/library/socket.html#socket.setdefaulttimeout - """ - def __init__(self, host, port=None, key_file=None, cert_file=None, - strict=None, timeout=None, proxy_info=None, - ca_certs=None, disable_ssl_certificate_validation=False): - httplib.HTTPSConnection.__init__(self, host, port=port, - key_file=key_file, - cert_file=cert_file, strict=strict) - self.timeout = timeout - self.proxy_info = proxy_info - if ca_certs is None: - ca_certs = CA_CERTS - self.ca_certs = ca_certs - self.disable_ssl_certificate_validation = \ - disable_ssl_certificate_validation - - # The following two methods were adapted from https_wrapper.py, released - # with the Google Appengine SDK at - # http://googleappengine.googlecode.com/svn-history/r136/trunk/python/google/appengine/tools/https_wrapper.py - # under the following license: - # - # Copyright 2007 Google Inc. - # - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. - # - - def _GetValidHostsForCert(self, cert): - """Returns a list of valid host globs for an SSL certificate. - - Args: - cert: A dictionary representing an SSL certificate. - Returns: - list: A list of valid host globs. - """ - if 'subjectAltName' in cert: - return [x[1] for x in cert['subjectAltName'] - if x[0].lower() == 'dns'] - else: - return [x[0][1] for x in cert['subject'] - if x[0][0].lower() == 'commonname'] - - def _ValidateCertificateHostname(self, cert, hostname): - """Validates that a given hostname is valid for an SSL certificate. - - Args: - cert: A dictionary representing an SSL certificate. - hostname: The hostname to test. - Returns: - bool: Whether or not the hostname is valid for this certificate. - """ - hosts = self._GetValidHostsForCert(cert) - for host in hosts: - host_re = host.replace('.', '\.').replace('*', '[^.]*') - if re.search('^%s$' % (host_re,), hostname, re.I): - return True - return False - - def connect(self): - "Connect to a host on a given (SSL) port." - - msg = "getaddrinfo returns an empty list" - if self.proxy_info and self.proxy_info.isgood(): - use_proxy = True - proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass = self.proxy_info.astuple() - - host = proxy_host - port = proxy_port - else: - use_proxy = False - - host = self.host - port = self.port - - address_info = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM) - for family, socktype, proto, canonname, sockaddr in address_info: - try: - if use_proxy: - sock = socks.socksocket(family, socktype, proto) - - sock.setproxy(proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass) - else: - sock = socket.socket(family, socktype, proto) - sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - - if has_timeout(self.timeout): - sock.settimeout(self.timeout) - sock.connect((self.host, self.port)) - self.sock =_ssl_wrap_socket( - sock, self.key_file, self.cert_file, - self.disable_ssl_certificate_validation, self.ca_certs) - if self.debuglevel > 0: - print "connect: (%s, %s)" % (self.host, self.port) - if use_proxy: - print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass)) - if not self.disable_ssl_certificate_validation: - cert = self.sock.getpeercert() - hostname = self.host.split(':', 0)[0] - if not self._ValidateCertificateHostname(cert, hostname): - raise CertificateHostnameMismatch( - 'Server presented certificate that does not match ' - 'host %s: %s' % (hostname, cert), hostname, cert) - except ssl_SSLError, e: - if sock: - sock.close() - if self.sock: - self.sock.close() - self.sock = None - # Unfortunately the ssl module doesn't seem to provide any way - # to get at more detailed error information, in particular - # whether the error is due to certificate validation or - # something else (such as SSL protocol mismatch). - if e.errno == ssl.SSL_ERROR_SSL: - raise SSLHandshakeError(e) - else: - raise - except (socket.timeout, socket.gaierror): - raise - except socket.error, msg: - if self.debuglevel > 0: - print "connect fail: (%s, %s)" % (self.host, self.port) - if use_proxy: - print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass)) - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg - -SCHEME_TO_CONNECTION = { - 'http': HTTPConnectionWithTimeout, - 'https': HTTPSConnectionWithTimeout -} - -# Use a different connection object for Google App Engine -try: - try: - from google.appengine.api import apiproxy_stub_map - if apiproxy_stub_map.apiproxy.GetStub('urlfetch') is None: - raise ImportError # Bail out; we're not actually running on App Engine. - from google.appengine.api.urlfetch import fetch - from google.appengine.api.urlfetch import InvalidURLError - except (ImportError, AttributeError): - from google3.apphosting.api import apiproxy_stub_map - if apiproxy_stub_map.apiproxy.GetStub('urlfetch') is None: - raise ImportError # Bail out; we're not actually running on App Engine. - from google3.apphosting.api.urlfetch import fetch - from google3.apphosting.api.urlfetch import InvalidURLError - - def _new_fixed_fetch(validate_certificate): - def fixed_fetch(url, payload=None, method="GET", headers={}, - allow_truncated=False, follow_redirects=True, - deadline=None): - if deadline is None: - deadline = socket.getdefaulttimeout() or 5 - return fetch(url, payload=payload, method=method, headers=headers, - allow_truncated=allow_truncated, - follow_redirects=follow_redirects, deadline=deadline, - validate_certificate=validate_certificate) - return fixed_fetch - - class AppEngineHttpConnection(httplib.HTTPConnection): - """Use httplib on App Engine, but compensate for its weirdness. - - The parameters key_file, cert_file, proxy_info, ca_certs, and - disable_ssl_certificate_validation are all dropped on the ground. - """ - def __init__(self, host, port=None, key_file=None, cert_file=None, - strict=None, timeout=None, proxy_info=None, ca_certs=None, - disable_ssl_certificate_validation=False): - httplib.HTTPConnection.__init__(self, host, port=port, - strict=strict, timeout=timeout) - - class AppEngineHttpsConnection(httplib.HTTPSConnection): - """Same as AppEngineHttpConnection, but for HTTPS URIs.""" - def __init__(self, host, port=None, key_file=None, cert_file=None, - strict=None, timeout=None, proxy_info=None, ca_certs=None, - disable_ssl_certificate_validation=False): - httplib.HTTPSConnection.__init__(self, host, port=port, - key_file=key_file, - cert_file=cert_file, strict=strict, - timeout=timeout) - self._fetch = _new_fixed_fetch( - not disable_ssl_certificate_validation) - - # Update the connection classes to use the Googel App Engine specific ones. - SCHEME_TO_CONNECTION = { - 'http': AppEngineHttpConnection, - 'https': AppEngineHttpsConnection - } -except (ImportError, AttributeError): - pass - - -class Http(object): - """An HTTP client that handles: - - - all methods - - caching - - ETags - - compression, - - HTTPS - - Basic - - Digest - - WSSE - - and more. - """ - def __init__(self, cache=None, timeout=None, - proxy_info=proxy_info_from_environment, - ca_certs=None, disable_ssl_certificate_validation=False): - """If 'cache' is a string then it is used as a directory name for - a disk cache. Otherwise it must be an object that supports the - same interface as FileCache. - - All timeouts are in seconds. If None is passed for timeout - then Python's default timeout for sockets will be used. See - for example the docs of socket.setdefaulttimeout(): - http://docs.python.org/library/socket.html#socket.setdefaulttimeout - - `proxy_info` may be: - - a callable that takes the http scheme ('http' or 'https') and - returns a ProxyInfo instance per request. By default, uses - proxy_nfo_from_environment. - - a ProxyInfo instance (static proxy config). - - None (proxy disabled). - - ca_certs is the path of a file containing root CA certificates for SSL - server certificate validation. By default, a CA cert file bundled with - httplib2 is used. - - If disable_ssl_certificate_validation is true, SSL cert validation will - not be performed. - """ - self.proxy_info = proxy_info - self.ca_certs = ca_certs - self.disable_ssl_certificate_validation = \ - disable_ssl_certificate_validation - - # Map domain name to an httplib connection - self.connections = {} - # The location of the cache, for now a directory - # where cached responses are held. - if cache and isinstance(cache, basestring): - self.cache = FileCache(cache) - else: - self.cache = cache - - # Name/password - self.credentials = Credentials() - - # Key/cert - self.certificates = KeyCerts() - - # authorization objects - self.authorizations = [] - - # If set to False then no redirects are followed, even safe ones. - self.follow_redirects = True - - # Which HTTP methods do we apply optimistic concurrency to, i.e. - # which methods get an "if-match:" etag header added to them. - self.optimistic_concurrency_methods = ["PUT", "PATCH"] - - # If 'follow_redirects' is True, and this is set to True then - # all redirecs are followed, including unsafe ones. - self.follow_all_redirects = False - - self.ignore_etag = False - - self.force_exception_to_status_code = False - - self.timeout = timeout - - # Keep Authorization: headers on a redirect. - self.forward_authorization_headers = False - - def __getstate__(self): - state_dict = copy.copy(self.__dict__) - # In case request is augmented by some foreign object such as - # credentials which handle auth - if 'request' in state_dict: - del state_dict['request'] - if 'connections' in state_dict: - del state_dict['connections'] - return state_dict - - def __setstate__(self, state): - self.__dict__.update(state) - self.connections = {} - - def _auth_from_challenge(self, host, request_uri, headers, response, content): - """A generator that creates Authorization objects - that can be applied to requests. - """ - challenges = _parse_www_authenticate(response, 'www-authenticate') - for cred in self.credentials.iter(host): - for scheme in AUTH_SCHEME_ORDER: - if challenges.has_key(scheme): - yield AUTH_SCHEME_CLASSES[scheme](cred, host, request_uri, headers, response, content, self) - - def add_credentials(self, name, password, domain=""): - """Add a name and password that will be used - any time a request requires authentication.""" - self.credentials.add(name, password, domain) - - def add_certificate(self, key, cert, domain): - """Add a key and cert that will be used - any time a request requires authentication.""" - self.certificates.add(key, cert, domain) - - def clear_credentials(self): - """Remove all the names and passwords - that are used for authentication""" - self.credentials.clear() - self.authorizations = [] - - def _conn_request(self, conn, request_uri, method, body, headers): - i = 0 - seen_bad_status_line = False - while i < RETRIES: - i += 1 - try: - if hasattr(conn, 'sock') and conn.sock is None: - conn.connect() - conn.request(method, request_uri, body, headers) - except socket.timeout: - raise - except socket.gaierror: - conn.close() - raise ServerNotFoundError("Unable to find the server at %s" % conn.host) - except ssl_SSLError: - conn.close() - raise - except socket.error, e: - err = 0 - if hasattr(e, 'args'): - err = getattr(e, 'args')[0] - else: - err = e.errno - if err == errno.ECONNREFUSED: # Connection refused - raise - except httplib.HTTPException: - # Just because the server closed the connection doesn't apparently mean - # that the server didn't send a response. - if hasattr(conn, 'sock') and conn.sock is None: - if i < RETRIES-1: - conn.close() - conn.connect() - continue - else: - conn.close() - raise - if i < RETRIES-1: - conn.close() - conn.connect() - continue - try: - response = conn.getresponse() - except httplib.BadStatusLine: - # If we get a BadStatusLine on the first try then that means - # the connection just went stale, so retry regardless of the - # number of RETRIES set. - if not seen_bad_status_line and i == 1: - i = 0 - seen_bad_status_line = True - conn.close() - conn.connect() - continue - else: - conn.close() - raise - except (socket.error, httplib.HTTPException): - if i < RETRIES-1: - conn.close() - conn.connect() - continue - else: - conn.close() - raise - else: - content = "" - if method == "HEAD": - conn.close() - else: - content = response.read() - response = Response(response) - if method != "HEAD": - content = _decompressContent(response, content) - break - return (response, content) - - - def _request(self, conn, host, absolute_uri, request_uri, method, body, headers, redirections, cachekey): - """Do the actual request using the connection object - and also follow one level of redirects if necessary""" - - auths = [(auth.depth(request_uri), auth) for auth in self.authorizations if auth.inscope(host, request_uri)] - auth = auths and sorted(auths)[0][1] or None - if auth: - auth.request(method, request_uri, headers, body) - - (response, content) = self._conn_request(conn, request_uri, method, body, headers) - - if auth: - if auth.response(response, body): - auth.request(method, request_uri, headers, body) - (response, content) = self._conn_request(conn, request_uri, method, body, headers ) - response._stale_digest = 1 - - if response.status == 401: - for authorization in self._auth_from_challenge(host, request_uri, headers, response, content): - authorization.request(method, request_uri, headers, body) - (response, content) = self._conn_request(conn, request_uri, method, body, headers, ) - if response.status != 401: - self.authorizations.append(authorization) - authorization.response(response, body) - break - - if (self.follow_all_redirects or (method in ["GET", "HEAD"]) or response.status == 303): - if self.follow_redirects and response.status in [300, 301, 302, 303, 307]: - # Pick out the location header and basically start from the beginning - # remembering first to strip the ETag header and decrement our 'depth' - if redirections: - if not response.has_key('location') and response.status != 300: - raise RedirectMissingLocation( _("Redirected but the response is missing a Location: header."), response, content) - # Fix-up relative redirects (which violate an RFC 2616 MUST) - if response.has_key('location'): - location = response['location'] - (scheme, authority, path, query, fragment) = parse_uri(location) - if authority == None: - response['location'] = urlparse.urljoin(absolute_uri, location) - if response.status == 301 and method in ["GET", "HEAD"]: - response['-x-permanent-redirect-url'] = response['location'] - if not response.has_key('content-location'): - response['content-location'] = absolute_uri - _updateCache(headers, response, content, self.cache, cachekey) - if headers.has_key('if-none-match'): - del headers['if-none-match'] - if headers.has_key('if-modified-since'): - del headers['if-modified-since'] - if 'authorization' in headers and not self.forward_authorization_headers: - del headers['authorization'] - if response.has_key('location'): - location = response['location'] - old_response = copy.deepcopy(response) - if not old_response.has_key('content-location'): - old_response['content-location'] = absolute_uri - redirect_method = method - if response.status in [302, 303]: - redirect_method = "GET" - body = None - (response, content) = self.request( - location, method=redirect_method, - body=body, headers=headers, - redirections=redirections - 1) - response.previous = old_response - else: - raise RedirectLimit("Redirected more times than rediection_limit allows.", response, content) - elif response.status in [200, 203] and method in ["GET", "HEAD"]: - # Don't cache 206's since we aren't going to handle byte range requests - if not response.has_key('content-location'): - response['content-location'] = absolute_uri - _updateCache(headers, response, content, self.cache, cachekey) - - return (response, content) - - def _normalize_headers(self, headers): - return _normalize_headers(headers) - -# Need to catch and rebrand some exceptions -# Then need to optionally turn all exceptions into status codes -# including all socket.* and httplib.* exceptions. - - - def request(self, uri, method="GET", body=None, headers=None, redirections=DEFAULT_MAX_REDIRECTS, connection_type=None): - """ Performs a single HTTP request. - - The 'uri' is the URI of the HTTP resource and can begin with either - 'http' or 'https'. The value of 'uri' must be an absolute URI. - - The 'method' is the HTTP method to perform, such as GET, POST, DELETE, - etc. There is no restriction on the methods allowed. - - The 'body' is the entity body to be sent with the request. It is a - string object. - - Any extra headers that are to be sent with the request should be - provided in the 'headers' dictionary. - - The maximum number of redirect to follow before raising an - exception is 'redirections. The default is 5. - - The return value is a tuple of (response, content), the first - being and instance of the 'Response' class, the second being - a string that contains the response entity body. - """ - try: - if headers is None: - headers = {} - else: - headers = self._normalize_headers(headers) - - if not headers.has_key('user-agent'): - headers['user-agent'] = "Python-httplib2/%s (gzip)" % __version__ - - uri = iri2uri(uri) - - (scheme, authority, request_uri, defrag_uri) = urlnorm(uri) - domain_port = authority.split(":")[0:2] - if len(domain_port) == 2 and domain_port[1] == '443' and scheme == 'http': - scheme = 'https' - authority = domain_port[0] - - proxy_info = self._get_proxy_info(scheme, authority) - - conn_key = scheme+":"+authority - if conn_key in self.connections: - conn = self.connections[conn_key] - else: - if not connection_type: - connection_type = SCHEME_TO_CONNECTION[scheme] - certs = list(self.certificates.iter(authority)) - if scheme == 'https': - if certs: - conn = self.connections[conn_key] = connection_type( - authority, key_file=certs[0][0], - cert_file=certs[0][1], timeout=self.timeout, - proxy_info=proxy_info, - ca_certs=self.ca_certs, - disable_ssl_certificate_validation= - self.disable_ssl_certificate_validation) - else: - conn = self.connections[conn_key] = connection_type( - authority, timeout=self.timeout, - proxy_info=proxy_info, - ca_certs=self.ca_certs, - disable_ssl_certificate_validation= - self.disable_ssl_certificate_validation) - else: - conn = self.connections[conn_key] = connection_type( - authority, timeout=self.timeout, - proxy_info=proxy_info) - conn.set_debuglevel(debuglevel) - - if 'range' not in headers and 'accept-encoding' not in headers: - headers['accept-encoding'] = 'gzip, deflate' - - info = email.Message.Message() - cached_value = None - if self.cache: - cachekey = defrag_uri.encode('utf-8') - cached_value = self.cache.get(cachekey) - if cached_value: - # info = email.message_from_string(cached_value) - # - # Need to replace the line above with the kludge below - # to fix the non-existent bug not fixed in this - # bug report: http://mail.python.org/pipermail/python-bugs-list/2005-September/030289.html - try: - info, content = cached_value.split('\r\n\r\n', 1) - feedparser = email.FeedParser.FeedParser() - feedparser.feed(info) - info = feedparser.close() - feedparser._parse = None - except (IndexError, ValueError): - self.cache.delete(cachekey) - cachekey = None - cached_value = None - else: - cachekey = None - - if method in self.optimistic_concurrency_methods and self.cache and info.has_key('etag') and not self.ignore_etag and 'if-match' not in headers: - # http://www.w3.org/1999/04/Editing/ - headers['if-match'] = info['etag'] - - if method not in ["GET", "HEAD"] and self.cache and cachekey: - # RFC 2616 Section 13.10 - self.cache.delete(cachekey) - - # Check the vary header in the cache to see if this request - # matches what varies in the cache. - if method in ['GET', 'HEAD'] and 'vary' in info: - vary = info['vary'] - vary_headers = vary.lower().replace(' ', '').split(',') - for header in vary_headers: - key = '-varied-%s' % header - value = info[key] - if headers.get(header, None) != value: - cached_value = None - break - - if cached_value and method in ["GET", "HEAD"] and self.cache and 'range' not in headers: - if info.has_key('-x-permanent-redirect-url'): - # Should cached permanent redirects be counted in our redirection count? For now, yes. - if redirections <= 0: - raise RedirectLimit("Redirected more times than rediection_limit allows.", {}, "") - (response, new_content) = self.request( - info['-x-permanent-redirect-url'], method='GET', - headers=headers, redirections=redirections - 1) - response.previous = Response(info) - response.previous.fromcache = True - else: - # Determine our course of action: - # Is the cached entry fresh or stale? - # Has the client requested a non-cached response? - # - # There seems to be three possible answers: - # 1. [FRESH] Return the cache entry w/o doing a GET - # 2. [STALE] Do the GET (but add in cache validators if available) - # 3. [TRANSPARENT] Do a GET w/o any cache validators (Cache-Control: no-cache) on the request - entry_disposition = _entry_disposition(info, headers) - - if entry_disposition == "FRESH": - if not cached_value: - info['status'] = '504' - content = "" - response = Response(info) - if cached_value: - response.fromcache = True - return (response, content) - - if entry_disposition == "STALE": - if info.has_key('etag') and not self.ignore_etag and not 'if-none-match' in headers: - headers['if-none-match'] = info['etag'] - if info.has_key('last-modified') and not 'last-modified' in headers: - headers['if-modified-since'] = info['last-modified'] - elif entry_disposition == "TRANSPARENT": - pass - - (response, new_content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey) - - if response.status == 304 and method == "GET": - # Rewrite the cache entry with the new end-to-end headers - # Take all headers that are in response - # and overwrite their values in info. - # unless they are hop-by-hop, or are listed in the connection header. - - for key in _get_end2end_headers(response): - info[key] = response[key] - merged_response = Response(info) - if hasattr(response, "_stale_digest"): - merged_response._stale_digest = response._stale_digest - _updateCache(headers, merged_response, content, self.cache, cachekey) - response = merged_response - response.status = 200 - response.fromcache = True - - elif response.status == 200: - content = new_content - else: - self.cache.delete(cachekey) - content = new_content - else: - cc = _parse_cache_control(headers) - if cc.has_key('only-if-cached'): - info['status'] = '504' - response = Response(info) - content = "" - else: - (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey) - except Exception, e: - if self.force_exception_to_status_code: - if isinstance(e, HttpLib2ErrorWithResponse): - response = e.response - content = e.content - response.status = 500 - response.reason = str(e) - elif isinstance(e, socket.timeout): - content = "Request Timeout" - response = Response({ - "content-type": "text/plain", - "status": "408", - "content-length": len(content) - }) - response.reason = "Request Timeout" - else: - content = str(e) - response = Response({ - "content-type": "text/plain", - "status": "400", - "content-length": len(content) - }) - response.reason = "Bad Request" - else: - raise - - - return (response, content) - - def _get_proxy_info(self, scheme, authority): - """Return a ProxyInfo instance (or None) based on the scheme - and authority. - """ - hostname, port = urllib.splitport(authority) - proxy_info = self.proxy_info - if callable(proxy_info): - proxy_info = proxy_info(scheme) - - if (hasattr(proxy_info, 'applies_to') - and not proxy_info.applies_to(hostname)): - proxy_info = None - return proxy_info - - -class Response(dict): - """An object more like email.Message than httplib.HTTPResponse.""" - - """Is this response from our local cache""" - fromcache = False - - """HTTP protocol version used by server. 10 for HTTP/1.0, 11 for HTTP/1.1. """ - version = 11 - - "Status code returned by server. " - status = 200 - - """Reason phrase returned by server.""" - reason = "Ok" - - previous = None - - def __init__(self, info): - # info is either an email.Message or - # an httplib.HTTPResponse object. - if isinstance(info, httplib.HTTPResponse): - for key, value in info.getheaders(): - self[key.lower()] = value - self.status = info.status - self['status'] = str(self.status) - self.reason = info.reason - self.version = info.version - elif isinstance(info, email.Message.Message): - for key, value in info.items(): - self[key.lower()] = value - self.status = int(self['status']) - else: - for key, value in info.iteritems(): - self[key.lower()] = value - self.status = int(self.get('status', self.status)) - self.reason = self.get('reason', self.reason) - - - def __getattr__(self, name): - if name == 'dict': - return self - else: - raise AttributeError, name diff --git a/catapult/third_party/httplib2/httplib2/cacerts.txt b/catapult/third_party/httplib2/httplib2/cacerts.txt deleted file mode 100644 index 70990f1f..00000000 --- a/catapult/third_party/httplib2/httplib2/cacerts.txt +++ /dev/null @@ -1,2183 +0,0 @@ -# Issuer: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc. -# Subject: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc. -# Label: "GTE CyberTrust Global Root" -# Serial: 421 -# MD5 Fingerprint: ca:3d:d3:68:f1:03:5c:d0:32:fa:b8:2b:59:e8:5a:db -# SHA1 Fingerprint: 97:81:79:50:d8:1c:96:70:cc:34:d8:09:cf:79:44:31:36:7e:f4:74 -# SHA256 Fingerprint: a5:31:25:18:8d:21:10:aa:96:4b:02:c7:b7:c6:da:32:03:17:08:94:e5:fb:71:ff:fb:66:67:d5:e6:81:0a:36 ------BEGIN CERTIFICATE----- -MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD -VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv -bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv -b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV -UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU -cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds -b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH -iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS -r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 -04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r -GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 -3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P -lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ ------END CERTIFICATE----- - -# Issuer: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division -# Subject: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division -# Label: "Thawte Server CA" -# Serial: 1 -# MD5 Fingerprint: c5:70:c4:a2:ed:53:78:0c:c8:10:53:81:64:cb:d0:1d -# SHA1 Fingerprint: 23:e5:94:94:51:95:f2:41:48:03:b4:d5:64:d2:a3:a3:f5:d8:8b:8c -# SHA256 Fingerprint: b4:41:0b:73:e2:e6:ea:ca:47:fb:c4:2f:8f:a4:01:8a:f4:38:1d:c5:4c:fa:a8:44:50:46:1e:ed:09:45:4d:e9 ------BEGIN CERTIFICATE----- -MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm -MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx -MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT -DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 -dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl -cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 -DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD -gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 -yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX -L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj -EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG -7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e -QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ -qdq5snUb9kLy78fyGPmJvKP/iiMucEc= ------END CERTIFICATE----- - -# Issuer: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division -# Subject: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division -# Label: "Thawte Premium Server CA" -# Serial: 1 -# MD5 Fingerprint: 06:9f:69:79:16:66:90:02:1b:8c:8c:a2:c3:07:6f:3a -# SHA1 Fingerprint: 62:7f:8d:78:27:65:63:99:d2:7d:7f:90:44:c9:fe:b3:f3:3e:fa:9a -# SHA256 Fingerprint: ab:70:36:36:5c:71:54:aa:29:c2:c2:9f:5d:41:91:16:3b:16:2a:22:25:01:13:57:d5:6d:07:ff:a7:bc:1f:72 ------BEGIN CERTIFICATE----- -MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy -dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t -MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB -MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG -A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp -b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl -cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv -bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE -VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ -ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR -uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG -9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI -hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM -pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== ------END CERTIFICATE----- - -# Issuer: O=Equifax OU=Equifax Secure Certificate Authority -# Subject: O=Equifax OU=Equifax Secure Certificate Authority -# Label: "Equifax Secure CA" -# Serial: 903804111 -# MD5 Fingerprint: 67:cb:9d:c0:13:24:8a:82:9b:b2:17:1e:d1:1b:ec:d4 -# SHA1 Fingerprint: d2:32:09:ad:23:d3:14:23:21:74:e4:0d:7f:9d:62:13:97:86:63:3a -# SHA256 Fingerprint: 08:29:7a:40:47:db:a2:36:80:c7:31:db:6e:31:76:53:ca:78:48:e1:be:bd:3a:0b:01:79:a7:07:f9:2c:f1:78 ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy -dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 -MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx -dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f -BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A -cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ -MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm -aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw -ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj -IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y -7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh -1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 ------END CERTIFICATE----- - -# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority -# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority -# Label: "Verisign Class 3 Public Primary Certification Authority" -# Serial: 149843929435818692848040365716851702463 -# MD5 Fingerprint: 10:fc:63:5d:f6:26:3e:0d:f3:25:be:5f:79:cd:67:67 -# SHA1 Fingerprint: 74:2c:31:92:e6:07:e4:24:eb:45:49:54:2b:e1:bb:c5:3e:61:74:e2 -# SHA256 Fingerprint: e7:68:56:34:ef:ac:f6:9a:ce:93:9a:6b:25:5b:7b:4f:ab:ef:42:93:5b:50:a2:65:ac:b5:cb:60:27:e4:4e:70 ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE -BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is -I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do -lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc -AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k ------END CERTIFICATE----- - -# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network -# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network -# Label: "Verisign Class 3 Public Primary Certification Authority - G2" -# Serial: 167285380242319648451154478808036881606 -# MD5 Fingerprint: a2:33:9b:4c:74:78:73:d4:6c:e7:c1:f3:8d:cb:5c:e9 -# SHA1 Fingerprint: 85:37:1c:a6:e5:50:14:3d:ce:28:03:47:1b:de:3a:09:e8:f8:77:0f -# SHA256 Fingerprint: 83:ce:3c:12:29:68:8a:59:3d:48:5f:81:97:3c:0f:91:95:43:1e:da:37:cc:5e:36:43:0e:79:c7:a8:88:63:8b ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 -pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 -13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk -U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i -F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY -oJ2daZH9 ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA -# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA -# Label: "GlobalSign Root CA" -# Serial: 4835703278459707669005204 -# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a -# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c -# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B -AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz -yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE -38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP -AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad -DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME -HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 -# Label: "GlobalSign Root CA - R2" -# Serial: 4835703278459682885658125 -# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 -# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe -# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- - -# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority -# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority -# Label: "ValiCert Class 1 VA" -# Serial: 1 -# MD5 Fingerprint: 65:58:ab:15:ad:57:6c:1e:a8:a7:b5:69:ac:bf:ff:eb -# SHA1 Fingerprint: e5:df:74:3c:b6:01:c4:9b:98:43:dc:ab:8c:e8:6a:81:10:9f:e4:8e -# SHA256 Fingerprint: f4:c1:49:55:1a:30:13:a3:5b:c7:bf:fe:17:a7:f3:44:9b:c1:ab:5b:5a:0a:e7:4b:06:c2:3b:90:00:4c:01:04 ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy -NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y -LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ -TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y -TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 -LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW -I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw -nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI ------END CERTIFICATE----- - -# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority -# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority -# Label: "ValiCert Class 2 VA" -# Serial: 1 -# MD5 Fingerprint: a9:23:75:9b:ba:49:36:6e:31:c2:db:f2:e7:66:ba:87 -# SHA1 Fingerprint: 31:7a:2a:d0:7f:2b:33:5e:f5:a1:c3:4e:4b:57:e8:b7:d8:f1:fc:a6 -# SHA256 Fingerprint: 58:d0:17:27:9c:d4:dc:63:ab:dd:b1:96:a6:c9:90:6c:30:c4:e0:87:83:ea:e8:c1:60:99:54:d6:93:55:59:6b ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy -NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY -dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 -WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS -v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v -UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu -IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC -W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd ------END CERTIFICATE----- - -# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority -# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority -# Label: "RSA Root Certificate 1" -# Serial: 1 -# MD5 Fingerprint: a2:6f:53:b7:ee:40:db:4a:68:e7:fa:18:d9:10:4b:72 -# SHA1 Fingerprint: 69:bd:8c:f4:9c:d3:00:fb:59:2e:17:93:ca:55:6a:f3:ec:aa:35:fb -# SHA256 Fingerprint: bc:23:f9:8a:31:3c:b9:2d:e3:bb:fc:3a:5a:9f:44:61:ac:39:49:4c:4a:e1:5a:9e:9d:f1:31:e9:9b:73:01:9a ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy -NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD -cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs -2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY -JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE -Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ -n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A -PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Label: "Verisign Class 3 Public Primary Certification Authority - G3" -# Serial: 206684696279472310254277870180966723415 -# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09 -# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6 -# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44 ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b -N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t -KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu -kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm -CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ -Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu -imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te -2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe -DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p -F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt -TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Label: "Verisign Class 4 Public Primary Certification Authority - G3" -# Serial: 314531972711909413743075096039378935511 -# MD5 Fingerprint: db:c8:f2:27:2e:b1:ea:6a:29:23:5d:fe:56:3e:33:df -# SHA1 Fingerprint: c8:ec:8c:87:92:69:cb:4b:ab:39:e9:8d:7e:57:67:f3:14:95:73:9d -# SHA256 Fingerprint: e3:89:36:0d:0f:db:ae:b3:d2:50:58:4b:47:30:31:4e:22:2f:39:c1:56:a0:20:14:4e:8d:96:05:61:79:15:06 ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 -GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ -+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd -U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm -NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY -ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ -ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 -CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq -g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm -fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c -2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ -bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== ------END CERTIFICATE----- - -# Issuer: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Subject: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Label: "Entrust.net Secure Server CA" -# Serial: 927650371 -# MD5 Fingerprint: df:f2:80:73:cc:f1:e6:61:73:fc:f5:42:e9:c5:7c:ee -# SHA1 Fingerprint: 99:a6:9b:e6:1a:fe:88:6b:4d:2b:82:00:7c:b8:54:fc:31:7e:15:39 -# SHA256 Fingerprint: 62:f2:40:27:8c:56:4c:4d:d8:bf:7d:9d:4f:6f:36:6e:a8:94:d2:2f:5f:34:d9:89:a9:83:ac:ec:2f:ff:ed:50 ------BEGIN CERTIFICATE----- -MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u -ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc -KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u -ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 -MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE -ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j -b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF -bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg -U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA -A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ -I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 -wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC -AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb -oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 -BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p -dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk -MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp -b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu -dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 -MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi -E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa -MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI -hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN -95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd -2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= ------END CERTIFICATE----- - -# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Label: "Entrust.net Premium 2048 Secure Server CA" -# Serial: 946059622 -# MD5 Fingerprint: ba:21:ea:20:d6:dd:db:8f:c1:57:8b:40:ad:a1:fc:fc -# SHA1 Fingerprint: 80:1d:62:d0:7b:44:9d:5c:5c:03:5c:98:ea:61:fa:44:3c:2a:58:fe -# SHA256 Fingerprint: d1:c3:39:ea:27:84:eb:87:0f:93:4f:c5:63:4e:4a:a9:ad:55:05:01:64:01:f2:64:65:d3:7a:57:46:63:35:9f ------BEGIN CERTIFICATE----- -MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy -MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA -vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G -CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA -WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo -oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ -h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 -f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN -B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy -vUxFnmG6v4SBkgPR0ml8xQ== ------END CERTIFICATE----- - -# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust -# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust -# Label: "Baltimore CyberTrust Root" -# Serial: 33554617 -# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 -# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 -# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- - -# Issuer: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc. -# Subject: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc. -# Label: "Equifax Secure Global eBusiness CA" -# Serial: 1 -# MD5 Fingerprint: 8f:5d:77:06:27:c4:98:3c:5b:93:78:e7:d7:7d:9b:cc -# SHA1 Fingerprint: 7e:78:4a:10:1c:82:65:cc:2d:e1:f1:6d:47:b4:40:ca:d9:0a:19:45 -# SHA256 Fingerprint: 5f:0b:62:ea:b5:e3:53:ea:65:21:65:16:58:fb:b6:53:59:f4:43:28:0a:4a:fb:d1:04:d7:7d:10:f9:f0:4c:07 ------BEGIN CERTIFICATE----- -MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT -ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw -MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj -dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l -c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC -UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc -58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ -o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr -aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA -A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA -Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv -8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV ------END CERTIFICATE----- - -# Issuer: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc. -# Subject: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc. -# Label: "Equifax Secure eBusiness CA 1" -# Serial: 4 -# MD5 Fingerprint: 64:9c:ef:2e:44:fc:c6:8f:52:07:d0:51:73:8f:cb:3d -# SHA1 Fingerprint: da:40:18:8b:91:89:a3:ed:ee:ae:da:97:fe:2f:9d:f5:b7:d1:8a:41 -# SHA256 Fingerprint: cf:56:ff:46:a4:a1:86:10:9d:d9:65:84:b5:ee:b5:8a:51:0c:42:75:b0:e5:f9:4f:40:bb:ae:86:5e:19:f6:73 ------BEGIN CERTIFICATE----- -MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT -ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw -MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j -LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ -KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo -RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu -WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw -Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD -AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK -eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM -zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ -WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN -/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== ------END CERTIFICATE----- - -# Issuer: O=Equifax Secure OU=Equifax Secure eBusiness CA-2 -# Subject: O=Equifax Secure OU=Equifax Secure eBusiness CA-2 -# Label: "Equifax Secure eBusiness CA 2" -# Serial: 930140085 -# MD5 Fingerprint: aa:bf:bf:64:97:da:98:1d:6f:c6:08:3a:95:70:33:ca -# SHA1 Fingerprint: 39:4f:f6:85:0b:06:be:52:e5:18:56:cc:10:e1:80:e8:82:b3:85:cc -# SHA256 Fingerprint: 2f:27:4e:48:ab:a4:ac:7b:76:59:33:10:17:75:50:6d:c3:0e:e3:8e:f6:ac:d5:c0:49:32:cf:e0:41:23:42:20 ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj -dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 -NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD -VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G -vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ -BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX -MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl -IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw -NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq -y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy -0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 -E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN ------END CERTIFICATE----- - -# Issuer: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network -# Subject: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network -# Label: "AddTrust Low-Value Services Root" -# Serial: 1 -# MD5 Fingerprint: 1e:42:95:02:33:92:6b:b9:5f:c0:7f:da:d6:b2:4b:fc -# SHA1 Fingerprint: cc:ab:0e:a0:4c:23:01:d6:69:7b:dd:37:9f:cd:12:eb:24:e3:94:9d -# SHA256 Fingerprint: 8c:72:09:27:9a:c0:4e:27:5e:16:d0:7f:d3:b7:75:e8:01:54:b5:96:80:46:e3:1f:52:dd:25:76:63:24:e9:a7 ------BEGIN CERTIFICATE----- -MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw -MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD -VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA -A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul -CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n -tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl -dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch -PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC -+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O -BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl -MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk -ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB -IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X -7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz -43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY -eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl -pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA -WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= ------END CERTIFICATE----- - -# Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network -# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network -# Label: "AddTrust External Root" -# Serial: 1 -# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f -# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68 -# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2 ------BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs -IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 -MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h -bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v -dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt -H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 -uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX -mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX -a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN -E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 -WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD -VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 -Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU -cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx -IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN -AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH -YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC -Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX -c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a -mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= ------END CERTIFICATE----- - -# Issuer: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network -# Subject: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network -# Label: "AddTrust Public Services Root" -# Serial: 1 -# MD5 Fingerprint: c1:62:3e:23:c5:82:73:9c:03:59:4b:2b:e9:77:49:7f -# SHA1 Fingerprint: 2a:b6:28:48:5e:78:fb:f3:ad:9e:79:10:dd:6b:df:99:72:2c:96:e5 -# SHA256 Fingerprint: 07:91:ca:07:49:b2:07:82:aa:d3:c7:d7:bd:0c:df:c9:48:58:35:84:3e:b2:d7:99:60:09:ce:43:ab:6c:69:27 ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx -MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB -ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV -BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV -6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX -GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP -dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH -1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF -62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW -BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw -AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL -MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU -cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv -b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 -IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ -iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao -GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh -4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm -XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= ------END CERTIFICATE----- - -# Issuer: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network -# Subject: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network -# Label: "AddTrust Qualified Certificates Root" -# Serial: 1 -# MD5 Fingerprint: 27:ec:39:47:cd:da:5a:af:e2:9a:01:65:21:a9:4c:bb -# SHA1 Fingerprint: 4d:23:78:ec:91:95:39:b5:00:7f:75:8f:03:3b:21:1e:c5:4d:8b:cf -# SHA256 Fingerprint: 80:95:21:08:05:db:4b:bc:35:5e:44:28:d8:fd:6e:c2:cd:e3:ab:5f:b9:7a:99:42:98:8e:b8:f4:dc:d0:60:16 ------BEGIN CERTIFICATE----- -MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 -MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK -EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh -BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq -xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G -87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i -2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U -WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 -0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G -A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr -pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL -ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm -aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv -hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm -hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X -dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 -P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y -iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no -xqE= ------END CERTIFICATE----- - -# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Label: "Entrust Root Certification Authority" -# Serial: 1164660820 -# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 -# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 -# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc. -# Subject: CN=GeoTrust Global CA O=GeoTrust Inc. -# Label: "GeoTrust Global CA" -# Serial: 144470 -# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 -# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 -# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a ------BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Global CA 2 O=GeoTrust Inc. -# Subject: CN=GeoTrust Global CA 2 O=GeoTrust Inc. -# Label: "GeoTrust Global CA 2" -# Serial: 1 -# MD5 Fingerprint: 0e:40:a7:6c:de:03:5d:8f:d1:0f:e4:d1:8d:f9:6c:a9 -# SHA1 Fingerprint: a9:e9:78:08:14:37:58:88:f2:05:19:b0:6d:2b:0d:2b:60:16:90:7d -# SHA256 Fingerprint: ca:2d:82:a0:86:77:07:2f:8a:b6:76:4f:f0:35:67:6c:fe:3e:5e:32:5e:01:21:72:df:3f:92:09:6d:b7:9b:85 ------BEGIN CERTIFICATE----- -MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs -IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg -R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A -PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 -Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL -TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL -5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 -S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe -2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap -EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td -EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv -/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN -A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 -abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF -I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz -4iIprn2DQKi6bA== ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. -# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. -# Label: "GeoTrust Universal CA" -# Serial: 1 -# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 -# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 -# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 ------BEGIN CERTIFICATE----- -MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy -c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 -IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV -VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 -cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT -QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh -F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v -c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w -mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd -VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX -teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ -f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe -Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ -nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB -/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY -MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG -9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc -aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX -IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn -ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z -uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN -Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja -QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW -koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 -ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt -DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm -bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. -# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. -# Label: "GeoTrust Universal CA 2" -# Serial: 1 -# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 -# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 -# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy -c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD -VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 -c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 -WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG -FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq -XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL -se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb -KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd -IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 -y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt -hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc -QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 -Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV -HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ -KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z -dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ -L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr -Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo -ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY -T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz -GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m -1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV -OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH -6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX -QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS ------END CERTIFICATE----- - -# Issuer: CN=America Online Root Certification Authority 1 O=America Online Inc. -# Subject: CN=America Online Root Certification Authority 1 O=America Online Inc. -# Label: "America Online Root Certification Authority 1" -# Serial: 1 -# MD5 Fingerprint: 14:f1:08:ad:9d:fa:64:e2:89:e7:1c:cf:a8:ad:7d:5e -# SHA1 Fingerprint: 39:21:c1:15:c1:5d:0e:ca:5c:cb:5b:c4:f0:7d:21:d8:05:0b:56:6a -# SHA256 Fingerprint: 77:40:73:12:c6:3a:15:3d:5b:c0:0b:4e:51:75:9c:df:da:c2:37:dc:2a:33:b6:79:46:e9:8e:9b:fa:68:0a:e3 ------BEGIN CERTIFICATE----- -MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP -bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2 -MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft -ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk -hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym -1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW -OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb -2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko -O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU -AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF -Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb -LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir -oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C -MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds -sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 ------END CERTIFICATE----- - -# Issuer: CN=America Online Root Certification Authority 2 O=America Online Inc. -# Subject: CN=America Online Root Certification Authority 2 O=America Online Inc. -# Label: "America Online Root Certification Authority 2" -# Serial: 1 -# MD5 Fingerprint: d6:ed:3c:ca:e2:66:0f:af:10:43:0d:77:9b:04:09:bf -# SHA1 Fingerprint: 85:b5:ff:67:9b:0c:79:96:1f:c8:6e:44:22:00:46:13:db:17:92:84 -# SHA256 Fingerprint: 7d:3b:46:5a:60:14:e5:26:c0:af:fc:ee:21:27:d2:31:17:27:ad:81:1c:26:84:2d:00:6a:f3:73:06:cc:80:bd ------BEGIN CERTIFICATE----- -MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP -bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2 -MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft -ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC -206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci -KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2 -JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9 -BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e -Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B -PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67 -Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq -Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ -o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3 -+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj -YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj -FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE -AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn -xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2 -LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc -obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8 -CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe -IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA -DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F -AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX -Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb -AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl -Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw -RY8mkaKO/qk= ------END CERTIFICATE----- - -# Issuer: CN=AAA Certificate Services O=Comodo CA Limited -# Subject: CN=AAA Certificate Services O=Comodo CA Limited -# Label: "Comodo AAA Services root" -# Serial: 1 -# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 -# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 -# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 ------BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj -YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM -GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua -BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe -3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 -YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR -rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm -ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU -oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v -QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t -b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF -AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q -GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 -G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi -l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 -smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ------END CERTIFICATE----- - -# Issuer: CN=Secure Certificate Services O=Comodo CA Limited -# Subject: CN=Secure Certificate Services O=Comodo CA Limited -# Label: "Comodo Secure Services root" -# Serial: 1 -# MD5 Fingerprint: d3:d9:bd:ae:9f:ac:67:24:b3:c8:1b:52:e1:b9:a9:bd -# SHA1 Fingerprint: 4a:65:d5:f4:1d:ef:39:b8:b8:90:4a:4a:d3:64:81:33:cf:c7:a1:d1 -# SHA256 Fingerprint: bd:81:ce:3b:4f:65:91:d1:1a:67:b5:fc:7a:47:fd:ef:25:52:1b:f9:aa:4e:18:b9:e3:df:2e:34:a7:80:3b:e8 ------BEGIN CERTIFICATE----- -MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp -ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow -fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV -BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM -cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S -HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 -CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk -3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz -6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV -HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud -EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv -Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw -Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww -DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 -5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj -Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI -gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ -aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl -izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= ------END CERTIFICATE----- - -# Issuer: CN=Trusted Certificate Services O=Comodo CA Limited -# Subject: CN=Trusted Certificate Services O=Comodo CA Limited -# Label: "Comodo Trusted Services root" -# Serial: 1 -# MD5 Fingerprint: 91:1b:3f:6e:cd:9e:ab:ee:07:fe:1f:71:d2:b3:61:27 -# SHA1 Fingerprint: e1:9f:e3:0e:8b:84:60:9e:80:9b:17:0d:72:a8:c5:ba:6e:14:09:bd -# SHA256 Fingerprint: 3f:06:e5:56:81:d4:96:f5:be:16:9e:b5:38:9f:9f:2b:8f:f6:1e:17:08:df:68:81:72:48:49:cd:5d:27:cb:69 ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 -aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla -MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO -BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD -VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW -fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt -TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL -fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW -1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 -kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G -A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v -ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo -dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu -Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ -HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 -pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS -jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ -xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn -dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi ------END CERTIFICATE----- - -# Issuer: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com -# Subject: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com -# Label: "UTN DATACorp SGC Root CA" -# Serial: 91374294542884689855167577680241077609 -# MD5 Fingerprint: b3:a5:3e:77:21:6d:ac:4a:c0:c9:fb:d5:41:3d:ca:06 -# SHA1 Fingerprint: 58:11:9f:0e:12:82:87:ea:50:fd:d9:87:45:6f:4f:78:dc:fa:d6:d4 -# SHA256 Fingerprint: 85:fb:2f:91:dd:12:27:5a:01:45:b6:36:53:4f:84:02:4a:d6:8b:69:b8:ee:88:68:4f:f7:11:37:58:05:b3:48 ------BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -mfnGV/TJVTl4uix5yaaIK/QI ------END CERTIFICATE----- - -# Issuer: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com -# Subject: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com -# Label: "UTN USERFirst Hardware Root CA" -# Serial: 91374294542884704022267039221184531197 -# MD5 Fingerprint: 4c:56:41:e5:0d:bb:2b:e8:ca:a3:ed:18:08:ad:43:39 -# SHA1 Fingerprint: 04:83:ed:33:99:ac:36:08:05:87:22:ed:bc:5e:46:00:e3:be:f9:d7 -# SHA256 Fingerprint: 6e:a5:47:41:d0:04:66:7e:ed:1b:48:16:63:4a:a3:a7:9e:6e:4b:96:95:0f:82:79:da:fc:8d:9b:d8:81:21:37 ------BEGIN CERTIFICATE----- -MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB -lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt -SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG -A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe -MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v -d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh -cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn -0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ -M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a -MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd -oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI -DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy -oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 -dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy -bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF -BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM -//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli -CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE -CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t -3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS -KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== ------END CERTIFICATE----- - -# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com -# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com -# Label: "XRamp Global CA Root" -# Serial: 107108908803651509692980124233745014957 -# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 -# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 -# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB -gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk -MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY -UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx -NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 -dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy -dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 -38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP -KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q -DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 -qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa -JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi -PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P -BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs -jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 -eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD -ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR -vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt -qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa -IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy -i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ -O+7ETPTsJ3xCwnR8gooJybQDJbw= ------END CERTIFICATE----- - -# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority -# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority -# Label: "Go Daddy Class 2 CA" -# Serial: 0 -# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 -# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 -# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 ------BEGIN CERTIFICATE----- -MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh -MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE -YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 -MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo -ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg -MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN -ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA -PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w -wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi -EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY -avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ -YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE -sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h -/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 -IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy -OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P -TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ -HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER -dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf -ReYNnyicsbkqWletNw+vHX/bvZ8= ------END CERTIFICATE----- - -# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority -# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority -# Label: "Starfield Class 2 CA" -# Serial: 0 -# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 -# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a -# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl -MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp -U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw -NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE -ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp -ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 -DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf -8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN -+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 -X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa -K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA -1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G -A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR -zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 -YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD -bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 -L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D -eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp -VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY -WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= ------END CERTIFICATE----- - -# Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing -# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing -# Label: "StartCom Certification Authority" -# Serial: 1 -# MD5 Fingerprint: 22:4d:8f:8a:fc:f7:35:c2:bb:57:34:90:7b:8b:22:16 -# SHA1 Fingerprint: 3e:2b:f7:f2:03:1b:96:f3:8c:e6:c4:d8:a8:5d:3e:2d:58:47:6a:0f -# SHA256 Fingerprint: c7:66:a9:be:f2:d4:07:1c:86:3a:31:aa:49:20:e8:13:b2:d1:98:60:8c:b7:b7:cf:e2:11:43:b8:36:df:09:ea ------BEGIN CERTIFICATE----- -MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE -FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j -ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js -LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM -BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 -Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy -dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh -cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh -YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg -dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp -bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ -YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT -TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ -9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 -jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW -FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz -ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 -ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L -EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu -L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq -yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC -O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V -um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh -NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root CA" -# Serial: 17154717934120587862167794914071425081 -# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 -# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 -# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c ------BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root CA" -# Serial: 10944719598952040374951832963794454346 -# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e -# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 -# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- - -# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert High Assurance EV Root CA" -# Serial: 3553400076410547919724730734378100087 -# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a -# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 -# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. -# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. -# Label: "GeoTrust Primary Certification Authority" -# Serial: 32798226551256963324313806436981982369 -# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf -# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96 -# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY -MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo -R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx -MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 -AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA -ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 -7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W -kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI -mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ -KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 -6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl -4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K -oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj -UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU -AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA" -# Serial: 69529181992039203566298953787712940909 -# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12 -# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81 -# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB -qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV -BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw -NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j -LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG -A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs -W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta -3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk -6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 -Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J -NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP -r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU -DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz -YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 -/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ -LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 -jVaMaA== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Class 3 Public Primary Certification Authority - G5" -# Serial: 33037644167568058970164719475676101450 -# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c -# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5 -# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- - -# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO Certification Authority O=COMODO CA Limited -# Label: "COMODO Certification Authority" -# Serial: 104350513648249232941998508985834464573 -# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 -# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b -# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 ------BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW -/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g -PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u -QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY -SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv -IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 -zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd -BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB -ZQ== ------END CERTIFICATE----- - -# Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. -# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. -# Label: "Network Solutions Certificate Authority" -# Serial: 116697915152937497490437556386812487904 -# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e -# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce -# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi -MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu -MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV -UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO -ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz -c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP -OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl -mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF -BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 -qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw -gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu -bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp -dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 -6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ -h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH -/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv -wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN -pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey ------END CERTIFICATE----- - -# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited -# Label: "COMODO ECC Certification Authority" -# Serial: 41578283867086692638256921589707938090 -# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 -# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 -# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 ------BEGIN CERTIFICATE----- -MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT -IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw -MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy -ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N -T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR -FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J -cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW -BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm -fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv -GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= ------END CERTIFICATE----- - -# Issuer: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA -# Subject: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA -# Label: "TC TrustCenter Class 2 CA II" -# Serial: 941389028203453866782103406992443 -# MD5 Fingerprint: ce:78:33:5c:59:78:01:6e:18:ea:b9:36:a0:b9:2e:23 -# SHA1 Fingerprint: ae:50:83:ed:7c:f4:5c:bc:8f:61:c6:21:fe:68:5d:79:42:21:15:6e -# SHA256 Fingerprint: e6:b8:f8:76:64:85:f8:07:ae:7f:8d:ac:16:70:46:1f:07:c0:a1:3e:ef:3a:1f:f7:17:53:8d:7a:ba:d3:91:b4 ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf -tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg -uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J -XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK -8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99 -5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3 -kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy -dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6 -Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz -JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 -Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS -GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt -ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8 -au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV -hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI -dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ== ------END CERTIFICATE----- - -# Issuer: CN=TC TrustCenter Class 3 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 3 CA -# Subject: CN=TC TrustCenter Class 3 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 3 CA -# Label: "TC TrustCenter Class 3 CA II" -# Serial: 1506523511417715638772220530020799 -# MD5 Fingerprint: 56:5f:aa:80:61:12:17:f6:67:21:e6:2b:6d:61:56:8e -# SHA1 Fingerprint: 80:25:ef:f4:6e:70:c8:d4:72:24:65:84:fe:40:3b:8a:8d:6a:db:f5 -# SHA256 Fingerprint: 8d:a0:84:fc:f9:9c:e0:77:22:f8:9b:32:05:93:98:06:fa:5c:b8:11:e1:c8:13:f6:a1:08:c7:d3:36:b3:40:8e ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW -Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q -Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2 -1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq -ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1 -Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX -XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy -dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6 -Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz -JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 -Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN -irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8 -TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6 -g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB -95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj -S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A== ------END CERTIFICATE----- - -# Issuer: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA -# Subject: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA -# Label: "TC TrustCenter Universal CA I" -# Serial: 601024842042189035295619584734726 -# MD5 Fingerprint: 45:e1:a5:72:c5:a9:36:64:40:9e:f5:e4:58:84:67:8c -# SHA1 Fingerprint: 6b:2f:34:ad:89:58:be:62:fd:b0:6b:5c:ce:bb:9d:d9:4f:4e:39:f3 -# SHA256 Fingerprint: eb:f3:c0:2a:87:89:b1:fb:7d:51:19:95:d6:63:b7:29:06:d9:13:ce:0d:5e:10:56:8a:8a:77:e2:58:61:67:e7 ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV -BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1 -c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx -MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg -R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD -VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR -JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T -fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu -jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z -wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ -fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD -VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G -CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1 -7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn -8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs -ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT -ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/ -2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY ------END CERTIFICATE----- - -# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc -# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc -# Label: "Cybertrust Global Root" -# Serial: 4835703278459682877484360 -# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1 -# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6 -# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3 ------BEGIN CERTIFICATE----- -MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG -A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh -bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE -ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS -b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 -7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS -J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y -HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP -t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz -FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY -XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ -MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw -hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js -MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA -A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj -Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx -XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o -omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc -A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW -WL1WMRJOEcgh4LMRkWXbtKaIOM5V ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only -# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only -# Label: "GeoTrust Primary Certification Authority - G3" -# Serial: 28809105769928564313984085209975885599 -# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05 -# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd -# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4 ------BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB -mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT -MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv -cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ -BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg -MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 -BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz -+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm -hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn -5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W -JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL -DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC -huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw -HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB -AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB -zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN -kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD -AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH -SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G -spki4cErx5z481+oghLrGREt ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA - G2" -# Serial: 71758320672825410020661621085256472406 -# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f -# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12 -# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57 ------BEGIN CERTIFICATE----- -MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp -IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi -BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw -MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh -d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig -YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v -dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ -BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 -papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K -DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 -KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox -XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA - G3" -# Serial: 127614157056681299805556476275995414779 -# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31 -# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2 -# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB -rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV -BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa -Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl -LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u -MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl -ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm -gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 -YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf -b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 -9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S -zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk -OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV -HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA -2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW -oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu -t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c -KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM -m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu -MdRAGmI0Nj81Aa6sY6A= ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only -# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only -# Label: "GeoTrust Primary Certification Authority - G2" -# Serial: 80682863203381065782177908751794619243 -# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a -# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0 -# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66 ------BEGIN CERTIFICATE----- -MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL -MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj -KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 -MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV -BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw -NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV -BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH -MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL -So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal -tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG -CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT -qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz -rD6ogRLQy7rQkgu2npaqBA+K ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Universal Root Certification Authority" -# Serial: 85209574734084581917763752644031726877 -# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19 -# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54 -# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c ------BEGIN CERTIFICATE----- -MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB -vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W -ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 -IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y -IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh -bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF -9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH -H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H -LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN -/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT -rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw -WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs -exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud -DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 -sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ -seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz -4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ -BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR -lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 -7M2CYfE45k+XmCpajQ== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Class 3 Public Primary Certification Authority - G4" -# Serial: 63143484348153506665311985501458640051 -# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41 -# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a -# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79 ------BEGIN CERTIFICATE----- -MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp -U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg -SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln -biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm -GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve -fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ -aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj -aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW -kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC -4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga -FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== ------END CERTIFICATE----- - -# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority -# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority -# Label: "Verisign Class 3 Public Primary Certification Authority" -# Serial: 80507572722862485515306429940691309246 -# MD5 Fingerprint: ef:5a:f1:33:ef:f1:cd:bb:51:02:ee:12:14:4b:96:c4 -# SHA1 Fingerprint: a1:db:63:93:91:6f:17:e4:18:55:09:40:04:15:c7:02:40:b0:ae:6b -# SHA256 Fingerprint: a4:b6:b3:99:6f:c2:f3:06:b3:fd:86:81:bd:63:41:3d:8c:50:09:cc:4f:a3:29:c2:cc:f0:e2:fa:1b:14:03:05 ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE -BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is -I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G -CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i -2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ -2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 -# Label: "GlobalSign Root CA - R3" -# Serial: 4835703278459759426209954 -# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 -# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad -# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 -MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 -RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT -gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm -KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd -QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ -XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o -LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU -RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp -jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK -6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX -mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs -Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH -WD9f ------END CERTIFICATE----- - -# Issuer: CN=TC TrustCenter Universal CA III O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA -# Subject: CN=TC TrustCenter Universal CA III O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA -# Label: "TC TrustCenter Universal CA III" -# Serial: 2010889993983507346460533407902964 -# MD5 Fingerprint: 9f:dd:db:ab:ff:8e:ff:45:21:5f:f0:6c:9d:8f:fe:2b -# SHA1 Fingerprint: 96:56:cd:7b:57:96:98:95:d0:e1:41:46:68:06:fb:b8:c6:11:06:87 -# SHA256 Fingerprint: 30:9b:4a:87:f6:ca:56:c9:31:69:aa:a9:9c:6d:98:88:54:d7:89:2b:d5:43:7e:2d:07:b2:9c:be:da:55:d3:5d ------BEGIN CERTIFICATE----- -MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV -BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1 -c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAeFw0wOTA5MDkwODE1MjdaFw0yOTEy -MzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRl -ciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAm -BgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF -5+cvAqBNLaT6hdqbJYUtQCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYv -DIRlzg9uwliT6CwLOunBjvvya8o84pxOjuT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8v -zArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+EutCHnNaYlAJ/Uqwa1D7KRT -yGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1M4BDj5yj -dipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBh -MB8GA1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI -4jANBgkqhkiG9w0BAQUFAAOCAQEAg8ev6n9NCjw5sWi+e22JLumzCecYV42Fmhfz -dkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+KGwWaODIl0YgoGhnYIg5IFHY -aAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhKBgePxLcHsU0G -DeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV -CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPH -LQNjO9Po5KIqwoIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== ------END CERTIFICATE----- - -# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. -# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. -# Label: "Go Daddy Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 -# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b -# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT -EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp -ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz -NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH -EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE -AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD -E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH -/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy -DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh -GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR -tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA -AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX -WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu -9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr -gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo -2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI -4uJEvlz36hz1 ------END CERTIFICATE----- - -# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Label: "Starfield Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 -# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e -# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs -ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw -MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj -aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp -Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg -nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 -HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N -Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN -dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 -HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G -CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU -sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 -4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg -8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 -mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ------END CERTIFICATE----- - -# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Label: "Starfield Services Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 -# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f -# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 ------BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs -ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD -VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy -ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy -dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p -OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 -8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K -Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe -hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk -6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q -AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI -bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB -ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z -qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn -0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN -sSi6 ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Commercial O=AffirmTrust -# Subject: CN=AffirmTrust Commercial O=AffirmTrust -# Label: "AffirmTrust Commercial" -# Serial: 8608355977964138876 -# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 -# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 -# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP -Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr -ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL -MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 -yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr -VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ -nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG -XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj -vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt -Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g -N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC -nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Networking O=AffirmTrust -# Subject: CN=AffirmTrust Networking O=AffirmTrust -# Label: "AffirmTrust Networking" -# Serial: 8957382827206547757 -# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f -# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f -# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y -YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua -kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL -QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp -6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG -yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i -QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO -tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu -QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ -Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u -olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 -x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Premium O=AffirmTrust -# Subject: CN=AffirmTrust Premium O=AffirmTrust -# Label: "AffirmTrust Premium" -# Serial: 7893706540734352110 -# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 -# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 -# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz -dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG -A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U -cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf -qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ -JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ -+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS -s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 -HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 -70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG -V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S -qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S -5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia -C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX -OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE -FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 -KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B -8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ -MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc -0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ -u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF -u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH -YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 -GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO -RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e -KeC2uAloGRwYQw== ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust -# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust -# Label: "AffirmTrust Premium ECC" -# Serial: 8401224907861490260 -# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d -# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb -# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC -VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ -cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ -BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt -VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D -0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 -ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G -A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs -aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I -flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== ------END CERTIFICATE----- - -# Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing -# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing -# Label: "StartCom Certification Authority" -# Serial: 45 -# MD5 Fingerprint: c9:3b:0d:84:41:fc:a4:76:79:23:08:57:de:10:19:16 -# SHA1 Fingerprint: a3:f1:33:3f:e2:42:bf:cf:c5:d1:4e:8f:39:42:98:40:68:10:d1:a0 -# SHA256 Fingerprint: e1:78:90:ee:09:a3:fb:f4:f4:8b:9c:41:4a:17:d6:37:b7:a5:06:47:e9:bc:75:23:22:72:7f:cc:17:42:a9:11 ------BEGIN CERTIFICATE----- -MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul -F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC -ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w -ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk -aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 -YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg -c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 -d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG -CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF -wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS -Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst -0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc -pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl -CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF -P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK -1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm -KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE -JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ -8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm -fyWl8kgAwKQB2j8= ------END CERTIFICATE----- - -# Issuer: CN=StartCom Certification Authority G2 O=StartCom Ltd. -# Subject: CN=StartCom Certification Authority G2 O=StartCom Ltd. -# Label: "StartCom Certification Authority G2" -# Serial: 59 -# MD5 Fingerprint: 78:4b:fb:9e:64:82:0a:d3:b8:4c:62:f3:64:f2:90:64 -# SHA1 Fingerprint: 31:f1:fd:68:22:63:20:ee:c6:3b:3f:9d:ea:4a:3e:53:7c:7c:39:17 -# SHA256 Fingerprint: c7:ba:65:67:de:93:a7:98:ae:1f:aa:79:1e:71:2d:37:8f:ae:1f:93:c4:39:7f:ea:44:1b:b7:cb:e6:fd:59:95 ------BEGIN CERTIFICATE----- -MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1 -OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG -A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G -CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ -JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD -vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo -D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/ -Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW -RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK -HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN -nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM -0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i -UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9 -Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg -TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL -BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K -2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX -UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl -6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK -9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ -HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI -wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY -XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l -IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo -hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr -so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI ------END CERTIFICATE----- diff --git a/catapult/third_party/httplib2/httplib2/iri2uri.py b/catapult/third_party/httplib2/httplib2/iri2uri.py deleted file mode 100644 index d88c91fd..00000000 --- a/catapult/third_party/httplib2/httplib2/iri2uri.py +++ /dev/null @@ -1,110 +0,0 @@ -""" -iri2uri - -Converts an IRI to a URI. - -""" -__author__ = "Joe Gregorio (joe@bitworking.org)" -__copyright__ = "Copyright 2006, Joe Gregorio" -__contributors__ = [] -__version__ = "1.0.0" -__license__ = "MIT" -__history__ = """ -""" - -import urlparse - - -# Convert an IRI to a URI following the rules in RFC 3987 -# -# The characters we need to enocde and escape are defined in the spec: -# -# iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD -# ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF -# / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD -# / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD -# / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD -# / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD -# / %xD0000-DFFFD / %xE1000-EFFFD - -escape_range = [ - (0xA0, 0xD7FF), - (0xE000, 0xF8FF), - (0xF900, 0xFDCF), - (0xFDF0, 0xFFEF), - (0x10000, 0x1FFFD), - (0x20000, 0x2FFFD), - (0x30000, 0x3FFFD), - (0x40000, 0x4FFFD), - (0x50000, 0x5FFFD), - (0x60000, 0x6FFFD), - (0x70000, 0x7FFFD), - (0x80000, 0x8FFFD), - (0x90000, 0x9FFFD), - (0xA0000, 0xAFFFD), - (0xB0000, 0xBFFFD), - (0xC0000, 0xCFFFD), - (0xD0000, 0xDFFFD), - (0xE1000, 0xEFFFD), - (0xF0000, 0xFFFFD), - (0x100000, 0x10FFFD), -] - -def encode(c): - retval = c - i = ord(c) - for low, high in escape_range: - if i < low: - break - if i >= low and i <= high: - retval = "".join(["%%%2X" % ord(o) for o in c.encode('utf-8')]) - break - return retval - - -def iri2uri(uri): - """Convert an IRI to a URI. Note that IRIs must be - passed in a unicode strings. That is, do not utf-8 encode - the IRI before passing it into the function.""" - if isinstance(uri ,unicode): - (scheme, authority, path, query, fragment) = urlparse.urlsplit(uri) - authority = authority.encode('idna') - # For each character in 'ucschar' or 'iprivate' - # 1. encode as utf-8 - # 2. then %-encode each octet of that utf-8 - uri = urlparse.urlunsplit((scheme, authority, path, query, fragment)) - uri = "".join([encode(c) for c in uri]) - return uri - -if __name__ == "__main__": - import unittest - - class Test(unittest.TestCase): - - def test_uris(self): - """Test that URIs are invariant under the transformation.""" - invariant = [ - u"ftp://ftp.is.co.za/rfc/rfc1808.txt", - u"http://www.ietf.org/rfc/rfc2396.txt", - u"ldap://[2001:db8::7]/c=GB?objectClass?one", - u"mailto:John.Doe@example.com", - u"news:comp.infosystems.www.servers.unix", - u"tel:+1-816-555-1212", - u"telnet://192.0.2.16:80/", - u"urn:oasis:names:specification:docbook:dtd:xml:4.1.2" ] - for uri in invariant: - self.assertEqual(uri, iri2uri(uri)) - - def test_iri(self): - """ Test that the right type of escaping is done for each part of the URI.""" - self.assertEqual("http://xn--o3h.com/%E2%98%84", iri2uri(u"http://\N{COMET}.com/\N{COMET}")) - self.assertEqual("http://bitworking.org/?fred=%E2%98%84", iri2uri(u"http://bitworking.org/?fred=\N{COMET}")) - self.assertEqual("http://bitworking.org/#%E2%98%84", iri2uri(u"http://bitworking.org/#\N{COMET}")) - self.assertEqual("#%E2%98%84", iri2uri(u"#\N{COMET}")) - self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")) - self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"))) - self.assertNotEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode('utf-8'))) - - unittest.main() - - diff --git a/catapult/third_party/httplib2/httplib2/socks.py b/catapult/third_party/httplib2/httplib2/socks.py deleted file mode 100644 index 0991f4cf..00000000 --- a/catapult/third_party/httplib2/httplib2/socks.py +++ /dev/null @@ -1,438 +0,0 @@ -"""SocksiPy - Python SOCKS module. -Version 1.00 - -Copyright 2006 Dan-Haim. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -3. Neither the name of Dan Haim nor the names of his contributors may be used - to endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE. - - -This module provides a standard socket-like interface for Python -for tunneling connections through SOCKS proxies. - -""" - -""" - -Minor modifications made by Christopher Gilbert (http://motomastyle.com/) -for use in PyLoris (http://pyloris.sourceforge.net/) - -Minor modifications made by Mario Vilas (http://breakingcode.wordpress.com/) -mainly to merge bug fixes found in Sourceforge - -""" - -import base64 -import socket -import struct -import sys - -if getattr(socket, 'socket', None) is None: - raise ImportError('socket.socket missing, proxy support unusable') - -PROXY_TYPE_SOCKS4 = 1 -PROXY_TYPE_SOCKS5 = 2 -PROXY_TYPE_HTTP = 3 -PROXY_TYPE_HTTP_NO_TUNNEL = 4 - -_defaultproxy = None -_orgsocket = socket.socket - -class ProxyError(Exception): pass -class GeneralProxyError(ProxyError): pass -class Socks5AuthError(ProxyError): pass -class Socks5Error(ProxyError): pass -class Socks4Error(ProxyError): pass -class HTTPError(ProxyError): pass - -_generalerrors = ("success", - "invalid data", - "not connected", - "not available", - "bad proxy type", - "bad input") - -_socks5errors = ("succeeded", - "general SOCKS server failure", - "connection not allowed by ruleset", - "Network unreachable", - "Host unreachable", - "Connection refused", - "TTL expired", - "Command not supported", - "Address type not supported", - "Unknown error") - -_socks5autherrors = ("succeeded", - "authentication is required", - "all offered authentication methods were rejected", - "unknown username or invalid password", - "unknown error") - -_socks4errors = ("request granted", - "request rejected or failed", - "request rejected because SOCKS server cannot connect to identd on the client", - "request rejected because the client program and identd report different user-ids", - "unknown error") - -def setdefaultproxy(proxytype=None, addr=None, port=None, rdns=True, username=None, password=None): - """setdefaultproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) - Sets a default proxy which all further socksocket objects will use, - unless explicitly changed. - """ - global _defaultproxy - _defaultproxy = (proxytype, addr, port, rdns, username, password) - -def wrapmodule(module): - """wrapmodule(module) - Attempts to replace a module's socket library with a SOCKS socket. Must set - a default proxy using setdefaultproxy(...) first. - This will only work on modules that import socket directly into the namespace; - most of the Python Standard Library falls into this category. - """ - if _defaultproxy != None: - module.socket.socket = socksocket - else: - raise GeneralProxyError((4, "no proxy specified")) - -class socksocket(socket.socket): - """socksocket([family[, type[, proto]]]) -> socket object - Open a SOCKS enabled socket. The parameters are the same as - those of the standard socket init. In order for SOCKS to work, - you must specify family=AF_INET, type=SOCK_STREAM and proto=0. - """ - - def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None): - _orgsocket.__init__(self, family, type, proto, _sock) - if _defaultproxy != None: - self.__proxy = _defaultproxy - else: - self.__proxy = (None, None, None, None, None, None) - self.__proxysockname = None - self.__proxypeername = None - self.__httptunnel = True - - def __recvall(self, count): - """__recvall(count) -> data - Receive EXACTLY the number of bytes requested from the socket. - Blocks until the required number of bytes have been received. - """ - data = self.recv(count) - while len(data) < count: - d = self.recv(count-len(data)) - if not d: raise GeneralProxyError((0, "connection closed unexpectedly")) - data = data + d - return data - - def sendall(self, content, *args): - """ override socket.socket.sendall method to rewrite the header - for non-tunneling proxies if needed - """ - if not self.__httptunnel: - content = self.__rewriteproxy(content) - return super(socksocket, self).sendall(content, *args) - - def __rewriteproxy(self, header): - """ rewrite HTTP request headers to support non-tunneling proxies - (i.e. those which do not support the CONNECT method). - This only works for HTTP (not HTTPS) since HTTPS requires tunneling. - """ - host, endpt = None, None - hdrs = header.split("\r\n") - for hdr in hdrs: - if hdr.lower().startswith("host:"): - host = hdr - elif hdr.lower().startswith("get") or hdr.lower().startswith("post"): - endpt = hdr - if host and endpt: - hdrs.remove(host) - hdrs.remove(endpt) - host = host.split(" ")[1] - endpt = endpt.split(" ") - if (self.__proxy[4] != None and self.__proxy[5] != None): - hdrs.insert(0, self.__getauthheader()) - hdrs.insert(0, "Host: %s" % host) - hdrs.insert(0, "%s http://%s%s %s" % (endpt[0], host, endpt[1], endpt[2])) - return "\r\n".join(hdrs) - - def __getauthheader(self): - auth = self.__proxy[4] + ":" + self.__proxy[5] - return "Proxy-Authorization: Basic " + base64.b64encode(auth) - - def setproxy(self, proxytype=None, addr=None, port=None, rdns=True, username=None, password=None): - """setproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) - Sets the proxy to be used. - proxytype - The type of the proxy to be used. Three types - are supported: PROXY_TYPE_SOCKS4 (including socks4a), - PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP - addr - The address of the server (IP or DNS). - port - The port of the server. Defaults to 1080 for SOCKS - servers and 8080 for HTTP proxy servers. - rdns - Should DNS queries be preformed on the remote side - (rather than the local side). The default is True. - Note: This has no effect with SOCKS4 servers. - username - Username to authenticate with to the server. - The default is no authentication. - password - Password to authenticate with to the server. - Only relevant when username is also provided. - """ - self.__proxy = (proxytype, addr, port, rdns, username, password) - - def __negotiatesocks5(self, destaddr, destport): - """__negotiatesocks5(self,destaddr,destport) - Negotiates a connection through a SOCKS5 server. - """ - # First we'll send the authentication packages we support. - if (self.__proxy[4]!=None) and (self.__proxy[5]!=None): - # The username/password details were supplied to the - # setproxy method so we support the USERNAME/PASSWORD - # authentication (in addition to the standard none). - self.sendall(struct.pack('BBBB', 0x05, 0x02, 0x00, 0x02)) - else: - # No username/password were entered, therefore we - # only support connections with no authentication. - self.sendall(struct.pack('BBB', 0x05, 0x01, 0x00)) - # We'll receive the server's response to determine which - # method was selected - chosenauth = self.__recvall(2) - if chosenauth[0:1] != chr(0x05).encode(): - self.close() - raise GeneralProxyError((1, _generalerrors[1])) - # Check the chosen authentication method - if chosenauth[1:2] == chr(0x00).encode(): - # No authentication is required - pass - elif chosenauth[1:2] == chr(0x02).encode(): - # Okay, we need to perform a basic username/password - # authentication. - self.sendall(chr(0x01).encode() + chr(len(self.__proxy[4])) + self.__proxy[4] + chr(len(self.__proxy[5])) + self.__proxy[5]) - authstat = self.__recvall(2) - if authstat[0:1] != chr(0x01).encode(): - # Bad response - self.close() - raise GeneralProxyError((1, _generalerrors[1])) - if authstat[1:2] != chr(0x00).encode(): - # Authentication failed - self.close() - raise Socks5AuthError((3, _socks5autherrors[3])) - # Authentication succeeded - else: - # Reaching here is always bad - self.close() - if chosenauth[1] == chr(0xFF).encode(): - raise Socks5AuthError((2, _socks5autherrors[2])) - else: - raise GeneralProxyError((1, _generalerrors[1])) - # Now we can request the actual connection - req = struct.pack('BBB', 0x05, 0x01, 0x00) - # If the given destination address is an IP address, we'll - # use the IPv4 address request even if remote resolving was specified. - try: - ipaddr = socket.inet_aton(destaddr) - req = req + chr(0x01).encode() + ipaddr - except socket.error: - # Well it's not an IP number, so it's probably a DNS name. - if self.__proxy[3]: - # Resolve remotely - ipaddr = None - req = req + chr(0x03).encode() + chr(len(destaddr)).encode() + destaddr - else: - # Resolve locally - ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) - req = req + chr(0x01).encode() + ipaddr - req = req + struct.pack(">H", destport) - self.sendall(req) - # Get the response - resp = self.__recvall(4) - if resp[0:1] != chr(0x05).encode(): - self.close() - raise GeneralProxyError((1, _generalerrors[1])) - elif resp[1:2] != chr(0x00).encode(): - # Connection failed - self.close() - if ord(resp[1:2])<=8: - raise Socks5Error((ord(resp[1:2]), _socks5errors[ord(resp[1:2])])) - else: - raise Socks5Error((9, _socks5errors[9])) - # Get the bound address/port - elif resp[3:4] == chr(0x01).encode(): - boundaddr = self.__recvall(4) - elif resp[3:4] == chr(0x03).encode(): - resp = resp + self.recv(1) - boundaddr = self.__recvall(ord(resp[4:5])) - else: - self.close() - raise GeneralProxyError((1,_generalerrors[1])) - boundport = struct.unpack(">H", self.__recvall(2))[0] - self.__proxysockname = (boundaddr, boundport) - if ipaddr != None: - self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) - else: - self.__proxypeername = (destaddr, destport) - - def getproxysockname(self): - """getsockname() -> address info - Returns the bound IP address and port number at the proxy. - """ - return self.__proxysockname - - def getproxypeername(self): - """getproxypeername() -> address info - Returns the IP and port number of the proxy. - """ - return _orgsocket.getpeername(self) - - def getpeername(self): - """getpeername() -> address info - Returns the IP address and port number of the destination - machine (note: getproxypeername returns the proxy) - """ - return self.__proxypeername - - def __negotiatesocks4(self,destaddr,destport): - """__negotiatesocks4(self,destaddr,destport) - Negotiates a connection through a SOCKS4 server. - """ - # Check if the destination address provided is an IP address - rmtrslv = False - try: - ipaddr = socket.inet_aton(destaddr) - except socket.error: - # It's a DNS name. Check where it should be resolved. - if self.__proxy[3]: - ipaddr = struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01) - rmtrslv = True - else: - ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) - # Construct the request packet - req = struct.pack(">BBH", 0x04, 0x01, destport) + ipaddr - # The username parameter is considered userid for SOCKS4 - if self.__proxy[4] != None: - req = req + self.__proxy[4] - req = req + chr(0x00).encode() - # DNS name if remote resolving is required - # NOTE: This is actually an extension to the SOCKS4 protocol - # called SOCKS4A and may not be supported in all cases. - if rmtrslv: - req = req + destaddr + chr(0x00).encode() - self.sendall(req) - # Get the response from the server - resp = self.__recvall(8) - if resp[0:1] != chr(0x00).encode(): - # Bad data - self.close() - raise GeneralProxyError((1,_generalerrors[1])) - if resp[1:2] != chr(0x5A).encode(): - # Server returned an error - self.close() - if ord(resp[1:2]) in (91, 92, 93): - self.close() - raise Socks4Error((ord(resp[1:2]), _socks4errors[ord(resp[1:2]) - 90])) - else: - raise Socks4Error((94, _socks4errors[4])) - # Get the bound address/port - self.__proxysockname = (socket.inet_ntoa(resp[4:]), struct.unpack(">H", resp[2:4])[0]) - if rmtrslv != None: - self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) - else: - self.__proxypeername = (destaddr, destport) - - def __negotiatehttp(self, destaddr, destport): - """__negotiatehttp(self,destaddr,destport) - Negotiates a connection through an HTTP server. - """ - # If we need to resolve locally, we do this now - if not self.__proxy[3]: - addr = socket.gethostbyname(destaddr) - else: - addr = destaddr - headers = ["CONNECT ", addr, ":", str(destport), " HTTP/1.1\r\n"] - headers += ["Host: ", destaddr, "\r\n"] - if (self.__proxy[4] != None and self.__proxy[5] != None): - headers += [self.__getauthheader(), "\r\n"] - headers.append("\r\n") - self.sendall("".join(headers).encode()) - # We read the response until we get the string "\r\n\r\n" - resp = self.recv(1) - while resp.find("\r\n\r\n".encode()) == -1: - resp = resp + self.recv(1) - # We just need the first line to check if the connection - # was successful - statusline = resp.splitlines()[0].split(" ".encode(), 2) - if statusline[0] not in ("HTTP/1.0".encode(), "HTTP/1.1".encode()): - self.close() - raise GeneralProxyError((1, _generalerrors[1])) - try: - statuscode = int(statusline[1]) - except ValueError: - self.close() - raise GeneralProxyError((1, _generalerrors[1])) - if statuscode != 200: - self.close() - raise HTTPError((statuscode, statusline[2])) - self.__proxysockname = ("0.0.0.0", 0) - self.__proxypeername = (addr, destport) - - def connect(self, destpair): - """connect(self, despair) - Connects to the specified destination through a proxy. - destpar - A tuple of the IP/DNS address and the port number. - (identical to socket's connect). - To select the proxy server use setproxy(). - """ - # Do a minimal input check first - if (not type(destpair) in (list,tuple)) or (len(destpair) < 2) or (not isinstance(destpair[0], basestring)) or (type(destpair[1]) != int): - raise GeneralProxyError((5, _generalerrors[5])) - if self.__proxy[0] == PROXY_TYPE_SOCKS5: - if self.__proxy[2] != None: - portnum = self.__proxy[2] - else: - portnum = 1080 - _orgsocket.connect(self, (self.__proxy[1], portnum)) - self.__negotiatesocks5(destpair[0], destpair[1]) - elif self.__proxy[0] == PROXY_TYPE_SOCKS4: - if self.__proxy[2] != None: - portnum = self.__proxy[2] - else: - portnum = 1080 - _orgsocket.connect(self,(self.__proxy[1], portnum)) - self.__negotiatesocks4(destpair[0], destpair[1]) - elif self.__proxy[0] == PROXY_TYPE_HTTP: - if self.__proxy[2] != None: - portnum = self.__proxy[2] - else: - portnum = 8080 - _orgsocket.connect(self,(self.__proxy[1], portnum)) - self.__negotiatehttp(destpair[0], destpair[1]) - elif self.__proxy[0] == PROXY_TYPE_HTTP_NO_TUNNEL: - if self.__proxy[2] != None: - portnum = self.__proxy[2] - else: - portnum = 8080 - _orgsocket.connect(self,(self.__proxy[1],portnum)) - if destpair[1] == 443: - self.__negotiatehttp(destpair[0],destpair[1]) - else: - self.__httptunnel = False - elif self.__proxy[0] == None: - _orgsocket.connect(self, (destpair[0], destpair[1])) - else: - raise GeneralProxyError((4, _generalerrors[4])) diff --git a/catapult/third_party/httplib2/httplib2/test/brokensocket/socket.py b/catapult/third_party/httplib2/httplib2/test/brokensocket/socket.py deleted file mode 100644 index ff7c0b74..00000000 --- a/catapult/third_party/httplib2/httplib2/test/brokensocket/socket.py +++ /dev/null @@ -1 +0,0 @@ -from realsocket import gaierror, error, getaddrinfo, SOCK_STREAM diff --git a/catapult/third_party/httplib2/httplib2/test/functional/test_proxies.py b/catapult/third_party/httplib2/httplib2/test/functional/test_proxies.py deleted file mode 100644 index 0b7880fe..00000000 --- a/catapult/third_party/httplib2/httplib2/test/functional/test_proxies.py +++ /dev/null @@ -1,88 +0,0 @@ -import unittest -import errno -import os -import signal -import subprocess -import tempfile - -import nose - -import httplib2 -from httplib2 import socks -from httplib2.test import miniserver - -tinyproxy_cfg = """ -User "%(user)s" -Port %(port)s -Listen 127.0.0.1 -PidFile "%(pidfile)s" -LogFile "%(logfile)s" -MaxClients 2 -StartServers 1 -LogLevel Info -""" - - -class FunctionalProxyHttpTest(unittest.TestCase): - def setUp(self): - if not socks: - raise nose.SkipTest('socks module unavailable') - if not subprocess: - raise nose.SkipTest('subprocess module unavailable') - - # start a short-lived miniserver so we can get a likely port - # for the proxy - self.httpd, self.proxyport = miniserver.start_server( - miniserver.ThisDirHandler) - self.httpd.shutdown() - self.httpd, self.port = miniserver.start_server( - miniserver.ThisDirHandler) - - self.pidfile = tempfile.mktemp() - self.logfile = tempfile.mktemp() - fd, self.conffile = tempfile.mkstemp() - f = os.fdopen(fd, 'w') - our_cfg = tinyproxy_cfg % {'user': os.getlogin(), - 'pidfile': self.pidfile, - 'port': self.proxyport, - 'logfile': self.logfile} - f.write(our_cfg) - f.close() - try: - # TODO use subprocess.check_call when 2.4 is dropped - ret = subprocess.call(['tinyproxy', '-c', self.conffile]) - self.assertEqual(0, ret) - except OSError, e: - if e.errno == errno.ENOENT: - raise nose.SkipTest('tinyproxy not available') - raise - - def tearDown(self): - self.httpd.shutdown() - try: - pid = int(open(self.pidfile).read()) - os.kill(pid, signal.SIGTERM) - except OSError, e: - if e.errno == errno.ESRCH: - print '\n\n\nTinyProxy Failed to start, log follows:' - print open(self.logfile).read() - print 'end tinyproxy log\n\n\n' - raise - map(os.unlink, (self.pidfile, - self.logfile, - self.conffile)) - - def testSimpleProxy(self): - proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, - 'localhost', self.proxyport) - client = httplib2.Http(proxy_info=proxy_info) - src = 'miniserver.py' - response, body = client.request('http://localhost:%d/%s' % - (self.port, src)) - self.assertEqual(response.status, 200) - self.assertEqual(body, open(os.path.join(miniserver.HERE, src)).read()) - lf = open(self.logfile).read() - expect = ('Established connection to host "127.0.0.1" ' - 'using file descriptor') - self.assertTrue(expect in lf, - 'tinyproxy did not proxy a request for miniserver') diff --git a/catapult/third_party/httplib2/httplib2/test/miniserver.py b/catapult/third_party/httplib2/httplib2/test/miniserver.py deleted file mode 100644 index e32bf5e5..00000000 --- a/catapult/third_party/httplib2/httplib2/test/miniserver.py +++ /dev/null @@ -1,100 +0,0 @@ -import logging -import os -import select -import SimpleHTTPServer -import SocketServer -import threading - -HERE = os.path.dirname(__file__) -logger = logging.getLogger(__name__) - - -class ThisDirHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): - def translate_path(self, path): - path = path.split('?', 1)[0].split('#', 1)[0] - return os.path.join(HERE, *filter(None, path.split('/'))) - - def log_message(self, s, *args): - # output via logging so nose can catch it - logger.info(s, *args) - - -class ShutdownServer(SocketServer.TCPServer): - """Mixin that allows serve_forever to be shut down. - - The methods in this mixin are backported from SocketServer.py in the Python - 2.6.4 standard library. The mixin is unnecessary in 2.6 and later, when - BaseServer supports the shutdown method directly. - """ - - def __init__(self, *args, **kwargs): - SocketServer.TCPServer.__init__(self, *args, **kwargs) - self.__is_shut_down = threading.Event() - self.__serving = False - - def serve_forever(self, poll_interval=0.1): - """Handle one request at a time until shutdown. - - Polls for shutdown every poll_interval seconds. Ignores - self.timeout. If you need to do periodic tasks, do them in - another thread. - """ - self.__serving = True - self.__is_shut_down.clear() - while self.__serving: - r, w, e = select.select([self.socket], [], [], poll_interval) - if r: - self._handle_request_noblock() - self.__is_shut_down.set() - - def shutdown(self): - """Stops the serve_forever loop. - - Blocks until the loop has finished. This must be called while - serve_forever() is running in another thread, or it will deadlock. - """ - self.__serving = False - self.__is_shut_down.wait() - - def handle_request(self): - """Handle one request, possibly blocking. - - Respects self.timeout. - """ - # Support people who used socket.settimeout() to escape - # handle_request before self.timeout was available. - timeout = self.socket.gettimeout() - if timeout is None: - timeout = self.timeout - elif self.timeout is not None: - timeout = min(timeout, self.timeout) - fd_sets = select.select([self], [], [], timeout) - if not fd_sets[0]: - self.handle_timeout() - return - self._handle_request_noblock() - - def _handle_request_noblock(self): - """Handle one request, without blocking. - - I assume that select.select has returned that the socket is - readable before this function was called, so there should be - no risk of blocking in get_request(). - """ - try: - request, client_address = self.get_request() - except socket.error: - return - if self.verify_request(request, client_address): - try: - self.process_request(request, client_address) - except: - self.handle_error(request, client_address) - self.close_request(request) - - -def start_server(handler): - httpd = ShutdownServer(("", 0), handler) - threading.Thread(target=httpd.serve_forever).start() - _, port = httpd.socket.getsockname() - return httpd, port diff --git a/catapult/third_party/httplib2/httplib2/test/other_cacerts.txt b/catapult/third_party/httplib2/httplib2/test/other_cacerts.txt deleted file mode 100644 index 360954a2..00000000 --- a/catapult/third_party/httplib2/httplib2/test/other_cacerts.txt +++ /dev/null @@ -1,70 +0,0 @@ -# Certifcate Authority certificates for validating SSL connections. -# -# This file contains PEM format certificates generated from -# http://mxr.mozilla.org/seamonkey/source/security/nss/lib/ckfw/builtins/certdata.txt -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is the Netscape security libraries. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1994-2000 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - - -Comodo CA Limited, CN=Trusted Certificate Services -================================================== - ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 -aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla -MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO -BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD -VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW -fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt -TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL -fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW -1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 -kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G -A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v -ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo -dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu -Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ -HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 -pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS -jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ -xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn -dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi ------END CERTIFICATE----- diff --git a/catapult/third_party/httplib2/httplib2/test/smoke_test.py b/catapult/third_party/httplib2/httplib2/test/smoke_test.py deleted file mode 100644 index 9f1e6f01..00000000 --- a/catapult/third_party/httplib2/httplib2/test/smoke_test.py +++ /dev/null @@ -1,23 +0,0 @@ -import os -import unittest - -import httplib2 - -from httplib2.test import miniserver - - -class HttpSmokeTest(unittest.TestCase): - def setUp(self): - self.httpd, self.port = miniserver.start_server( - miniserver.ThisDirHandler) - - def tearDown(self): - self.httpd.shutdown() - - def testGetFile(self): - client = httplib2.Http() - src = 'miniserver.py' - response, body = client.request('http://localhost:%d/%s' % - (self.port, src)) - self.assertEqual(response.status, 200) - self.assertEqual(body, open(os.path.join(miniserver.HERE, src)).read()) diff --git a/catapult/third_party/httplib2/httplib2/test/test_no_socket.py b/catapult/third_party/httplib2/httplib2/test/test_no_socket.py deleted file mode 100644 index 66ba0563..00000000 --- a/catapult/third_party/httplib2/httplib2/test/test_no_socket.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Tests for httplib2 when the socket module is missing. - -This helps ensure compatibility with environments such as AppEngine. -""" -import os -import sys -import unittest - -import httplib2 - -class MissingSocketTest(unittest.TestCase): - def setUp(self): - self._oldsocks = httplib2.socks - httplib2.socks = None - - def tearDown(self): - httplib2.socks = self._oldsocks - - def testProxyDisabled(self): - proxy_info = httplib2.ProxyInfo('blah', - 'localhost', 0) - client = httplib2.Http(proxy_info=proxy_info) - self.assertRaises(httplib2.ProxiesUnavailableError, - client.request, 'http://localhost:-1/') diff --git a/catapult/third_party/oauth2client/LICENSE b/catapult/third_party/oauth2client/LICENSE deleted file mode 100644 index b506d50d..00000000 --- a/catapult/third_party/oauth2client/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ - Copyright 2014 Google Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -Dependent Modules -================= - -This code has the following dependencies -above and beyond the Python standard library: - -uritemplates - Apache License 2.0 -httplib2 - MIT License diff --git a/catapult/third_party/oauth2client/README.chromium b/catapult/third_party/oauth2client/README.chromium deleted file mode 100644 index 6db76105..00000000 --- a/catapult/third_party/oauth2client/README.chromium +++ /dev/null @@ -1,11 +0,0 @@ -Name: oauth2client -URL: https://github.com/google/oauth2client -Version: 1.4.11 -License: Apache - -Description: -This is a client library for accessing resources protected by OAuth 2.0. -It depends on the library "six". - -Local Modifications: -Removed everything except for the contents of oauth2client/. diff --git a/catapult/third_party/oauth2client/oauth2client/__init__.py b/catapult/third_party/oauth2client/oauth2client/__init__.py deleted file mode 100644 index f2841772..00000000 --- a/catapult/third_party/oauth2client/oauth2client/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -"""Client library for using OAuth2, especially with Google APIs.""" - -__version__ = '1.4.11' - -GOOGLE_AUTH_URI = 'https://accounts.google.com/o/oauth2/auth' -GOOGLE_DEVICE_URI = 'https://accounts.google.com/o/oauth2/device/code' -GOOGLE_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke' -GOOGLE_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token' diff --git a/catapult/third_party/oauth2client/oauth2client/appengine.py b/catapult/third_party/oauth2client/oauth2client/appengine.py deleted file mode 100644 index 00fe9855..00000000 --- a/catapult/third_party/oauth2client/oauth2client/appengine.py +++ /dev/null @@ -1,987 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Utilities for Google App Engine - -Utilities for making it easier to use OAuth 2.0 on Google App Engine. -""" - -__author__ = 'jcgregorio@google.com (Joe Gregorio)' - -import cgi -import json -import logging -import os -import pickle -import threading - -import httplib2 - -from google.appengine.api import app_identity -from google.appengine.api import memcache -from google.appengine.api import users -from google.appengine.ext import db -from google.appengine.ext import webapp -from google.appengine.ext.webapp.util import login_required -from google.appengine.ext.webapp.util import run_wsgi_app -from oauth2client import GOOGLE_AUTH_URI -from oauth2client import GOOGLE_REVOKE_URI -from oauth2client import GOOGLE_TOKEN_URI -from oauth2client import clientsecrets -from oauth2client import util -from oauth2client import xsrfutil -from oauth2client.client import AccessTokenRefreshError -from oauth2client.client import AssertionCredentials -from oauth2client.client import Credentials -from oauth2client.client import Flow -from oauth2client.client import OAuth2WebServerFlow -from oauth2client.client import Storage - -# TODO(dhermes): Resolve import issue. -# This is a temporary fix for a Google internal issue. -try: - from google.appengine.ext import ndb -except ImportError: - ndb = None - - -logger = logging.getLogger(__name__) - -OAUTH2CLIENT_NAMESPACE = 'oauth2client#ns' - -XSRF_MEMCACHE_ID = 'xsrf_secret_key' - - -def _safe_html(s): - """Escape text to make it safe to display. - - Args: - s: string, The text to escape. - - Returns: - The escaped text as a string. - """ - return cgi.escape(s, quote=1).replace("'", ''') - - -class InvalidClientSecretsError(Exception): - """The client_secrets.json file is malformed or missing required fields.""" - - -class InvalidXsrfTokenError(Exception): - """The XSRF token is invalid or expired.""" - - -class SiteXsrfSecretKey(db.Model): - """Storage for the sites XSRF secret key. - - There will only be one instance stored of this model, the one used for the - site. - """ - secret = db.StringProperty() - -if ndb is not None: - class SiteXsrfSecretKeyNDB(ndb.Model): - """NDB Model for storage for the sites XSRF secret key. - - Since this model uses the same kind as SiteXsrfSecretKey, it can be used - interchangeably. This simply provides an NDB model for interacting with the - same data the DB model interacts with. - - There should only be one instance stored of this model, the one used for the - site. - """ - secret = ndb.StringProperty() - - @classmethod - def _get_kind(cls): - """Return the kind name for this class.""" - return 'SiteXsrfSecretKey' - - -def _generate_new_xsrf_secret_key(): - """Returns a random XSRF secret key. - """ - return os.urandom(16).encode("hex") - - -def xsrf_secret_key(): - """Return the secret key for use for XSRF protection. - - If the Site entity does not have a secret key, this method will also create - one and persist it. - - Returns: - The secret key. - """ - secret = memcache.get(XSRF_MEMCACHE_ID, namespace=OAUTH2CLIENT_NAMESPACE) - if not secret: - # Load the one and only instance of SiteXsrfSecretKey. - model = SiteXsrfSecretKey.get_or_insert(key_name='site') - if not model.secret: - model.secret = _generate_new_xsrf_secret_key() - model.put() - secret = model.secret - memcache.add(XSRF_MEMCACHE_ID, secret, namespace=OAUTH2CLIENT_NAMESPACE) - - return str(secret) - - -class AppAssertionCredentials(AssertionCredentials): - """Credentials object for App Engine Assertion Grants - - This object will allow an App Engine application to identify itself to Google - and other OAuth 2.0 servers that can verify assertions. It can be used for the - purpose of accessing data stored under an account assigned to the App Engine - application itself. - - This credential does not require a flow to instantiate because it represents - a two legged flow, and therefore has all of the required information to - generate and refresh its own access tokens. - """ - - @util.positional(2) - def __init__(self, scope, **kwargs): - """Constructor for AppAssertionCredentials - - Args: - scope: string or iterable of strings, scope(s) of the credentials being - requested. - **kwargs: optional keyword args, including: - service_account_id: service account id of the application. If None or - unspecified, the default service account for the app is used. - """ - self.scope = util.scopes_to_string(scope) - self._kwargs = kwargs - self.service_account_id = kwargs.get('service_account_id', None) - - # Assertion type is no longer used, but still in the parent class signature. - super(AppAssertionCredentials, self).__init__(None) - - @classmethod - def from_json(cls, json_data): - data = json.loads(json_data) - return AppAssertionCredentials(data['scope']) - - def _refresh(self, http_request): - """Refreshes the access_token. - - Since the underlying App Engine app_identity implementation does its own - caching we can skip all the storage hoops and just to a refresh using the - API. - - Args: - http_request: callable, a callable that matches the method signature of - httplib2.Http.request, used to make the refresh request. - - Raises: - AccessTokenRefreshError: When the refresh fails. - """ - try: - scopes = self.scope.split() - (token, _) = app_identity.get_access_token( - scopes, service_account_id=self.service_account_id) - except app_identity.Error as e: - raise AccessTokenRefreshError(str(e)) - self.access_token = token - - @property - def serialization_data(self): - raise NotImplementedError('Cannot serialize credentials for AppEngine.') - - def create_scoped_required(self): - return not self.scope - - def create_scoped(self, scopes): - return AppAssertionCredentials(scopes, **self._kwargs) - - -class FlowProperty(db.Property): - """App Engine datastore Property for Flow. - - Utility property that allows easy storage and retrieval of an - oauth2client.Flow""" - - # Tell what the user type is. - data_type = Flow - - # For writing to datastore. - def get_value_for_datastore(self, model_instance): - flow = super(FlowProperty, - self).get_value_for_datastore(model_instance) - return db.Blob(pickle.dumps(flow)) - - # For reading from datastore. - def make_value_from_datastore(self, value): - if value is None: - return None - return pickle.loads(value) - - def validate(self, value): - if value is not None and not isinstance(value, Flow): - raise db.BadValueError('Property %s must be convertible ' - 'to a FlowThreeLegged instance (%s)' % - (self.name, value)) - return super(FlowProperty, self).validate(value) - - def empty(self, value): - return not value - - -if ndb is not None: - class FlowNDBProperty(ndb.PickleProperty): - """App Engine NDB datastore Property for Flow. - - Serves the same purpose as the DB FlowProperty, but for NDB models. Since - PickleProperty inherits from BlobProperty, the underlying representation of - the data in the datastore will be the same as in the DB case. - - Utility property that allows easy storage and retrieval of an - oauth2client.Flow - """ - - def _validate(self, value): - """Validates a value as a proper Flow object. - - Args: - value: A value to be set on the property. - - Raises: - TypeError if the value is not an instance of Flow. - """ - logger.info('validate: Got type %s', type(value)) - if value is not None and not isinstance(value, Flow): - raise TypeError('Property %s must be convertible to a flow ' - 'instance; received: %s.' % (self._name, value)) - - -class CredentialsProperty(db.Property): - """App Engine datastore Property for Credentials. - - Utility property that allows easy storage and retrieval of - oath2client.Credentials - """ - - # Tell what the user type is. - data_type = Credentials - - # For writing to datastore. - def get_value_for_datastore(self, model_instance): - logger.info("get: Got type " + str(type(model_instance))) - cred = super(CredentialsProperty, - self).get_value_for_datastore(model_instance) - if cred is None: - cred = '' - else: - cred = cred.to_json() - return db.Blob(cred) - - # For reading from datastore. - def make_value_from_datastore(self, value): - logger.info("make: Got type " + str(type(value))) - if value is None: - return None - if len(value) == 0: - return None - try: - credentials = Credentials.new_from_json(value) - except ValueError: - credentials = None - return credentials - - def validate(self, value): - value = super(CredentialsProperty, self).validate(value) - logger.info("validate: Got type " + str(type(value))) - if value is not None and not isinstance(value, Credentials): - raise db.BadValueError('Property %s must be convertible ' - 'to a Credentials instance (%s)' % - (self.name, value)) - #if value is not None and not isinstance(value, Credentials): - # return None - return value - - -if ndb is not None: - # TODO(dhermes): Turn this into a JsonProperty and overhaul the Credentials - # and subclass mechanics to use new_from_dict, to_dict, - # from_dict, etc. - class CredentialsNDBProperty(ndb.BlobProperty): - """App Engine NDB datastore Property for Credentials. - - Serves the same purpose as the DB CredentialsProperty, but for NDB models. - Since CredentialsProperty stores data as a blob and this inherits from - BlobProperty, the data in the datastore will be the same as in the DB case. - - Utility property that allows easy storage and retrieval of Credentials and - subclasses. - """ - def _validate(self, value): - """Validates a value as a proper credentials object. - - Args: - value: A value to be set on the property. - - Raises: - TypeError if the value is not an instance of Credentials. - """ - logger.info('validate: Got type %s', type(value)) - if value is not None and not isinstance(value, Credentials): - raise TypeError('Property %s must be convertible to a credentials ' - 'instance; received: %s.' % (self._name, value)) - - def _to_base_type(self, value): - """Converts our validated value to a JSON serialized string. - - Args: - value: A value to be set in the datastore. - - Returns: - A JSON serialized version of the credential, else '' if value is None. - """ - if value is None: - return '' - else: - return value.to_json() - - def _from_base_type(self, value): - """Converts our stored JSON string back to the desired type. - - Args: - value: A value from the datastore to be converted to the desired type. - - Returns: - A deserialized Credentials (or subclass) object, else None if the - value can't be parsed. - """ - if not value: - return None - try: - # Uses the from_json method of the implied class of value - credentials = Credentials.new_from_json(value) - except ValueError: - credentials = None - return credentials - - -class StorageByKeyName(Storage): - """Store and retrieve a credential to and from the App Engine datastore. - - This Storage helper presumes the Credentials have been stored as a - CredentialsProperty or CredentialsNDBProperty on a datastore model class, and - that entities are stored by key_name. - """ - - @util.positional(4) - def __init__(self, model, key_name, property_name, cache=None, user=None): - """Constructor for Storage. - - Args: - model: db.Model or ndb.Model, model class - key_name: string, key name for the entity that has the credentials - property_name: string, name of the property that is a CredentialsProperty - or CredentialsNDBProperty. - cache: memcache, a write-through cache to put in front of the datastore. - If the model you are using is an NDB model, using a cache will be - redundant since the model uses an instance cache and memcache for you. - user: users.User object, optional. Can be used to grab user ID as a - key_name if no key name is specified. - """ - if key_name is None: - if user is None: - raise ValueError('StorageByKeyName called with no key name or user.') - key_name = user.user_id() - - self._model = model - self._key_name = key_name - self._property_name = property_name - self._cache = cache - - def _is_ndb(self): - """Determine whether the model of the instance is an NDB model. - - Returns: - Boolean indicating whether or not the model is an NDB or DB model. - """ - # issubclass will fail if one of the arguments is not a class, only need - # worry about new-style classes since ndb and db models are new-style - if isinstance(self._model, type): - if ndb is not None and issubclass(self._model, ndb.Model): - return True - elif issubclass(self._model, db.Model): - return False - - raise TypeError('Model class not an NDB or DB model: %s.' % (self._model,)) - - def _get_entity(self): - """Retrieve entity from datastore. - - Uses a different model method for db or ndb models. - - Returns: - Instance of the model corresponding to the current storage object - and stored using the key name of the storage object. - """ - if self._is_ndb(): - return self._model.get_by_id(self._key_name) - else: - return self._model.get_by_key_name(self._key_name) - - def _delete_entity(self): - """Delete entity from datastore. - - Attempts to delete using the key_name stored on the object, whether or not - the given key is in the datastore. - """ - if self._is_ndb(): - ndb.Key(self._model, self._key_name).delete() - else: - entity_key = db.Key.from_path(self._model.kind(), self._key_name) - db.delete(entity_key) - - @db.non_transactional(allow_existing=True) - def locked_get(self): - """Retrieve Credential from datastore. - - Returns: - oauth2client.Credentials - """ - credentials = None - if self._cache: - json = self._cache.get(self._key_name) - if json: - credentials = Credentials.new_from_json(json) - if credentials is None: - entity = self._get_entity() - if entity is not None: - credentials = getattr(entity, self._property_name) - if self._cache: - self._cache.set(self._key_name, credentials.to_json()) - - if credentials and hasattr(credentials, 'set_store'): - credentials.set_store(self) - return credentials - - @db.non_transactional(allow_existing=True) - def locked_put(self, credentials): - """Write a Credentials to the datastore. - - Args: - credentials: Credentials, the credentials to store. - """ - entity = self._model.get_or_insert(self._key_name) - setattr(entity, self._property_name, credentials) - entity.put() - if self._cache: - self._cache.set(self._key_name, credentials.to_json()) - - @db.non_transactional(allow_existing=True) - def locked_delete(self): - """Delete Credential from datastore.""" - - if self._cache: - self._cache.delete(self._key_name) - - self._delete_entity() - - -class CredentialsModel(db.Model): - """Storage for OAuth 2.0 Credentials - - Storage of the model is keyed by the user.user_id(). - """ - credentials = CredentialsProperty() - - -if ndb is not None: - class CredentialsNDBModel(ndb.Model): - """NDB Model for storage of OAuth 2.0 Credentials - - Since this model uses the same kind as CredentialsModel and has a property - which can serialize and deserialize Credentials correctly, it can be used - interchangeably with a CredentialsModel to access, insert and delete the - same entities. This simply provides an NDB model for interacting with the - same data the DB model interacts with. - - Storage of the model is keyed by the user.user_id(). - """ - credentials = CredentialsNDBProperty() - - @classmethod - def _get_kind(cls): - """Return the kind name for this class.""" - return 'CredentialsModel' - - -def _build_state_value(request_handler, user): - """Composes the value for the 'state' parameter. - - Packs the current request URI and an XSRF token into an opaque string that - can be passed to the authentication server via the 'state' parameter. - - Args: - request_handler: webapp.RequestHandler, The request. - user: google.appengine.api.users.User, The current user. - - Returns: - The state value as a string. - """ - uri = request_handler.request.url - token = xsrfutil.generate_token(xsrf_secret_key(), user.user_id(), - action_id=str(uri)) - return uri + ':' + token - - -def _parse_state_value(state, user): - """Parse the value of the 'state' parameter. - - Parses the value and validates the XSRF token in the state parameter. - - Args: - state: string, The value of the state parameter. - user: google.appengine.api.users.User, The current user. - - Raises: - InvalidXsrfTokenError: if the XSRF token is invalid. - - Returns: - The redirect URI. - """ - uri, token = state.rsplit(':', 1) - if not xsrfutil.validate_token(xsrf_secret_key(), token, user.user_id(), - action_id=uri): - raise InvalidXsrfTokenError() - - return uri - - -class OAuth2Decorator(object): - """Utility for making OAuth 2.0 easier. - - Instantiate and then use with oauth_required or oauth_aware - as decorators on webapp.RequestHandler methods. - - :: - - decorator = OAuth2Decorator( - client_id='837...ent.com', - client_secret='Qh...wwI', - scope='https://www.googleapis.com/auth/plus') - - class MainHandler(webapp.RequestHandler): - @decorator.oauth_required - def get(self): - http = decorator.http() - # http is authorized with the user's Credentials and can be used - # in API calls - - """ - - def set_credentials(self, credentials): - self._tls.credentials = credentials - - def get_credentials(self): - """A thread local Credentials object. - - Returns: - A client.Credentials object, or None if credentials hasn't been set in - this thread yet, which may happen when calling has_credentials inside - oauth_aware. - """ - return getattr(self._tls, 'credentials', None) - - credentials = property(get_credentials, set_credentials) - - def set_flow(self, flow): - self._tls.flow = flow - - def get_flow(self): - """A thread local Flow object. - - Returns: - A credentials.Flow object, or None if the flow hasn't been set in this - thread yet, which happens in _create_flow() since Flows are created - lazily. - """ - return getattr(self._tls, 'flow', None) - - flow = property(get_flow, set_flow) - - - @util.positional(4) - def __init__(self, client_id, client_secret, scope, - auth_uri=GOOGLE_AUTH_URI, - token_uri=GOOGLE_TOKEN_URI, - revoke_uri=GOOGLE_REVOKE_URI, - user_agent=None, - message=None, - callback_path='/oauth2callback', - token_response_param=None, - _storage_class=StorageByKeyName, - _credentials_class=CredentialsModel, - _credentials_property_name='credentials', - **kwargs): - - """Constructor for OAuth2Decorator - - Args: - client_id: string, client identifier. - client_secret: string client secret. - scope: string or iterable of strings, scope(s) of the credentials being - requested. - auth_uri: string, URI for authorization endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - token_uri: string, URI for token endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - revoke_uri: string, URI for revoke endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - user_agent: string, User agent of your application, default to None. - message: Message to display if there are problems with the OAuth 2.0 - configuration. The message may contain HTML and will be presented on the - web interface for any method that uses the decorator. - callback_path: string, The absolute path to use as the callback URI. Note - that this must match up with the URI given when registering the - application in the APIs Console. - token_response_param: string. If provided, the full JSON response - to the access token request will be encoded and included in this query - parameter in the callback URI. This is useful with providers (e.g. - wordpress.com) that include extra fields that the client may want. - _storage_class: "Protected" keyword argument not typically provided to - this constructor. A storage class to aid in storing a Credentials object - for a user in the datastore. Defaults to StorageByKeyName. - _credentials_class: "Protected" keyword argument not typically provided to - this constructor. A db or ndb Model class to hold credentials. Defaults - to CredentialsModel. - _credentials_property_name: "Protected" keyword argument not typically - provided to this constructor. A string indicating the name of the field - on the _credentials_class where a Credentials object will be stored. - Defaults to 'credentials'. - **kwargs: dict, Keyword arguments are passed along as kwargs to - the OAuth2WebServerFlow constructor. - - """ - self._tls = threading.local() - self.flow = None - self.credentials = None - self._client_id = client_id - self._client_secret = client_secret - self._scope = util.scopes_to_string(scope) - self._auth_uri = auth_uri - self._token_uri = token_uri - self._revoke_uri = revoke_uri - self._user_agent = user_agent - self._kwargs = kwargs - self._message = message - self._in_error = False - self._callback_path = callback_path - self._token_response_param = token_response_param - self._storage_class = _storage_class - self._credentials_class = _credentials_class - self._credentials_property_name = _credentials_property_name - - def _display_error_message(self, request_handler): - request_handler.response.out.write('<html><body>') - request_handler.response.out.write(_safe_html(self._message)) - request_handler.response.out.write('</body></html>') - - def oauth_required(self, method): - """Decorator that starts the OAuth 2.0 dance. - - Starts the OAuth dance for the logged in user if they haven't already - granted access for this application. - - Args: - method: callable, to be decorated method of a webapp.RequestHandler - instance. - """ - - def check_oauth(request_handler, *args, **kwargs): - if self._in_error: - self._display_error_message(request_handler) - return - - user = users.get_current_user() - # Don't use @login_decorator as this could be used in a POST request. - if not user: - request_handler.redirect(users.create_login_url( - request_handler.request.uri)) - return - - self._create_flow(request_handler) - - # Store the request URI in 'state' so we can use it later - self.flow.params['state'] = _build_state_value(request_handler, user) - self.credentials = self._storage_class( - self._credentials_class, None, - self._credentials_property_name, user=user).get() - - if not self.has_credentials(): - return request_handler.redirect(self.authorize_url()) - try: - resp = method(request_handler, *args, **kwargs) - except AccessTokenRefreshError: - return request_handler.redirect(self.authorize_url()) - finally: - self.credentials = None - return resp - - return check_oauth - - def _create_flow(self, request_handler): - """Create the Flow object. - - The Flow is calculated lazily since we don't know where this app is - running until it receives a request, at which point redirect_uri can be - calculated and then the Flow object can be constructed. - - Args: - request_handler: webapp.RequestHandler, the request handler. - """ - if self.flow is None: - redirect_uri = request_handler.request.relative_url( - self._callback_path) # Usually /oauth2callback - self.flow = OAuth2WebServerFlow(self._client_id, self._client_secret, - self._scope, redirect_uri=redirect_uri, - user_agent=self._user_agent, - auth_uri=self._auth_uri, - token_uri=self._token_uri, - revoke_uri=self._revoke_uri, - **self._kwargs) - - def oauth_aware(self, method): - """Decorator that sets up for OAuth 2.0 dance, but doesn't do it. - - Does all the setup for the OAuth dance, but doesn't initiate it. - This decorator is useful if you want to create a page that knows - whether or not the user has granted access to this application. - From within a method decorated with @oauth_aware the has_credentials() - and authorize_url() methods can be called. - - Args: - method: callable, to be decorated method of a webapp.RequestHandler - instance. - """ - - def setup_oauth(request_handler, *args, **kwargs): - if self._in_error: - self._display_error_message(request_handler) - return - - user = users.get_current_user() - # Don't use @login_decorator as this could be used in a POST request. - if not user: - request_handler.redirect(users.create_login_url( - request_handler.request.uri)) - return - - self._create_flow(request_handler) - - self.flow.params['state'] = _build_state_value(request_handler, user) - self.credentials = self._storage_class( - self._credentials_class, None, - self._credentials_property_name, user=user).get() - try: - resp = method(request_handler, *args, **kwargs) - finally: - self.credentials = None - return resp - return setup_oauth - - - def has_credentials(self): - """True if for the logged in user there are valid access Credentials. - - Must only be called from with a webapp.RequestHandler subclassed method - that had been decorated with either @oauth_required or @oauth_aware. - """ - return self.credentials is not None and not self.credentials.invalid - - def authorize_url(self): - """Returns the URL to start the OAuth dance. - - Must only be called from with a webapp.RequestHandler subclassed method - that had been decorated with either @oauth_required or @oauth_aware. - """ - url = self.flow.step1_get_authorize_url() - return str(url) - - def http(self, *args, **kwargs): - """Returns an authorized http instance. - - Must only be called from within an @oauth_required decorated method, or - from within an @oauth_aware decorated method where has_credentials() - returns True. - - Args: - *args: Positional arguments passed to httplib2.Http constructor. - **kwargs: Positional arguments passed to httplib2.Http constructor. - """ - return self.credentials.authorize(httplib2.Http(*args, **kwargs)) - - @property - def callback_path(self): - """The absolute path where the callback will occur. - - Note this is the absolute path, not the absolute URI, that will be - calculated by the decorator at runtime. See callback_handler() for how this - should be used. - - Returns: - The callback path as a string. - """ - return self._callback_path - - - def callback_handler(self): - """RequestHandler for the OAuth 2.0 redirect callback. - - Usage:: - - app = webapp.WSGIApplication([ - ('/index', MyIndexHandler), - ..., - (decorator.callback_path, decorator.callback_handler()) - ]) - - Returns: - A webapp.RequestHandler that handles the redirect back from the - server during the OAuth 2.0 dance. - """ - decorator = self - - class OAuth2Handler(webapp.RequestHandler): - """Handler for the redirect_uri of the OAuth 2.0 dance.""" - - @login_required - def get(self): - error = self.request.get('error') - if error: - errormsg = self.request.get('error_description', error) - self.response.out.write( - 'The authorization request failed: %s' % _safe_html(errormsg)) - else: - user = users.get_current_user() - decorator._create_flow(self) - credentials = decorator.flow.step2_exchange(self.request.params) - decorator._storage_class( - decorator._credentials_class, None, - decorator._credentials_property_name, user=user).put(credentials) - redirect_uri = _parse_state_value(str(self.request.get('state')), - user) - - if decorator._token_response_param and credentials.token_response: - resp_json = json.dumps(credentials.token_response) - redirect_uri = util._add_query_parameter( - redirect_uri, decorator._token_response_param, resp_json) - - self.redirect(redirect_uri) - - return OAuth2Handler - - def callback_application(self): - """WSGI application for handling the OAuth 2.0 redirect callback. - - If you need finer grained control use `callback_handler` which returns just - the webapp.RequestHandler. - - Returns: - A webapp.WSGIApplication that handles the redirect back from the - server during the OAuth 2.0 dance. - """ - return webapp.WSGIApplication([ - (self.callback_path, self.callback_handler()) - ]) - - -class OAuth2DecoratorFromClientSecrets(OAuth2Decorator): - """An OAuth2Decorator that builds from a clientsecrets file. - - Uses a clientsecrets file as the source for all the information when - constructing an OAuth2Decorator. - - :: - - decorator = OAuth2DecoratorFromClientSecrets( - os.path.join(os.path.dirname(__file__), 'client_secrets.json') - scope='https://www.googleapis.com/auth/plus') - - class MainHandler(webapp.RequestHandler): - @decorator.oauth_required - def get(self): - http = decorator.http() - # http is authorized with the user's Credentials and can be used - # in API calls - - """ - - @util.positional(3) - def __init__(self, filename, scope, message=None, cache=None, **kwargs): - """Constructor - - Args: - filename: string, File name of client secrets. - scope: string or iterable of strings, scope(s) of the credentials being - requested. - message: string, A friendly string to display to the user if the - clientsecrets file is missing or invalid. The message may contain HTML - and will be presented on the web interface for any method that uses the - decorator. - cache: An optional cache service client that implements get() and set() - methods. See clientsecrets.loadfile() for details. - **kwargs: dict, Keyword arguments are passed along as kwargs to - the OAuth2WebServerFlow constructor. - """ - client_type, client_info = clientsecrets.loadfile(filename, cache=cache) - if client_type not in [ - clientsecrets.TYPE_WEB, clientsecrets.TYPE_INSTALLED]: - raise InvalidClientSecretsError( - "OAuth2Decorator doesn't support this OAuth 2.0 flow.") - constructor_kwargs = dict(kwargs) - constructor_kwargs.update({ - 'auth_uri': client_info['auth_uri'], - 'token_uri': client_info['token_uri'], - 'message': message, - }) - revoke_uri = client_info.get('revoke_uri') - if revoke_uri is not None: - constructor_kwargs['revoke_uri'] = revoke_uri - super(OAuth2DecoratorFromClientSecrets, self).__init__( - client_info['client_id'], client_info['client_secret'], - scope, **constructor_kwargs) - if message is not None: - self._message = message - else: - self._message = 'Please configure your application for OAuth 2.0.' - - -@util.positional(2) -def oauth2decorator_from_clientsecrets(filename, scope, - message=None, cache=None): - """Creates an OAuth2Decorator populated from a clientsecrets file. - - Args: - filename: string, File name of client secrets. - scope: string or list of strings, scope(s) of the credentials being - requested. - message: string, A friendly string to display to the user if the - clientsecrets file is missing or invalid. The message may contain HTML and - will be presented on the web interface for any method that uses the - decorator. - cache: An optional cache service client that implements get() and set() - methods. See clientsecrets.loadfile() for details. - - Returns: An OAuth2Decorator - - """ - return OAuth2DecoratorFromClientSecrets(filename, scope, - message=message, cache=cache) diff --git a/catapult/third_party/oauth2client/oauth2client/client.py b/catapult/third_party/oauth2client/oauth2client/client.py deleted file mode 100644 index 8108bd86..00000000 --- a/catapult/third_party/oauth2client/oauth2client/client.py +++ /dev/null @@ -1,2077 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""An OAuth 2.0 client. - -Tools for interacting with OAuth 2.0 protected resources. -""" - -__author__ = 'jcgregorio@google.com (Joe Gregorio)' - -import base64 -import collections -import copy -import datetime -import json -import logging -import os -import socket -import sys -import tempfile -import time -import shutil -import six -from six.moves import urllib - -import httplib2 -from oauth2client import clientsecrets -from oauth2client import GOOGLE_AUTH_URI -from oauth2client import GOOGLE_DEVICE_URI -from oauth2client import GOOGLE_REVOKE_URI -from oauth2client import GOOGLE_TOKEN_URI -from oauth2client import util - -HAS_OPENSSL = False -HAS_CRYPTO = False -try: - from oauth2client import crypt - HAS_CRYPTO = True - if crypt.OpenSSLVerifier is not None: - HAS_OPENSSL = True -except ImportError: - pass - -logger = logging.getLogger(__name__) - -# Expiry is stored in RFC3339 UTC format -EXPIRY_FORMAT = '%Y-%m-%dT%H:%M:%SZ' - -# Which certs to use to validate id_tokens received. -ID_TOKEN_VERIFICATION_CERTS = 'https://www.googleapis.com/oauth2/v1/certs' -# This symbol previously had a typo in the name; we keep the old name -# around for now, but will remove it in the future. -ID_TOKEN_VERIFICATON_CERTS = ID_TOKEN_VERIFICATION_CERTS - -# Constant to use for the out of band OAuth 2.0 flow. -OOB_CALLBACK_URN = 'urn:ietf:wg:oauth:2.0:oob' - -# Google Data client libraries may need to set this to [401, 403]. -REFRESH_STATUS_CODES = [401] - -# The value representing user credentials. -AUTHORIZED_USER = 'authorized_user' - -# The value representing service account credentials. -SERVICE_ACCOUNT = 'service_account' - -# The environment variable pointing the file with local -# Application Default Credentials. -GOOGLE_APPLICATION_CREDENTIALS = 'GOOGLE_APPLICATION_CREDENTIALS' -# The ~/.config subdirectory containing gcloud credentials. Intended -# to be swapped out in tests. -_CLOUDSDK_CONFIG_DIRECTORY = 'gcloud' -# The environment variable name which can replace ~/.config if set. -_CLOUDSDK_CONFIG_ENV_VAR = 'CLOUDSDK_CONFIG' - -# The error message we show users when we can't find the Application -# Default Credentials. -ADC_HELP_MSG = ( - 'The Application Default Credentials are not available. They are available ' - 'if running in Google Compute Engine. Otherwise, the environment variable ' - + GOOGLE_APPLICATION_CREDENTIALS + - ' must be defined pointing to a file defining the credentials. See ' - 'https://developers.google.com/accounts/docs/application-default-credentials' # pylint:disable=line-too-long - ' for more information.') - -# The access token along with the seconds in which it expires. -AccessTokenInfo = collections.namedtuple( - 'AccessTokenInfo', ['access_token', 'expires_in']) - -DEFAULT_ENV_NAME = 'UNKNOWN' - -# If set to True _get_environment avoid GCE check (_detect_gce_environment) -NO_GCE_CHECK = os.environ.setdefault('NO_GCE_CHECK', 'False') - -class SETTINGS(object): - """Settings namespace for globally defined values.""" - env_name = None - - -class Error(Exception): - """Base error for this module.""" - - -class FlowExchangeError(Error): - """Error trying to exchange an authorization grant for an access token.""" - - -class AccessTokenRefreshError(Error): - """Error trying to refresh an expired access token.""" - - -class TokenRevokeError(Error): - """Error trying to revoke a token.""" - - -class UnknownClientSecretsFlowError(Error): - """The client secrets file called for an unknown type of OAuth 2.0 flow. """ - - -class AccessTokenCredentialsError(Error): - """Having only the access_token means no refresh is possible.""" - - -class VerifyJwtTokenError(Error): - """Could not retrieve certificates for validation.""" - - -class NonAsciiHeaderError(Error): - """Header names and values must be ASCII strings.""" - - -class ApplicationDefaultCredentialsError(Error): - """Error retrieving the Application Default Credentials.""" - - -class OAuth2DeviceCodeError(Error): - """Error trying to retrieve a device code.""" - - -class CryptoUnavailableError(Error, NotImplementedError): - """Raised when a crypto library is required, but none is available.""" - - -def _abstract(): - raise NotImplementedError('You need to override this function') - - -class MemoryCache(object): - """httplib2 Cache implementation which only caches locally.""" - - def __init__(self): - self.cache = {} - - def get(self, key): - return self.cache.get(key) - - def set(self, key, value): - self.cache[key] = value - - def delete(self, key): - self.cache.pop(key, None) - - -class Credentials(object): - """Base class for all Credentials objects. - - Subclasses must define an authorize() method that applies the credentials to - an HTTP transport. - - Subclasses must also specify a classmethod named 'from_json' that takes a JSON - string as input and returns an instantiated Credentials object. - """ - - NON_SERIALIZED_MEMBERS = ['store'] - - - def authorize(self, http): - """Take an httplib2.Http instance (or equivalent) and authorizes it. - - Authorizes it for the set of credentials, usually by replacing - http.request() with a method that adds in the appropriate headers and then - delegates to the original Http.request() method. - - Args: - http: httplib2.Http, an http object to be used to make the refresh - request. - """ - _abstract() - - - def refresh(self, http): - """Forces a refresh of the access_token. - - Args: - http: httplib2.Http, an http object to be used to make the refresh - request. - """ - _abstract() - - - def revoke(self, http): - """Revokes a refresh_token and makes the credentials void. - - Args: - http: httplib2.Http, an http object to be used to make the revoke - request. - """ - _abstract() - - - def apply(self, headers): - """Add the authorization to the headers. - - Args: - headers: dict, the headers to add the Authorization header to. - """ - _abstract() - - def _to_json(self, strip): - """Utility function that creates JSON repr. of a Credentials object. - - Args: - strip: array, An array of names of members to not include in the JSON. - - Returns: - string, a JSON representation of this instance, suitable to pass to - from_json(). - """ - t = type(self) - d = copy.copy(self.__dict__) - for member in strip: - if member in d: - del d[member] - if (d.get('token_expiry') and - isinstance(d['token_expiry'], datetime.datetime)): - d['token_expiry'] = d['token_expiry'].strftime(EXPIRY_FORMAT) - # Add in information we will need later to reconsistitue this instance. - d['_class'] = t.__name__ - d['_module'] = t.__module__ - for key, val in d.items(): - if isinstance(val, bytes): - d[key] = val.decode('utf-8') - return json.dumps(d) - - def to_json(self): - """Creating a JSON representation of an instance of Credentials. - - Returns: - string, a JSON representation of this instance, suitable to pass to - from_json(). - """ - return self._to_json(Credentials.NON_SERIALIZED_MEMBERS) - - @classmethod - def new_from_json(cls, s): - """Utility class method to instantiate a Credentials subclass from a JSON - representation produced by to_json(). - - Args: - s: string, JSON from to_json(). - - Returns: - An instance of the subclass of Credentials that was serialized with - to_json(). - """ - if six.PY3 and isinstance(s, bytes): - s = s.decode('utf-8') - data = json.loads(s) - # Find and call the right classmethod from_json() to restore the object. - module = data['_module'] - try: - m = __import__(module) - except ImportError: - # In case there's an object from the old package structure, update it - module = module.replace('.googleapiclient', '') - m = __import__(module) - - m = __import__(module, fromlist=module.split('.')[:-1]) - kls = getattr(m, data['_class']) - from_json = getattr(kls, 'from_json') - return from_json(s) - - @classmethod - def from_json(cls, unused_data): - """Instantiate a Credentials object from a JSON description of it. - - The JSON should have been produced by calling .to_json() on the object. - - Args: - unused_data: dict, A deserialized JSON object. - - Returns: - An instance of a Credentials subclass. - """ - return Credentials() - - -class Flow(object): - """Base class for all Flow objects.""" - pass - - -class Storage(object): - """Base class for all Storage objects. - - Store and retrieve a single credential. This class supports locking - such that multiple processes and threads can operate on a single - store. - """ - - def acquire_lock(self): - """Acquires any lock necessary to access this Storage. - - This lock is not reentrant. - """ - pass - - def release_lock(self): - """Release the Storage lock. - - Trying to release a lock that isn't held will result in a - RuntimeError. - """ - pass - - def locked_get(self): - """Retrieve credential. - - The Storage lock must be held when this is called. - - Returns: - oauth2client.client.Credentials - """ - _abstract() - - def locked_put(self, credentials): - """Write a credential. - - The Storage lock must be held when this is called. - - Args: - credentials: Credentials, the credentials to store. - """ - _abstract() - - def locked_delete(self): - """Delete a credential. - - The Storage lock must be held when this is called. - """ - _abstract() - - def get(self): - """Retrieve credential. - - The Storage lock must *not* be held when this is called. - - Returns: - oauth2client.client.Credentials - """ - self.acquire_lock() - try: - return self.locked_get() - finally: - self.release_lock() - - def put(self, credentials): - """Write a credential. - - The Storage lock must be held when this is called. - - Args: - credentials: Credentials, the credentials to store. - """ - self.acquire_lock() - try: - self.locked_put(credentials) - finally: - self.release_lock() - - def delete(self): - """Delete credential. - - Frees any resources associated with storing the credential. - The Storage lock must *not* be held when this is called. - - Returns: - None - """ - self.acquire_lock() - try: - return self.locked_delete() - finally: - self.release_lock() - - -def clean_headers(headers): - """Forces header keys and values to be strings, i.e not unicode. - - The httplib module just concats the header keys and values in a way that may - make the message header a unicode string, which, if it then tries to - contatenate to a binary request body may result in a unicode decode error. - - Args: - headers: dict, A dictionary of headers. - - Returns: - The same dictionary but with all the keys converted to strings. - """ - clean = {} - try: - for k, v in six.iteritems(headers): - clean_k = k if isinstance(k, bytes) else str(k).encode('ascii') - clean_v = v if isinstance(v, bytes) else str(v).encode('ascii') - clean[clean_k] = clean_v - except UnicodeEncodeError: - raise NonAsciiHeaderError(k + ': ' + v) - return clean - - -def _update_query_params(uri, params): - """Updates a URI with new query parameters. - - Args: - uri: string, A valid URI, with potential existing query parameters. - params: dict, A dictionary of query parameters. - - Returns: - The same URI but with the new query parameters added. - """ - parts = urllib.parse.urlparse(uri) - query_params = dict(urllib.parse.parse_qsl(parts.query)) - query_params.update(params) - new_parts = parts._replace(query=urllib.parse.urlencode(query_params)) - return urllib.parse.urlunparse(new_parts) - - -class OAuth2Credentials(Credentials): - """Credentials object for OAuth 2.0. - - Credentials can be applied to an httplib2.Http object using the authorize() - method, which then adds the OAuth 2.0 access token to each request. - - OAuth2Credentials objects may be safely pickled and unpickled. - """ - - @util.positional(8) - def __init__(self, access_token, client_id, client_secret, refresh_token, - token_expiry, token_uri, user_agent, revoke_uri=None, - id_token=None, token_response=None): - """Create an instance of OAuth2Credentials. - - This constructor is not usually called by the user, instead - OAuth2Credentials objects are instantiated by the OAuth2WebServerFlow. - - Args: - access_token: string, access token. - client_id: string, client identifier. - client_secret: string, client secret. - refresh_token: string, refresh token. - token_expiry: datetime, when the access_token expires. - token_uri: string, URI of token endpoint. - user_agent: string, The HTTP User-Agent to provide for this application. - revoke_uri: string, URI for revoke endpoint. Defaults to None; a token - can't be revoked if this is None. - id_token: object, The identity of the resource owner. - token_response: dict, the decoded response to the token request. None - if a token hasn't been requested yet. Stored because some providers - (e.g. wordpress.com) include extra fields that clients may want. - - Notes: - store: callable, A callable that when passed a Credential - will store the credential back to where it came from. - This is needed to store the latest access_token if it - has expired and been refreshed. - """ - self.access_token = access_token - self.client_id = client_id - self.client_secret = client_secret - self.refresh_token = refresh_token - self.store = None - self.token_expiry = token_expiry - self.token_uri = token_uri - self.user_agent = user_agent - self.revoke_uri = revoke_uri - self.id_token = id_token - self.token_response = token_response - - # True if the credentials have been revoked or expired and can't be - # refreshed. - self.invalid = False - - def authorize(self, http): - """Authorize an httplib2.Http instance with these credentials. - - The modified http.request method will add authentication headers to each - request and will refresh access_tokens when a 401 is received on a - request. In addition the http.request method has a credentials property, - http.request.credentials, which is the Credentials object that authorized - it. - - Args: - http: An instance of ``httplib2.Http`` or something that acts - like it. - - Returns: - A modified instance of http that was passed in. - - Example:: - - h = httplib2.Http() - h = credentials.authorize(h) - - You can't create a new OAuth subclass of httplib2.Authentication - because it never gets passed the absolute URI, which is needed for - signing. So instead we have to overload 'request' with a closure - that adds in the Authorization header and then calls the original - version of 'request()'. - - """ - request_orig = http.request - - # The closure that will replace 'httplib2.Http.request'. - @util.positional(1) - def new_request(uri, method='GET', body=None, headers=None, - redirections=httplib2.DEFAULT_MAX_REDIRECTS, - connection_type=None): - if not self.access_token: - logger.info('Attempting refresh to obtain initial access_token') - self._refresh(request_orig) - - # Clone and modify the request headers to add the appropriate - # Authorization header. - if headers is None: - headers = {} - else: - headers = dict(headers) - self.apply(headers) - - if self.user_agent is not None: - if 'user-agent' in headers: - headers['user-agent'] = self.user_agent + ' ' + headers['user-agent'] - else: - headers['user-agent'] = self.user_agent - - body_stream_position = None - if all(getattr(body, stream_prop, None) for stream_prop in - ('read', 'seek', 'tell')): - body_stream_position = body.tell() - - resp, content = request_orig(uri, method, body, clean_headers(headers), - redirections, connection_type) - - # A stored token may expire between the time it is retrieved and the time - # the request is made, so we may need to try twice. - max_refresh_attempts = 2 - for refresh_attempt in range(max_refresh_attempts): - if resp.status not in REFRESH_STATUS_CODES: - break - logger.info('Refreshing due to a %s (attempt %s/%s)', resp.status, - refresh_attempt + 1, max_refresh_attempts) - self._refresh(request_orig) - self.apply(headers) - if body_stream_position is not None: - body.seek(body_stream_position) - - resp, content = request_orig(uri, method, body, clean_headers(headers), - redirections, connection_type) - - return (resp, content) - - # Replace the request method with our own closure. - http.request = new_request - - # Set credentials as a property of the request method. - setattr(http.request, 'credentials', self) - - return http - - def refresh(self, http): - """Forces a refresh of the access_token. - - Args: - http: httplib2.Http, an http object to be used to make the refresh - request. - """ - self._refresh(http.request) - - def revoke(self, http): - """Revokes a refresh_token and makes the credentials void. - - Args: - http: httplib2.Http, an http object to be used to make the revoke - request. - """ - self._revoke(http.request) - - def apply(self, headers): - """Add the authorization to the headers. - - Args: - headers: dict, the headers to add the Authorization header to. - """ - headers['Authorization'] = 'Bearer ' + self.access_token - - def to_json(self): - return self._to_json(Credentials.NON_SERIALIZED_MEMBERS) - - @classmethod - def from_json(cls, s): - """Instantiate a Credentials object from a JSON description of it. The JSON - should have been produced by calling .to_json() on the object. - - Args: - data: dict, A deserialized JSON object. - - Returns: - An instance of a Credentials subclass. - """ - if six.PY3 and isinstance(s, bytes): - s = s.decode('utf-8') - data = json.loads(s) - if (data.get('token_expiry') and - not isinstance(data['token_expiry'], datetime.datetime)): - try: - data['token_expiry'] = datetime.datetime.strptime( - data['token_expiry'], EXPIRY_FORMAT) - except ValueError: - data['token_expiry'] = None - retval = cls( - data['access_token'], - data['client_id'], - data['client_secret'], - data['refresh_token'], - data['token_expiry'], - data['token_uri'], - data['user_agent'], - revoke_uri=data.get('revoke_uri', None), - id_token=data.get('id_token', None), - token_response=data.get('token_response', None)) - retval.invalid = data['invalid'] - return retval - - @property - def access_token_expired(self): - """True if the credential is expired or invalid. - - If the token_expiry isn't set, we assume the token doesn't expire. - """ - if self.invalid: - return True - - if not self.token_expiry: - return False - - now = datetime.datetime.utcnow() - if now >= self.token_expiry: - logger.info('access_token is expired. Now: %s, token_expiry: %s', - now, self.token_expiry) - return True - return False - - def get_access_token(self, http=None): - """Return the access token and its expiration information. - - If the token does not exist, get one. - If the token expired, refresh it. - """ - if not self.access_token or self.access_token_expired: - if not http: - http = httplib2.Http() - self.refresh(http) - return AccessTokenInfo(access_token=self.access_token, - expires_in=self._expires_in()) - - def set_store(self, store): - """Set the Storage for the credential. - - Args: - store: Storage, an implementation of Storage object. - This is needed to store the latest access_token if it - has expired and been refreshed. This implementation uses - locking to check for updates before updating the - access_token. - """ - self.store = store - - def _expires_in(self): - """Return the number of seconds until this token expires. - - If token_expiry is in the past, this method will return 0, meaning the - token has already expired. - If token_expiry is None, this method will return None. Note that returning - 0 in such a case would not be fair: the token may still be valid; - we just don't know anything about it. - """ - if self.token_expiry: - now = datetime.datetime.utcnow() - if self.token_expiry > now: - time_delta = self.token_expiry - now - # TODO(orestica): return time_delta.total_seconds() - # once dropping support for Python 2.6 - return time_delta.days * 86400 + time_delta.seconds - else: - return 0 - - def _updateFromCredential(self, other): - """Update this Credential from another instance.""" - self.__dict__.update(other.__getstate__()) - - def __getstate__(self): - """Trim the state down to something that can be pickled.""" - d = copy.copy(self.__dict__) - del d['store'] - return d - - def __setstate__(self, state): - """Reconstitute the state of the object from being pickled.""" - self.__dict__.update(state) - self.store = None - - def _generate_refresh_request_body(self): - """Generate the body that will be used in the refresh request.""" - body = urllib.parse.urlencode({ - 'grant_type': 'refresh_token', - 'client_id': self.client_id, - 'client_secret': self.client_secret, - 'refresh_token': self.refresh_token, - }) - return body - - def _generate_refresh_request_headers(self): - """Generate the headers that will be used in the refresh request.""" - headers = { - 'content-type': 'application/x-www-form-urlencoded', - } - - if self.user_agent is not None: - headers['user-agent'] = self.user_agent - - return headers - - def _refresh(self, http_request): - """Refreshes the access_token. - - This method first checks by reading the Storage object if available. - If a refresh is still needed, it holds the Storage lock until the - refresh is completed. - - Args: - http_request: callable, a callable that matches the method signature of - httplib2.Http.request, used to make the refresh request. - - Raises: - AccessTokenRefreshError: When the refresh fails. - """ - if not self.store: - self._do_refresh_request(http_request) - else: - self.store.acquire_lock() - try: - new_cred = self.store.locked_get() - - if (new_cred and not new_cred.invalid and - new_cred.access_token != self.access_token and - not new_cred.access_token_expired): - logger.info('Updated access_token read from Storage') - self._updateFromCredential(new_cred) - else: - self._do_refresh_request(http_request) - finally: - self.store.release_lock() - - def _do_refresh_request(self, http_request): - """Refresh the access_token using the refresh_token. - - Args: - http_request: callable, a callable that matches the method signature of - httplib2.Http.request, used to make the refresh request. - - Raises: - AccessTokenRefreshError: When the refresh fails. - """ - body = self._generate_refresh_request_body() - headers = self._generate_refresh_request_headers() - - logger.info('Refreshing access_token') - resp, content = http_request( - self.token_uri, method='POST', body=body, headers=headers) - if six.PY3 and isinstance(content, bytes): - content = content.decode('utf-8') - if resp.status == 200: - d = json.loads(content) - self.token_response = d - self.access_token = d['access_token'] - self.refresh_token = d.get('refresh_token', self.refresh_token) - if 'expires_in' in d: - self.token_expiry = datetime.timedelta( - seconds=int(d['expires_in'])) + datetime.datetime.utcnow() - else: - self.token_expiry = None - # On temporary refresh errors, the user does not actually have to - # re-authorize, so we unflag here. - self.invalid = False - if self.store: - self.store.locked_put(self) - else: - # An {'error':...} response body means the token is expired or revoked, - # so we flag the credentials as such. - logger.info('Failed to retrieve access token: %s', content) - error_msg = 'Invalid response %s.' % resp['status'] - try: - d = json.loads(content) - if 'error' in d: - error_msg = d['error'] - if 'error_description' in d: - error_msg += ': ' + d['error_description'] - self.invalid = True - if self.store: - self.store.locked_put(self) - except (TypeError, ValueError): - pass - raise AccessTokenRefreshError(error_msg) - - def _revoke(self, http_request): - """Revokes this credential and deletes the stored copy (if it exists). - - Args: - http_request: callable, a callable that matches the method signature of - httplib2.Http.request, used to make the revoke request. - """ - self._do_revoke(http_request, self.refresh_token or self.access_token) - - def _do_revoke(self, http_request, token): - """Revokes this credential and deletes the stored copy (if it exists). - - Args: - http_request: callable, a callable that matches the method signature of - httplib2.Http.request, used to make the refresh request. - token: A string used as the token to be revoked. Can be either an - access_token or refresh_token. - - Raises: - TokenRevokeError: If the revoke request does not return with a 200 OK. - """ - logger.info('Revoking token') - query_params = {'token': token} - token_revoke_uri = _update_query_params(self.revoke_uri, query_params) - resp, content = http_request(token_revoke_uri) - if resp.status == 200: - self.invalid = True - else: - error_msg = 'Invalid response %s.' % resp.status - try: - d = json.loads(content) - if 'error' in d: - error_msg = d['error'] - except (TypeError, ValueError): - pass - raise TokenRevokeError(error_msg) - - if self.store: - self.store.delete() - - -class AccessTokenCredentials(OAuth2Credentials): - """Credentials object for OAuth 2.0. - - Credentials can be applied to an httplib2.Http object using the - authorize() method, which then signs each request from that object - with the OAuth 2.0 access token. This set of credentials is for the - use case where you have acquired an OAuth 2.0 access_token from - another place such as a JavaScript client or another web - application, and wish to use it from Python. Because only the - access_token is present it can not be refreshed and will in time - expire. - - AccessTokenCredentials objects may be safely pickled and unpickled. - - Usage:: - - credentials = AccessTokenCredentials('<an access token>', - 'my-user-agent/1.0') - http = httplib2.Http() - http = credentials.authorize(http) - - Exceptions: - AccessTokenCredentialsExpired: raised when the access_token expires or is - revoked. - """ - - def __init__(self, access_token, user_agent, revoke_uri=None): - """Create an instance of OAuth2Credentials - - This is one of the few types if Credentials that you should contrust, - Credentials objects are usually instantiated by a Flow. - - Args: - access_token: string, access token. - user_agent: string, The HTTP User-Agent to provide for this application. - revoke_uri: string, URI for revoke endpoint. Defaults to None; a token - can't be revoked if this is None. - """ - super(AccessTokenCredentials, self).__init__( - access_token, - None, - None, - None, - None, - None, - user_agent, - revoke_uri=revoke_uri) - - - @classmethod - def from_json(cls, s): - if six.PY3 and isinstance(s, bytes): - s = s.decode('utf-8') - data = json.loads(s) - retval = AccessTokenCredentials( - data['access_token'], - data['user_agent']) - return retval - - def _refresh(self, http_request): - raise AccessTokenCredentialsError( - 'The access_token is expired or invalid and can\'t be refreshed.') - - def _revoke(self, http_request): - """Revokes the access_token and deletes the store if available. - - Args: - http_request: callable, a callable that matches the method signature of - httplib2.Http.request, used to make the revoke request. - """ - self._do_revoke(http_request, self.access_token) - - -def _detect_gce_environment(urlopen=None): - """Determine if the current environment is Compute Engine. - - Args: - urlopen: Optional argument. Function used to open a connection to a URL. - - Returns: - Boolean indicating whether or not the current environment is Google - Compute Engine. - """ - urlopen = urlopen or urllib.request.urlopen - # Note: the explicit `timeout` below is a workaround. The underlying - # issue is that resolving an unknown host on some networks will take - # 20-30 seconds; making this timeout short fixes the issue, but - # could lead to false negatives in the event that we are on GCE, but - # the metadata resolution was particularly slow. The latter case is - # "unlikely". - try: - response = urlopen('http://169.254.169.254/', timeout=1) - return response.info().get('Metadata-Flavor', '') == 'Google' - except socket.timeout: - logger.info('Timeout attempting to reach GCE metadata service.') - return False - except urllib.error.URLError as e: - if isinstance(getattr(e, 'reason', None), socket.timeout): - logger.info('Timeout attempting to reach GCE metadata service.') - return False - - -def _get_environment(urlopen=None): - """Detect the environment the code is being run on. - - Args: - urlopen: Optional argument. Function used to open a connection to a URL. - - Returns: - The value of SETTINGS.env_name after being set. If already - set, simply returns the value. - """ - if SETTINGS.env_name is not None: - return SETTINGS.env_name - - # None is an unset value, not the default. - SETTINGS.env_name = DEFAULT_ENV_NAME - - try: - import google.appengine - has_gae_sdk = True - except ImportError: - has_gae_sdk = False - - if has_gae_sdk: - server_software = os.environ.get('SERVER_SOFTWARE', '') - if server_software.startswith('Google App Engine/'): - SETTINGS.env_name = 'GAE_PRODUCTION' - elif server_software.startswith('Development/'): - SETTINGS.env_name = 'GAE_LOCAL' - elif NO_GCE_CHECK != 'True' and _detect_gce_environment(urlopen=urlopen): - SETTINGS.env_name = 'GCE_PRODUCTION' - - return SETTINGS.env_name - - -class GoogleCredentials(OAuth2Credentials): - """Application Default Credentials for use in calling Google APIs. - - The Application Default Credentials are being constructed as a function of - the environment where the code is being run. - More details can be found on this page: - https://developers.google.com/accounts/docs/application-default-credentials - - Here is an example of how to use the Application Default Credentials for a - service that requires authentication: - - from googleapiclient.discovery import build - from oauth2client.client import GoogleCredentials - - credentials = GoogleCredentials.get_application_default() - service = build('compute', 'v1', credentials=credentials) - - PROJECT = 'bamboo-machine-422' - ZONE = 'us-central1-a' - request = service.instances().list(project=PROJECT, zone=ZONE) - response = request.execute() - - print(response) - """ - - def __init__(self, access_token, client_id, client_secret, refresh_token, - token_expiry, token_uri, user_agent, - revoke_uri=GOOGLE_REVOKE_URI): - """Create an instance of GoogleCredentials. - - This constructor is not usually called by the user, instead - GoogleCredentials objects are instantiated by - GoogleCredentials.from_stream() or - GoogleCredentials.get_application_default(). - - Args: - access_token: string, access token. - client_id: string, client identifier. - client_secret: string, client secret. - refresh_token: string, refresh token. - token_expiry: datetime, when the access_token expires. - token_uri: string, URI of token endpoint. - user_agent: string, The HTTP User-Agent to provide for this application. - revoke_uri: string, URI for revoke endpoint. - Defaults to GOOGLE_REVOKE_URI; a token can't be revoked if this is None. - """ - super(GoogleCredentials, self).__init__( - access_token, client_id, client_secret, refresh_token, token_expiry, - token_uri, user_agent, revoke_uri=revoke_uri) - - def create_scoped_required(self): - """Whether this Credentials object is scopeless. - - create_scoped(scopes) method needs to be called in order to create - a Credentials object for API calls. - """ - return False - - def create_scoped(self, scopes): - """Create a Credentials object for the given scopes. - - The Credentials type is preserved. - """ - return self - - @property - def serialization_data(self): - """Get the fields and their values identifying the current credentials.""" - return { - 'type': 'authorized_user', - 'client_id': self.client_id, - 'client_secret': self.client_secret, - 'refresh_token': self.refresh_token - } - - @staticmethod - def _implicit_credentials_from_gae(env_name=None): - """Attempts to get implicit credentials in Google App Engine env. - - If the current environment is not detected as App Engine, returns None, - indicating no Google App Engine credentials can be detected from the - current environment. - - Args: - env_name: String, indicating current environment. - - Returns: - None, if not in GAE, else an appengine.AppAssertionCredentials object. - """ - env_name = env_name or _get_environment() - if env_name not in ('GAE_PRODUCTION', 'GAE_LOCAL'): - return None - - return _get_application_default_credential_GAE() - - @staticmethod - def _implicit_credentials_from_gce(env_name=None): - """Attempts to get implicit credentials in Google Compute Engine env. - - If the current environment is not detected as Compute Engine, returns None, - indicating no Google Compute Engine credentials can be detected from the - current environment. - - Args: - env_name: String, indicating current environment. - - Returns: - None, if not in GCE, else a gce.AppAssertionCredentials object. - """ - env_name = env_name or _get_environment() - if env_name != 'GCE_PRODUCTION': - return None - - return _get_application_default_credential_GCE() - - @staticmethod - def _implicit_credentials_from_files(env_name=None): - """Attempts to get implicit credentials from local credential files. - - First checks if the environment variable GOOGLE_APPLICATION_CREDENTIALS - is set with a filename and then falls back to a configuration file (the - "well known" file) associated with the 'gcloud' command line tool. - - Args: - env_name: Unused argument. - - Returns: - Credentials object associated with the GOOGLE_APPLICATION_CREDENTIALS - file or the "well known" file if either exist. If neither file is - define, returns None, indicating no credentials from a file can - detected from the current environment. - """ - credentials_filename = _get_environment_variable_file() - if not credentials_filename: - credentials_filename = _get_well_known_file() - if os.path.isfile(credentials_filename): - extra_help = (' (produced automatically when running' - ' "gcloud auth login" command)') - else: - credentials_filename = None - else: - extra_help = (' (pointed to by ' + GOOGLE_APPLICATION_CREDENTIALS + - ' environment variable)') - - if not credentials_filename: - return - - try: - return _get_application_default_credential_from_file(credentials_filename) - except (ApplicationDefaultCredentialsError, ValueError) as error: - _raise_exception_for_reading_json(credentials_filename, extra_help, error) - - @classmethod - def _get_implicit_credentials(cls): - """Gets credentials implicitly from the environment. - - Checks environment in order of precedence: - - Google App Engine (production and testing) - - Environment variable GOOGLE_APPLICATION_CREDENTIALS pointing to - a file with stored credentials information. - - Stored "well known" file associated with `gcloud` command line tool. - - Google Compute Engine production environment. - - Exceptions: - ApplicationDefaultCredentialsError: raised when the credentials fail - to be retrieved. - """ - env_name = _get_environment() - - # Environ checks (in order). Assumes each checker takes `env_name` - # as a kwarg. - environ_checkers = [ - cls._implicit_credentials_from_gae, - cls._implicit_credentials_from_files, - cls._implicit_credentials_from_gce, - ] - - for checker in environ_checkers: - credentials = checker(env_name=env_name) - if credentials is not None: - return credentials - - # If no credentials, fail. - raise ApplicationDefaultCredentialsError(ADC_HELP_MSG) - - @staticmethod - def get_application_default(): - """Get the Application Default Credentials for the current environment. - - Exceptions: - ApplicationDefaultCredentialsError: raised when the credentials fail - to be retrieved. - """ - return GoogleCredentials._get_implicit_credentials() - - @staticmethod - def from_stream(credential_filename): - """Create a Credentials object by reading the information from a given file. - - It returns an object of type GoogleCredentials. - - Args: - credential_filename: the path to the file from where the credentials - are to be read - - Exceptions: - ApplicationDefaultCredentialsError: raised when the credentials fail - to be retrieved. - """ - - if credential_filename and os.path.isfile(credential_filename): - try: - return _get_application_default_credential_from_file( - credential_filename) - except (ApplicationDefaultCredentialsError, ValueError) as error: - extra_help = ' (provided as parameter to the from_stream() method)' - _raise_exception_for_reading_json(credential_filename, - extra_help, - error) - else: - raise ApplicationDefaultCredentialsError( - 'The parameter passed to the from_stream() ' - 'method should point to a file.') - - -def _save_private_file(filename, json_contents): - """Saves a file with read-write permissions on for the owner. - - Args: - filename: String. Absolute path to file. - json_contents: JSON serializable object to be saved. - """ - temp_filename = tempfile.mktemp() - file_desc = os.open(temp_filename, os.O_WRONLY | os.O_CREAT, 0o600) - with os.fdopen(file_desc, 'w') as file_handle: - json.dump(json_contents, file_handle, sort_keys=True, - indent=2, separators=(',', ': ')) - shutil.move(temp_filename, filename) - - -def save_to_well_known_file(credentials, well_known_file=None): - """Save the provided GoogleCredentials to the well known file. - - Args: - credentials: - the credentials to be saved to the well known file; - it should be an instance of GoogleCredentials - well_known_file: - the name of the file where the credentials are to be saved; - this parameter is supposed to be used for testing only - """ - # TODO(orestica): move this method to tools.py - # once the argparse import gets fixed (it is not present in Python 2.6) - - if well_known_file is None: - well_known_file = _get_well_known_file() - - config_dir = os.path.dirname(well_known_file) - if not os.path.isdir(config_dir): - raise OSError('Config directory does not exist: %s' % config_dir) - - credentials_data = credentials.serialization_data - _save_private_file(well_known_file, credentials_data) - - -def _get_environment_variable_file(): - application_default_credential_filename = ( - os.environ.get(GOOGLE_APPLICATION_CREDENTIALS, - None)) - - if application_default_credential_filename: - if os.path.isfile(application_default_credential_filename): - return application_default_credential_filename - else: - raise ApplicationDefaultCredentialsError( - 'File ' + application_default_credential_filename + ' (pointed by ' + - GOOGLE_APPLICATION_CREDENTIALS + - ' environment variable) does not exist!') - - -def _get_well_known_file(): - """Get the well known file produced by command 'gcloud auth login'.""" - # TODO(orestica): Revisit this method once gcloud provides a better way - # of pinpointing the exact location of the file. - - WELL_KNOWN_CREDENTIALS_FILE = 'application_default_credentials.json' - - default_config_dir = os.getenv(_CLOUDSDK_CONFIG_ENV_VAR) - if default_config_dir is None: - if os.name == 'nt': - try: - default_config_dir = os.path.join(os.environ['APPDATA'], - _CLOUDSDK_CONFIG_DIRECTORY) - except KeyError: - # This should never happen unless someone is really messing with things. - drive = os.environ.get('SystemDrive', 'C:') - default_config_dir = os.path.join(drive, '\\', - _CLOUDSDK_CONFIG_DIRECTORY) - else: - default_config_dir = os.path.join(os.path.expanduser('~'), - '.config', - _CLOUDSDK_CONFIG_DIRECTORY) - - return os.path.join(default_config_dir, WELL_KNOWN_CREDENTIALS_FILE) - - -def _get_application_default_credential_from_file(filename): - """Build the Application Default Credentials from file.""" - - from oauth2client import service_account - - # read the credentials from the file - with open(filename) as file_obj: - client_credentials = json.load(file_obj) - - credentials_type = client_credentials.get('type') - if credentials_type == AUTHORIZED_USER: - required_fields = set(['client_id', 'client_secret', 'refresh_token']) - elif credentials_type == SERVICE_ACCOUNT: - required_fields = set(['client_id', 'client_email', 'private_key_id', - 'private_key']) - else: - raise ApplicationDefaultCredentialsError( - "'type' field should be defined (and have one of the '" + - AUTHORIZED_USER + "' or '" + SERVICE_ACCOUNT + "' values)") - - missing_fields = required_fields.difference(client_credentials.keys()) - - if missing_fields: - _raise_exception_for_missing_fields(missing_fields) - - if client_credentials['type'] == AUTHORIZED_USER: - return GoogleCredentials( - access_token=None, - client_id=client_credentials['client_id'], - client_secret=client_credentials['client_secret'], - refresh_token=client_credentials['refresh_token'], - token_expiry=None, - token_uri=GOOGLE_TOKEN_URI, - user_agent='Python client library') - else: # client_credentials['type'] == SERVICE_ACCOUNT - return service_account._ServiceAccountCredentials( - service_account_id=client_credentials['client_id'], - service_account_email=client_credentials['client_email'], - private_key_id=client_credentials['private_key_id'], - private_key_pkcs8_text=client_credentials['private_key'], - scopes=[]) - - -def _raise_exception_for_missing_fields(missing_fields): - raise ApplicationDefaultCredentialsError( - 'The following field(s) must be defined: ' + ', '.join(missing_fields)) - - -def _raise_exception_for_reading_json(credential_file, - extra_help, - error): - raise ApplicationDefaultCredentialsError( - 'An error was encountered while reading json file: '+ - credential_file + extra_help + ': ' + str(error)) - - -def _get_application_default_credential_GAE(): - from oauth2client.appengine import AppAssertionCredentials - - return AppAssertionCredentials([]) - - -def _get_application_default_credential_GCE(): - from oauth2client.gce import AppAssertionCredentials - - return AppAssertionCredentials([]) - - -class AssertionCredentials(GoogleCredentials): - """Abstract Credentials object used for OAuth 2.0 assertion grants. - - This credential does not require a flow to instantiate because it - represents a two legged flow, and therefore has all of the required - information to generate and refresh its own access tokens. It must - be subclassed to generate the appropriate assertion string. - - AssertionCredentials objects may be safely pickled and unpickled. - """ - - @util.positional(2) - def __init__(self, assertion_type, user_agent=None, - token_uri=GOOGLE_TOKEN_URI, - revoke_uri=GOOGLE_REVOKE_URI, - **unused_kwargs): - """Constructor for AssertionFlowCredentials. - - Args: - assertion_type: string, assertion type that will be declared to the auth - server - user_agent: string, The HTTP User-Agent to provide for this application. - token_uri: string, URI for token endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - revoke_uri: string, URI for revoke endpoint. - """ - super(AssertionCredentials, self).__init__( - None, - None, - None, - None, - None, - token_uri, - user_agent, - revoke_uri=revoke_uri) - self.assertion_type = assertion_type - - def _generate_refresh_request_body(self): - assertion = self._generate_assertion() - - body = urllib.parse.urlencode({ - 'assertion': assertion, - 'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer', - }) - - return body - - def _generate_assertion(self): - """Generate the assertion string that will be used in the access token - request. - """ - _abstract() - - def _revoke(self, http_request): - """Revokes the access_token and deletes the store if available. - - Args: - http_request: callable, a callable that matches the method signature of - httplib2.Http.request, used to make the revoke request. - """ - self._do_revoke(http_request, self.access_token) - - -def _RequireCryptoOrDie(): - """Ensure we have a crypto library, or throw CryptoUnavailableError. - - The oauth2client.crypt module requires either PyCrypto or PyOpenSSL - to be available in order to function, but these are optional - dependencies. - """ - if not HAS_CRYPTO: - raise CryptoUnavailableError('No crypto library available') - - -class SignedJwtAssertionCredentials(AssertionCredentials): - """Credentials object used for OAuth 2.0 Signed JWT assertion grants. - - This credential does not require a flow to instantiate because it - represents a two legged flow, and therefore has all of the required - information to generate and refresh its own access tokens. - - SignedJwtAssertionCredentials requires either PyOpenSSL, or PyCrypto - 2.6 or later. For App Engine you may also consider using - AppAssertionCredentials. - """ - - MAX_TOKEN_LIFETIME_SECS = 3600 # 1 hour in seconds - - @util.positional(4) - def __init__(self, - service_account_name, - private_key, - scope, - private_key_password='notasecret', - user_agent=None, - token_uri=GOOGLE_TOKEN_URI, - revoke_uri=GOOGLE_REVOKE_URI, - **kwargs): - """Constructor for SignedJwtAssertionCredentials. - - Args: - service_account_name: string, id for account, usually an email address. - private_key: string, private key in PKCS12 or PEM format. - scope: string or iterable of strings, scope(s) of the credentials being - requested. - private_key_password: string, password for private_key, unused if - private_key is in PEM format. - user_agent: string, HTTP User-Agent to provide for this application. - token_uri: string, URI for token endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - revoke_uri: string, URI for revoke endpoint. - kwargs: kwargs, Additional parameters to add to the JWT token, for - example sub=joe@xample.org. - - Raises: - CryptoUnavailableError if no crypto library is available. - """ - _RequireCryptoOrDie() - super(SignedJwtAssertionCredentials, self).__init__( - None, - user_agent=user_agent, - token_uri=token_uri, - revoke_uri=revoke_uri, - ) - - self.scope = util.scopes_to_string(scope) - - # Keep base64 encoded so it can be stored in JSON. - self.private_key = base64.b64encode(private_key) - if isinstance(self.private_key, six.text_type): - self.private_key = self.private_key.encode('utf-8') - - self.private_key_password = private_key_password - self.service_account_name = service_account_name - self.kwargs = kwargs - - @classmethod - def from_json(cls, s): - data = json.loads(s) - retval = SignedJwtAssertionCredentials( - data['service_account_name'], - base64.b64decode(data['private_key']), - data['scope'], - private_key_password=data['private_key_password'], - user_agent=data['user_agent'], - token_uri=data['token_uri'], - **data['kwargs'] - ) - retval.invalid = data['invalid'] - retval.access_token = data['access_token'] - return retval - - def _generate_assertion(self): - """Generate the assertion that will be used in the request.""" - now = int(time.time()) - payload = { - 'aud': self.token_uri, - 'scope': self.scope, - 'iat': now, - 'exp': now + SignedJwtAssertionCredentials.MAX_TOKEN_LIFETIME_SECS, - 'iss': self.service_account_name - } - payload.update(self.kwargs) - logger.debug(str(payload)) - - private_key = base64.b64decode(self.private_key) - return crypt.make_signed_jwt(crypt.Signer.from_string( - private_key, self.private_key_password), payload) - -# Only used in verify_id_token(), which is always calling to the same URI -# for the certs. -_cached_http = httplib2.Http(MemoryCache()) - -@util.positional(2) -def verify_id_token(id_token, audience, http=None, - cert_uri=ID_TOKEN_VERIFICATION_CERTS): - """Verifies a signed JWT id_token. - - This function requires PyOpenSSL and because of that it does not work on - App Engine. - - Args: - id_token: string, A Signed JWT. - audience: string, The audience 'aud' that the token should be for. - http: httplib2.Http, instance to use to make the HTTP request. Callers - should supply an instance that has caching enabled. - cert_uri: string, URI of the certificates in JSON format to - verify the JWT against. - - Returns: - The deserialized JSON in the JWT. - - Raises: - oauth2client.crypt.AppIdentityError: if the JWT fails to verify. - CryptoUnavailableError: if no crypto library is available. - """ - _RequireCryptoOrDie() - if http is None: - http = _cached_http - - resp, content = http.request(cert_uri) - - if resp.status == 200: - certs = json.loads(content.decode('utf-8')) - return crypt.verify_signed_jwt_with_certs(id_token, certs, audience) - else: - raise VerifyJwtTokenError('Status code: %d' % resp.status) - - -def _urlsafe_b64decode(b64string): - # Guard against unicode strings, which base64 can't handle. - if isinstance(b64string, six.text_type): - b64string = b64string.encode('ascii') - padded = b64string + b'=' * (4 - len(b64string) % 4) - return base64.urlsafe_b64decode(padded) - - -def _extract_id_token(id_token): - """Extract the JSON payload from a JWT. - - Does the extraction w/o checking the signature. - - Args: - id_token: string or bytestring, OAuth 2.0 id_token. - - Returns: - object, The deserialized JSON payload. - """ - if type(id_token) == bytes: - segments = id_token.split(b'.') - else: - segments = id_token.split(u'.') - - if len(segments) != 3: - raise VerifyJwtTokenError( - 'Wrong number of segments in token: %s' % id_token) - - return json.loads(_urlsafe_b64decode(segments[1]).decode('utf-8')) - - -def _parse_exchange_token_response(content): - """Parses response of an exchange token request. - - Most providers return JSON but some (e.g. Facebook) return a - url-encoded string. - - Args: - content: The body of a response - - Returns: - Content as a dictionary object. Note that the dict could be empty, - i.e. {}. That basically indicates a failure. - """ - resp = {} - try: - resp = json.loads(content.decode('utf-8')) - except Exception: - # different JSON libs raise different exceptions, - # so we just do a catch-all here - content = content.decode('utf-8') - resp = dict(urllib.parse.parse_qsl(content)) - - # some providers respond with 'expires', others with 'expires_in' - if resp and 'expires' in resp: - resp['expires_in'] = resp.pop('expires') - - return resp - - -@util.positional(4) -def credentials_from_code(client_id, client_secret, scope, code, - redirect_uri='postmessage', http=None, - user_agent=None, token_uri=GOOGLE_TOKEN_URI, - auth_uri=GOOGLE_AUTH_URI, - revoke_uri=GOOGLE_REVOKE_URI, - device_uri=GOOGLE_DEVICE_URI): - """Exchanges an authorization code for an OAuth2Credentials object. - - Args: - client_id: string, client identifier. - client_secret: string, client secret. - scope: string or iterable of strings, scope(s) to request. - code: string, An authorization code, most likely passed down from - the client - redirect_uri: string, this is generally set to 'postmessage' to match the - redirect_uri that the client specified - http: httplib2.Http, optional http instance to use to do the fetch - token_uri: string, URI for token endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - auth_uri: string, URI for authorization endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - revoke_uri: string, URI for revoke endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - device_uri: string, URI for device authorization endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - - Returns: - An OAuth2Credentials object. - - Raises: - FlowExchangeError if the authorization code cannot be exchanged for an - access token - """ - flow = OAuth2WebServerFlow(client_id, client_secret, scope, - redirect_uri=redirect_uri, user_agent=user_agent, - auth_uri=auth_uri, token_uri=token_uri, - revoke_uri=revoke_uri, device_uri=device_uri) - - credentials = flow.step2_exchange(code, http=http) - return credentials - - -@util.positional(3) -def credentials_from_clientsecrets_and_code(filename, scope, code, - message = None, - redirect_uri='postmessage', - http=None, - cache=None, - device_uri=None): - """Returns OAuth2Credentials from a clientsecrets file and an auth code. - - Will create the right kind of Flow based on the contents of the clientsecrets - file or will raise InvalidClientSecretsError for unknown types of Flows. - - Args: - filename: string, File name of clientsecrets. - scope: string or iterable of strings, scope(s) to request. - code: string, An authorization code, most likely passed down from - the client - message: string, A friendly string to display to the user if the - clientsecrets file is missing or invalid. If message is provided then - sys.exit will be called in the case of an error. If message in not - provided then clientsecrets.InvalidClientSecretsError will be raised. - redirect_uri: string, this is generally set to 'postmessage' to match the - redirect_uri that the client specified - http: httplib2.Http, optional http instance to use to do the fetch - cache: An optional cache service client that implements get() and set() - methods. See clientsecrets.loadfile() for details. - device_uri: string, OAuth 2.0 device authorization endpoint - - Returns: - An OAuth2Credentials object. - - Raises: - FlowExchangeError if the authorization code cannot be exchanged for an - access token - UnknownClientSecretsFlowError if the file describes an unknown kind of Flow. - clientsecrets.InvalidClientSecretsError if the clientsecrets file is - invalid. - """ - flow = flow_from_clientsecrets(filename, scope, message=message, cache=cache, - redirect_uri=redirect_uri, - device_uri=device_uri) - credentials = flow.step2_exchange(code, http=http) - return credentials - - -class DeviceFlowInfo(collections.namedtuple('DeviceFlowInfo', ( - 'device_code', 'user_code', 'interval', 'verification_url', - 'user_code_expiry'))): - """Intermediate information the OAuth2 for devices flow.""" - - @classmethod - def FromResponse(cls, response): - """Create a DeviceFlowInfo from a server response. - - The response should be a dict containing entries as described here: - - http://tools.ietf.org/html/draft-ietf-oauth-v2-05#section-3.7.1 - """ - # device_code, user_code, and verification_url are required. - kwargs = { - 'device_code': response['device_code'], - 'user_code': response['user_code'], - } - # The response may list the verification address as either - # verification_url or verification_uri, so we check for both. - verification_url = response.get( - 'verification_url', response.get('verification_uri')) - if verification_url is None: - raise OAuth2DeviceCodeError( - 'No verification_url provided in server response') - kwargs['verification_url'] = verification_url - # expires_in and interval are optional. - kwargs.update({ - 'interval': response.get('interval'), - 'user_code_expiry': None, - }) - if 'expires_in' in response: - kwargs['user_code_expiry'] = datetime.datetime.now() + datetime.timedelta( - seconds=int(response['expires_in'])) - - return cls(**kwargs) - -class OAuth2WebServerFlow(Flow): - """Does the Web Server Flow for OAuth 2.0. - - OAuth2WebServerFlow objects may be safely pickled and unpickled. - """ - - @util.positional(4) - def __init__(self, client_id, client_secret, scope, - redirect_uri=None, - user_agent=None, - auth_uri=GOOGLE_AUTH_URI, - token_uri=GOOGLE_TOKEN_URI, - revoke_uri=GOOGLE_REVOKE_URI, - login_hint=None, - device_uri=GOOGLE_DEVICE_URI, - **kwargs): - """Constructor for OAuth2WebServerFlow. - - The kwargs argument is used to set extra query parameters on the - auth_uri. For example, the access_type and approval_prompt - query parameters can be set via kwargs. - - Args: - client_id: string, client identifier. - client_secret: string client secret. - scope: string or iterable of strings, scope(s) of the credentials being - requested. - redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob' for - a non-web-based application, or a URI that handles the callback from - the authorization server. - user_agent: string, HTTP User-Agent to provide for this application. - auth_uri: string, URI for authorization endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - token_uri: string, URI for token endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - revoke_uri: string, URI for revoke endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - login_hint: string, Either an email address or domain. Passing this hint - will either pre-fill the email box on the sign-in form or select the - proper multi-login session, thereby simplifying the login flow. - device_uri: string, URI for device authorization endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - **kwargs: dict, The keyword arguments are all optional and required - parameters for the OAuth calls. - """ - self.client_id = client_id - self.client_secret = client_secret - self.scope = util.scopes_to_string(scope) - self.redirect_uri = redirect_uri - self.login_hint = login_hint - self.user_agent = user_agent - self.auth_uri = auth_uri - self.token_uri = token_uri - self.revoke_uri = revoke_uri - self.device_uri = device_uri - self.params = { - 'access_type': 'offline', - 'response_type': 'code', - } - self.params.update(kwargs) - - @util.positional(1) - def step1_get_authorize_url(self, redirect_uri=None): - """Returns a URI to redirect to the provider. - - Args: - redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob' for - a non-web-based application, or a URI that handles the callback from - the authorization server. This parameter is deprecated, please move to - passing the redirect_uri in via the constructor. - - Returns: - A URI as a string to redirect the user to begin the authorization flow. - """ - if redirect_uri is not None: - logger.warning(( - 'The redirect_uri parameter for ' - 'OAuth2WebServerFlow.step1_get_authorize_url is deprecated. Please ' - 'move to passing the redirect_uri in via the constructor.')) - self.redirect_uri = redirect_uri - - if self.redirect_uri is None: - raise ValueError('The value of redirect_uri must not be None.') - - query_params = { - 'client_id': self.client_id, - 'redirect_uri': self.redirect_uri, - 'scope': self.scope, - } - if self.login_hint is not None: - query_params['login_hint'] = self.login_hint - query_params.update(self.params) - return _update_query_params(self.auth_uri, query_params) - - @util.positional(1) - def step1_get_device_and_user_codes(self, http=None): - """Returns a user code and the verification URL where to enter it - - Returns: - A user code as a string for the user to authorize the application - An URL as a string where the user has to enter the code - """ - if self.device_uri is None: - raise ValueError('The value of device_uri must not be None.') - - body = urllib.parse.urlencode({ - 'client_id': self.client_id, - 'scope': self.scope, - }) - headers = { - 'content-type': 'application/x-www-form-urlencoded', - } - - if self.user_agent is not None: - headers['user-agent'] = self.user_agent - - if http is None: - http = httplib2.Http() - - resp, content = http.request(self.device_uri, method='POST', body=body, - headers=headers) - if resp.status == 200: - try: - flow_info = json.loads(content) - except ValueError as e: - raise OAuth2DeviceCodeError( - 'Could not parse server response as JSON: "%s", error: "%s"' % ( - content, e)) - return DeviceFlowInfo.FromResponse(flow_info) - else: - error_msg = 'Invalid response %s.' % resp.status - try: - d = json.loads(content) - if 'error' in d: - error_msg += ' Error: %s' % d['error'] - except ValueError: - # Couldn't decode a JSON response, stick with the default message. - pass - raise OAuth2DeviceCodeError(error_msg) - - @util.positional(2) - def step2_exchange(self, code=None, http=None, device_flow_info=None): - """Exchanges a code for OAuth2Credentials. - - Args: - - code: string, a dict-like object, or None. For a non-device - flow, this is either the response code as a string, or a - dictionary of query parameters to the redirect_uri. For a - device flow, this should be None. - http: httplib2.Http, optional http instance to use when fetching - credentials. - device_flow_info: DeviceFlowInfo, return value from step1 in the - case of a device flow. - - Returns: - An OAuth2Credentials object that can be used to authorize requests. - - Raises: - FlowExchangeError: if a problem occurred exchanging the code for a - refresh_token. - ValueError: if code and device_flow_info are both provided or both - missing. - - """ - if code is None and device_flow_info is None: - raise ValueError('No code or device_flow_info provided.') - if code is not None and device_flow_info is not None: - raise ValueError('Cannot provide both code and device_flow_info.') - - if code is None: - code = device_flow_info.device_code - elif not isinstance(code, six.string_types): - if 'code' not in code: - raise FlowExchangeError(code.get( - 'error', 'No code was supplied in the query parameters.')) - code = code['code'] - - post_data = { - 'client_id': self.client_id, - 'client_secret': self.client_secret, - 'code': code, - 'scope': self.scope, - } - if device_flow_info is not None: - post_data['grant_type'] = 'http://oauth.net/grant_type/device/1.0' - else: - post_data['grant_type'] = 'authorization_code' - post_data['redirect_uri'] = self.redirect_uri - body = urllib.parse.urlencode(post_data) - headers = { - 'content-type': 'application/x-www-form-urlencoded', - } - - if self.user_agent is not None: - headers['user-agent'] = self.user_agent - - if http is None: - http = httplib2.Http() - - resp, content = http.request(self.token_uri, method='POST', body=body, - headers=headers) - d = _parse_exchange_token_response(content) - if resp.status == 200 and 'access_token' in d: - access_token = d['access_token'] - refresh_token = d.get('refresh_token', None) - if not refresh_token: - logger.info( - 'Received token response with no refresh_token. Consider ' - "reauthenticating with approval_prompt='force'.") - token_expiry = None - if 'expires_in' in d: - token_expiry = datetime.datetime.utcnow() + datetime.timedelta( - seconds=int(d['expires_in'])) - - extracted_id_token = None - if 'id_token' in d: - extracted_id_token = _extract_id_token(d['id_token']) - - logger.info('Successfully retrieved access token') - return OAuth2Credentials(access_token, self.client_id, - self.client_secret, refresh_token, token_expiry, - self.token_uri, self.user_agent, - revoke_uri=self.revoke_uri, - id_token=extracted_id_token, - token_response=d) - else: - logger.info('Failed to retrieve access token: %s', content) - if 'error' in d: - # you never know what those providers got to say - error_msg = str(d['error']) + str(d.get('error_description', '')) - else: - error_msg = 'Invalid response: %s.' % str(resp.status) - raise FlowExchangeError(error_msg) - - -@util.positional(2) -def flow_from_clientsecrets(filename, scope, redirect_uri=None, - message=None, cache=None, login_hint=None, - device_uri=None): - """Create a Flow from a clientsecrets file. - - Will create the right kind of Flow based on the contents of the clientsecrets - file or will raise InvalidClientSecretsError for unknown types of Flows. - - Args: - filename: string, File name of client secrets. - scope: string or iterable of strings, scope(s) to request. - redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob' for - a non-web-based application, or a URI that handles the callback from - the authorization server. - message: string, A friendly string to display to the user if the - clientsecrets file is missing or invalid. If message is provided then - sys.exit will be called in the case of an error. If message in not - provided then clientsecrets.InvalidClientSecretsError will be raised. - cache: An optional cache service client that implements get() and set() - methods. See clientsecrets.loadfile() for details. - login_hint: string, Either an email address or domain. Passing this hint - will either pre-fill the email box on the sign-in form or select the - proper multi-login session, thereby simplifying the login flow. - device_uri: string, URI for device authorization endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - - Returns: - A Flow object. - - Raises: - UnknownClientSecretsFlowError if the file describes an unknown kind of Flow. - clientsecrets.InvalidClientSecretsError if the clientsecrets file is - invalid. - """ - try: - client_type, client_info = clientsecrets.loadfile(filename, cache=cache) - if client_type in (clientsecrets.TYPE_WEB, clientsecrets.TYPE_INSTALLED): - constructor_kwargs = { - 'redirect_uri': redirect_uri, - 'auth_uri': client_info['auth_uri'], - 'token_uri': client_info['token_uri'], - 'login_hint': login_hint, - } - revoke_uri = client_info.get('revoke_uri') - if revoke_uri is not None: - constructor_kwargs['revoke_uri'] = revoke_uri - if device_uri is not None: - constructor_kwargs['device_uri'] = device_uri - return OAuth2WebServerFlow( - client_info['client_id'], client_info['client_secret'], - scope, **constructor_kwargs) - - except clientsecrets.InvalidClientSecretsError: - if message: - sys.exit(message) - else: - raise - else: - raise UnknownClientSecretsFlowError( - 'This OAuth 2.0 flow is unsupported: %r' % client_type) diff --git a/catapult/third_party/oauth2client/oauth2client/clientsecrets.py b/catapult/third_party/oauth2client/oauth2client/clientsecrets.py deleted file mode 100644 index 08a17020..00000000 --- a/catapult/third_party/oauth2client/oauth2client/clientsecrets.py +++ /dev/null @@ -1,163 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Utilities for reading OAuth 2.0 client secret files. - -A client_secrets.json file contains all the information needed to interact with -an OAuth 2.0 protected service. -""" - -__author__ = 'jcgregorio@google.com (Joe Gregorio)' - -import json -import six - - -# Properties that make a client_secrets.json file valid. -TYPE_WEB = 'web' -TYPE_INSTALLED = 'installed' - -VALID_CLIENT = { - TYPE_WEB: { - 'required': [ - 'client_id', - 'client_secret', - 'redirect_uris', - 'auth_uri', - 'token_uri', - ], - 'string': [ - 'client_id', - 'client_secret', - ], - }, - TYPE_INSTALLED: { - 'required': [ - 'client_id', - 'client_secret', - 'redirect_uris', - 'auth_uri', - 'token_uri', - ], - 'string': [ - 'client_id', - 'client_secret', - ], - }, -} - - -class Error(Exception): - """Base error for this module.""" - pass - - -class InvalidClientSecretsError(Error): - """Format of ClientSecrets file is invalid.""" - pass - - -def _validate_clientsecrets(obj): - _INVALID_FILE_FORMAT_MSG = ( - 'Invalid file format. See ' - 'https://developers.google.com/api-client-library/' - 'python/guide/aaa_client_secrets') - - if obj is None: - raise InvalidClientSecretsError(_INVALID_FILE_FORMAT_MSG) - if len(obj) != 1: - raise InvalidClientSecretsError( - _INVALID_FILE_FORMAT_MSG + ' ' - 'Expected a JSON object with a single property for a "web" or ' - '"installed" application') - client_type = tuple(obj)[0] - if client_type not in VALID_CLIENT: - raise InvalidClientSecretsError('Unknown client type: %s.' % (client_type,)) - client_info = obj[client_type] - for prop_name in VALID_CLIENT[client_type]['required']: - if prop_name not in client_info: - raise InvalidClientSecretsError( - 'Missing property "%s" in a client type of "%s".' % (prop_name, - client_type)) - for prop_name in VALID_CLIENT[client_type]['string']: - if client_info[prop_name].startswith('[['): - raise InvalidClientSecretsError( - 'Property "%s" is not configured.' % prop_name) - return client_type, client_info - - -def load(fp): - obj = json.load(fp) - return _validate_clientsecrets(obj) - - -def loads(s): - obj = json.loads(s) - return _validate_clientsecrets(obj) - - -def _loadfile(filename): - try: - with open(filename, 'r') as fp: - obj = json.load(fp) - except IOError: - raise InvalidClientSecretsError('File not found: "%s"' % filename) - return _validate_clientsecrets(obj) - - -def loadfile(filename, cache=None): - """Loading of client_secrets JSON file, optionally backed by a cache. - - Typical cache storage would be App Engine memcache service, - but you can pass in any other cache client that implements - these methods: - - * ``get(key, namespace=ns)`` - * ``set(key, value, namespace=ns)`` - - Usage:: - - # without caching - client_type, client_info = loadfile('secrets.json') - # using App Engine memcache service - from google.appengine.api import memcache - client_type, client_info = loadfile('secrets.json', cache=memcache) - - Args: - filename: string, Path to a client_secrets.json file on a filesystem. - cache: An optional cache service client that implements get() and set() - methods. If not specified, the file is always being loaded from - a filesystem. - - Raises: - InvalidClientSecretsError: In case of a validation error or some - I/O failure. Can happen only on cache miss. - - Returns: - (client_type, client_info) tuple, as _loadfile() normally would. - JSON contents is validated only during first load. Cache hits are not - validated. - """ - _SECRET_NAMESPACE = 'oauth2client:secrets#ns' - - if not cache: - return _loadfile(filename) - - obj = cache.get(filename, namespace=_SECRET_NAMESPACE) - if obj is None: - client_type, client_info = _loadfile(filename) - obj = {client_type: client_info} - cache.set(filename, obj, namespace=_SECRET_NAMESPACE) - - return next(six.iteritems(obj)) diff --git a/catapult/third_party/oauth2client/oauth2client/crypt.py b/catapult/third_party/oauth2client/oauth2client/crypt.py deleted file mode 100644 index 19f9d9f3..00000000 --- a/catapult/third_party/oauth2client/oauth2client/crypt.py +++ /dev/null @@ -1,461 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Crypto-related routines for oauth2client.""" - -import base64 -import imp -import json -import logging -import os -import sys -import time - -import six - - -CLOCK_SKEW_SECS = 300 # 5 minutes in seconds -AUTH_TOKEN_LIFETIME_SECS = 300 # 5 minutes in seconds -MAX_TOKEN_LIFETIME_SECS = 86400 # 1 day in seconds - - -logger = logging.getLogger(__name__) - - -class AppIdentityError(Exception): - pass - - -def _TryOpenSslImport(): - """Import OpenSSL, avoiding the explicit import where possible. - - Importing OpenSSL 0.14 can take up to 0.5s, which is a large price - to pay at module import time. However, it's also possible for - ``imp.find_module`` to fail to find the module, even when it's - installed. (This is the case in various exotic environments, - including some relevant for Google.) So we first try a fast-path, - and fall back to the slow import as needed. - - Args: - None - Returns: - None - Raises: - ImportError if OpenSSL is unavailable. - - """ - try: - _ = imp.find_module('OpenSSL') - return - except ImportError: - import OpenSSL - - -try: - _TryOpenSslImport() - - class OpenSSLVerifier(object): - """Verifies the signature on a message.""" - - def __init__(self, pubkey): - """Constructor. - - Args: - pubkey, OpenSSL.crypto.PKey, The public key to verify with. - """ - self._pubkey = pubkey - - def verify(self, message, signature): - """Verifies a message against a signature. - - Args: - message: string, The message to verify. - signature: string, The signature on the message. - - Returns: - True if message was signed by the private key associated with the public - key that this object was constructed with. - """ - from OpenSSL import crypto - try: - if isinstance(message, six.text_type): - message = message.encode('utf-8') - crypto.verify(self._pubkey, signature, message, 'sha256') - return True - except: - return False - - @staticmethod - def from_string(key_pem, is_x509_cert): - """Construct a Verified instance from a string. - - Args: - key_pem: string, public key in PEM format. - is_x509_cert: bool, True if key_pem is an X509 cert, otherwise it is - expected to be an RSA key in PEM format. - - Returns: - Verifier instance. - - Raises: - OpenSSL.crypto.Error if the key_pem can't be parsed. - """ - from OpenSSL import crypto - if is_x509_cert: - pubkey = crypto.load_certificate(crypto.FILETYPE_PEM, key_pem) - else: - pubkey = crypto.load_privatekey(crypto.FILETYPE_PEM, key_pem) - return OpenSSLVerifier(pubkey) - - - class OpenSSLSigner(object): - """Signs messages with a private key.""" - - def __init__(self, pkey): - """Constructor. - - Args: - pkey, OpenSSL.crypto.PKey (or equiv), The private key to sign with. - """ - self._key = pkey - - def sign(self, message): - """Signs a message. - - Args: - message: bytes, Message to be signed. - - Returns: - string, The signature of the message for the given key. - """ - from OpenSSL import crypto - if isinstance(message, six.text_type): - message = message.encode('utf-8') - return crypto.sign(self._key, message, 'sha256') - - @staticmethod - def from_string(key, password=b'notasecret'): - """Construct a Signer instance from a string. - - Args: - key: string, private key in PKCS12 or PEM format. - password: string, password for the private key file. - - Returns: - Signer instance. - - Raises: - OpenSSL.crypto.Error if the key can't be parsed. - """ - from OpenSSL import crypto - parsed_pem_key = _parse_pem_key(key) - if parsed_pem_key: - pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, parsed_pem_key) - else: - if isinstance(password, six.text_type): - password = password.encode('utf-8') - pkey = crypto.load_pkcs12(key, password).get_privatekey() - return OpenSSLSigner(pkey) - - - def pkcs12_key_as_pem(private_key_text, private_key_password): - """Convert the contents of a PKCS12 key to PEM using OpenSSL. - - Args: - private_key_text: String. Private key. - private_key_password: String. Password for PKCS12. - - Returns: - String. PEM contents of ``private_key_text``. - """ - from OpenSSL import crypto - decoded_body = base64.b64decode(private_key_text) - if isinstance(private_key_password, six.string_types): - private_key_password = private_key_password.encode('ascii') - - pkcs12 = crypto.load_pkcs12(decoded_body, private_key_password) - return crypto.dump_privatekey(crypto.FILETYPE_PEM, - pkcs12.get_privatekey()) -except ImportError: - OpenSSLVerifier = None - OpenSSLSigner = None - def pkcs12_key_as_pem(*args, **kwargs): - raise NotImplementedError('pkcs12_key_as_pem requires OpenSSL.') - - -try: - from Crypto.PublicKey import RSA - from Crypto.Hash import SHA256 - from Crypto.Signature import PKCS1_v1_5 - from Crypto.Util.asn1 import DerSequence - - - class PyCryptoVerifier(object): - """Verifies the signature on a message.""" - - def __init__(self, pubkey): - """Constructor. - - Args: - pubkey, OpenSSL.crypto.PKey (or equiv), The public key to verify with. - """ - self._pubkey = pubkey - - def verify(self, message, signature): - """Verifies a message against a signature. - - Args: - message: string, The message to verify. - signature: string, The signature on the message. - - Returns: - True if message was signed by the private key associated with the public - key that this object was constructed with. - """ - try: - return PKCS1_v1_5.new(self._pubkey).verify( - SHA256.new(message), signature) - except: - return False - - @staticmethod - def from_string(key_pem, is_x509_cert): - """Construct a Verified instance from a string. - - Args: - key_pem: string, public key in PEM format. - is_x509_cert: bool, True if key_pem is an X509 cert, otherwise it is - expected to be an RSA key in PEM format. - - Returns: - Verifier instance. - """ - if is_x509_cert: - if isinstance(key_pem, six.text_type): - key_pem = key_pem.encode('ascii') - pemLines = key_pem.replace(b' ', b'').split() - certDer = _urlsafe_b64decode(b''.join(pemLines[1:-1])) - certSeq = DerSequence() - certSeq.decode(certDer) - tbsSeq = DerSequence() - tbsSeq.decode(certSeq[0]) - pubkey = RSA.importKey(tbsSeq[6]) - else: - pubkey = RSA.importKey(key_pem) - return PyCryptoVerifier(pubkey) - - - class PyCryptoSigner(object): - """Signs messages with a private key.""" - - def __init__(self, pkey): - """Constructor. - - Args: - pkey, OpenSSL.crypto.PKey (or equiv), The private key to sign with. - """ - self._key = pkey - - def sign(self, message): - """Signs a message. - - Args: - message: string, Message to be signed. - - Returns: - string, The signature of the message for the given key. - """ - if isinstance(message, six.text_type): - message = message.encode('utf-8') - return PKCS1_v1_5.new(self._key).sign(SHA256.new(message)) - - @staticmethod - def from_string(key, password='notasecret'): - """Construct a Signer instance from a string. - - Args: - key: string, private key in PEM format. - password: string, password for private key file. Unused for PEM files. - - Returns: - Signer instance. - - Raises: - NotImplementedError if they key isn't in PEM format. - """ - parsed_pem_key = _parse_pem_key(key) - if parsed_pem_key: - pkey = RSA.importKey(parsed_pem_key) - else: - raise NotImplementedError( - 'PKCS12 format is not supported by the PyCrypto library. ' - 'Try converting to a "PEM" ' - '(openssl pkcs12 -in xxxxx.p12 -nodes -nocerts > privatekey.pem) ' - 'or using PyOpenSSL if native code is an option.') - return PyCryptoSigner(pkey) - -except ImportError: - PyCryptoVerifier = None - PyCryptoSigner = None - - -if OpenSSLSigner: - Signer = OpenSSLSigner - Verifier = OpenSSLVerifier -elif PyCryptoSigner: - Signer = PyCryptoSigner - Verifier = PyCryptoVerifier -else: - raise ImportError('No encryption library found. Please install either ' - 'PyOpenSSL, or PyCrypto 2.6 or later') - - -def _parse_pem_key(raw_key_input): - """Identify and extract PEM keys. - - Determines whether the given key is in the format of PEM key, and extracts - the relevant part of the key if it is. - - Args: - raw_key_input: The contents of a private key file (either PEM or PKCS12). - - Returns: - string, The actual key if the contents are from a PEM file, or else None. - """ - offset = raw_key_input.find(b'-----BEGIN ') - if offset != -1: - return raw_key_input[offset:] - - -def _urlsafe_b64encode(raw_bytes): - if isinstance(raw_bytes, six.text_type): - raw_bytes = raw_bytes.encode('utf-8') - return base64.urlsafe_b64encode(raw_bytes).decode('ascii').rstrip('=') - - -def _urlsafe_b64decode(b64string): - # Guard against unicode strings, which base64 can't handle. - if isinstance(b64string, six.text_type): - b64string = b64string.encode('ascii') - padded = b64string + b'=' * (4 - len(b64string) % 4) - return base64.urlsafe_b64decode(padded) - - -def _json_encode(data): - return json.dumps(data, separators=(',', ':')) - - -def make_signed_jwt(signer, payload): - """Make a signed JWT. - - See http://self-issued.info/docs/draft-jones-json-web-token.html. - - Args: - signer: crypt.Signer, Cryptographic signer. - payload: dict, Dictionary of data to convert to JSON and then sign. - - Returns: - string, The JWT for the payload. - """ - header = {'typ': 'JWT', 'alg': 'RS256'} - - segments = [ - _urlsafe_b64encode(_json_encode(header)), - _urlsafe_b64encode(_json_encode(payload)), - ] - signing_input = '.'.join(segments) - - signature = signer.sign(signing_input) - segments.append(_urlsafe_b64encode(signature)) - - logger.debug(str(segments)) - - return '.'.join(segments) - - -def verify_signed_jwt_with_certs(jwt, certs, audience): - """Verify a JWT against public certs. - - See http://self-issued.info/docs/draft-jones-json-web-token.html. - - Args: - jwt: string, A JWT. - certs: dict, Dictionary where values of public keys in PEM format. - audience: string, The audience, 'aud', that this JWT should contain. If - None then the JWT's 'aud' parameter is not verified. - - Returns: - dict, The deserialized JSON payload in the JWT. - - Raises: - AppIdentityError if any checks are failed. - """ - segments = jwt.split('.') - - if len(segments) != 3: - raise AppIdentityError('Wrong number of segments in token: %s' % jwt) - signed = '%s.%s' % (segments[0], segments[1]) - - signature = _urlsafe_b64decode(segments[2]) - - # Parse token. - json_body = _urlsafe_b64decode(segments[1]) - try: - parsed = json.loads(json_body.decode('utf-8')) - except: - raise AppIdentityError('Can\'t parse token: %s' % json_body) - - # Check signature. - verified = False - for pem in certs.values(): - verifier = Verifier.from_string(pem, True) - if verifier.verify(signed, signature): - verified = True - break - if not verified: - raise AppIdentityError('Invalid token signature: %s' % jwt) - - # Check creation timestamp. - iat = parsed.get('iat') - if iat is None: - raise AppIdentityError('No iat field in token: %s' % json_body) - earliest = iat - CLOCK_SKEW_SECS - - # Check expiration timestamp. - now = int(time.time()) - exp = parsed.get('exp') - if exp is None: - raise AppIdentityError('No exp field in token: %s' % json_body) - if exp >= now + MAX_TOKEN_LIFETIME_SECS: - raise AppIdentityError('exp field too far in future: %s' % json_body) - latest = exp + CLOCK_SKEW_SECS - - if now < earliest: - raise AppIdentityError('Token used too early, %d < %d: %s' % - (now, earliest, json_body)) - if now > latest: - raise AppIdentityError('Token used too late, %d > %d: %s' % - (now, latest, json_body)) - - # Check audience. - if audience is not None: - aud = parsed.get('aud') - if aud is None: - raise AppIdentityError('No aud field in token: %s' % json_body) - if aud != audience: - raise AppIdentityError('Wrong recipient, %s != %s: %s' % - (aud, audience, json_body)) - - return parsed diff --git a/catapult/third_party/oauth2client/oauth2client/devshell.py b/catapult/third_party/oauth2client/oauth2client/devshell.py deleted file mode 100644 index a33de871..00000000 --- a/catapult/third_party/oauth2client/oauth2client/devshell.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright 2015 Google Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""OAuth 2.0 utitilies for Google Developer Shell environment.""" - -import json -import os - -from oauth2client import client - - -DEVSHELL_ENV = 'DEVSHELL_CLIENT_PORT' - - -class Error(Exception): - """Errors for this module.""" - pass - - -class CommunicationError(Error): - """Errors for communication with the Developer Shell server.""" - - -class NoDevshellServer(Error): - """Error when no Developer Shell server can be contacted.""" - - -# The request for credential information to the Developer Shell client socket is -# always an empty PBLite-formatted JSON object, so just define it as a constant. -CREDENTIAL_INFO_REQUEST_JSON = '[]' - - -class CredentialInfoResponse(object): - """Credential information response from Developer Shell server. - - The credential information response from Developer Shell socket is a - PBLite-formatted JSON array with fields encoded by their index in the array: - * Index 0 - user email - * Index 1 - default project ID. None if the project context is not known. - * Index 2 - OAuth2 access token. None if there is no valid auth context. - """ - - def __init__(self, json_string): - """Initialize the response data from JSON PBLite array.""" - pbl = json.loads(json_string) - if not isinstance(pbl, list): - raise ValueError('Not a list: ' + str(pbl)) - pbl_len = len(pbl) - self.user_email = pbl[0] if pbl_len > 0 else None - self.project_id = pbl[1] if pbl_len > 1 else None - self.access_token = pbl[2] if pbl_len > 2 else None - - -def _SendRecv(): - """Communicate with the Developer Shell server socket.""" - - port = int(os.getenv(DEVSHELL_ENV, 0)) - if port == 0: - raise NoDevshellServer() - - import socket - - sock = socket.socket() - sock.connect(('localhost', port)) - - data = CREDENTIAL_INFO_REQUEST_JSON - msg = '%s\n%s' % (len(data), data) - sock.sendall(msg.encode()) - - header = sock.recv(6).decode() - if '\n' not in header: - raise CommunicationError('saw no newline in the first 6 bytes') - len_str, json_str = header.split('\n', 1) - to_read = int(len_str) - len(json_str) - if to_read > 0: - json_str += sock.recv(to_read, socket.MSG_WAITALL).decode() - - return CredentialInfoResponse(json_str) - - -class DevshellCredentials(client.GoogleCredentials): - """Credentials object for Google Developer Shell environment. - - This object will allow a Google Developer Shell session to identify its user - to Google and other OAuth 2.0 servers that can verify assertions. It can be - used for the purpose of accessing data stored under the user account. - - This credential does not require a flow to instantiate because it represents - a two legged flow, and therefore has all of the required information to - generate and refresh its own access tokens. - """ - - def __init__(self, user_agent=None): - super(DevshellCredentials, self).__init__( - None, # access_token, initialized below - None, # client_id - None, # client_secret - None, # refresh_token - None, # token_expiry - None, # token_uri - user_agent) - self._refresh(None) - - def _refresh(self, http_request): - self.devshell_response = _SendRecv() - self.access_token = self.devshell_response.access_token - - @property - def user_email(self): - return self.devshell_response.user_email - - @property - def project_id(self): - return self.devshell_response.project_id - - @classmethod - def from_json(cls, json_data): - raise NotImplementedError( - 'Cannot load Developer Shell credentials from JSON.') - - @property - def serialization_data(self): - raise NotImplementedError( - 'Cannot serialize Developer Shell credentials.') - diff --git a/catapult/third_party/oauth2client/oauth2client/django_orm.py b/catapult/third_party/oauth2client/oauth2client/django_orm.py deleted file mode 100644 index 65c5d201..00000000 --- a/catapult/third_party/oauth2client/oauth2client/django_orm.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""OAuth 2.0 utilities for Django. - -Utilities for using OAuth 2.0 in conjunction with -the Django datastore. -""" - -__author__ = 'jcgregorio@google.com (Joe Gregorio)' - -import oauth2client -import base64 -import pickle - -from django.db import models -from oauth2client.client import Storage as BaseStorage - -class CredentialsField(models.Field): - - __metaclass__ = models.SubfieldBase - - def __init__(self, *args, **kwargs): - if 'null' not in kwargs: - kwargs['null'] = True - super(CredentialsField, self).__init__(*args, **kwargs) - - def get_internal_type(self): - return "TextField" - - def to_python(self, value): - if value is None: - return None - if isinstance(value, oauth2client.client.Credentials): - return value - return pickle.loads(base64.b64decode(value)) - - def get_db_prep_value(self, value, connection, prepared=False): - if value is None: - return None - return base64.b64encode(pickle.dumps(value)) - - -class FlowField(models.Field): - - __metaclass__ = models.SubfieldBase - - def __init__(self, *args, **kwargs): - if 'null' not in kwargs: - kwargs['null'] = True - super(FlowField, self).__init__(*args, **kwargs) - - def get_internal_type(self): - return "TextField" - - def to_python(self, value): - if value is None: - return None - if isinstance(value, oauth2client.client.Flow): - return value - return pickle.loads(base64.b64decode(value)) - - def get_db_prep_value(self, value, connection, prepared=False): - if value is None: - return None - return base64.b64encode(pickle.dumps(value)) - - -class Storage(BaseStorage): - """Store and retrieve a single credential to and from - the datastore. - - This Storage helper presumes the Credentials - have been stored as a CredenialsField - on a db model class. - """ - - def __init__(self, model_class, key_name, key_value, property_name): - """Constructor for Storage. - - Args: - model: db.Model, model class - key_name: string, key name for the entity that has the credentials - key_value: string, key value for the entity that has the credentials - property_name: string, name of the property that is an CredentialsProperty - """ - self.model_class = model_class - self.key_name = key_name - self.key_value = key_value - self.property_name = property_name - - def locked_get(self): - """Retrieve Credential from datastore. - - Returns: - oauth2client.Credentials - """ - credential = None - - query = {self.key_name: self.key_value} - entities = self.model_class.objects.filter(**query) - if len(entities) > 0: - credential = getattr(entities[0], self.property_name) - if credential and hasattr(credential, 'set_store'): - credential.set_store(self) - return credential - - def locked_put(self, credentials, overwrite=False): - """Write a Credentials to the datastore. - - Args: - credentials: Credentials, the credentials to store. - overwrite: Boolean, indicates whether you would like these credentials to - overwrite any existing stored credentials. - """ - args = {self.key_name: self.key_value} - - if overwrite: - entity, unused_is_new = self.model_class.objects.get_or_create(**args) - else: - entity = self.model_class(**args) - - setattr(entity, self.property_name, credentials) - entity.save() - - def locked_delete(self): - """Delete Credentials from the datastore.""" - - query = {self.key_name: self.key_value} - entities = self.model_class.objects.filter(**query).delete() diff --git a/catapult/third_party/oauth2client/oauth2client/file.py b/catapult/third_party/oauth2client/oauth2client/file.py deleted file mode 100644 index 9d0ae7fa..00000000 --- a/catapult/third_party/oauth2client/oauth2client/file.py +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Utilities for OAuth. - -Utilities for making it easier to work with OAuth 2.0 -credentials. -""" - -__author__ = 'jcgregorio@google.com (Joe Gregorio)' - -import os -import threading - -from oauth2client.client import Credentials -from oauth2client.client import Storage as BaseStorage - - -class CredentialsFileSymbolicLinkError(Exception): - """Credentials files must not be symbolic links.""" - - -class Storage(BaseStorage): - """Store and retrieve a single credential to and from a file.""" - - def __init__(self, filename): - self._filename = filename - self._lock = threading.Lock() - - def _validate_file(self): - if os.path.islink(self._filename): - raise CredentialsFileSymbolicLinkError( - 'File: %s is a symbolic link.' % self._filename) - - def acquire_lock(self): - """Acquires any lock necessary to access this Storage. - - This lock is not reentrant.""" - self._lock.acquire() - - def release_lock(self): - """Release the Storage lock. - - Trying to release a lock that isn't held will result in a - RuntimeError. - """ - self._lock.release() - - def locked_get(self): - """Retrieve Credential from file. - - Returns: - oauth2client.client.Credentials - - Raises: - CredentialsFileSymbolicLinkError if the file is a symbolic link. - """ - credentials = None - self._validate_file() - try: - f = open(self._filename, 'rb') - content = f.read() - f.close() - except IOError: - return credentials - - try: - credentials = Credentials.new_from_json(content) - credentials.set_store(self) - except ValueError: - pass - - return credentials - - def _create_file_if_needed(self): - """Create an empty file if necessary. - - This method will not initialize the file. Instead it implements a - simple version of "touch" to ensure the file has been created. - """ - if not os.path.exists(self._filename): - old_umask = os.umask(0o177) - try: - open(self._filename, 'a+b').close() - finally: - os.umask(old_umask) - - def locked_put(self, credentials): - """Write Credentials to file. - - Args: - credentials: Credentials, the credentials to store. - - Raises: - CredentialsFileSymbolicLinkError if the file is a symbolic link. - """ - - self._create_file_if_needed() - self._validate_file() - f = open(self._filename, 'w') - f.write(credentials.to_json()) - f.close() - - def locked_delete(self): - """Delete Credentials file. - - Args: - credentials: Credentials, the credentials to store. - """ - - os.unlink(self._filename) diff --git a/catapult/third_party/oauth2client/oauth2client/gce.py b/catapult/third_party/oauth2client/oauth2client/gce.py deleted file mode 100644 index fc3bd77b..00000000 --- a/catapult/third_party/oauth2client/oauth2client/gce.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Utilities for Google Compute Engine - -Utilities for making it easier to use OAuth 2.0 on Google Compute Engine. -""" - -__author__ = 'jcgregorio@google.com (Joe Gregorio)' - -import json -import logging -from six.moves import urllib - -from oauth2client import util -from oauth2client.client import AccessTokenRefreshError -from oauth2client.client import AssertionCredentials - -logger = logging.getLogger(__name__) - -# URI Template for the endpoint that returns access_tokens. -META = ('http://metadata.google.internal/0.1/meta-data/service-accounts/' - 'default/acquire{?scope}') - - -class AppAssertionCredentials(AssertionCredentials): - """Credentials object for Compute Engine Assertion Grants - - This object will allow a Compute Engine instance to identify itself to - Google and other OAuth 2.0 servers that can verify assertions. It can be used - for the purpose of accessing data stored under an account assigned to the - Compute Engine instance itself. - - This credential does not require a flow to instantiate because it represents - a two legged flow, and therefore has all of the required information to - generate and refresh its own access tokens. - """ - - @util.positional(2) - def __init__(self, scope, **kwargs): - """Constructor for AppAssertionCredentials - - Args: - scope: string or iterable of strings, scope(s) of the credentials being - requested. - """ - self.scope = util.scopes_to_string(scope) - self.kwargs = kwargs - - # Assertion type is no longer used, but still in the parent class signature. - super(AppAssertionCredentials, self).__init__(None) - - @classmethod - def from_json(cls, json_data): - data = json.loads(json_data) - return AppAssertionCredentials(data['scope']) - - def _refresh(self, http_request): - """Refreshes the access_token. - - Skip all the storage hoops and just refresh using the API. - - Args: - http_request: callable, a callable that matches the method signature of - httplib2.Http.request, used to make the refresh request. - - Raises: - AccessTokenRefreshError: When the refresh fails. - """ - query = '?scope=%s' % urllib.parse.quote(self.scope, '') - uri = META.replace('{?scope}', query) - response, content = http_request(uri) - if response.status == 200: - try: - d = json.loads(content) - except Exception as e: - raise AccessTokenRefreshError(str(e)) - self.access_token = d['accessToken'] - else: - if response.status == 404: - content += (' This can occur if a VM was created' - ' with no service account or scopes.') - raise AccessTokenRefreshError(content) - - @property - def serialization_data(self): - raise NotImplementedError( - 'Cannot serialize credentials for GCE service accounts.') - - def create_scoped_required(self): - return not self.scope - - def create_scoped(self, scopes): - return AppAssertionCredentials(scopes, **self.kwargs) diff --git a/catapult/third_party/oauth2client/oauth2client/keyring_storage.py b/catapult/third_party/oauth2client/oauth2client/keyring_storage.py deleted file mode 100644 index cda1d9a3..00000000 --- a/catapult/third_party/oauth2client/oauth2client/keyring_storage.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A keyring based Storage. - -A Storage for Credentials that uses the keyring module. -""" - -__author__ = 'jcgregorio@google.com (Joe Gregorio)' - -import threading - -import keyring - -from oauth2client.client import Credentials -from oauth2client.client import Storage as BaseStorage - - -class Storage(BaseStorage): - """Store and retrieve a single credential to and from the keyring. - - To use this module you must have the keyring module installed. See - <http://pypi.python.org/pypi/keyring/>. This is an optional module and is not - installed with oauth2client by default because it does not work on all the - platforms that oauth2client supports, such as Google App Engine. - - The keyring module <http://pypi.python.org/pypi/keyring/> is a cross-platform - library for access the keyring capabilities of the local system. The user will - be prompted for their keyring password when this module is used, and the - manner in which the user is prompted will vary per platform. - - Usage: - from oauth2client.keyring_storage import Storage - - s = Storage('name_of_application', 'user1') - credentials = s.get() - - """ - - def __init__(self, service_name, user_name): - """Constructor. - - Args: - service_name: string, The name of the service under which the credentials - are stored. - user_name: string, The name of the user to store credentials for. - """ - self._service_name = service_name - self._user_name = user_name - self._lock = threading.Lock() - - def acquire_lock(self): - """Acquires any lock necessary to access this Storage. - - This lock is not reentrant.""" - self._lock.acquire() - - def release_lock(self): - """Release the Storage lock. - - Trying to release a lock that isn't held will result in a - RuntimeError. - """ - self._lock.release() - - def locked_get(self): - """Retrieve Credential from file. - - Returns: - oauth2client.client.Credentials - """ - credentials = None - content = keyring.get_password(self._service_name, self._user_name) - - if content is not None: - try: - credentials = Credentials.new_from_json(content) - credentials.set_store(self) - except ValueError: - pass - - return credentials - - def locked_put(self, credentials): - """Write Credentials to file. - - Args: - credentials: Credentials, the credentials to store. - """ - keyring.set_password(self._service_name, self._user_name, - credentials.to_json()) - - def locked_delete(self): - """Delete Credentials file. - - Args: - credentials: Credentials, the credentials to store. - """ - keyring.set_password(self._service_name, self._user_name, '') diff --git a/catapult/third_party/oauth2client/oauth2client/locked_file.py b/catapult/third_party/oauth2client/oauth2client/locked_file.py deleted file mode 100644 index af92398e..00000000 --- a/catapult/third_party/oauth2client/oauth2client/locked_file.py +++ /dev/null @@ -1,378 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Locked file interface that should work on Unix and Windows pythons. - -This module first tries to use fcntl locking to ensure serialized access -to a file, then falls back on a lock file if that is unavialable. - -Usage:: - - f = LockedFile('filename', 'r+b', 'rb') - f.open_and_lock() - if f.is_locked(): - print('Acquired filename with r+b mode') - f.file_handle().write('locked data') - else: - print('Acquired filename with rb mode') - f.unlock_and_close() - -""" - -from __future__ import print_function - -__author__ = 'cache@google.com (David T McWherter)' - -import errno -import logging -import os -import time - -from oauth2client import util - -logger = logging.getLogger(__name__) - - -class CredentialsFileSymbolicLinkError(Exception): - """Credentials files must not be symbolic links.""" - - -class AlreadyLockedException(Exception): - """Trying to lock a file that has already been locked by the LockedFile.""" - pass - - -def validate_file(filename): - if os.path.islink(filename): - raise CredentialsFileSymbolicLinkError( - 'File: %s is a symbolic link.' % filename) - -class _Opener(object): - """Base class for different locking primitives.""" - - def __init__(self, filename, mode, fallback_mode): - """Create an Opener. - - Args: - filename: string, The pathname of the file. - mode: string, The preferred mode to access the file with. - fallback_mode: string, The mode to use if locking fails. - """ - self._locked = False - self._filename = filename - self._mode = mode - self._fallback_mode = fallback_mode - self._fh = None - self._lock_fd = None - - def is_locked(self): - """Was the file locked.""" - return self._locked - - def file_handle(self): - """The file handle to the file. Valid only after opened.""" - return self._fh - - def filename(self): - """The filename that is being locked.""" - return self._filename - - def open_and_lock(self, timeout, delay): - """Open the file and lock it. - - Args: - timeout: float, How long to try to lock for. - delay: float, How long to wait between retries. - """ - pass - - def unlock_and_close(self): - """Unlock and close the file.""" - pass - - -class _PosixOpener(_Opener): - """Lock files using Posix advisory lock files.""" - - def open_and_lock(self, timeout, delay): - """Open the file and lock it. - - Tries to create a .lock file next to the file we're trying to open. - - Args: - timeout: float, How long to try to lock for. - delay: float, How long to wait between retries. - - Raises: - AlreadyLockedException: if the lock is already acquired. - IOError: if the open fails. - CredentialsFileSymbolicLinkError if the file is a symbolic link. - """ - if self._locked: - raise AlreadyLockedException('File %s is already locked' % - self._filename) - self._locked = False - - validate_file(self._filename) - try: - self._fh = open(self._filename, self._mode) - except IOError as e: - # If we can't access with _mode, try _fallback_mode and don't lock. - if e.errno == errno.EACCES: - self._fh = open(self._filename, self._fallback_mode) - return - - lock_filename = self._posix_lockfile(self._filename) - start_time = time.time() - while True: - try: - self._lock_fd = os.open(lock_filename, - os.O_CREAT|os.O_EXCL|os.O_RDWR) - self._locked = True - break - - except OSError as e: - if e.errno != errno.EEXIST: - raise - if (time.time() - start_time) >= timeout: - logger.warn('Could not acquire lock %s in %s seconds', - lock_filename, timeout) - # Close the file and open in fallback_mode. - if self._fh: - self._fh.close() - self._fh = open(self._filename, self._fallback_mode) - return - time.sleep(delay) - - def unlock_and_close(self): - """Unlock a file by removing the .lock file, and close the handle.""" - if self._locked: - lock_filename = self._posix_lockfile(self._filename) - os.close(self._lock_fd) - os.unlink(lock_filename) - self._locked = False - self._lock_fd = None - if self._fh: - self._fh.close() - - def _posix_lockfile(self, filename): - """The name of the lock file to use for posix locking.""" - return '%s.lock' % filename - - -try: - import fcntl - - class _FcntlOpener(_Opener): - """Open, lock, and unlock a file using fcntl.lockf.""" - - def open_and_lock(self, timeout, delay): - """Open the file and lock it. - - Args: - timeout: float, How long to try to lock for. - delay: float, How long to wait between retries - - Raises: - AlreadyLockedException: if the lock is already acquired. - IOError: if the open fails. - CredentialsFileSymbolicLinkError if the file is a symbolic link. - """ - if self._locked: - raise AlreadyLockedException('File %s is already locked' % - self._filename) - start_time = time.time() - - validate_file(self._filename) - try: - self._fh = open(self._filename, self._mode) - except IOError as e: - # If we can't access with _mode, try _fallback_mode and don't lock. - if e.errno in (errno.EPERM, errno.EACCES): - self._fh = open(self._filename, self._fallback_mode) - return - - # We opened in _mode, try to lock the file. - while True: - try: - fcntl.lockf(self._fh.fileno(), fcntl.LOCK_EX) - self._locked = True - return - except IOError as e: - # If not retrying, then just pass on the error. - if timeout == 0: - raise - if e.errno != errno.EACCES: - raise - # We could not acquire the lock. Try again. - if (time.time() - start_time) >= timeout: - logger.warn('Could not lock %s in %s seconds', - self._filename, timeout) - if self._fh: - self._fh.close() - self._fh = open(self._filename, self._fallback_mode) - return - time.sleep(delay) - - def unlock_and_close(self): - """Close and unlock the file using the fcntl.lockf primitive.""" - if self._locked: - fcntl.lockf(self._fh.fileno(), fcntl.LOCK_UN) - self._locked = False - if self._fh: - self._fh.close() -except ImportError: - _FcntlOpener = None - - -try: - import pywintypes - import win32con - import win32file - - class _Win32Opener(_Opener): - """Open, lock, and unlock a file using windows primitives.""" - - # Error #33: - # 'The process cannot access the file because another process' - FILE_IN_USE_ERROR = 33 - - # Error #158: - # 'The segment is already unlocked.' - FILE_ALREADY_UNLOCKED_ERROR = 158 - - def open_and_lock(self, timeout, delay): - """Open the file and lock it. - - Args: - timeout: float, How long to try to lock for. - delay: float, How long to wait between retries - - Raises: - AlreadyLockedException: if the lock is already acquired. - IOError: if the open fails. - CredentialsFileSymbolicLinkError if the file is a symbolic link. - """ - if self._locked: - raise AlreadyLockedException('File %s is already locked' % - self._filename) - start_time = time.time() - - validate_file(self._filename) - try: - self._fh = open(self._filename, self._mode) - except IOError as e: - # If we can't access with _mode, try _fallback_mode and don't lock. - if e.errno == errno.EACCES: - self._fh = open(self._filename, self._fallback_mode) - return - - # We opened in _mode, try to lock the file. - while True: - try: - hfile = win32file._get_osfhandle(self._fh.fileno()) - win32file.LockFileEx( - hfile, - (win32con.LOCKFILE_FAIL_IMMEDIATELY| - win32con.LOCKFILE_EXCLUSIVE_LOCK), 0, -0x10000, - pywintypes.OVERLAPPED()) - self._locked = True - return - except pywintypes.error as e: - if timeout == 0: - raise - - # If the error is not that the file is already in use, raise. - if e[0] != _Win32Opener.FILE_IN_USE_ERROR: - raise - - # We could not acquire the lock. Try again. - if (time.time() - start_time) >= timeout: - logger.warn('Could not lock %s in %s seconds' % ( - self._filename, timeout)) - if self._fh: - self._fh.close() - self._fh = open(self._filename, self._fallback_mode) - return - time.sleep(delay) - - def unlock_and_close(self): - """Close and unlock the file using the win32 primitive.""" - if self._locked: - try: - hfile = win32file._get_osfhandle(self._fh.fileno()) - win32file.UnlockFileEx(hfile, 0, -0x10000, pywintypes.OVERLAPPED()) - except pywintypes.error as e: - if e[0] != _Win32Opener.FILE_ALREADY_UNLOCKED_ERROR: - raise - self._locked = False - if self._fh: - self._fh.close() -except ImportError: - _Win32Opener = None - - -class LockedFile(object): - """Represent a file that has exclusive access.""" - - @util.positional(4) - def __init__(self, filename, mode, fallback_mode, use_native_locking=True): - """Construct a LockedFile. - - Args: - filename: string, The path of the file to open. - mode: string, The mode to try to open the file with. - fallback_mode: string, The mode to use if locking fails. - use_native_locking: bool, Whether or not fcntl/win32 locking is used. - """ - opener = None - if not opener and use_native_locking: - if _Win32Opener: - opener = _Win32Opener(filename, mode, fallback_mode) - if _FcntlOpener: - opener = _FcntlOpener(filename, mode, fallback_mode) - - if not opener: - opener = _PosixOpener(filename, mode, fallback_mode) - - self._opener = opener - - def filename(self): - """Return the filename we were constructed with.""" - return self._opener._filename - - def file_handle(self): - """Return the file_handle to the opened file.""" - return self._opener.file_handle() - - def is_locked(self): - """Return whether we successfully locked the file.""" - return self._opener.is_locked() - - def open_and_lock(self, timeout=0, delay=0.05): - """Open the file, trying to lock it. - - Args: - timeout: float, The number of seconds to try to acquire the lock. - delay: float, The number of seconds to wait between retry attempts. - - Raises: - AlreadyLockedException: if the lock is already acquired. - IOError: if the open fails. - """ - self._opener.open_and_lock(timeout, delay) - - def unlock_and_close(self): - """Unlock and close a file.""" - self._opener.unlock_and_close() diff --git a/catapult/third_party/oauth2client/oauth2client/multistore_file.py b/catapult/third_party/oauth2client/oauth2client/multistore_file.py deleted file mode 100644 index f4ba4a70..00000000 --- a/catapult/third_party/oauth2client/oauth2client/multistore_file.py +++ /dev/null @@ -1,475 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Multi-credential file store with lock support. - -This module implements a JSON credential store where multiple -credentials can be stored in one file. That file supports locking -both in a single process and across processes. - -The credential themselves are keyed off of: - -* client_id -* user_agent -* scope - -The format of the stored data is like so:: - - { - 'file_version': 1, - 'data': [ - { - 'key': { - 'clientId': '<client id>', - 'userAgent': '<user agent>', - 'scope': '<scope>' - }, - 'credential': { - # JSON serialized Credentials. - } - } - ] - } - -""" - -__author__ = 'jbeda@google.com (Joe Beda)' - -import errno -import json -import logging -import os -import threading - -from oauth2client.client import Credentials -from oauth2client.client import Storage as BaseStorage -from oauth2client import util -from oauth2client.locked_file import LockedFile - -logger = logging.getLogger(__name__) - -# A dict from 'filename'->_MultiStore instances -_multistores = {} -_multistores_lock = threading.Lock() - - -class Error(Exception): - """Base error for this module.""" - - -class NewerCredentialStoreError(Error): - """The credential store is a newer version than supported.""" - - -@util.positional(4) -def get_credential_storage(filename, client_id, user_agent, scope, - warn_on_readonly=True): - """Get a Storage instance for a credential. - - Args: - filename: The JSON file storing a set of credentials - client_id: The client_id for the credential - user_agent: The user agent for the credential - scope: string or iterable of strings, Scope(s) being requested - warn_on_readonly: if True, log a warning if the store is readonly - - Returns: - An object derived from client.Storage for getting/setting the - credential. - """ - # Recreate the legacy key with these specific parameters - key = {'clientId': client_id, 'userAgent': user_agent, - 'scope': util.scopes_to_string(scope)} - return get_credential_storage_custom_key( - filename, key, warn_on_readonly=warn_on_readonly) - - -@util.positional(2) -def get_credential_storage_custom_string_key( - filename, key_string, warn_on_readonly=True): - """Get a Storage instance for a credential using a single string as a key. - - Allows you to provide a string as a custom key that will be used for - credential storage and retrieval. - - Args: - filename: The JSON file storing a set of credentials - key_string: A string to use as the key for storing this credential. - warn_on_readonly: if True, log a warning if the store is readonly - - Returns: - An object derived from client.Storage for getting/setting the - credential. - """ - # Create a key dictionary that can be used - key_dict = {'key': key_string} - return get_credential_storage_custom_key( - filename, key_dict, warn_on_readonly=warn_on_readonly) - - -@util.positional(2) -def get_credential_storage_custom_key( - filename, key_dict, warn_on_readonly=True): - """Get a Storage instance for a credential using a dictionary as a key. - - Allows you to provide a dictionary as a custom key that will be used for - credential storage and retrieval. - - Args: - filename: The JSON file storing a set of credentials - key_dict: A dictionary to use as the key for storing this credential. There - is no ordering of the keys in the dictionary. Logically equivalent - dictionaries will produce equivalent storage keys. - warn_on_readonly: if True, log a warning if the store is readonly - - Returns: - An object derived from client.Storage for getting/setting the - credential. - """ - multistore = _get_multistore(filename, warn_on_readonly=warn_on_readonly) - key = util.dict_to_tuple_key(key_dict) - return multistore._get_storage(key) - - -@util.positional(1) -def get_all_credential_keys(filename, warn_on_readonly=True): - """Gets all the registered credential keys in the given Multistore. - - Args: - filename: The JSON file storing a set of credentials - warn_on_readonly: if True, log a warning if the store is readonly - - Returns: - A list of the credential keys present in the file. They are returned as - dictionaries that can be passed into get_credential_storage_custom_key to - get the actual credentials. - """ - multistore = _get_multistore(filename, warn_on_readonly=warn_on_readonly) - multistore._lock() - try: - return multistore._get_all_credential_keys() - finally: - multistore._unlock() - - -@util.positional(1) -def _get_multistore(filename, warn_on_readonly=True): - """A helper method to initialize the multistore with proper locking. - - Args: - filename: The JSON file storing a set of credentials - warn_on_readonly: if True, log a warning if the store is readonly - - Returns: - A multistore object - """ - filename = os.path.expanduser(filename) - _multistores_lock.acquire() - try: - multistore = _multistores.setdefault( - filename, _MultiStore(filename, warn_on_readonly=warn_on_readonly)) - finally: - _multistores_lock.release() - return multistore - - -class _MultiStore(object): - """A file backed store for multiple credentials.""" - - @util.positional(2) - def __init__(self, filename, warn_on_readonly=True): - """Initialize the class. - - This will create the file if necessary. - """ - self._file = LockedFile(filename, 'r+', 'r') - self._thread_lock = threading.Lock() - self._read_only = False - self._warn_on_readonly = warn_on_readonly - - self._create_file_if_needed() - - # Cache of deserialized store. This is only valid after the - # _MultiStore is locked or _refresh_data_cache is called. This is - # of the form of: - # - # ((key, value), (key, value)...) -> OAuth2Credential - # - # If this is None, then the store hasn't been read yet. - self._data = None - - class _Storage(BaseStorage): - """A Storage object that knows how to read/write a single credential.""" - - def __init__(self, multistore, key): - self._multistore = multistore - self._key = key - - def acquire_lock(self): - """Acquires any lock necessary to access this Storage. - - This lock is not reentrant. - """ - self._multistore._lock() - - def release_lock(self): - """Release the Storage lock. - - Trying to release a lock that isn't held will result in a - RuntimeError. - """ - self._multistore._unlock() - - def locked_get(self): - """Retrieve credential. - - The Storage lock must be held when this is called. - - Returns: - oauth2client.client.Credentials - """ - credential = self._multistore._get_credential(self._key) - if credential: - credential.set_store(self) - return credential - - def locked_put(self, credentials): - """Write a credential. - - The Storage lock must be held when this is called. - - Args: - credentials: Credentials, the credentials to store. - """ - self._multistore._update_credential(self._key, credentials) - - def locked_delete(self): - """Delete a credential. - - The Storage lock must be held when this is called. - - Args: - credentials: Credentials, the credentials to store. - """ - self._multistore._delete_credential(self._key) - - def _create_file_if_needed(self): - """Create an empty file if necessary. - - This method will not initialize the file. Instead it implements a - simple version of "touch" to ensure the file has been created. - """ - if not os.path.exists(self._file.filename()): - old_umask = os.umask(0o177) - try: - open(self._file.filename(), 'a+b').close() - finally: - os.umask(old_umask) - - def _lock(self): - """Lock the entire multistore.""" - self._thread_lock.acquire() - try: - self._file.open_and_lock() - except IOError as e: - if e.errno == errno.ENOSYS: - logger.warn('File system does not support locking the credentials ' - 'file.') - elif e.errno == errno.ENOLCK: - logger.warn('File system is out of resources for writing the ' - 'credentials file (is your disk full?).') - else: - raise - if not self._file.is_locked(): - self._read_only = True - if self._warn_on_readonly: - logger.warn('The credentials file (%s) is not writable. Opening in ' - 'read-only mode. Any refreshed credentials will only be ' - 'valid for this run.', self._file.filename()) - if os.path.getsize(self._file.filename()) == 0: - logger.debug('Initializing empty multistore file') - # The multistore is empty so write out an empty file. - self._data = {} - self._write() - elif not self._read_only or self._data is None: - # Only refresh the data if we are read/write or we haven't - # cached the data yet. If we are readonly, we assume is isn't - # changing out from under us and that we only have to read it - # once. This prevents us from whacking any new access keys that - # we have cached in memory but were unable to write out. - self._refresh_data_cache() - - def _unlock(self): - """Release the lock on the multistore.""" - self._file.unlock_and_close() - self._thread_lock.release() - - def _locked_json_read(self): - """Get the raw content of the multistore file. - - The multistore must be locked when this is called. - - Returns: - The contents of the multistore decoded as JSON. - """ - assert self._thread_lock.locked() - self._file.file_handle().seek(0) - return json.load(self._file.file_handle()) - - def _locked_json_write(self, data): - """Write a JSON serializable data structure to the multistore. - - The multistore must be locked when this is called. - - Args: - data: The data to be serialized and written. - """ - assert self._thread_lock.locked() - if self._read_only: - return - self._file.file_handle().seek(0) - json.dump(data, self._file.file_handle(), sort_keys=True, indent=2, separators=(',', ': ')) - self._file.file_handle().truncate() - - def _refresh_data_cache(self): - """Refresh the contents of the multistore. - - The multistore must be locked when this is called. - - Raises: - NewerCredentialStoreError: Raised when a newer client has written the - store. - """ - self._data = {} - try: - raw_data = self._locked_json_read() - except Exception: - logger.warn('Credential data store could not be loaded. ' - 'Will ignore and overwrite.') - return - - version = 0 - try: - version = raw_data['file_version'] - except Exception: - logger.warn('Missing version for credential data store. It may be ' - 'corrupt or an old version. Overwriting.') - if version > 1: - raise NewerCredentialStoreError( - 'Credential file has file_version of %d. ' - 'Only file_version of 1 is supported.' % version) - - credentials = [] - try: - credentials = raw_data['data'] - except (TypeError, KeyError): - pass - - for cred_entry in credentials: - try: - (key, credential) = self._decode_credential_from_json(cred_entry) - self._data[key] = credential - except: - # If something goes wrong loading a credential, just ignore it - logger.info('Error decoding credential, skipping', exc_info=True) - - def _decode_credential_from_json(self, cred_entry): - """Load a credential from our JSON serialization. - - Args: - cred_entry: A dict entry from the data member of our format - - Returns: - (key, cred) where the key is the key tuple and the cred is the - OAuth2Credential object. - """ - raw_key = cred_entry['key'] - key = util.dict_to_tuple_key(raw_key) - credential = None - credential = Credentials.new_from_json(json.dumps(cred_entry['credential'])) - return (key, credential) - - def _write(self): - """Write the cached data back out. - - The multistore must be locked. - """ - raw_data = {'file_version': 1} - raw_creds = [] - raw_data['data'] = raw_creds - for (cred_key, cred) in self._data.items(): - raw_key = dict(cred_key) - raw_cred = json.loads(cred.to_json()) - raw_creds.append({'key': raw_key, 'credential': raw_cred}) - self._locked_json_write(raw_data) - - def _get_all_credential_keys(self): - """Gets all the registered credential keys in the multistore. - - Returns: - A list of dictionaries corresponding to all the keys currently registered - """ - return [dict(key) for key in self._data.keys()] - - def _get_credential(self, key): - """Get a credential from the multistore. - - The multistore must be locked. - - Args: - key: The key used to retrieve the credential - - Returns: - The credential specified or None if not present - """ - return self._data.get(key, None) - - def _update_credential(self, key, cred): - """Update a credential and write the multistore. - - This must be called when the multistore is locked. - - Args: - key: The key used to retrieve the credential - cred: The OAuth2Credential to update/set - """ - self._data[key] = cred - self._write() - - def _delete_credential(self, key): - """Delete a credential and write the multistore. - - This must be called when the multistore is locked. - - Args: - key: The key used to retrieve the credential - """ - try: - del self._data[key] - except KeyError: - pass - self._write() - - def _get_storage(self, key): - """Get a Storage object to get/set a credential. - - This Storage is a 'view' into the multistore. - - Args: - key: The key used to retrieve the credential - - Returns: - A Storage object that can be used to get/set this cred - """ - return self._Storage(self, key) diff --git a/catapult/third_party/oauth2client/oauth2client/old_run.py b/catapult/third_party/oauth2client/oauth2client/old_run.py deleted file mode 100644 index 51db69b8..00000000 --- a/catapult/third_party/oauth2client/oauth2client/old_run.py +++ /dev/null @@ -1,161 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This module holds the old run() function which is deprecated, the -tools.run_flow() function should be used in its place.""" - -from __future__ import print_function - -import logging -import socket -import sys -import webbrowser - -import gflags -from six.moves import input - -from oauth2client import client -from oauth2client import util -from oauth2client.tools import ClientRedirectHandler -from oauth2client.tools import ClientRedirectServer - - -FLAGS = gflags.FLAGS - -gflags.DEFINE_boolean('auth_local_webserver', True, - ('Run a local web server to handle redirects during ' - 'OAuth authorization.')) - -gflags.DEFINE_string('auth_host_name', 'localhost', - ('Host name to use when running a local web server to ' - 'handle redirects during OAuth authorization.')) - -gflags.DEFINE_multi_int('auth_host_port', [8080, 8090], - ('Port to use when running a local web server to ' - 'handle redirects during OAuth authorization.')) - - -@util.positional(2) -def run(flow, storage, http=None): - """Core code for a command-line application. - - The ``run()`` function is called from your application and runs - through all the steps to obtain credentials. It takes a ``Flow`` - argument and attempts to open an authorization server page in the - user's default web browser. The server asks the user to grant your - application access to the user's data. If the user grants access, - the ``run()`` function returns new credentials. The new credentials - are also stored in the ``storage`` argument, which updates the file - associated with the ``Storage`` object. - - It presumes it is run from a command-line application and supports the - following flags: - - ``--auth_host_name`` (string, default: ``localhost``) - Host name to use when running a local web server to handle - redirects during OAuth authorization. - - ``--auth_host_port`` (integer, default: ``[8080, 8090]``) - Port to use when running a local web server to handle redirects - during OAuth authorization. Repeat this option to specify a list - of values. - - ``--[no]auth_local_webserver`` (boolean, default: ``True``) - Run a local web server to handle redirects during OAuth authorization. - - Since it uses flags make sure to initialize the ``gflags`` module before - calling ``run()``. - - Args: - flow: Flow, an OAuth 2.0 Flow to step through. - storage: Storage, a ``Storage`` to store the credential in. - http: An instance of ``httplib2.Http.request`` or something that acts - like it. - - Returns: - Credentials, the obtained credential. - """ - logging.warning('This function, oauth2client.tools.run(), and the use of ' - 'the gflags library are deprecated and will be removed in a future ' - 'version of the library.') - if FLAGS.auth_local_webserver: - success = False - port_number = 0 - for port in FLAGS.auth_host_port: - port_number = port - try: - httpd = ClientRedirectServer((FLAGS.auth_host_name, port), - ClientRedirectHandler) - except socket.error as e: - pass - else: - success = True - break - FLAGS.auth_local_webserver = success - if not success: - print('Failed to start a local webserver listening on either port 8080') - print('or port 9090. Please check your firewall settings and locally') - print('running programs that may be blocking or using those ports.') - print() - print('Falling back to --noauth_local_webserver and continuing with') - print('authorization.') - print() - - if FLAGS.auth_local_webserver: - oauth_callback = 'http://%s:%s/' % (FLAGS.auth_host_name, port_number) - else: - oauth_callback = client.OOB_CALLBACK_URN - flow.redirect_uri = oauth_callback - authorize_url = flow.step1_get_authorize_url() - - if FLAGS.auth_local_webserver: - webbrowser.open(authorize_url, new=1, autoraise=True) - print('Your browser has been opened to visit:') - print() - print(' ' + authorize_url) - print() - print('If your browser is on a different machine then exit and re-run') - print('this application with the command-line parameter ') - print() - print(' --noauth_local_webserver') - print() - else: - print('Go to the following link in your browser:') - print() - print(' ' + authorize_url) - print() - - code = None - if FLAGS.auth_local_webserver: - httpd.handle_request() - if 'error' in httpd.query_params: - sys.exit('Authentication request was rejected.') - if 'code' in httpd.query_params: - code = httpd.query_params['code'] - else: - print('Failed to find "code" in the query parameters of the redirect.') - sys.exit('Try running with --noauth_local_webserver.') - else: - code = input('Enter verification code: ').strip() - - try: - credential = flow.step2_exchange(code, http=http) - except client.FlowExchangeError as e: - sys.exit('Authentication has failed: %s' % e) - - storage.put(credential) - credential.set_store(storage) - print('Authentication successful.') - - return credential diff --git a/catapult/third_party/oauth2client/oauth2client/service_account.py b/catapult/third_party/oauth2client/oauth2client/service_account.py deleted file mode 100644 index d1d1d895..00000000 --- a/catapult/third_party/oauth2client/oauth2client/service_account.py +++ /dev/null @@ -1,139 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A service account credentials class. - -This credentials class is implemented on top of rsa library. -""" - -import base64 -import json -import six -import time - -from pyasn1.codec.ber import decoder -from pyasn1_modules.rfc5208 import PrivateKeyInfo -import rsa - -from oauth2client import GOOGLE_REVOKE_URI -from oauth2client import GOOGLE_TOKEN_URI -from oauth2client import util -from oauth2client.client import AssertionCredentials - - -class _ServiceAccountCredentials(AssertionCredentials): - """Class representing a service account (signed JWT) credential.""" - - MAX_TOKEN_LIFETIME_SECS = 3600 # 1 hour in seconds - - def __init__(self, service_account_id, service_account_email, private_key_id, - private_key_pkcs8_text, scopes, user_agent=None, - token_uri=GOOGLE_TOKEN_URI, revoke_uri=GOOGLE_REVOKE_URI, - **kwargs): - - super(_ServiceAccountCredentials, self).__init__( - None, user_agent=user_agent, token_uri=token_uri, revoke_uri=revoke_uri) - - self._service_account_id = service_account_id - self._service_account_email = service_account_email - self._private_key_id = private_key_id - self._private_key = _get_private_key(private_key_pkcs8_text) - self._private_key_pkcs8_text = private_key_pkcs8_text - self._scopes = util.scopes_to_string(scopes) - self._user_agent = user_agent - self._token_uri = token_uri - self._revoke_uri = revoke_uri - self._kwargs = kwargs - - def _generate_assertion(self): - """Generate the assertion that will be used in the request.""" - - header = { - 'alg': 'RS256', - 'typ': 'JWT', - 'kid': self._private_key_id - } - - now = int(time.time()) - payload = { - 'aud': self._token_uri, - 'scope': self._scopes, - 'iat': now, - 'exp': now + _ServiceAccountCredentials.MAX_TOKEN_LIFETIME_SECS, - 'iss': self._service_account_email - } - payload.update(self._kwargs) - - assertion_input = (_urlsafe_b64encode(header) + b'.' + - _urlsafe_b64encode(payload)) - - # Sign the assertion. - rsa_bytes = rsa.pkcs1.sign(assertion_input, self._private_key, 'SHA-256') - signature = base64.urlsafe_b64encode(rsa_bytes).rstrip(b'=') - - return assertion_input + b'.' + signature - - def sign_blob(self, blob): - # Ensure that it is bytes - try: - blob = blob.encode('utf-8') - except AttributeError: - pass - return (self._private_key_id, - rsa.pkcs1.sign(blob, self._private_key, 'SHA-256')) - - @property - def service_account_email(self): - return self._service_account_email - - @property - def serialization_data(self): - return { - 'type': 'service_account', - 'client_id': self._service_account_id, - 'client_email': self._service_account_email, - 'private_key_id': self._private_key_id, - 'private_key': self._private_key_pkcs8_text - } - - def create_scoped_required(self): - return not self._scopes - - def create_scoped(self, scopes): - return _ServiceAccountCredentials(self._service_account_id, - self._service_account_email, - self._private_key_id, - self._private_key_pkcs8_text, - scopes, - user_agent=self._user_agent, - token_uri=self._token_uri, - revoke_uri=self._revoke_uri, - **self._kwargs) - - -def _urlsafe_b64encode(data): - return base64.urlsafe_b64encode( - json.dumps(data, separators=(',', ':')).encode('UTF-8')).rstrip(b'=') - - -def _get_private_key(private_key_pkcs8_text): - """Get an RSA private key object from a pkcs8 representation.""" - - if not isinstance(private_key_pkcs8_text, six.binary_type): - private_key_pkcs8_text = private_key_pkcs8_text.encode('ascii') - der = rsa.pem.load_pem(private_key_pkcs8_text, 'PRIVATE KEY') - asn1_private_key, _ = decoder.decode(der, asn1Spec=PrivateKeyInfo()) - return rsa.PrivateKey.load_pkcs1( - asn1_private_key.getComponentByName('privateKey').asOctets(), - format='DER') diff --git a/catapult/third_party/oauth2client/oauth2client/tools.py b/catapult/third_party/oauth2client/oauth2client/tools.py deleted file mode 100644 index 2caa1342..00000000 --- a/catapult/third_party/oauth2client/oauth2client/tools.py +++ /dev/null @@ -1,249 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Command-line tools for authenticating via OAuth 2.0 - -Do the OAuth 2.0 Web Server dance for a command line application. Stores the -generated credentials in a common file that is used by other example apps in -the same directory. -""" - -from __future__ import print_function - -__author__ = 'jcgregorio@google.com (Joe Gregorio)' -__all__ = ['argparser', 'run_flow', 'run', 'message_if_missing'] - -import logging -import socket -import sys - -from six.moves import BaseHTTPServer -from six.moves import urllib -from six.moves import input - -from oauth2client import client -from oauth2client import util - - -_CLIENT_SECRETS_MESSAGE = """WARNING: Please configure OAuth 2.0 - -To make this sample run you will need to populate the client_secrets.json file -found at: - - %s - -with information from the APIs Console <https://code.google.com/apis/console>. - -""" - -def _CreateArgumentParser(): - try: - import argparse - except ImportError: - return None - parser = argparse.ArgumentParser(add_help=False) - parser.add_argument('--auth_host_name', default='localhost', - help='Hostname when running a local web server.') - parser.add_argument('--noauth_local_webserver', action='store_true', - default=False, help='Do not run a local web server.') - parser.add_argument('--auth_host_port', default=[8080, 8090], type=int, - nargs='*', help='Port web server should listen on.') - parser.add_argument('--logging_level', default='ERROR', - choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], - help='Set the logging level of detail.') - return parser - -# argparser is an ArgumentParser that contains command-line options expected -# by tools.run(). Pass it in as part of the 'parents' argument to your own -# ArgumentParser. -argparser = _CreateArgumentParser() - - -class ClientRedirectServer(BaseHTTPServer.HTTPServer): - """A server to handle OAuth 2.0 redirects back to localhost. - - Waits for a single request and parses the query parameters - into query_params and then stops serving. - """ - query_params = {} - - -class ClientRedirectHandler(BaseHTTPServer.BaseHTTPRequestHandler): - """A handler for OAuth 2.0 redirects back to localhost. - - Waits for a single request and parses the query parameters - into the servers query_params and then stops serving. - """ - - def do_GET(self): - """Handle a GET request. - - Parses the query parameters and prints a message - if the flow has completed. Note that we can't detect - if an error occurred. - """ - self.send_response(200) - self.send_header("Content-type", "text/html") - self.end_headers() - query = self.path.split('?', 1)[-1] - query = dict(urllib.parse.parse_qsl(query)) - self.server.query_params = query - self.wfile.write(b"<html><head><title>Authentication Status</title></head>") - self.wfile.write(b"<body><p>The authentication flow has completed.</p>") - self.wfile.write(b"</body></html>") - - def log_message(self, format, *args): - """Do not log messages to stdout while running as command line program.""" - - -@util.positional(3) -def run_flow(flow, storage, flags, http=None): - """Core code for a command-line application. - - The ``run()`` function is called from your application and runs - through all the steps to obtain credentials. It takes a ``Flow`` - argument and attempts to open an authorization server page in the - user's default web browser. The server asks the user to grant your - application access to the user's data. If the user grants access, - the ``run()`` function returns new credentials. The new credentials - are also stored in the ``storage`` argument, which updates the file - associated with the ``Storage`` object. - - It presumes it is run from a command-line application and supports the - following flags: - - ``--auth_host_name`` (string, default: ``localhost``) - Host name to use when running a local web server to handle - redirects during OAuth authorization. - - ``--auth_host_port`` (integer, default: ``[8080, 8090]``) - Port to use when running a local web server to handle redirects - during OAuth authorization. Repeat this option to specify a list - of values. - - ``--[no]auth_local_webserver`` (boolean, default: ``True``) - Run a local web server to handle redirects during OAuth authorization. - - - - - The tools module defines an ``ArgumentParser`` the already contains the flag - definitions that ``run()`` requires. You can pass that ``ArgumentParser`` to your - ``ArgumentParser`` constructor:: - - parser = argparse.ArgumentParser(description=__doc__, - formatter_class=argparse.RawDescriptionHelpFormatter, - parents=[tools.argparser]) - flags = parser.parse_args(argv) - - Args: - flow: Flow, an OAuth 2.0 Flow to step through. - storage: Storage, a ``Storage`` to store the credential in. - flags: ``argparse.Namespace``, The command-line flags. This is the - object returned from calling ``parse_args()`` on - ``argparse.ArgumentParser`` as described above. - http: An instance of ``httplib2.Http.request`` or something that - acts like it. - - Returns: - Credentials, the obtained credential. - """ - logging.getLogger().setLevel(getattr(logging, flags.logging_level)) - if not flags.noauth_local_webserver: - success = False - port_number = 0 - for port in flags.auth_host_port: - port_number = port - try: - httpd = ClientRedirectServer((flags.auth_host_name, port), - ClientRedirectHandler) - except socket.error: - pass - else: - success = True - break - flags.noauth_local_webserver = not success - if not success: - print('Failed to start a local webserver listening on either port 8080') - print('or port 9090. Please check your firewall settings and locally') - print('running programs that may be blocking or using those ports.') - print() - print('Falling back to --noauth_local_webserver and continuing with') - print('authorization.') - print() - - if not flags.noauth_local_webserver: - oauth_callback = 'http://%s:%s/' % (flags.auth_host_name, port_number) - else: - oauth_callback = client.OOB_CALLBACK_URN - flow.redirect_uri = oauth_callback - authorize_url = flow.step1_get_authorize_url() - - if not flags.noauth_local_webserver: - import webbrowser - webbrowser.open(authorize_url, new=1, autoraise=True) - print('Your browser has been opened to visit:') - print() - print(' ' + authorize_url) - print() - print('If your browser is on a different machine then exit and re-run this') - print('application with the command-line parameter ') - print() - print(' --noauth_local_webserver') - print() - else: - print('Go to the following link in your browser:') - print() - print(' ' + authorize_url) - print() - - code = None - if not flags.noauth_local_webserver: - httpd.handle_request() - if 'error' in httpd.query_params: - sys.exit('Authentication request was rejected.') - if 'code' in httpd.query_params: - code = httpd.query_params['code'] - else: - print('Failed to find "code" in the query parameters of the redirect.') - sys.exit('Try running with --noauth_local_webserver.') - else: - code = input('Enter verification code: ').strip() - - try: - credential = flow.step2_exchange(code, http=http) - except client.FlowExchangeError as e: - sys.exit('Authentication has failed: %s' % e) - - storage.put(credential) - credential.set_store(storage) - print('Authentication successful.') - - return credential - - -def message_if_missing(filename): - """Helpful message to display if the CLIENT_SECRETS file is missing.""" - - return _CLIENT_SECRETS_MESSAGE % filename - -try: - from oauth2client.old_run import run - from oauth2client.old_run import FLAGS -except ImportError: - def run(*args, **kwargs): - raise NotImplementedError( - 'The gflags library must be installed to use tools.run(). ' - 'Please install gflags or preferrably switch to using ' - 'tools.run_flow().') diff --git a/catapult/third_party/oauth2client/oauth2client/util.py b/catapult/third_party/oauth2client/oauth2client/util.py deleted file mode 100644 index a706f026..00000000 --- a/catapult/third_party/oauth2client/oauth2client/util.py +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -"""Common utility library.""" - -__author__ = [ - 'rafek@google.com (Rafe Kaplan)', - 'guido@google.com (Guido van Rossum)', -] - -__all__ = [ - 'positional', - 'POSITIONAL_WARNING', - 'POSITIONAL_EXCEPTION', - 'POSITIONAL_IGNORE', -] - -import functools -import inspect -import logging -import sys -import types - -import six -from six.moves import urllib - - -logger = logging.getLogger(__name__) - -POSITIONAL_WARNING = 'WARNING' -POSITIONAL_EXCEPTION = 'EXCEPTION' -POSITIONAL_IGNORE = 'IGNORE' -POSITIONAL_SET = frozenset([POSITIONAL_WARNING, POSITIONAL_EXCEPTION, - POSITIONAL_IGNORE]) - -positional_parameters_enforcement = POSITIONAL_WARNING - -def positional(max_positional_args): - """A decorator to declare that only the first N arguments my be positional. - - This decorator makes it easy to support Python 3 style keyword-only - parameters. For example, in Python 3 it is possible to write:: - - def fn(pos1, *, kwonly1=None, kwonly1=None): - ... - - All named parameters after ``*`` must be a keyword:: - - fn(10, 'kw1', 'kw2') # Raises exception. - fn(10, kwonly1='kw1') # Ok. - - Example - ^^^^^^^ - - To define a function like above, do:: - - @positional(1) - def fn(pos1, kwonly1=None, kwonly2=None): - ... - - If no default value is provided to a keyword argument, it becomes a required - keyword argument:: - - @positional(0) - def fn(required_kw): - ... - - This must be called with the keyword parameter:: - - fn() # Raises exception. - fn(10) # Raises exception. - fn(required_kw=10) # Ok. - - When defining instance or class methods always remember to account for - ``self`` and ``cls``:: - - class MyClass(object): - - @positional(2) - def my_method(self, pos1, kwonly1=None): - ... - - @classmethod - @positional(2) - def my_method(cls, pos1, kwonly1=None): - ... - - The positional decorator behavior is controlled by - ``util.positional_parameters_enforcement``, which may be set to - ``POSITIONAL_EXCEPTION``, ``POSITIONAL_WARNING`` or - ``POSITIONAL_IGNORE`` to raise an exception, log a warning, or do - nothing, respectively, if a declaration is violated. - - Args: - max_positional_arguments: Maximum number of positional arguments. All - parameters after the this index must be keyword only. - - Returns: - A decorator that prevents using arguments after max_positional_args from - being used as positional parameters. - - Raises: - TypeError if a key-word only argument is provided as a positional - parameter, but only if util.positional_parameters_enforcement is set to - POSITIONAL_EXCEPTION. - - """ - def positional_decorator(wrapped): - @functools.wraps(wrapped) - def positional_wrapper(*args, **kwargs): - if len(args) > max_positional_args: - plural_s = '' - if max_positional_args != 1: - plural_s = 's' - message = '%s() takes at most %d positional argument%s (%d given)' % ( - wrapped.__name__, max_positional_args, plural_s, len(args)) - if positional_parameters_enforcement == POSITIONAL_EXCEPTION: - raise TypeError(message) - elif positional_parameters_enforcement == POSITIONAL_WARNING: - logger.warning(message) - else: # IGNORE - pass - return wrapped(*args, **kwargs) - return positional_wrapper - - if isinstance(max_positional_args, six.integer_types): - return positional_decorator - else: - args, _, _, defaults = inspect.getargspec(max_positional_args) - return positional(len(args) - len(defaults))(max_positional_args) - - -def scopes_to_string(scopes): - """Converts scope value to a string. - - If scopes is a string then it is simply passed through. If scopes is an - iterable then a string is returned that is all the individual scopes - concatenated with spaces. - - Args: - scopes: string or iterable of strings, the scopes. - - Returns: - The scopes formatted as a single string. - """ - if isinstance(scopes, six.string_types): - return scopes - else: - return ' '.join(scopes) - - -def dict_to_tuple_key(dictionary): - """Converts a dictionary to a tuple that can be used as an immutable key. - - The resulting key is always sorted so that logically equivalent dictionaries - always produce an identical tuple for a key. - - Args: - dictionary: the dictionary to use as the key. - - Returns: - A tuple representing the dictionary in it's naturally sorted ordering. - """ - return tuple(sorted(dictionary.items())) - - -def _add_query_parameter(url, name, value): - """Adds a query parameter to a url. - - Replaces the current value if it already exists in the URL. - - Args: - url: string, url to add the query parameter to. - name: string, query parameter name. - value: string, query parameter value. - - Returns: - Updated query parameter. Does not update the url if value is None. - """ - if value is None: - return url - else: - parsed = list(urllib.parse.urlparse(url)) - q = dict(urllib.parse.parse_qsl(parsed[4])) - q[name] = value - parsed[4] = urllib.parse.urlencode(q) - return urllib.parse.urlunparse(parsed) diff --git a/catapult/third_party/oauth2client/oauth2client/xsrfutil.py b/catapult/third_party/oauth2client/oauth2client/xsrfutil.py deleted file mode 100644 index 5739dcf5..00000000 --- a/catapult/third_party/oauth2client/oauth2client/xsrfutil.py +++ /dev/null @@ -1,118 +0,0 @@ -# -# Copyright 2014 the Melange authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helper methods for creating & verifying XSRF tokens.""" - -__authors__ = [ - '"Doug Coker" <dcoker@google.com>', - '"Joe Gregorio" <jcgregorio@google.com>', -] - - -import base64 -import hmac -import time - -import six -from oauth2client import util - - -# Delimiter character -DELIMITER = b':' - - -# 1 hour in seconds -DEFAULT_TIMEOUT_SECS = 1*60*60 - - -def _force_bytes(s): - if isinstance(s, bytes): - return s - s = str(s) - if isinstance(s, six.text_type): - return s.encode('utf-8') - return s - - -@util.positional(2) -def generate_token(key, user_id, action_id="", when=None): - """Generates a URL-safe token for the given user, action, time tuple. - - Args: - key: secret key to use. - user_id: the user ID of the authenticated user. - action_id: a string identifier of the action they requested - authorization for. - when: the time in seconds since the epoch at which the user was - authorized for this action. If not set the current time is used. - - Returns: - A string XSRF protection token. - """ - when = _force_bytes(when or int(time.time())) - digester = hmac.new(_force_bytes(key)) - digester.update(_force_bytes(user_id)) - digester.update(DELIMITER) - digester.update(_force_bytes(action_id)) - digester.update(DELIMITER) - digester.update(when) - digest = digester.digest() - - token = base64.urlsafe_b64encode(digest + DELIMITER + when) - return token - - -@util.positional(3) -def validate_token(key, token, user_id, action_id="", current_time=None): - """Validates that the given token authorizes the user for the action. - - Tokens are invalid if the time of issue is too old or if the token - does not match what generateToken outputs (i.e. the token was forged). - - Args: - key: secret key to use. - token: a string of the token generated by generateToken. - user_id: the user ID of the authenticated user. - action_id: a string identifier of the action they requested - authorization for. - - Returns: - A boolean - True if the user is authorized for the action, False - otherwise. - """ - if not token: - return False - try: - decoded = base64.urlsafe_b64decode(token) - token_time = int(decoded.split(DELIMITER)[-1]) - except (TypeError, ValueError): - return False - if current_time is None: - current_time = time.time() - # If the token is too old it's not valid. - if current_time - token_time > DEFAULT_TIMEOUT_SECS: - return False - - # The given token should match the generated one with the same time. - expected_token = generate_token(key, user_id, action_id=action_id, - when=token_time) - if len(token) != len(expected_token): - return False - - # Perform constant time comparison to avoid timing attacks - different = 0 - for x, y in zip(bytearray(token), bytearray(expected_token)): - different |= x ^ y - return not different diff --git a/catapult/tracing/README.md b/catapult/tracing/README.md index 4e2531cb..9721badf 100644 --- a/catapult/tracing/README.md +++ b/catapult/tracing/README.md @@ -10,11 +10,11 @@ systrace](http://developer.android.com/tools/help/systrace.html). It provides rich analysis and visualization capabilities for many types of trace files. Its particularly good at viewing linux kernel traces (aka [ftrace](https://www.kernel.org/doc/Documentation/trace/ftrace.txt)) and Chrome's -[trace_event format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview). Trace viewer can be [embedded](https://github.com/google/trace-viewer/wiki/Embedding) as a component in your own code, or used from a plain checkout to turn trace files into standalone, emailable HTML files from the commandline: +[trace_event format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview). Trace viewer can be [embedded](https://github.com/catapult-project/catapult/wiki/Embedding-Trace-Viewer) as a component in your own code, or used from a plain checkout to turn trace files into standalone, emailable HTML files from the commandline: ./tracing/trace2html my_trace.json --output=my_trace.html && open my_trace.html -Its easy to [extend trace viewer](https://github.com/google/trace-viewer/wiki/ExtendingAndCustomizing) to support your favorite trace format, or add domain specific visualizations to the UI to simplify drilling down into complex data. +Its easy to [extend trace viewer](https://github.com/catapult-project/catapult/wiki/Extending-and-Customizing-Trace-Viewer) to support your favorite trace format, or add domain specific visualizations to the UI to simplify drilling down into complex data. Contributing, quick version =========================================================================== @@ -34,11 +34,9 @@ To run all the unittests, you can also do: ./tracing/run_tests -Make sure tests pass before sending us changelist. **We use rietveld for codereview**. For more details, esp on rietveld, [read our contributing guide](https://github.com/google/trace-viewer/wiki/Contributing) or check out the [trace viewer wiki](https://github.com/google/trace-viewer/wiki). +Make sure tests pass before sending us changelist. **We use rietveld for codereview**. For more details, esp on rietveld, [read our contributing guide](https://github.com/catapult-project/catapult/blob/master/CONTRIBUTING.md) or check out the [trace viewer wiki](https://github.com/catapult-project/catapult/wiki/Trace-Viewer-Getting-Started). Contact Us =========================================================================== -Join our Google Groups: -* [trace-viewer](https://groups.google.com/forum/#!forum/trace-viewer) -* [trace-viewer-bugs](https://groups.google.com/forum/#!forum/trace-viewer-bugs) -* [tracing@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/tracing) (for c++ backend code)
\ No newline at end of file +Join our Google Group: +* [tracing@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/tracing) diff --git a/catapult/tracing/bin/index.html b/catapult/tracing/bin/index.html index 82c1435c..892e57a7 100644 --- a/catapult/tracing/bin/index.html +++ b/catapult/tracing/bin/index.html @@ -71,7 +71,8 @@ function onTraceViewerImportFail() { function onResult(result) { model = new tr.Model(); - var p = model.importTracesWithProgressDialog([result], true); + var i = new tr.importer.Import(m); + var p = i.importTracesWithProgressDialog([result]); p.then(onModelLoaded, onImportFail); } diff --git a/catapult/tracing/bin/run_dev_server_tests b/catapult/tracing/bin/run_dev_server_tests index f61e0e2e..1e973950 100755 --- a/catapult/tracing/bin/run_dev_server_tests +++ b/catapult/tracing/bin/run_dev_server_tests @@ -10,5 +10,5 @@ if __name__ == '__main__': catapult_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) sys.path.append(catapult_path) - from build import run_dev_server_tests + from catapult_build import run_dev_server_tests sys.exit(run_dev_server_tests.Main(sys.argv + ['--tests=tracing'])) diff --git a/catapult/tracing/bin/run_tests b/catapult/tracing/bin/run_tests index cf87e9c0..a1bbf158 100755 --- a/catapult/tracing/bin/run_tests +++ b/catapult/tracing/bin/run_tests @@ -21,5 +21,5 @@ if __name__ == '__main__': catapult_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) sys.path.append(catapult_path) - from build import test_runner + from catapult_build import test_runner sys.exit(test_runner.Main('tracing', _TESTS, sys.argv)) diff --git a/catapult/tracing/third_party/tvcm/third_party/beautifulsoup/BeautifulSoup.py b/catapult/tracing/third_party/tvcm/third_party/beautifulsoup/BeautifulSoup.py deleted file mode 100644 index 4b17b853..00000000 --- a/catapult/tracing/third_party/tvcm/third_party/beautifulsoup/BeautifulSoup.py +++ /dev/null @@ -1,2014 +0,0 @@ -"""Beautiful Soup -Elixir and Tonic -"The Screen-Scraper's Friend" -http://www.crummy.com/software/BeautifulSoup/ - -Beautiful Soup parses a (possibly invalid) XML or HTML document into a -tree representation. It provides methods and Pythonic idioms that make -it easy to navigate, search, and modify the tree. - -A well-formed XML/HTML document yields a well-formed data -structure. An ill-formed XML/HTML document yields a correspondingly -ill-formed data structure. If your document is only locally -well-formed, you can use this library to find and process the -well-formed part of it. - -Beautiful Soup works with Python 2.2 and up. It has no external -dependencies, but you'll have more success at converting data to UTF-8 -if you also install these three packages: - -* chardet, for auto-detecting character encodings - http://chardet.feedparser.org/ -* cjkcodecs and iconv_codec, which add more encodings to the ones supported - by stock Python. - http://cjkpython.i18n.org/ - -Beautiful Soup defines classes for two main parsing strategies: - - * BeautifulStoneSoup, for parsing XML, SGML, or your domain-specific - language that kind of looks like XML. - - * BeautifulSoup, for parsing run-of-the-mill HTML code, be it valid - or invalid. This class has web browser-like heuristics for - obtaining a sensible parse tree in the face of common HTML errors. - -Beautiful Soup also defines a class (UnicodeDammit) for autodetecting -the encoding of an HTML or XML document, and converting it to -Unicode. Much of this code is taken from Mark Pilgrim's Universal Feed Parser. - -For more than you ever wanted to know about Beautiful Soup, see the -documentation: -http://www.crummy.com/software/BeautifulSoup/documentation.html - -Here, have some legalese: - -Copyright (c) 2004-2010, Leonard Richardson - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - * Neither the name of the the Beautiful Soup Consortium and All - Night Kosher Bakery nor the names of its contributors may be - used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE, DAMMIT. - -""" -from __future__ import generators - -__author__ = "Leonard Richardson (leonardr@segfault.org)" -__version__ = "3.2.0" -__copyright__ = "Copyright (c) 2004-2010 Leonard Richardson" -__license__ = "New-style BSD" - -from sgmllib import SGMLParser, SGMLParseError -import codecs -import markupbase -import types -import re -import sgmllib -try: - from htmlentitydefs import name2codepoint -except ImportError: - name2codepoint = {} -try: - set -except NameError: - from sets import Set as set - -#These hacks make Beautiful Soup able to parse XML with namespaces -sgmllib.tagfind = re.compile('[a-zA-Z][-_.:a-zA-Z0-9]*') -markupbase._declname_match = re.compile(r'[a-zA-Z][-_.:a-zA-Z0-9]*\s*').match - -DEFAULT_OUTPUT_ENCODING = "utf-8" - -def _match_css_class(str): - """Build a RE to match the given CSS class.""" - return re.compile(r"(^|.*\s)%s($|\s)" % str) - -# First, the classes that represent markup elements. - -class PageElement(object): - """Contains the navigational information for some part of the page - (either a tag or a piece of text)""" - - def setup(self, parent=None, previous=None): - """Sets up the initial relations between this element and - other elements.""" - self.parent = parent - self.previous = previous - self.next = None - self.previousSibling = None - self.nextSibling = None - if self.parent and self.parent.contents: - self.previousSibling = self.parent.contents[-1] - self.previousSibling.nextSibling = self - - def replaceWith(self, replaceWith): - oldParent = self.parent - myIndex = self.parent.index(self) - if hasattr(replaceWith, "parent")\ - and replaceWith.parent is self.parent: - # We're replacing this element with one of its siblings. - index = replaceWith.parent.index(replaceWith) - if index and index < myIndex: - # Furthermore, it comes before this element. That - # means that when we extract it, the index of this - # element will change. - myIndex = myIndex - 1 - self.extract() - oldParent.insert(myIndex, replaceWith) - - def replaceWithChildren(self): - myParent = self.parent - myIndex = self.parent.index(self) - self.extract() - reversedChildren = list(self.contents) - reversedChildren.reverse() - for child in reversedChildren: - myParent.insert(myIndex, child) - - def extract(self): - """Destructively rips this element out of the tree.""" - if self.parent: - try: - del self.parent.contents[self.parent.index(self)] - except ValueError: - pass - - #Find the two elements that would be next to each other if - #this element (and any children) hadn't been parsed. Connect - #the two. - lastChild = self._lastRecursiveChild() - nextElement = lastChild.next - - if self.previous: - self.previous.next = nextElement - if nextElement: - nextElement.previous = self.previous - self.previous = None - lastChild.next = None - - self.parent = None - if self.previousSibling: - self.previousSibling.nextSibling = self.nextSibling - if self.nextSibling: - self.nextSibling.previousSibling = self.previousSibling - self.previousSibling = self.nextSibling = None - return self - - def _lastRecursiveChild(self): - "Finds the last element beneath this object to be parsed." - lastChild = self - while hasattr(lastChild, 'contents') and lastChild.contents: - lastChild = lastChild.contents[-1] - return lastChild - - def insert(self, position, newChild): - if isinstance(newChild, basestring) \ - and not isinstance(newChild, NavigableString): - newChild = NavigableString(newChild) - - position = min(position, len(self.contents)) - if hasattr(newChild, 'parent') and newChild.parent is not None: - # We're 'inserting' an element that's already one - # of this object's children. - if newChild.parent is self: - index = self.index(newChild) - if index > position: - # Furthermore we're moving it further down the - # list of this object's children. That means that - # when we extract this element, our target index - # will jump down one. - position = position - 1 - newChild.extract() - - newChild.parent = self - previousChild = None - if position == 0: - newChild.previousSibling = None - newChild.previous = self - else: - previousChild = self.contents[position-1] - newChild.previousSibling = previousChild - newChild.previousSibling.nextSibling = newChild - newChild.previous = previousChild._lastRecursiveChild() - if newChild.previous: - newChild.previous.next = newChild - - newChildsLastElement = newChild._lastRecursiveChild() - - if position >= len(self.contents): - newChild.nextSibling = None - - parent = self - parentsNextSibling = None - while not parentsNextSibling: - parentsNextSibling = parent.nextSibling - parent = parent.parent - if not parent: # This is the last element in the document. - break - if parentsNextSibling: - newChildsLastElement.next = parentsNextSibling - else: - newChildsLastElement.next = None - else: - nextChild = self.contents[position] - newChild.nextSibling = nextChild - if newChild.nextSibling: - newChild.nextSibling.previousSibling = newChild - newChildsLastElement.next = nextChild - - if newChildsLastElement.next: - newChildsLastElement.next.previous = newChildsLastElement - self.contents.insert(position, newChild) - - def append(self, tag): - """Appends the given tag to the contents of this tag.""" - self.insert(len(self.contents), tag) - - def findNext(self, name=None, attrs={}, text=None, **kwargs): - """Returns the first item that matches the given criteria and - appears after this Tag in the document.""" - return self._findOne(self.findAllNext, name, attrs, text, **kwargs) - - def findAllNext(self, name=None, attrs={}, text=None, limit=None, - **kwargs): - """Returns all items that match the given criteria and appear - after this Tag in the document.""" - return self._findAll(name, attrs, text, limit, self.nextGenerator, - **kwargs) - - def findNextSibling(self, name=None, attrs={}, text=None, **kwargs): - """Returns the closest sibling to this Tag that matches the - given criteria and appears after this Tag in the document.""" - return self._findOne(self.findNextSiblings, name, attrs, text, - **kwargs) - - def findNextSiblings(self, name=None, attrs={}, text=None, limit=None, - **kwargs): - """Returns the siblings of this Tag that match the given - criteria and appear after this Tag in the document.""" - return self._findAll(name, attrs, text, limit, - self.nextSiblingGenerator, **kwargs) - fetchNextSiblings = findNextSiblings # Compatibility with pre-3.x - - def findPrevious(self, name=None, attrs={}, text=None, **kwargs): - """Returns the first item that matches the given criteria and - appears before this Tag in the document.""" - return self._findOne(self.findAllPrevious, name, attrs, text, **kwargs) - - def findAllPrevious(self, name=None, attrs={}, text=None, limit=None, - **kwargs): - """Returns all items that match the given criteria and appear - before this Tag in the document.""" - return self._findAll(name, attrs, text, limit, self.previousGenerator, - **kwargs) - fetchPrevious = findAllPrevious # Compatibility with pre-3.x - - def findPreviousSibling(self, name=None, attrs={}, text=None, **kwargs): - """Returns the closest sibling to this Tag that matches the - given criteria and appears before this Tag in the document.""" - return self._findOne(self.findPreviousSiblings, name, attrs, text, - **kwargs) - - def findPreviousSiblings(self, name=None, attrs={}, text=None, - limit=None, **kwargs): - """Returns the siblings of this Tag that match the given - criteria and appear before this Tag in the document.""" - return self._findAll(name, attrs, text, limit, - self.previousSiblingGenerator, **kwargs) - fetchPreviousSiblings = findPreviousSiblings # Compatibility with pre-3.x - - def findParent(self, name=None, attrs={}, **kwargs): - """Returns the closest parent of this Tag that matches the given - criteria.""" - # NOTE: We can't use _findOne because findParents takes a different - # set of arguments. - r = None - l = self.findParents(name, attrs, 1) - if l: - r = l[0] - return r - - def findParents(self, name=None, attrs={}, limit=None, **kwargs): - """Returns the parents of this Tag that match the given - criteria.""" - - return self._findAll(name, attrs, None, limit, self.parentGenerator, - **kwargs) - fetchParents = findParents # Compatibility with pre-3.x - - #These methods do the real heavy lifting. - - def _findOne(self, method, name, attrs, text, **kwargs): - r = None - l = method(name, attrs, text, 1, **kwargs) - if l: - r = l[0] - return r - - def _findAll(self, name, attrs, text, limit, generator, **kwargs): - "Iterates over a generator looking for things that match." - - if isinstance(name, SoupStrainer): - strainer = name - # (Possibly) special case some findAll*(...) searches - elif text is None and not limit and not attrs and not kwargs: - # findAll*(True) - if name is True: - return [element for element in generator() - if isinstance(element, Tag)] - # findAll*('tag-name') - elif isinstance(name, basestring): - return [element for element in generator() - if isinstance(element, Tag) and - element.name == name] - else: - strainer = SoupStrainer(name, attrs, text, **kwargs) - # Build a SoupStrainer - else: - strainer = SoupStrainer(name, attrs, text, **kwargs) - results = ResultSet(strainer) - g = generator() - while True: - try: - i = g.next() - except StopIteration: - break - if i: - found = strainer.search(i) - if found: - results.append(found) - if limit and len(results) >= limit: - break - return results - - #These Generators can be used to navigate starting from both - #NavigableStrings and Tags. - def nextGenerator(self): - i = self - while i is not None: - i = i.next - yield i - - def nextSiblingGenerator(self): - i = self - while i is not None: - i = i.nextSibling - yield i - - def previousGenerator(self): - i = self - while i is not None: - i = i.previous - yield i - - def previousSiblingGenerator(self): - i = self - while i is not None: - i = i.previousSibling - yield i - - def parentGenerator(self): - i = self - while i is not None: - i = i.parent - yield i - - # Utility methods - def substituteEncoding(self, str, encoding=None): - encoding = encoding or "utf-8" - return str.replace("%SOUP-ENCODING%", encoding) - - def toEncoding(self, s, encoding=None): - """Encodes an object to a string in some encoding, or to Unicode. - .""" - if isinstance(s, unicode): - if encoding: - s = s.encode(encoding) - elif isinstance(s, str): - if encoding: - s = s.encode(encoding) - else: - s = unicode(s) - else: - if encoding: - s = self.toEncoding(str(s), encoding) - else: - s = unicode(s) - return s - -class NavigableString(unicode, PageElement): - - def __new__(cls, value): - """Create a new NavigableString. - - When unpickling a NavigableString, this method is called with - the string in DEFAULT_OUTPUT_ENCODING. That encoding needs to be - passed in to the superclass's __new__ or the superclass won't know - how to handle non-ASCII characters. - """ - if isinstance(value, unicode): - return unicode.__new__(cls, value) - return unicode.__new__(cls, value, DEFAULT_OUTPUT_ENCODING) - - def __getnewargs__(self): - return (NavigableString.__str__(self),) - - def __getattr__(self, attr): - """text.string gives you text. This is for backwards - compatibility for Navigable*String, but for CData* it lets you - get the string without the CData wrapper.""" - if attr == 'string': - return self - else: - raise AttributeError, "'%s' object has no attribute '%s'" % (self.__class__.__name__, attr) - - def __unicode__(self): - return str(self).decode(DEFAULT_OUTPUT_ENCODING) - - def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): - if encoding: - return self.encode(encoding) - else: - return self - -class CData(NavigableString): - - def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): - return "<![CDATA[%s]]>" % NavigableString.__str__(self, encoding) - -class ProcessingInstruction(NavigableString): - def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): - output = self - if "%SOUP-ENCODING%" in output: - output = self.substituteEncoding(output, encoding) - return "<?%s?>" % self.toEncoding(output, encoding) - -class Comment(NavigableString): - def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): - return "<!--%s-->" % NavigableString.__str__(self, encoding) - -class Declaration(NavigableString): - def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): - return "<!%s>" % NavigableString.__str__(self, encoding) - -class Tag(PageElement): - - """Represents a found HTML tag with its attributes and contents.""" - - def _invert(h): - "Cheap function to invert a hash." - i = {} - for k,v in h.items(): - i[v] = k - return i - - XML_ENTITIES_TO_SPECIAL_CHARS = { "apos" : "'", - "quot" : '"', - "amp" : "&", - "lt" : "<", - "gt" : ">" } - - XML_SPECIAL_CHARS_TO_ENTITIES = _invert(XML_ENTITIES_TO_SPECIAL_CHARS) - - def _convertEntities(self, match): - """Used in a call to re.sub to replace HTML, XML, and numeric - entities with the appropriate Unicode characters. If HTML - entities are being converted, any unrecognized entities are - escaped.""" - x = match.group(1) - if self.convertHTMLEntities and x in name2codepoint: - return unichr(name2codepoint[x]) - elif x in self.XML_ENTITIES_TO_SPECIAL_CHARS: - if self.convertXMLEntities: - return self.XML_ENTITIES_TO_SPECIAL_CHARS[x] - else: - return u'&%s;' % x - elif len(x) > 0 and x[0] == '#': - # Handle numeric entities - if len(x) > 1 and x[1] == 'x': - return unichr(int(x[2:], 16)) - else: - return unichr(int(x[1:])) - - elif self.escapeUnrecognizedEntities: - return u'&%s;' % x - else: - return u'&%s;' % x - - def __init__(self, parser, name, attrs=None, parent=None, - previous=None): - "Basic constructor." - - # We don't actually store the parser object: that lets extracted - # chunks be garbage-collected - self.parserClass = parser.__class__ - self.isSelfClosing = parser.isSelfClosingTag(name) - self.name = name - if attrs is None: - attrs = [] - elif isinstance(attrs, dict): - attrs = attrs.items() - self.attrs = attrs - self.contents = [] - self.setup(parent, previous) - self.hidden = False - self.containsSubstitutions = False - self.convertHTMLEntities = parser.convertHTMLEntities - self.convertXMLEntities = parser.convertXMLEntities - self.escapeUnrecognizedEntities = parser.escapeUnrecognizedEntities - - # Convert any HTML, XML, or numeric entities in the attribute values. - convert = lambda(k, val): (k, - re.sub("&(#\d+|#x[0-9a-fA-F]+|\w+);", - self._convertEntities, - val)) - self.attrs = map(convert, self.attrs) - - def getString(self): - if (len(self.contents) == 1 - and isinstance(self.contents[0], NavigableString)): - return self.contents[0] - - def setString(self, string): - """Replace the contents of the tag with a string""" - self.clear() - self.append(string) - - string = property(getString, setString) - - def getText(self, separator=u""): - if not len(self.contents): - return u"" - stopNode = self._lastRecursiveChild().next - strings = [] - current = self.contents[0] - while current is not stopNode: - if isinstance(current, NavigableString): - strings.append(current.strip()) - current = current.next - return separator.join(strings) - - text = property(getText) - - def get(self, key, default=None): - """Returns the value of the 'key' attribute for the tag, or - the value given for 'default' if it doesn't have that - attribute.""" - return self._getAttrMap().get(key, default) - - def clear(self): - """Extract all children.""" - for child in self.contents[:]: - child.extract() - - def index(self, element): - for i, child in enumerate(self.contents): - if child is element: - return i - raise ValueError("Tag.index: element not in tag") - - def has_key(self, key): - return self._getAttrMap().has_key(key) - - def __getitem__(self, key): - """tag[key] returns the value of the 'key' attribute for the tag, - and throws an exception if it's not there.""" - return self._getAttrMap()[key] - - def __iter__(self): - "Iterating over a tag iterates over its contents." - return iter(self.contents) - - def __len__(self): - "The length of a tag is the length of its list of contents." - return len(self.contents) - - def __contains__(self, x): - return x in self.contents - - def __nonzero__(self): - "A tag is non-None even if it has no contents." - return True - - def __setitem__(self, key, value): - """Setting tag[key] sets the value of the 'key' attribute for the - tag.""" - self._getAttrMap() - self.attrMap[key] = value - found = False - for i in range(0, len(self.attrs)): - if self.attrs[i][0] == key: - self.attrs[i] = (key, value) - found = True - if not found: - self.attrs.append((key, value)) - self._getAttrMap()[key] = value - - def __delitem__(self, key): - "Deleting tag[key] deletes all 'key' attributes for the tag." - for item in self.attrs: - if item[0] == key: - self.attrs.remove(item) - #We don't break because bad HTML can define the same - #attribute multiple times. - self._getAttrMap() - if self.attrMap.has_key(key): - del self.attrMap[key] - - def __call__(self, *args, **kwargs): - """Calling a tag like a function is the same as calling its - findAll() method. Eg. tag('a') returns a list of all the A tags - found within this tag.""" - return apply(self.findAll, args, kwargs) - - def __getattr__(self, tag): - #print "Getattr %s.%s" % (self.__class__, tag) - if len(tag) > 3 and tag.rfind('Tag') == len(tag)-3: - return self.find(tag[:-3]) - elif tag.find('__') != 0: - return self.find(tag) - raise AttributeError, "'%s' object has no attribute '%s'" % (self.__class__, tag) - - def __eq__(self, other): - """Returns true iff this tag has the same name, the same attributes, - and the same contents (recursively) as the given tag. - - NOTE: right now this will return false if two tags have the - same attributes in a different order. Should this be fixed?""" - if other is self: - return True - if not hasattr(other, 'name') or not hasattr(other, 'attrs') or not hasattr(other, 'contents') or self.name != other.name or self.attrs != other.attrs or len(self) != len(other): - return False - for i in range(0, len(self.contents)): - if self.contents[i] != other.contents[i]: - return False - return True - - def __ne__(self, other): - """Returns true iff this tag is not identical to the other tag, - as defined in __eq__.""" - return not self == other - - def __repr__(self, encoding=DEFAULT_OUTPUT_ENCODING): - """Renders this tag as a string.""" - return self.__str__(encoding) - - def __unicode__(self): - return self.__str__(None) - - BARE_AMPERSAND_OR_BRACKET = re.compile("([<>]|" - + "&(?!#\d+;|#x[0-9a-fA-F]+;|\w+;)" - + ")") - - def _sub_entity(self, x): - """Used with a regular expression to substitute the - appropriate XML entity for an XML special character.""" - return "&" + self.XML_SPECIAL_CHARS_TO_ENTITIES[x.group(0)[0]] + ";" - - def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING, - prettyPrint=False, indentLevel=0): - """Returns a string or Unicode representation of this tag and - its contents. To get Unicode, pass None for encoding. - - NOTE: since Python's HTML parser consumes whitespace, this - method is not certain to reproduce the whitespace present in - the original string.""" - - encodedName = self.toEncoding(self.name, encoding) - - attrs = [] - if self.attrs: - for key, val in self.attrs: - fmt = '%s="%s"' - if isinstance(val, basestring): - if self.containsSubstitutions and '%SOUP-ENCODING%' in val: - val = self.substituteEncoding(val, encoding) - - # The attribute value either: - # - # * Contains no embedded double quotes or single quotes. - # No problem: we enclose it in double quotes. - # * Contains embedded single quotes. No problem: - # double quotes work here too. - # * Contains embedded double quotes. No problem: - # we enclose it in single quotes. - # * Embeds both single _and_ double quotes. This - # can't happen naturally, but it can happen if - # you modify an attribute value after parsing - # the document. Now we have a bit of a - # problem. We solve it by enclosing the - # attribute in single quotes, and escaping any - # embedded single quotes to XML entities. - if '"' in val: - fmt = "%s='%s'" - if "'" in val: - # TODO: replace with apos when - # appropriate. - val = val.replace("'", "&squot;") - - # Now we're okay w/r/t quotes. But the attribute - # value might also contain angle brackets, or - # ampersands that aren't part of entities. We need - # to escape those to XML entities too. - val = self.BARE_AMPERSAND_OR_BRACKET.sub(self._sub_entity, val) - - attrs.append(fmt % (self.toEncoding(key, encoding), - self.toEncoding(val, encoding))) - close = '' - closeTag = '' - if self.isSelfClosing: - close = ' /' - else: - closeTag = '</%s>' % encodedName - - indentTag, indentContents = 0, 0 - if prettyPrint: - indentTag = indentLevel - space = (' ' * (indentTag-1)) - indentContents = indentTag + 1 - contents = self.renderContents(encoding, prettyPrint, indentContents) - if self.hidden: - s = contents - else: - s = [] - attributeString = '' - if attrs: - attributeString = ' ' + ' '.join(attrs) - if prettyPrint: - s.append(space) - s.append('<%s%s%s>' % (encodedName, attributeString, close)) - if prettyPrint: - s.append("\n") - s.append(contents) - if prettyPrint and contents and contents[-1] != "\n": - s.append("\n") - if prettyPrint and closeTag: - s.append(space) - s.append(closeTag) - if prettyPrint and closeTag and self.nextSibling: - s.append("\n") - s = ''.join(s) - return s - - def decompose(self): - """Recursively destroys the contents of this tree.""" - self.extract() - if len(self.contents) == 0: - return - current = self.contents[0] - while current is not None: - next = current.next - if isinstance(current, Tag): - del current.contents[:] - current.parent = None - current.previous = None - current.previousSibling = None - current.next = None - current.nextSibling = None - current = next - - def prettify(self, encoding=DEFAULT_OUTPUT_ENCODING): - return self.__str__(encoding, True) - - def renderContents(self, encoding=DEFAULT_OUTPUT_ENCODING, - prettyPrint=False, indentLevel=0): - """Renders the contents of this tag as a string in the given - encoding. If encoding is None, returns a Unicode string..""" - s=[] - for c in self: - text = None - if isinstance(c, NavigableString): - text = c.__str__(encoding) - elif isinstance(c, Tag): - s.append(c.__str__(encoding, prettyPrint, indentLevel)) - if text and prettyPrint: - text = text.strip() - if text: - if prettyPrint: - s.append(" " * (indentLevel-1)) - s.append(text) - if prettyPrint: - s.append("\n") - return ''.join(s) - - #Soup methods - - def find(self, name=None, attrs={}, recursive=True, text=None, - **kwargs): - """Return only the first child of this Tag matching the given - criteria.""" - r = None - l = self.findAll(name, attrs, recursive, text, 1, **kwargs) - if l: - r = l[0] - return r - findChild = find - - def findAll(self, name=None, attrs={}, recursive=True, text=None, - limit=None, **kwargs): - """Extracts a list of Tag objects that match the given - criteria. You can specify the name of the Tag and any - attributes you want the Tag to have. - - The value of a key-value pair in the 'attrs' map can be a - string, a list of strings, a regular expression object, or a - callable that takes a string and returns whether or not the - string matches for some custom definition of 'matches'. The - same is true of the tag name.""" - generator = self.recursiveChildGenerator - if not recursive: - generator = self.childGenerator - return self._findAll(name, attrs, text, limit, generator, **kwargs) - findChildren = findAll - - # Pre-3.x compatibility methods - first = find - fetch = findAll - - def fetchText(self, text=None, recursive=True, limit=None): - return self.findAll(text=text, recursive=recursive, limit=limit) - - def firstText(self, text=None, recursive=True): - return self.find(text=text, recursive=recursive) - - #Private methods - - def _getAttrMap(self): - """Initializes a map representation of this tag's attributes, - if not already initialized.""" - if not getattr(self, 'attrMap'): - self.attrMap = {} - for (key, value) in self.attrs: - self.attrMap[key] = value - return self.attrMap - - #Generator methods - def childGenerator(self): - # Just use the iterator from the contents - return iter(self.contents) - - def recursiveChildGenerator(self): - if not len(self.contents): - raise StopIteration - stopNode = self._lastRecursiveChild().next - current = self.contents[0] - while current is not stopNode: - yield current - current = current.next - - -# Next, a couple classes to represent queries and their results. -class SoupStrainer: - """Encapsulates a number of ways of matching a markup element (tag or - text).""" - - def __init__(self, name=None, attrs={}, text=None, **kwargs): - self.name = name - if isinstance(attrs, basestring): - kwargs['class'] = _match_css_class(attrs) - attrs = None - if kwargs: - if attrs: - attrs = attrs.copy() - attrs.update(kwargs) - else: - attrs = kwargs - self.attrs = attrs - self.text = text - - def __str__(self): - if self.text: - return self.text - else: - return "%s|%s" % (self.name, self.attrs) - - def searchTag(self, markupName=None, markupAttrs={}): - found = None - markup = None - if isinstance(markupName, Tag): - markup = markupName - markupAttrs = markup - callFunctionWithTagData = callable(self.name) \ - and not isinstance(markupName, Tag) - - if (not self.name) \ - or callFunctionWithTagData \ - or (markup and self._matches(markup, self.name)) \ - or (not markup and self._matches(markupName, self.name)): - if callFunctionWithTagData: - match = self.name(markupName, markupAttrs) - else: - match = True - markupAttrMap = None - for attr, matchAgainst in self.attrs.items(): - if not markupAttrMap: - if hasattr(markupAttrs, 'get'): - markupAttrMap = markupAttrs - else: - markupAttrMap = {} - for k,v in markupAttrs: - markupAttrMap[k] = v - attrValue = markupAttrMap.get(attr) - if not self._matches(attrValue, matchAgainst): - match = False - break - if match: - if markup: - found = markup - else: - found = markupName - return found - - def search(self, markup): - #print 'looking for %s in %s' % (self, markup) - found = None - # If given a list of items, scan it for a text element that - # matches. - if hasattr(markup, "__iter__") \ - and not isinstance(markup, Tag): - for element in markup: - if isinstance(element, NavigableString) \ - and self.search(element): - found = element - break - # If it's a Tag, make sure its name or attributes match. - # Don't bother with Tags if we're searching for text. - elif isinstance(markup, Tag): - if not self.text: - found = self.searchTag(markup) - # If it's text, make sure the text matches. - elif isinstance(markup, NavigableString) or \ - isinstance(markup, basestring): - if self._matches(markup, self.text): - found = markup - else: - raise Exception, "I don't know how to match against a %s" \ - % markup.__class__ - return found - - def _matches(self, markup, matchAgainst): - #print "Matching %s against %s" % (markup, matchAgainst) - result = False - if matchAgainst is True: - result = markup is not None - elif callable(matchAgainst): - result = matchAgainst(markup) - else: - #Custom match methods take the tag as an argument, but all - #other ways of matching match the tag name as a string. - if isinstance(markup, Tag): - markup = markup.name - if markup and not isinstance(markup, basestring): - markup = unicode(markup) - #Now we know that chunk is either a string, or None. - if hasattr(matchAgainst, 'match'): - # It's a regexp object. - result = markup and matchAgainst.search(markup) - elif hasattr(matchAgainst, '__iter__'): # list-like - result = markup in matchAgainst - elif hasattr(matchAgainst, 'items'): - result = markup.has_key(matchAgainst) - elif matchAgainst and isinstance(markup, basestring): - if isinstance(markup, unicode): - matchAgainst = unicode(matchAgainst) - else: - matchAgainst = str(matchAgainst) - - if not result: - result = matchAgainst == markup - return result - -class ResultSet(list): - """A ResultSet is just a list that keeps track of the SoupStrainer - that created it.""" - def __init__(self, source): - list.__init__([]) - self.source = source - -# Now, some helper functions. - -def buildTagMap(default, *args): - """Turns a list of maps, lists, or scalars into a single map. - Used to build the SELF_CLOSING_TAGS, NESTABLE_TAGS, and - NESTING_RESET_TAGS maps out of lists and partial maps.""" - built = {} - for portion in args: - if hasattr(portion, 'items'): - #It's a map. Merge it. - for k,v in portion.items(): - built[k] = v - elif hasattr(portion, '__iter__'): # is a list - #It's a list. Map each item to the default. - for k in portion: - built[k] = default - else: - #It's a scalar. Map it to the default. - built[portion] = default - return built - -# Now, the parser classes. - -class BeautifulStoneSoup(Tag, SGMLParser): - - """This class contains the basic parser and search code. It defines - a parser that knows nothing about tag behavior except for the - following: - - You can't close a tag without closing all the tags it encloses. - That is, "<foo><bar></foo>" actually means - "<foo><bar></bar></foo>". - - [Another possible explanation is "<foo><bar /></foo>", but since - this class defines no SELF_CLOSING_TAGS, it will never use that - explanation.] - - This class is useful for parsing XML or made-up markup languages, - or when BeautifulSoup makes an assumption counter to what you were - expecting.""" - - SELF_CLOSING_TAGS = {} - NESTABLE_TAGS = {} - RESET_NESTING_TAGS = {} - QUOTE_TAGS = {} - PRESERVE_WHITESPACE_TAGS = [] - - MARKUP_MASSAGE = [(re.compile('(<[^<>]*)/>'), - lambda x: x.group(1) + ' />'), - (re.compile('<!\s+([^<>]*)>'), - lambda x: '<!' + x.group(1) + '>') - ] - - ROOT_TAG_NAME = u'[document]' - - HTML_ENTITIES = "html" - XML_ENTITIES = "xml" - XHTML_ENTITIES = "xhtml" - # TODO: This only exists for backwards-compatibility - ALL_ENTITIES = XHTML_ENTITIES - - # Used when determining whether a text node is all whitespace and - # can be replaced with a single space. A text node that contains - # fancy Unicode spaces (usually non-breaking) should be left - # alone. - STRIP_ASCII_SPACES = { 9: None, 10: None, 12: None, 13: None, 32: None, } - - def __init__(self, markup="", parseOnlyThese=None, fromEncoding=None, - markupMassage=True, smartQuotesTo=XML_ENTITIES, - convertEntities=None, selfClosingTags=None, isHTML=False): - """The Soup object is initialized as the 'root tag', and the - provided markup (which can be a string or a file-like object) - is fed into the underlying parser. - - sgmllib will process most bad HTML, and the BeautifulSoup - class has some tricks for dealing with some HTML that kills - sgmllib, but Beautiful Soup can nonetheless choke or lose data - if your data uses self-closing tags or declarations - incorrectly. - - By default, Beautiful Soup uses regexes to sanitize input, - avoiding the vast majority of these problems. If the problems - don't apply to you, pass in False for markupMassage, and - you'll get better performance. - - The default parser massage techniques fix the two most common - instances of invalid HTML that choke sgmllib: - - <br/> (No space between name of closing tag and tag close) - <! --Comment--> (Extraneous whitespace in declaration) - - You can pass in a custom list of (RE object, replace method) - tuples to get Beautiful Soup to scrub your input the way you - want.""" - - self.parseOnlyThese = parseOnlyThese - self.fromEncoding = fromEncoding - self.smartQuotesTo = smartQuotesTo - self.convertEntities = convertEntities - # Set the rules for how we'll deal with the entities we - # encounter - if self.convertEntities: - # It doesn't make sense to convert encoded characters to - # entities even while you're converting entities to Unicode. - # Just convert it all to Unicode. - self.smartQuotesTo = None - if convertEntities == self.HTML_ENTITIES: - self.convertXMLEntities = False - self.convertHTMLEntities = True - self.escapeUnrecognizedEntities = True - elif convertEntities == self.XHTML_ENTITIES: - self.convertXMLEntities = True - self.convertHTMLEntities = True - self.escapeUnrecognizedEntities = False - elif convertEntities == self.XML_ENTITIES: - self.convertXMLEntities = True - self.convertHTMLEntities = False - self.escapeUnrecognizedEntities = False - else: - self.convertXMLEntities = False - self.convertHTMLEntities = False - self.escapeUnrecognizedEntities = False - - self.instanceSelfClosingTags = buildTagMap(None, selfClosingTags) - SGMLParser.__init__(self) - - if hasattr(markup, 'read'): # It's a file-type object. - markup = markup.read() - self.markup = markup - self.markupMassage = markupMassage - try: - self._feed(isHTML=isHTML) - except StopParsing: - pass - self.markup = None # The markup can now be GCed - - def convert_charref(self, name): - """This method fixes a bug in Python's SGMLParser.""" - try: - n = int(name) - except ValueError: - return - if not 0 <= n <= 127 : # ASCII ends at 127, not 255 - return - return self.convert_codepoint(n) - - def _feed(self, inDocumentEncoding=None, isHTML=False): - # Convert the document to Unicode. - markup = self.markup - if isinstance(markup, unicode): - if not hasattr(self, 'originalEncoding'): - self.originalEncoding = None - else: - dammit = UnicodeDammit\ - (markup, [self.fromEncoding, inDocumentEncoding], - smartQuotesTo=self.smartQuotesTo, isHTML=isHTML) - markup = dammit.unicode - self.originalEncoding = dammit.originalEncoding - self.declaredHTMLEncoding = dammit.declaredHTMLEncoding - if markup: - if self.markupMassage: - if not hasattr(self.markupMassage, "__iter__"): - self.markupMassage = self.MARKUP_MASSAGE - for fix, m in self.markupMassage: - markup = fix.sub(m, markup) - # TODO: We get rid of markupMassage so that the - # soup object can be deepcopied later on. Some - # Python installations can't copy regexes. If anyone - # was relying on the existence of markupMassage, this - # might cause problems. - del(self.markupMassage) - self.reset() - - SGMLParser.feed(self, markup) - # Close out any unfinished strings and close all the open tags. - self.endData() - while self.currentTag.name != self.ROOT_TAG_NAME: - self.popTag() - - def __getattr__(self, methodName): - """This method routes method call requests to either the SGMLParser - superclass or the Tag superclass, depending on the method name.""" - #print "__getattr__ called on %s.%s" % (self.__class__, methodName) - - if methodName.startswith('start_') or methodName.startswith('end_') \ - or methodName.startswith('do_'): - return SGMLParser.__getattr__(self, methodName) - elif not methodName.startswith('__'): - return Tag.__getattr__(self, methodName) - else: - raise AttributeError - - def isSelfClosingTag(self, name): - """Returns true iff the given string is the name of a - self-closing tag according to this parser.""" - return self.SELF_CLOSING_TAGS.has_key(name) \ - or self.instanceSelfClosingTags.has_key(name) - - def reset(self): - Tag.__init__(self, self, self.ROOT_TAG_NAME) - self.hidden = 1 - SGMLParser.reset(self) - self.currentData = [] - self.currentTag = None - self.tagStack = [] - self.quoteStack = [] - self.pushTag(self) - - def popTag(self): - tag = self.tagStack.pop() - - #print "Pop", tag.name - if self.tagStack: - self.currentTag = self.tagStack[-1] - return self.currentTag - - def pushTag(self, tag): - #print "Push", tag.name - if self.currentTag: - self.currentTag.contents.append(tag) - self.tagStack.append(tag) - self.currentTag = self.tagStack[-1] - - def endData(self, containerClass=NavigableString): - if self.currentData: - currentData = u''.join(self.currentData) - if (currentData.translate(self.STRIP_ASCII_SPACES) == '' and - not set([tag.name for tag in self.tagStack]).intersection( - self.PRESERVE_WHITESPACE_TAGS)): - if '\n' in currentData: - currentData = '\n' - else: - currentData = ' ' - self.currentData = [] - if self.parseOnlyThese and len(self.tagStack) <= 1 and \ - (not self.parseOnlyThese.text or \ - not self.parseOnlyThese.search(currentData)): - return - o = containerClass(currentData) - o.setup(self.currentTag, self.previous) - if self.previous: - self.previous.next = o - self.previous = o - self.currentTag.contents.append(o) - - - def _popToTag(self, name, inclusivePop=True): - """Pops the tag stack up to and including the most recent - instance of the given tag. If inclusivePop is false, pops the tag - stack up to but *not* including the most recent instqance of - the given tag.""" - #print "Popping to %s" % name - if name == self.ROOT_TAG_NAME: - return - - numPops = 0 - mostRecentTag = None - for i in range(len(self.tagStack)-1, 0, -1): - if name == self.tagStack[i].name: - numPops = len(self.tagStack)-i - break - if not inclusivePop: - numPops = numPops - 1 - - for i in range(0, numPops): - mostRecentTag = self.popTag() - return mostRecentTag - - def _smartPop(self, name): - - """We need to pop up to the previous tag of this type, unless - one of this tag's nesting reset triggers comes between this - tag and the previous tag of this type, OR unless this tag is a - generic nesting trigger and another generic nesting trigger - comes between this tag and the previous tag of this type. - - Examples: - <p>Foo<b>Bar *<p>* should pop to 'p', not 'b'. - <p>Foo<table>Bar *<p>* should pop to 'table', not 'p'. - <p>Foo<table><tr>Bar *<p>* should pop to 'tr', not 'p'. - - <li><ul><li> *<li>* should pop to 'ul', not the first 'li'. - <tr><table><tr> *<tr>* should pop to 'table', not the first 'tr' - <td><tr><td> *<td>* should pop to 'tr', not the first 'td' - """ - - nestingResetTriggers = self.NESTABLE_TAGS.get(name) - isNestable = nestingResetTriggers != None - isResetNesting = self.RESET_NESTING_TAGS.has_key(name) - popTo = None - inclusive = True - for i in range(len(self.tagStack)-1, 0, -1): - p = self.tagStack[i] - if (not p or p.name == name) and not isNestable: - #Non-nestable tags get popped to the top or to their - #last occurance. - popTo = name - break - if (nestingResetTriggers is not None - and p.name in nestingResetTriggers) \ - or (nestingResetTriggers is None and isResetNesting - and self.RESET_NESTING_TAGS.has_key(p.name)): - - #If we encounter one of the nesting reset triggers - #peculiar to this tag, or we encounter another tag - #that causes nesting to reset, pop up to but not - #including that tag. - popTo = p.name - inclusive = False - break - p = p.parent - if popTo: - self._popToTag(popTo, inclusive) - - def unknown_starttag(self, name, attrs, selfClosing=0): - #print "Start tag %s: %s" % (name, attrs) - if self.quoteStack: - #This is not a real tag. - #print "<%s> is not real!" % name - attrs = ''.join([' %s="%s"' % (x, y) for x, y in attrs]) - self.handle_data('<%s%s>' % (name, attrs)) - return - self.endData() - - if not self.isSelfClosingTag(name) and not selfClosing: - self._smartPop(name) - - if self.parseOnlyThese and len(self.tagStack) <= 1 \ - and (self.parseOnlyThese.text or not self.parseOnlyThese.searchTag(name, attrs)): - return - - tag = Tag(self, name, attrs, self.currentTag, self.previous) - if self.previous: - self.previous.next = tag - self.previous = tag - self.pushTag(tag) - if selfClosing or self.isSelfClosingTag(name): - self.popTag() - if name in self.QUOTE_TAGS: - #print "Beginning quote (%s)" % name - self.quoteStack.append(name) - self.literal = 1 - return tag - - def unknown_endtag(self, name): - #print "End tag %s" % name - if self.quoteStack and self.quoteStack[-1] != name: - #This is not a real end tag. - #print "</%s> is not real!" % name - self.handle_data('</%s>' % name) - return - self.endData() - self._popToTag(name) - if self.quoteStack and self.quoteStack[-1] == name: - self.quoteStack.pop() - self.literal = (len(self.quoteStack) > 0) - - def handle_data(self, data): - self.currentData.append(data) - - def _toStringSubclass(self, text, subclass): - """Adds a certain piece of text to the tree as a NavigableString - subclass.""" - self.endData() - self.handle_data(text) - self.endData(subclass) - - def handle_pi(self, text): - """Handle a processing instruction as a ProcessingInstruction - object, possibly one with a %SOUP-ENCODING% slot into which an - encoding will be plugged later.""" - if text[:3] == "xml": - text = u"xml version='1.0' encoding='%SOUP-ENCODING%'" - self._toStringSubclass(text, ProcessingInstruction) - - def handle_comment(self, text): - "Handle comments as Comment objects." - self._toStringSubclass(text, Comment) - - def handle_charref(self, ref): - "Handle character references as data." - if self.convertEntities: - data = unichr(int(ref)) - else: - data = '&#%s;' % ref - self.handle_data(data) - - def handle_entityref(self, ref): - """Handle entity references as data, possibly converting known - HTML and/or XML entity references to the corresponding Unicode - characters.""" - data = None - if self.convertHTMLEntities: - try: - data = unichr(name2codepoint[ref]) - except KeyError: - pass - - if not data and self.convertXMLEntities: - data = self.XML_ENTITIES_TO_SPECIAL_CHARS.get(ref) - - if not data and self.convertHTMLEntities and \ - not self.XML_ENTITIES_TO_SPECIAL_CHARS.get(ref): - # TODO: We've got a problem here. We're told this is - # an entity reference, but it's not an XML entity - # reference or an HTML entity reference. Nonetheless, - # the logical thing to do is to pass it through as an - # unrecognized entity reference. - # - # Except: when the input is "&carol;" this function - # will be called with input "carol". When the input is - # "AT&T", this function will be called with input - # "T". We have no way of knowing whether a semicolon - # was present originally, so we don't know whether - # this is an unknown entity or just a misplaced - # ampersand. - # - # The more common case is a misplaced ampersand, so I - # escape the ampersand and omit the trailing semicolon. - data = "&%s" % ref - if not data: - # This case is different from the one above, because we - # haven't already gone through a supposedly comprehensive - # mapping of entities to Unicode characters. We might not - # have gone through any mapping at all. So the chances are - # very high that this is a real entity, and not a - # misplaced ampersand. - data = "&%s;" % ref - self.handle_data(data) - - def handle_decl(self, data): - "Handle DOCTYPEs and the like as Declaration objects." - self._toStringSubclass(data, Declaration) - - def parse_declaration(self, i): - """Treat a bogus SGML declaration as raw data. Treat a CDATA - declaration as a CData object.""" - j = None - if self.rawdata[i:i+9] == '<![CDATA[': - k = self.rawdata.find(']]>', i) - if k == -1: - k = len(self.rawdata) - data = self.rawdata[i+9:k] - j = k+3 - self._toStringSubclass(data, CData) - else: - try: - j = SGMLParser.parse_declaration(self, i) - except SGMLParseError: - toHandle = self.rawdata[i:] - self.handle_data(toHandle) - j = i + len(toHandle) - return j - -class BeautifulSoup(BeautifulStoneSoup): - - """This parser knows the following facts about HTML: - - * Some tags have no closing tag and should be interpreted as being - closed as soon as they are encountered. - - * The text inside some tags (ie. 'script') may contain tags which - are not really part of the document and which should be parsed - as text, not tags. If you want to parse the text as tags, you can - always fetch it and parse it explicitly. - - * Tag nesting rules: - - Most tags can't be nested at all. For instance, the occurance of - a <p> tag should implicitly close the previous <p> tag. - - <p>Para1<p>Para2 - should be transformed into: - <p>Para1</p><p>Para2 - - Some tags can be nested arbitrarily. For instance, the occurance - of a <blockquote> tag should _not_ implicitly close the previous - <blockquote> tag. - - Alice said: <blockquote>Bob said: <blockquote>Blah - should NOT be transformed into: - Alice said: <blockquote>Bob said: </blockquote><blockquote>Blah - - Some tags can be nested, but the nesting is reset by the - interposition of other tags. For instance, a <tr> tag should - implicitly close the previous <tr> tag within the same <table>, - but not close a <tr> tag in another table. - - <table><tr>Blah<tr>Blah - should be transformed into: - <table><tr>Blah</tr><tr>Blah - but, - <tr>Blah<table><tr>Blah - should NOT be transformed into - <tr>Blah<table></tr><tr>Blah - - Differing assumptions about tag nesting rules are a major source - of problems with the BeautifulSoup class. If BeautifulSoup is not - treating as nestable a tag your page author treats as nestable, - try ICantBelieveItsBeautifulSoup, MinimalSoup, or - BeautifulStoneSoup before writing your own subclass.""" - - def __init__(self, *args, **kwargs): - if not kwargs.has_key('smartQuotesTo'): - kwargs['smartQuotesTo'] = self.HTML_ENTITIES - kwargs['isHTML'] = True - BeautifulStoneSoup.__init__(self, *args, **kwargs) - - SELF_CLOSING_TAGS = buildTagMap(None, - ('br' , 'hr', 'input', 'img', 'meta', - 'spacer', 'link', 'frame', 'base', 'col')) - - PRESERVE_WHITESPACE_TAGS = set(['pre', 'textarea']) - - QUOTE_TAGS = {'script' : None, 'textarea' : None} - - #According to the HTML standard, each of these inline tags can - #contain another tag of the same type. Furthermore, it's common - #to actually use these tags this way. - NESTABLE_INLINE_TAGS = ('span', 'font', 'q', 'object', 'bdo', 'sub', 'sup', - 'center') - - #According to the HTML standard, these block tags can contain - #another tag of the same type. Furthermore, it's common - #to actually use these tags this way. - NESTABLE_BLOCK_TAGS = ('blockquote', 'div', 'fieldset', 'ins', 'del') - - #Lists can contain other lists, but there are restrictions. - NESTABLE_LIST_TAGS = { 'ol' : [], - 'ul' : [], - 'li' : ['ul', 'ol'], - 'dl' : [], - 'dd' : ['dl'], - 'dt' : ['dl'] } - - #Tables can contain other tables, but there are restrictions. - NESTABLE_TABLE_TAGS = {'table' : [], - 'tr' : ['table', 'tbody', 'tfoot', 'thead'], - 'td' : ['tr'], - 'th' : ['tr'], - 'thead' : ['table'], - 'tbody' : ['table'], - 'tfoot' : ['table'], - } - - NON_NESTABLE_BLOCK_TAGS = ('address', 'form', 'p', 'pre') - - #If one of these tags is encountered, all tags up to the next tag of - #this type are popped. - RESET_NESTING_TAGS = buildTagMap(None, NESTABLE_BLOCK_TAGS, 'noscript', - NON_NESTABLE_BLOCK_TAGS, - NESTABLE_LIST_TAGS, - NESTABLE_TABLE_TAGS) - - NESTABLE_TAGS = buildTagMap([], NESTABLE_INLINE_TAGS, NESTABLE_BLOCK_TAGS, - NESTABLE_LIST_TAGS, NESTABLE_TABLE_TAGS) - - # Used to detect the charset in a META tag; see start_meta - CHARSET_RE = re.compile("((^|;)\s*charset=)([^;]*)", re.M) - - def start_meta(self, attrs): - """Beautiful Soup can detect a charset included in a META tag, - try to convert the document to that charset, and re-parse the - document from the beginning.""" - httpEquiv = None - contentType = None - contentTypeIndex = None - tagNeedsEncodingSubstitution = False - - for i in range(0, len(attrs)): - key, value = attrs[i] - key = key.lower() - if key == 'http-equiv': - httpEquiv = value - elif key == 'content': - contentType = value - contentTypeIndex = i - - if httpEquiv and contentType: # It's an interesting meta tag. - match = self.CHARSET_RE.search(contentType) - if match: - if (self.declaredHTMLEncoding is not None or - self.originalEncoding == self.fromEncoding): - # An HTML encoding was sniffed while converting - # the document to Unicode, or an HTML encoding was - # sniffed during a previous pass through the - # document, or an encoding was specified - # explicitly and it worked. Rewrite the meta tag. - def rewrite(match): - return match.group(1) + "%SOUP-ENCODING%" - newAttr = self.CHARSET_RE.sub(rewrite, contentType) - attrs[contentTypeIndex] = (attrs[contentTypeIndex][0], - newAttr) - tagNeedsEncodingSubstitution = True - else: - # This is our first pass through the document. - # Go through it again with the encoding information. - newCharset = match.group(3) - if newCharset and newCharset != self.originalEncoding: - self.declaredHTMLEncoding = newCharset - self._feed(self.declaredHTMLEncoding) - raise StopParsing - pass - tag = self.unknown_starttag("meta", attrs) - if tag and tagNeedsEncodingSubstitution: - tag.containsSubstitutions = True - -class StopParsing(Exception): - pass - -class ICantBelieveItsBeautifulSoup(BeautifulSoup): - - """The BeautifulSoup class is oriented towards skipping over - common HTML errors like unclosed tags. However, sometimes it makes - errors of its own. For instance, consider this fragment: - - <b>Foo<b>Bar</b></b> - - This is perfectly valid (if bizarre) HTML. However, the - BeautifulSoup class will implicitly close the first b tag when it - encounters the second 'b'. It will think the author wrote - "<b>Foo<b>Bar", and didn't close the first 'b' tag, because - there's no real-world reason to bold something that's already - bold. When it encounters '</b></b>' it will close two more 'b' - tags, for a grand total of three tags closed instead of two. This - can throw off the rest of your document structure. The same is - true of a number of other tags, listed below. - - It's much more common for someone to forget to close a 'b' tag - than to actually use nested 'b' tags, and the BeautifulSoup class - handles the common case. This class handles the not-co-common - case: where you can't believe someone wrote what they did, but - it's valid HTML and BeautifulSoup screwed up by assuming it - wouldn't be.""" - - I_CANT_BELIEVE_THEYRE_NESTABLE_INLINE_TAGS = \ - ('em', 'big', 'i', 'small', 'tt', 'abbr', 'acronym', 'strong', - 'cite', 'code', 'dfn', 'kbd', 'samp', 'strong', 'var', 'b', - 'big') - - I_CANT_BELIEVE_THEYRE_NESTABLE_BLOCK_TAGS = ('noscript',) - - NESTABLE_TAGS = buildTagMap([], BeautifulSoup.NESTABLE_TAGS, - I_CANT_BELIEVE_THEYRE_NESTABLE_BLOCK_TAGS, - I_CANT_BELIEVE_THEYRE_NESTABLE_INLINE_TAGS) - -class MinimalSoup(BeautifulSoup): - """The MinimalSoup class is for parsing HTML that contains - pathologically bad markup. It makes no assumptions about tag - nesting, but it does know which tags are self-closing, that - <script> tags contain Javascript and should not be parsed, that - META tags may contain encoding information, and so on. - - This also makes it better for subclassing than BeautifulStoneSoup - or BeautifulSoup.""" - - RESET_NESTING_TAGS = buildTagMap('noscript') - NESTABLE_TAGS = {} - -class BeautifulSOAP(BeautifulStoneSoup): - """This class will push a tag with only a single string child into - the tag's parent as an attribute. The attribute's name is the tag - name, and the value is the string child. An example should give - the flavor of the change: - - <foo><bar>baz</bar></foo> - => - <foo bar="baz"><bar>baz</bar></foo> - - You can then access fooTag['bar'] instead of fooTag.barTag.string. - - This is, of course, useful for scraping structures that tend to - use subelements instead of attributes, such as SOAP messages. Note - that it modifies its input, so don't print the modified version - out. - - I'm not sure how many people really want to use this class; let me - know if you do. Mainly I like the name.""" - - def popTag(self): - if len(self.tagStack) > 1: - tag = self.tagStack[-1] - parent = self.tagStack[-2] - parent._getAttrMap() - if (isinstance(tag, Tag) and len(tag.contents) == 1 and - isinstance(tag.contents[0], NavigableString) and - not parent.attrMap.has_key(tag.name)): - parent[tag.name] = tag.contents[0] - BeautifulStoneSoup.popTag(self) - -#Enterprise class names! It has come to our attention that some people -#think the names of the Beautiful Soup parser classes are too silly -#and "unprofessional" for use in enterprise screen-scraping. We feel -#your pain! For such-minded folk, the Beautiful Soup Consortium And -#All-Night Kosher Bakery recommends renaming this file to -#"RobustParser.py" (or, in cases of extreme enterprisiness, -#"RobustParserBeanInterface.class") and using the following -#enterprise-friendly class aliases: -class RobustXMLParser(BeautifulStoneSoup): - pass -class RobustHTMLParser(BeautifulSoup): - pass -class RobustWackAssHTMLParser(ICantBelieveItsBeautifulSoup): - pass -class RobustInsanelyWackAssHTMLParser(MinimalSoup): - pass -class SimplifyingSOAPParser(BeautifulSOAP): - pass - -###################################################### -# -# Bonus library: Unicode, Dammit -# -# This class forces XML data into a standard format (usually to UTF-8 -# or Unicode). It is heavily based on code from Mark Pilgrim's -# Universal Feed Parser. It does not rewrite the XML or HTML to -# reflect a new encoding: that happens in BeautifulStoneSoup.handle_pi -# (XML) and BeautifulSoup.start_meta (HTML). - -# Autodetects character encodings. -# Download from http://chardet.feedparser.org/ -try: - import chardet -# import chardet.constants -# chardet.constants._debug = 1 -except ImportError: - chardet = None - -# cjkcodecs and iconv_codec make Python know about more character encodings. -# Both are available from http://cjkpython.i18n.org/ -# They're built in if you use Python 2.4. -try: - import cjkcodecs.aliases -except ImportError: - pass -try: - import iconv_codec -except ImportError: - pass - -class UnicodeDammit: - """A class for detecting the encoding of a *ML document and - converting it to a Unicode string. If the source encoding is - windows-1252, can replace MS smart quotes with their HTML or XML - equivalents.""" - - # This dictionary maps commonly seen values for "charset" in HTML - # meta tags to the corresponding Python codec names. It only covers - # values that aren't in Python's aliases and can't be determined - # by the heuristics in find_codec. - CHARSET_ALIASES = { "macintosh" : "mac-roman", - "x-sjis" : "shift-jis" } - - def __init__(self, markup, overrideEncodings=[], - smartQuotesTo='xml', isHTML=False): - self.declaredHTMLEncoding = None - self.markup, documentEncoding, sniffedEncoding = \ - self._detectEncoding(markup, isHTML) - self.smartQuotesTo = smartQuotesTo - self.triedEncodings = [] - if markup == '' or isinstance(markup, unicode): - self.originalEncoding = None - self.unicode = unicode(markup) - return - - u = None - for proposedEncoding in overrideEncodings: - u = self._convertFrom(proposedEncoding) - if u: break - if not u: - for proposedEncoding in (documentEncoding, sniffedEncoding): - u = self._convertFrom(proposedEncoding) - if u: break - - # If no luck and we have auto-detection library, try that: - if not u and chardet and not isinstance(self.markup, unicode): - u = self._convertFrom(chardet.detect(self.markup)['encoding']) - - # As a last resort, try utf-8 and windows-1252: - if not u: - for proposed_encoding in ("utf-8", "windows-1252"): - u = self._convertFrom(proposed_encoding) - if u: break - - self.unicode = u - if not u: self.originalEncoding = None - - def _subMSChar(self, orig): - """Changes a MS smart quote character to an XML or HTML - entity.""" - sub = self.MS_CHARS.get(orig) - if isinstance(sub, tuple): - if self.smartQuotesTo == 'xml': - sub = '&#x%s;' % sub[1] - else: - sub = '&%s;' % sub[0] - return sub - - def _convertFrom(self, proposed): - proposed = self.find_codec(proposed) - if not proposed or proposed in self.triedEncodings: - return None - self.triedEncodings.append(proposed) - markup = self.markup - - # Convert smart quotes to HTML if coming from an encoding - # that might have them. - if self.smartQuotesTo and proposed.lower() in("windows-1252", - "iso-8859-1", - "iso-8859-2"): - markup = re.compile("([\x80-\x9f])").sub \ - (lambda(x): self._subMSChar(x.group(1)), - markup) - - try: - # print "Trying to convert document to %s" % proposed - u = self._toUnicode(markup, proposed) - self.markup = u - self.originalEncoding = proposed - except Exception, e: - # print "That didn't work!" - # print e - return None - #print "Correct encoding: %s" % proposed - return self.markup - - def _toUnicode(self, data, encoding): - '''Given a string and its encoding, decodes the string into Unicode. - %encoding is a string recognized by encodings.aliases''' - - # strip Byte Order Mark (if present) - if (len(data) >= 4) and (data[:2] == '\xfe\xff') \ - and (data[2:4] != '\x00\x00'): - encoding = 'utf-16be' - data = data[2:] - elif (len(data) >= 4) and (data[:2] == '\xff\xfe') \ - and (data[2:4] != '\x00\x00'): - encoding = 'utf-16le' - data = data[2:] - elif data[:3] == '\xef\xbb\xbf': - encoding = 'utf-8' - data = data[3:] - elif data[:4] == '\x00\x00\xfe\xff': - encoding = 'utf-32be' - data = data[4:] - elif data[:4] == '\xff\xfe\x00\x00': - encoding = 'utf-32le' - data = data[4:] - newdata = unicode(data, encoding) - return newdata - - def _detectEncoding(self, xml_data, isHTML=False): - """Given a document, tries to detect its XML encoding.""" - xml_encoding = sniffed_xml_encoding = None - try: - if xml_data[:4] == '\x4c\x6f\xa7\x94': - # EBCDIC - xml_data = self._ebcdic_to_ascii(xml_data) - elif xml_data[:4] == '\x00\x3c\x00\x3f': - # UTF-16BE - sniffed_xml_encoding = 'utf-16be' - xml_data = unicode(xml_data, 'utf-16be').encode('utf-8') - elif (len(xml_data) >= 4) and (xml_data[:2] == '\xfe\xff') \ - and (xml_data[2:4] != '\x00\x00'): - # UTF-16BE with BOM - sniffed_xml_encoding = 'utf-16be' - xml_data = unicode(xml_data[2:], 'utf-16be').encode('utf-8') - elif xml_data[:4] == '\x3c\x00\x3f\x00': - # UTF-16LE - sniffed_xml_encoding = 'utf-16le' - xml_data = unicode(xml_data, 'utf-16le').encode('utf-8') - elif (len(xml_data) >= 4) and (xml_data[:2] == '\xff\xfe') and \ - (xml_data[2:4] != '\x00\x00'): - # UTF-16LE with BOM - sniffed_xml_encoding = 'utf-16le' - xml_data = unicode(xml_data[2:], 'utf-16le').encode('utf-8') - elif xml_data[:4] == '\x00\x00\x00\x3c': - # UTF-32BE - sniffed_xml_encoding = 'utf-32be' - xml_data = unicode(xml_data, 'utf-32be').encode('utf-8') - elif xml_data[:4] == '\x3c\x00\x00\x00': - # UTF-32LE - sniffed_xml_encoding = 'utf-32le' - xml_data = unicode(xml_data, 'utf-32le').encode('utf-8') - elif xml_data[:4] == '\x00\x00\xfe\xff': - # UTF-32BE with BOM - sniffed_xml_encoding = 'utf-32be' - xml_data = unicode(xml_data[4:], 'utf-32be').encode('utf-8') - elif xml_data[:4] == '\xff\xfe\x00\x00': - # UTF-32LE with BOM - sniffed_xml_encoding = 'utf-32le' - xml_data = unicode(xml_data[4:], 'utf-32le').encode('utf-8') - elif xml_data[:3] == '\xef\xbb\xbf': - # UTF-8 with BOM - sniffed_xml_encoding = 'utf-8' - xml_data = unicode(xml_data[3:], 'utf-8').encode('utf-8') - else: - sniffed_xml_encoding = 'ascii' - pass - except: - xml_encoding_match = None - xml_encoding_match = re.compile( - '^<\?.*encoding=[\'"](.*?)[\'"].*\?>').match(xml_data) - if not xml_encoding_match and isHTML: - regexp = re.compile('<\s*meta[^>]+charset=([^>]*?)[;\'">]', re.I) - xml_encoding_match = regexp.search(xml_data) - if xml_encoding_match is not None: - xml_encoding = xml_encoding_match.groups()[0].lower() - if isHTML: - self.declaredHTMLEncoding = xml_encoding - if sniffed_xml_encoding and \ - (xml_encoding in ('iso-10646-ucs-2', 'ucs-2', 'csunicode', - 'iso-10646-ucs-4', 'ucs-4', 'csucs4', - 'utf-16', 'utf-32', 'utf_16', 'utf_32', - 'utf16', 'u16')): - xml_encoding = sniffed_xml_encoding - return xml_data, xml_encoding, sniffed_xml_encoding - - - def find_codec(self, charset): - return self._codec(self.CHARSET_ALIASES.get(charset, charset)) \ - or (charset and self._codec(charset.replace("-", ""))) \ - or (charset and self._codec(charset.replace("-", "_"))) \ - or charset - - def _codec(self, charset): - if not charset: return charset - codec = None - try: - codecs.lookup(charset) - codec = charset - except (LookupError, ValueError): - pass - return codec - - EBCDIC_TO_ASCII_MAP = None - def _ebcdic_to_ascii(self, s): - c = self.__class__ - if not c.EBCDIC_TO_ASCII_MAP: - emap = (0,1,2,3,156,9,134,127,151,141,142,11,12,13,14,15, - 16,17,18,19,157,133,8,135,24,25,146,143,28,29,30,31, - 128,129,130,131,132,10,23,27,136,137,138,139,140,5,6,7, - 144,145,22,147,148,149,150,4,152,153,154,155,20,21,158,26, - 32,160,161,162,163,164,165,166,167,168,91,46,60,40,43,33, - 38,169,170,171,172,173,174,175,176,177,93,36,42,41,59,94, - 45,47,178,179,180,181,182,183,184,185,124,44,37,95,62,63, - 186,187,188,189,190,191,192,193,194,96,58,35,64,39,61,34, - 195,97,98,99,100,101,102,103,104,105,196,197,198,199,200, - 201,202,106,107,108,109,110,111,112,113,114,203,204,205, - 206,207,208,209,126,115,116,117,118,119,120,121,122,210, - 211,212,213,214,215,216,217,218,219,220,221,222,223,224, - 225,226,227,228,229,230,231,123,65,66,67,68,69,70,71,72, - 73,232,233,234,235,236,237,125,74,75,76,77,78,79,80,81, - 82,238,239,240,241,242,243,92,159,83,84,85,86,87,88,89, - 90,244,245,246,247,248,249,48,49,50,51,52,53,54,55,56,57, - 250,251,252,253,254,255) - import string - c.EBCDIC_TO_ASCII_MAP = string.maketrans( \ - ''.join(map(chr, range(256))), ''.join(map(chr, emap))) - return s.translate(c.EBCDIC_TO_ASCII_MAP) - - MS_CHARS = { '\x80' : ('euro', '20AC'), - '\x81' : ' ', - '\x82' : ('sbquo', '201A'), - '\x83' : ('fnof', '192'), - '\x84' : ('bdquo', '201E'), - '\x85' : ('hellip', '2026'), - '\x86' : ('dagger', '2020'), - '\x87' : ('Dagger', '2021'), - '\x88' : ('circ', '2C6'), - '\x89' : ('permil', '2030'), - '\x8A' : ('Scaron', '160'), - '\x8B' : ('lsaquo', '2039'), - '\x8C' : ('OElig', '152'), - '\x8D' : '?', - '\x8E' : ('#x17D', '17D'), - '\x8F' : '?', - '\x90' : '?', - '\x91' : ('lsquo', '2018'), - '\x92' : ('rsquo', '2019'), - '\x93' : ('ldquo', '201C'), - '\x94' : ('rdquo', '201D'), - '\x95' : ('bull', '2022'), - '\x96' : ('ndash', '2013'), - '\x97' : ('mdash', '2014'), - '\x98' : ('tilde', '2DC'), - '\x99' : ('trade', '2122'), - '\x9a' : ('scaron', '161'), - '\x9b' : ('rsaquo', '203A'), - '\x9c' : ('oelig', '153'), - '\x9d' : '?', - '\x9e' : ('#x17E', '17E'), - '\x9f' : ('Yuml', ''),} - -####################################################################### - - -#By default, act as an HTML pretty-printer. -if __name__ == '__main__': - import sys - soup = BeautifulSoup(sys.stdin) - print soup.prettify() diff --git a/catapult/tracing/third_party/tvcm/third_party/beautifulsoup/README.chromium b/catapult/tracing/third_party/tvcm/third_party/beautifulsoup/README.chromium deleted file mode 100644 index 966d44f2..00000000 --- a/catapult/tracing/third_party/tvcm/third_party/beautifulsoup/README.chromium +++ /dev/null @@ -1,9 +0,0 @@ -me: BeautifulSoup - HTML parser -Short Name: BeautifulSoup -URL: http://www.crummy.com/software/BeautifulSoup/download/3.x/BeautifulSoup-3.2.1.tar.gz (?) -Version: 3.2 -License: MIT -License File: NOT_SHIPPED -Security Critical: no -Description: Used for HTML module parsing -Local Modifications: None diff --git a/catapult/tracing/third_party/tvcm/third_party/beautifulsoup/polymer_soup.py b/catapult/tracing/third_party/tvcm/third_party/beautifulsoup/polymer_soup.py deleted file mode 100644 index f8aa913b..00000000 --- a/catapult/tracing/third_party/tvcm/third_party/beautifulsoup/polymer_soup.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import BeautifulSoup - - -class PolymerSoup(BeautifulSoup.BeautifulSoup): - """Parser for HTML files containing Polymer tags.""" - NESTABLE_TAGS = BeautifulSoup.BeautifulSoup.NESTABLE_TAGS.copy() - NESTABLE_TAGS['template'] = [] diff --git a/catapult/tracing/third_party/tvcm/tvcm/html_module.py b/catapult/tracing/third_party/tvcm/tvcm/html_module.py index e4b75871..b2024326 100644 --- a/catapult/tracing/third_party/tvcm/tvcm/html_module.py +++ b/catapult/tracing/third_party/tvcm/tvcm/html_module.py @@ -111,11 +111,7 @@ def GetPolymerElementNameFromOpenTags(open_tags): if not found_tag: return None - for attr in found_tag.attrs: - if attr[0] == 'name': - return attr[1] - - return None + return found_tag.attrs.get('name', None) _POLYMER_RE_1 = 'Polymer(\s*?)\((\s*?)\{' _POLYMER_RE_2 = 'Polymer(\s*?)\((\s*?)\)' diff --git a/catapult/tracing/third_party/tvcm/tvcm/html_module_unittest.py b/catapult/tracing/third_party/tvcm/tvcm/html_module_unittest.py index ac95277e..7cb1ee76 100644 --- a/catapult/tracing/third_party/tvcm/tvcm/html_module_unittest.py +++ b/catapult/tracing/third_party/tvcm/tvcm/html_module_unittest.py @@ -202,7 +202,7 @@ console.log('Logging without strict mode is no fun.'); class HTMLModuleTests(unittest.TestCase): - def testBasic(self): + def testBasicModuleGeneration(self): file_contents = {} file_contents[os.path.normpath('/tmp/a/b/start.html')] = """ <!DOCTYPE html> @@ -371,4 +371,3 @@ console.log('/raw/raw_script.js was written'); background-image: url(data:image/jpg;base64,anBnZGF0YQ==); } """.rstrip() - print html diff --git a/catapult/tracing/third_party/tvcm/tvcm/parse_html_deps.py b/catapult/tracing/third_party/tvcm/tvcm/parse_html_deps.py index 2aa8c651..8866ba18 100644 --- a/catapult/tracing/third_party/tvcm/tvcm/parse_html_deps.py +++ b/catapult/tracing/third_party/tvcm/tvcm/parse_html_deps.py @@ -10,18 +10,23 @@ from tvcm import strip_js_comments from tvcm import html_generation_controller +def _AddToPathIfNeeded(path): + if path not in sys.path: + sys.path.insert(0, path) + + def _InitBeautifulSoup(): - tvcm_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) - bs_path = os.path.join(tvcm_path, 'third_party', 'beautifulsoup') - if bs_path in sys.path: - return - sys.path.insert(0, bs_path) + catapult_path = os.path.abspath(os.path.join(os.path.dirname(__file__), + '..', '..', '..', '..')) + bs_path = os.path.join(catapult_path, 'third_party', 'beautifulsoup4') + _AddToPathIfNeeded(bs_path) + html5lib_path = os.path.join(catapult_path, 'third_party', 'html5lib-python') + _AddToPathIfNeeded(html5lib_path) -_InitBeautifulSoup() -import BeautifulSoup -import polymer_soup +_InitBeautifulSoup() +import bs4 class InlineScript(object): def __init__(self, soup): @@ -33,7 +38,6 @@ class InlineScript(object): @property def contents(self): - #TODO(nednguyen): change other places to use unicode() instead of str(). return unicode(self._soup.string) @property @@ -50,7 +54,7 @@ class InlineScript(object): open_tags = [] cur = self._soup.parent while cur: - if isinstance(cur, BeautifulSoup.BeautifulSoup): + if isinstance(cur, bs4.BeautifulSoup): break open_tags.append(_Tag(cur.name, cur.attrs)) @@ -65,14 +69,27 @@ class InlineScript(object): def _IsDoctype(x): - if not isinstance(x, BeautifulSoup.Declaration): + if not isinstance(x, bs4.Doctype): return False - return x == 'DOCTYPE html' or x == 'DOCTYPE HTML' - + return x == 'html' or x == 'HTML' + +def _CreateSoupWithoutHeadOrBody(html): + soupCopy = bs4.BeautifulSoup(html, 'html5lib') + soup = bs4.BeautifulSoup() + soup.reset() + if soupCopy.head: + for n in soupCopy.head.contents: + n.extract() + soup.append(n) + if soupCopy.body: + for n in soupCopy.body.contents: + n.extract() + soup.append(n) + return soup class HTMLModuleParserResults(object): def __init__(self, html): - self._soup = polymer_soup.PolymerSoup(html) + self._soup = bs4.BeautifulSoup(html, 'html5lib') self._inline_scripts = None @property @@ -106,19 +123,23 @@ class HTMLModuleParserResults(object): @property def inline_stylesheets(self): tags = self._soup.findAll('style') - return [str(t.string) for t in tags] + return [unicode(t.string) for t in tags] def YieldHTMLInPieces(self, controller, minify=False): yield self.GenerateHTML(controller, minify) - def GenerateHTML(self, controller, minify=False): - soup = polymer_soup.PolymerSoup(str(self._soup)) + def GenerateHTML(self, controller, minify=False, prettify=False): + soup = _CreateSoupWithoutHeadOrBody(unicode(self._soup)) + + # Remove declaration. + for x in soup.contents: + if isinstance(x, bs4.Doctype): + x.extract() # Remove declaration. for x in soup.contents: - if isinstance(x, BeautifulSoup.Declaration): - if _IsDoctype(x): - x.extract() + if isinstance(x, bs4.Declaration): + x.extract() # Remove all imports. imports = soup.findAll('link', rel='import') @@ -138,10 +159,10 @@ class HTMLModuleParserResults(object): # Process all in-line styles. inline_styles = soup.findAll('style') for style in inline_styles: - html = controller.GetHTMLForInlineStylesheet(str(style.string)) + html = controller.GetHTMLForInlineStylesheet(unicode(style.string)) if html: - ns = BeautifulSoup.Tag(soup, 'style') - ns.append(BeautifulSoup.NavigableString(html)) + ns = soup.new_tag('style') + ns.append(bs4.NavigableString(html)) style.replaceWith(ns) else: style.extract() @@ -151,7 +172,7 @@ class HTMLModuleParserResults(object): for stylesheet_link in stylesheet_links: html = controller.GetHTMLForStylesheetHRef(stylesheet_link['href']) if html: - tmp = polymer_soup.PolymerSoup(html).findChildren() + tmp = bs4.BeautifulSoup(html, 'html5lib').findAll('style') assert len(tmp) == 1 stylesheet_link.replaceWith(tmp[0]) else: @@ -160,12 +181,14 @@ class HTMLModuleParserResults(object): # Remove comments if minifying. if minify: comments = soup.findAll( - text=lambda text: isinstance(text, BeautifulSoup.Comment)) + text=lambda text: isinstance(text, bs4.Comment)) for comment in comments: comment.extract() + if prettify: + return soup.prettify('utf-8').strip() # We are done. - return str(soup).strip() + return unicode(soup).strip() @property def html_contents_without_links_and_script(self): diff --git a/catapult/tracing/third_party/tvcm/tvcm/parse_html_deps_unittest.py b/catapult/tracing/third_party/tvcm/tvcm/parse_html_deps_unittest.py index 7c89c157..81cc66d0 100755 --- a/catapult/tracing/third_party/tvcm/tvcm/parse_html_deps_unittest.py +++ b/catapult/tracing/third_party/tvcm/tvcm/parse_html_deps_unittest.py @@ -27,7 +27,7 @@ class ParseTests(unittest.TestCase): self.assertEquals([], module.stylesheets) self.assertEquals([], module.imports) - def test_parse_script_src(self): + def test_parse_script_src_basic(self): html = """<!DOCTYPE html> <html> <head> @@ -88,8 +88,8 @@ class ParseTests(unittest.TestCase): inner_script = """tvcm.require("foo");tvcm.require('bar');""" self.assertEquals(inner_script, val) - self.assertEquals(1, len(script0.open_tags)) - self.assertEquals('polymer-element', script0.open_tags[0].tag) + self.assertEquals(3, len(script0.open_tags)) + self.assertEquals('polymer-element', script0.open_tags[2].tag) self.assertNotIn( 'tvcm.require("foo");', @@ -100,7 +100,8 @@ class ParseTests(unittest.TestCase): <script src="blah.js"></script> """ module = parse_html_deps.HTMLModuleParser().Parse(html) - self.assertEquals('', module.html_contents_without_links_and_script) + self.assertEquals('', + module.html_contents_without_links_and_script) def test_parse_link_rel_stylesheet(self): html = """<polymer-element name="hi"> @@ -124,10 +125,10 @@ class ParseTests(unittest.TestCase): gen_html = module.GenerateHTML(Ctl()) ghtm = """<polymer-element name="hi"> -<template> -<style>FRAMEWORK</style> -</template> -</polymer-element>""" + <template> + <style>FRAMEWORK</style> + </template> + </polymer-element>""" self.assertEquals(ghtm, gen_html) def test_parse_inline_style(self): @@ -161,19 +162,15 @@ class ParseTests(unittest.TestCase): self.assertRaises(lambda: parser.Parse(html)) def test_nested_templates(self): - html = """<template> + orig_html = """<template> <template> <div id="foo"></div> </template> </template>""" parser = parse_html_deps.HTMLModuleParser() - res = parser.Parse(html) + res = parser.Parse(orig_html) html = res.html_contents_without_links_and_script - self.assertEquals(html, """<template> -<template> -<div id="foo"></div> -</template> -</template>""") + self.assertEquals(html, orig_html) def test_html_contents_basic(self): html = """<a b="c">d</a>""" @@ -185,25 +182,29 @@ class ParseTests(unittest.TestCase): html = """<a>→</a>""" parser = parse_html_deps.HTMLModuleParser() module = parser.Parse(html) - self.assertEquals(html, module.html_contents_without_links_and_script) + self.assertEquals(u'<a>\u2192</a>', + module.html_contents_without_links_and_script) def test_html_content_with_charref(self): html = """<a>></a>""" parser = parse_html_deps.HTMLModuleParser() module = parser.Parse(html) - self.assertEquals(html, module.html_contents_without_links_and_script) + self.assertEquals('<a>></a>', + module.html_contents_without_links_and_script) def test_html_content_start_end_br(self): html = """<a><br /></a>""" parser = parse_html_deps.HTMLModuleParser() module = parser.Parse(html) - self.assertEquals(html, module.html_contents_without_links_and_script) + self.assertEquals('<a><br/></a>', + module.html_contents_without_links_and_script) def test_html_content_start_end_img(self): html = """<a><img src="foo.png" id="bar" /></a>""" parser = parse_html_deps.HTMLModuleParser() module = parser.Parse(html) - self.assertEquals(html, module.html_contents_without_links_and_script) + self.assertEquals('<a><img id="bar" src="foo.png"/></a>', + module.html_contents_without_links_and_script) def test_html_contents_with_link_stripping(self): html = """<a b="c">d</a> diff --git a/catapult/tracing/trace_viewer.gypi b/catapult/tracing/trace_viewer.gypi index dabc3f77..4d81c0e8 100644 --- a/catapult/tracing/trace_viewer.gypi +++ b/catapult/tracing/trace_viewer.gypi @@ -60,13 +60,12 @@ 'tracing/base/sorted_array_utils.html', 'tracing/base/statistics.html', 'tracing/base/task.html', - 'tracing/base/units/energy_in_joules.html', 'tracing/base/units/generic_table.html', - 'tracing/base/units/power_in_watts.html', - 'tracing/base/units/size_in_bytes.html', - 'tracing/base/units/time.html', + 'tracing/base/units/scalar.html', + 'tracing/base/units/time_display_mode.html', 'tracing/base/units/time_duration.html', 'tracing/base/units/time_stamp.html', + 'tracing/base/units/units.html', 'tracing/base/utils.html', 'tracing/core/auditor.html', 'tracing/core/constants.html', @@ -274,6 +273,8 @@ 'tracing/ui/analysis/single_thread_slice_sub_view.html', 'tracing/ui/analysis/single_thread_time_slice_sub_view.html', 'tracing/ui/analysis/stack_frame.html', + 'tracing/ui/analysis/stacked_pane.html', + 'tracing/ui/analysis/stacked_pane_view.html', 'tracing/ui/analysis/tab_view.html', 'tracing/ui/annotations/annotation_view.html', 'tracing/ui/annotations/comment_box_annotation_view.html', @@ -421,7 +422,7 @@ 'tracing/ui/units/array_of_numbers_span.html', 'tracing/ui/units/generic_table_view.html', 'tracing/ui/units/preferred_display_unit.html', - 'tracing/ui/units/size_in_bytes_span.html', + 'tracing/ui/units/scalar_span.html', 'tracing/ui/units/time_duration_span.html', 'tracing/ui/units/time_stamp_span.html', 'tracing/ui/view_specific_brushing_state.html', diff --git a/catapult/tracing/tracing/base/iteration_helpers.html b/catapult/tracing/tracing/base/iteration_helpers.html index 99c6b2e8..28ba14c6 100644 --- a/catapult/tracing/tracing/base/iteration_helpers.html +++ b/catapult/tracing/tracing/base/iteration_helpers.html @@ -48,6 +48,20 @@ tr.exportTo('tr.b', function() { return 0; } + /** + * Compares two numeric values when one or both might be undefined or NaNs. + * Undefined / NaN values are sorted after others. + */ + function compareNumericWithNaNs(x, y) { + if (!isNaN(x) && !isNaN(y)) + return x - y; + if (isNaN(x)) + return 1; + if (isNaN(y)) + return -1; + return 0; + } + function concatenateArrays(/*arguments*/) { var values = []; for (var i = 0; i < arguments.length; i++) { @@ -208,6 +222,7 @@ tr.exportTo('tr.b', function() { concatenateObjects: concatenateObjects, compareArrays: compareArrays, comparePossiblyUndefinedValues: comparePossiblyUndefinedValues, + compareNumericWithNaNs: compareNumericWithNaNs, dictionaryLength: dictionaryLength, dictionaryKeys: dictionaryKeys, dictionaryValues: dictionaryValues, diff --git a/catapult/tracing/tracing/base/units/energy_in_joules.html b/catapult/tracing/tracing/base/units/energy_in_joules.html deleted file mode 100644 index 24e27df5..00000000 --- a/catapult/tracing/tracing/base/units/energy_in_joules.html +++ /dev/null @@ -1,36 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/base/base.html"> - -<script> -'use strict'; - -tr.exportTo('tr.b.units', function() { - /** - * Wrapper around a float that represents an energy measurement in Joules. - */ - function EnergyInJoules(numJoules) { - this.numJoules_ = numJoules; - }; - - EnergyInJoules.prototype = { - toString: function() { - return EnergyInJoules.format(this.numJoules_); - } - }; - - EnergyInJoules.format = function(numJoules) { - return numJoules - .toLocaleString(undefined, { minimumFractionDigits: 3 }) + ' J'; - }; - - return { - EnergyInJoules: EnergyInJoules - }; -}); -</script> diff --git a/catapult/tracing/tracing/base/units/energy_in_joules_test.html b/catapult/tracing/tracing/base/units/energy_in_joules_test.html deleted file mode 100644 index 107cb91a..00000000 --- a/catapult/tracing/tracing/base/units/energy_in_joules_test.html +++ /dev/null @@ -1,22 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<link rel="import" href="/tracing/base/units/energy_in_joules.html"> -<script> -'use strict'; - -tr.b.unittest.testSuite(function() { - var EnergyInJoules = tr.b.units.EnergyInJoules; - - test('format', function() { - assert.equal(EnergyInJoules.format(1000), '1,000.000 J'); - assert.equal(EnergyInJoules.format(1), '1.000 J'); - assert.equal(EnergyInJoules.format(.005), '0.005 J'); - assert.equal(EnergyInJoules.format(.0005), '0.001 J'); - assert.equal(EnergyInJoules.format(.0004), '0.000 J'); - }); -}); -</script> diff --git a/catapult/tracing/tracing/base/units/generic_table.html b/catapult/tracing/tracing/base/units/generic_table.html index 7290c3b1..7f9bae57 100644 --- a/catapult/tracing/tracing/base/units/generic_table.html +++ b/catapult/tracing/tracing/base/units/generic_table.html @@ -8,7 +8,7 @@ found in the LICENSE file. <script> 'use strict'; -tr.exportTo('tr.b.units', function() { +tr.exportTo('tr.b.u', function() { /** * Tabular data wrapper. Simply wraps an array of items. */ diff --git a/catapult/tracing/tracing/base/units/histogram.html b/catapult/tracing/tracing/base/units/histogram.html new file mode 100644 index 00000000..3aac423a --- /dev/null +++ b/catapult/tracing/tracing/base/units/histogram.html @@ -0,0 +1,211 @@ +<!DOCTYPE HTML> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<link rel="import" href="/tracing/base/units/units.html"> +<link rel="import" href="/tracing/base/statistics.html"> +<link rel="import" href="/tracing/base/range.html"> +<script> +'use strict'; + +tr.exportTo('tr.b.u', function() { + var Range = tr.b.Range; + + var MAX_SOURCE_INFOS = 16; + + function HistogramBin(parentHistogram, opt_range) { + this.parentHistogram = parentHistogram; + this.range = opt_range || (new tr.b.Range()); + this.count = 0; + this.sourceInfos = []; + } + + HistogramBin.fromDict = function(parentHistogram, d) { + var h = new HistogramBin(parentHistogram); + h.range.min = d.min; + h.range.max = d.max; + h.count = d.count; + h.sourceInfos = d.sourceInfos; + return h; + } + + HistogramBin.prototype = { + add: function(value, sourceInfo) { + this.count += 1; + if (this.sourceInfos.length < MAX_SOURCE_INFOS) { + this.sourceInfos.push(sourceInfo); + } + }, + + addBin: function(other) { + if (!this.range.equals(other.range)) + throw new Error('Merging incompatible histogram bins.'); + this.count += other.count; + this.sourceInfos.push.apply(this.sourceInfos, other.sourceInfos); + }, + + asDict: function() { + return { + min: this.range.min, + max: this.range.max, + count: this.count, + sourceInfos: this.sourceInfos.slice(0) + }; + }, + + asJSON: function() { + return this.asDict(); + } + }; + + function Histogram(unit, range, binInfo) { + this.range = range; + this.unit = unit; + + this.numNans = 0; + this.nanSourceInfos = []; + + this.runningSum = 0; + + this.underflowBin = binInfo.underflowBin; + this.centralBins = binInfo.centralBins; + this.centralBinWidth = binInfo.centralBinWidth; + this.overflowBin = binInfo.overflowBin; + + this.allBins = []; + this.allBins.push(this.underflowBin); + this.allBins.push.apply(this.allBins, this.centralBins); + this.allBins.push(this.overflowBin); + } + + Histogram.fromDict = function(d) { + var range = Range.fromExplicitRange(d.min, d.max); + var binInfo = {}; + binInfo.underflowBin = HistogramBin.fromDict(undefined, d.underflowBin); + binInfo.centralBins = d.centralBins.map(function(binAsDict) { + return HistogramBin.fromDict(undefined, binAsDict); + }); + binInfo.centralBinWidth = d.centralBinWidth; + binInfo.overflowBin = HistogramBin.fromDict(undefined, d.overflowBin); + var h = new Histogram(tr.b.u.Units.fromJSON(d.unit), range, binInfo); + h.allBins.forEach(function(bin) { + bin.parentHistogram = h; + }); + h.runningSum = d.runningSum; + h.numNans = d.numNans; + h.nanSourceInfos = d.nanSourceInfos; + return h; + } + + Histogram.createLinear = function(unit, range, numBins) { + if (range.isEmpty) + throw new Error('Nope'); + + var binInfo = {}; + binInfo.underflowBin = new HistogramBin( + this, Range.fromExplicitRange(-Number.MAX_VALUE, range.min)); + binInfo.overflowBin = new HistogramBin( + this, Range.fromExplicitRange(range.max, Number.MAX_VALUE)); + binInfo.centralBins = []; + binInfo.centralBinWidth = range.range / numBins; + + for (var i = 0; i < numBins; i++) { + var lo = range.min + (binInfo.centralBinWidth * i); + var hi = lo + binInfo.centralBinWidth; + binInfo.centralBins.push( + new HistogramBin(undefined, Range.fromExplicitRange(lo, hi))); + } + + var h = new Histogram(unit, range, binInfo); + h.allBins.forEach(function(bin) { + bin.parentHistogram = h; + }); + return h; + }, + + Histogram.prototype = { + get numValues() { + return tr.b.Statistics.sum(this.allBins, function(e) { + return e.count; + }); + }, + + get average() { + return this.runningSum / this.numValues; + }, + + getBinForValue: function(value) { + if (value < this.range.min) + return this.underflowBin; + if (value >= this.range.max) + return this.overflowBin; + var binIdx = Math.floor((value - this.range.min) / this.centralBinWidth); + return this.centralBins[binIdx]; + }, + + add: function(value, sourceInfo) { + if (typeof(value) !== 'number' || isNaN(value)) { + this.numNans++; + if (this.nanSourceInfos.length < MAX_SOURCE_INFOS) + this.nanSourceInfos.push(sourceInfo); + return; + } + + var bin = this.getBinForValue(value); + bin.add(value, sourceInfo); + this.runningSum += value; + }, + + addHistogram: function(other) { + if (!this.range.equals(other.range) || + !this.unit === other.unit || + this.allBins.length !== other.allBins.length) { + throw new Error('Merging incompatible histograms.'); + } + this.numNans += other.numNans; + this.nanSourceInfos.push.apply(this.nanSourceInfos, other.nanSourceInfos); + this.runningSum += other.runningSum; + for (var i = 0; i < this.allBins.length; ++i) { + this.allBins[i].addBin(other.allBins[i]); + } + }, + + clone: function() { + return Histogram.fromDict(this.asDict()); + }, + + asDict: function() { + var d = { + unit: this.unit.asJSON(), + + min: this.range.min, + max: this.range.max, + + numNans: this.numNans, + nanSourceInfos: this.nanSourceInfos, + + runningSum: this.runningSum, + + underflowBin: this.underflowBin.asDict(), + centralBins: this.centralBins.map(function(bin) { + return bin.asDict(); + }), + centralBinWidth: this.centralBinWidth, + overflowBin: this.overflowBin.asDict() + }; + return d; + }, + + asJSON: function() { + return this.asDict(); + } + }; + + return { + HistogramBin: HistogramBin, + Histogram: Histogram + }; +}); +</script> diff --git a/catapult/tracing/tracing/base/units/histogram_test.html b/catapult/tracing/tracing/base/units/histogram_test.html new file mode 100644 index 00000000..b543c5c4 --- /dev/null +++ b/catapult/tracing/tracing/base/units/histogram_test.html @@ -0,0 +1,118 @@ +<!DOCTYPE html> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<link rel="import" href="/tracing/base/units/histogram.html"> + +<script> +'use strict'; + +tr.b.unittest.testSuite(function() { + test('basic', function() { + var h = new tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, 1000), + 10); + assert.equal(h.getBinForValue(250).range.min, 200); + assert.equal(h.getBinForValue(250).range.max, 300); + h.add(-1, 'a'); + h.add(0, 'b'); + h.add(0, 'c'); + h.add(500, 'c'); + h.add(999, 'd'); + h.add(1000, 'd'); + assert.equal(h.underflowBin.count, 1); + + assert.equal(h.getBinForValue(0).count, 2); + assert.deepEqual(h.getBinForValue(0).sourceInfos, + ['b', 'c']); + + assert.equal(h.getBinForValue(500).count, 1); + assert.equal(h.getBinForValue(999).count, 1); + + assert.equal(h.overflowBin.count, 1); + assert.equal(h.numValues, 6); + assert.closeTo(h.average, 416.3, 0.1); + }); + + test('nans', function() { + var h = new tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, 1000), + 10); + h.add(undefined, 'b'); + h.add(NaN, 'c'); + + assert.equal(h.numNans, 2); + assert.deepEqual(h.nanSourceInfos, ['b', 'c']); + }); + + test('addHistogramsValid', function() { + var h0 = new tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, 1000), + 10); + var h1 = new tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, 1000), + 10); + h0.add(-1, 'a0'); + h0.add(0, 'b0'); + h0.add(0, 'c0'); + h0.add(500, 'c0'); + h0.add(1000, 'd0'); + h0.add(NaN, 'e0'); + + h1.add(-1, 'a1'); + h1.add(0, 'b1'); + h1.add(0, 'c1'); + h1.add(999, 'd1'); + h1.add(1000, 'd1'); + h1.add(NaN, 'e1'); + + h0.addHistogram(h1); + + assert.equal(h0.numNans, 2); + assert.deepEqual(h0.nanSourceInfos, ['e0', 'e1']); + + assert.equal(h0.underflowBin.count, 2); + assert.deepEqual(h0.underflowBin.sourceInfos, ['a0', 'a1']); + + assert.equal(h0.getBinForValue(0).count, 4); + assert.deepEqual(h0.getBinForValue(0).sourceInfos, + ['b0', 'c0', 'b1', 'c1']); + + assert.equal(h0.getBinForValue(500).count, 1); + assert.deepEqual(h0.getBinForValue(500).sourceInfos, ['c0']); + + assert.equal(h0.getBinForValue(999).count, 1); + assert.deepEqual(h0.getBinForValue(999).sourceInfos, ['d1']); + + assert.equal(h0.overflowBin.count, 2); + assert.deepEqual(h0.overflowBin.sourceInfos, ['d0', 'd1']); + + assert.equal(h0.numValues, 10); + assert.closeTo(h0.average, 349.7, 0.1); + }); + + test('addHistogramsInvalid', function() { + var h0 = new tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, 1000), + 10); + var h1 = new tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, 1001), + 10); + var h2 = new tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, 1000), + 11); + + assert.throws(h0.addHistogram.bind(h0, h1), Error); + assert.throws(h0.addHistogram.bind(h0, h1), Error); + }); +}); +</script> diff --git a/catapult/tracing/tracing/base/units/power_in_watts.html b/catapult/tracing/tracing/base/units/power_in_watts.html deleted file mode 100644 index b84f5d3a..00000000 --- a/catapult/tracing/tracing/base/units/power_in_watts.html +++ /dev/null @@ -1,36 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/base/base.html"> - -<script> -'use strict'; - -tr.exportTo('tr.b.units', function() { - /** - * Wrapper around a float that represents a power measurement in Watts. - */ - function PowerInWatts(numWatts) { - this.numWatts_ = numWatts; - }; - - PowerInWatts.prototype = { - toString: function() { - return PowerInWatts.format(this.numWatts_); - } - }; - - PowerInWatts.format = function(numWatts) { - return (numWatts * 1000.0) - .toLocaleString(undefined, { minimumFractionDigits: 3 }) + ' mW'; - }; - - return { - PowerInWatts: PowerInWatts - }; -}); -</script> diff --git a/catapult/tracing/tracing/base/units/power_in_watts_test.html b/catapult/tracing/tracing/base/units/power_in_watts_test.html deleted file mode 100644 index b9d1cbc3..00000000 --- a/catapult/tracing/tracing/base/units/power_in_watts_test.html +++ /dev/null @@ -1,23 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<link rel="import" href="/tracing/base/units/power_in_watts.html"> -<script> -'use strict'; - -tr.b.unittest.testSuite(function() { - var PowerInWatts = tr.b.units.PowerInWatts; - - test('format', function() { - assert.equal(PowerInWatts.format(1000), '1,000,000.000 mW'); - assert.equal(PowerInWatts.format(1), '1,000.000 mW'); - assert.equal(PowerInWatts.format(.001), '1.000 mW'); - assert.equal(PowerInWatts.format(.001005), '1.005 mW'); - assert.equal(PowerInWatts.format(.0010005), '1.001 mW'); - assert.equal(PowerInWatts.format(.0010004), '1.000 mW'); - }); -}); -</script> diff --git a/catapult/tracing/tracing/base/units/scalar.html b/catapult/tracing/tracing/base/units/scalar.html new file mode 100644 index 00000000..b1873442 --- /dev/null +++ b/catapult/tracing/tracing/base/units/scalar.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<!-- +Copyright 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/base/units/time_display_mode.html"> + +<script> +'use strict'; + +tr.exportTo('tr.b.u', function() { + /** + * Scalar wrapper, representing a scalar value and its unit. + */ + function Scalar(value, unit) { + this.value = value; + this.unit = unit; + }; + + Scalar.prototype = { + toString: function() { + return this.unit.format(this.value); + } + }; + + return { + Scalar: Scalar + }; +}); +</script> diff --git a/catapult/tracing/tracing/base/units/size_in_bytes.html b/catapult/tracing/tracing/base/units/size_in_bytes.html deleted file mode 100644 index 8ce1c0bb..00000000 --- a/catapult/tracing/tracing/base/units/size_in_bytes.html +++ /dev/null @@ -1,49 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/base/base.html"> - -<script> -'use strict'; - -tr.exportTo('tr.b.units', function() { - var UNIT_PREFIXES = ['', 'Ki', 'Mi', 'Gi', 'Ti']; - - /** - * Float wrapper, representing a size in bytes, capable of pretty-printing. - */ - function SizeInBytes(numBytes) { - this.numBytes = numBytes; - }; - - SizeInBytes.prototype = { - toString: function() { - return SizeInBytes.format(this.numBytes); - } - }; - - SizeInBytes.format = function(numBytes) { - var signPrefix = ''; - if (numBytes < 0) { - signPrefix = '-'; - numBytes = -numBytes; - } - - var i = 0; - while (numBytes >= 1024 && i < UNIT_PREFIXES.length - 1) { - numBytes /= 1024; - i++; - } - - return signPrefix + numBytes.toFixed(1) + ' ' + UNIT_PREFIXES[i] + 'B'; - }; - - return { - SizeInBytes: SizeInBytes - }; -}); -</script> diff --git a/catapult/tracing/tracing/base/units/size_in_bytes_test.html b/catapult/tracing/tracing/base/units/size_in_bytes_test.html deleted file mode 100644 index 8c357230..00000000 --- a/catapult/tracing/tracing/base/units/size_in_bytes_test.html +++ /dev/null @@ -1,31 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/base/units/size_in_bytes.html"> - -<script> -'use strict'; - -tr.b.unittest.testSuite(function() { - var SizeInBytes = tr.b.units.SizeInBytes; - - function checkFormat(numBytes, expectedString) { - assert.equal(SizeInBytes.format(numBytes), expectedString); - assert.equal(new SizeInBytes(numBytes).toString(), expectedString); - } - - test('format', function() { - checkFormat(0, '0.0 B'); - checkFormat(1, '1.0 B'); - checkFormat(1536, '1.5 KiB'); - checkFormat(424.2 * 1024 * 1024, '424.2 MiB'); - checkFormat(5 * 1024 * 1024 * 1024, '5.0 GiB'); - checkFormat(1025 * 1024 * 1024 * 1024 * 1024, '1025.0 TiB'); - checkFormat(-2.5 * 1024 * 1024, '-2.5 MiB'); - }); -}); -</script> diff --git a/catapult/tracing/tracing/base/units/time.html b/catapult/tracing/tracing/base/units/time.html deleted file mode 100644 index 509a8315..00000000 --- a/catapult/tracing/tracing/base/units/time.html +++ /dev/null @@ -1,100 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<link rel="import" href="/tracing/base/base.html"> -<link rel="import" href="/tracing/base/event_target.html"> -<link rel="import" href="/tracing/ui/base/deep_utils.html"> - -<script> -'use strict'; - -/** - * @fileoverview Time currentDisplayUnit - */ -tr.exportTo('tr.b.units', function() { - var ms = { - scale: 1e-3, - suffix: 'ms', - // compares a < b with adjustments to precision errors - roundedLess: function(a, b) { - return Math.round(a * 1000) < Math.round(b * 1000); - }, - format: function(ts) { - return new Number(ts) - .toLocaleString(undefined, { minimumFractionDigits: 3 }) + ' ms'; - } - }; - - var ns = { - scale: 1e-9, - suffix: 'ns', - // compares a < b with adjustments to precision errors - roundedLess: function(a, b) { - return Math.round(a * 1000000) < Math.round(b * 1000000); - }, - format: function(ts) { - return new Number(ts * 1000000) - .toLocaleString(undefined, { maximumFractionDigits: 0 }) + ' ns'; - } - }; - - function max(a, b) { - if (a === undefined) - return b; - if (b === undefined) - return a; - return a.scale > b.scale ? a : b; - } - - var Time = { - supportedUnits: { - ms: ms, - ns: ns - }, - - reset: function() { - this.currentDisplayUnit = ms; - }, - - currentDisplayUnit_: ms, - get currentDisplayUnit() { - return this.currentDisplayUnit_; - }, - // use preferred-display-unit component instead of directly setting directly - set currentDisplayUnit(value) { - if (this.currentDisplayUnit_ == value) - return; - - this.currentDisplayUnit_ = value; - this.dispatchEvent(new tr.b.Event('display-unit-changed')); - }, - - didPreferredUnitChange: function() { - var largest = undefined; - var els = tr.b.findDeepElementsMatching(document.body, - 'tr-ui-u-preferred-display-unit'); - els.forEach(function(el) { - largest = max(largest, el.preferredDisplayUnit); - }); - - this.currentDisplayUnit = largest === undefined ? ms : largest; - }, - - timestampFromUs: function(us) { - return us / 1000; - }, - maybeTimestampFromUs: function(us) { - return us === undefined ? undefined : us / 1000; - } - }; - - tr.b.EventTarget.decorate(Time); - - return { - Time: Time - }; -}); -</script> diff --git a/catapult/tracing/tracing/base/units/time_display_mode.html b/catapult/tracing/tracing/base/units/time_display_mode.html new file mode 100644 index 00000000..4fd8bec9 --- /dev/null +++ b/catapult/tracing/tracing/base/units/time_display_mode.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<!-- +Copyright 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/base/base.html"> +<link rel="import" href="/tracing/base/event_target.html"> +<link rel="import" href="/tracing/ui/base/deep_utils.html"> + +<script> +'use strict'; + +/** + * @fileoverview Time currentDisplayUnit + */ +tr.exportTo('tr.b.u', function() { + var msDisplayMode = { + scale: 1e-3, + suffix: 'ms', + // Compares a < b with adjustments to precision errors. + roundedLess: function(a, b) { + return Math.round(a * 1000) < Math.round(b * 1000); + }, + format: function(ts) { + return new Number(ts) + .toLocaleString(undefined, { minimumFractionDigits: 3 }) + ' ms'; + } + }; + + var nsDisplayMode = { + scale: 1e-9, + suffix: 'ns', + // Compares a < b with adjustments to precision errors. + roundedLess: function(a, b) { + return Math.round(a * 1000000) < Math.round(b * 1000000); + }, + format: function(ts) { + return new Number(ts * 1000000) + .toLocaleString(undefined, { maximumFractionDigits: 0 }) + ' ns'; + } + }; + + var TimeDisplayModes = { + ns: nsDisplayMode, + ms: msDisplayMode + }; + + return { + TimeDisplayModes: TimeDisplayModes + }; +}); +</script> diff --git a/catapult/tracing/tracing/base/units/time_test.html b/catapult/tracing/tracing/base/units/time_display_mode_test.html index 1cc3d85d..3523129d 100644 --- a/catapult/tracing/tracing/base/units/time_test.html +++ b/catapult/tracing/tracing/base/units/time_display_mode_test.html @@ -1,10 +1,12 @@ <!DOCTYPE html> <!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. +Copyright 2015 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> + +<link rel="import" href="/tracing/base/units/time_display_mode.html"> + <script> 'use strict'; @@ -14,7 +16,7 @@ tr.b.unittest.testSuite(function() { return v.toLocaleString(undefined, { minimumFractionDigits: 3}) + ' ms'; } - var unit = tr.b.units.Time.supportedUnits.ms; + var unit = tr.b.u.TimeDisplayModes.ms; assert.equal(unit.format(1), local(1)); assert.equal(unit.format(1.001), local(1.001)); assert.equal(unit.format(1.0005), local(1.001)); @@ -28,7 +30,7 @@ tr.b.unittest.testSuite(function() { return v.toLocaleString(undefined, { maximumFractionDigits: 0}) + ' ns'; } - var unit = tr.b.units.Time.supportedUnits.ns; + var unit = tr.b.u.TimeDisplayModes.ns; assert.equal(unit.format(1), local(1000000)); assert.equal(unit.format(0.001), local(1000)); assert.equal(unit.format(0.000001), local(1)); @@ -36,27 +38,5 @@ tr.b.unittest.testSuite(function() { assert.equal(unit.format(0.0000004), local(0)); assert.equal(unit.format(0.0000015), local(2)); }); - - test('Time.display-unit-changed', function() { - var Time = tr.b.units.Time; - - var listenerWasCalled = false; - function listener(e) { - listenerWasCalled = true; - } - - try { - Time.currentDisplayUnit = Time.supportedUnits.ms; - Time.addEventListener('display-unit-changed', listener); - - listenerWasCalled = false; - Time.currentDisplayUnit = Time.supportedUnits.ns; - assert.isTrue(listenerWasCalled); - assert.equal(Time.currentDisplayUnit, Time.supportedUnits.ns); - } finally { - Time.removeEventListener('display-unit-changed', listener); - Time.reset(); - } - }); }); </script> diff --git a/catapult/tracing/tracing/base/units/time_duration.html b/catapult/tracing/tracing/base/units/time_duration.html index f54e5b25..5db2f82c 100644 --- a/catapult/tracing/tracing/base/units/time_duration.html +++ b/catapult/tracing/tracing/base/units/time_duration.html @@ -5,32 +5,30 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/scalar.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <script> 'use strict'; -tr.exportTo('tr.b.units', function() { +tr.exportTo('tr.b.u', function() { /** * Float wrapper, representing a time duration, capable of pretty-printing. */ - // TODO(petrcermak): Although this class is currently identical to - // tr.b.units.TimeStamp, we should probably keep both classes in case we want - // to handle them differently in the future. Therefore, rather than removing - // one of the classes, it would probably make more sense to have one inherit - // the prototype chain of the other one. function TimeDuration(duration) { - this.duration = duration; + tr.b.u.Scalar.call(this, duration, tr.b.u.Units.timeDurationInMs); }; TimeDuration.prototype = { - toString: function() { - return TimeDuration.format(this.duration); + __proto__: tr.b.u.Scalar.prototype, + + get duration() { + return this.value; } }; TimeDuration.format = function(duration) { - return tr.b.units.Time.currentDisplayUnit.format(duration); + return tr.b.u.Units.timeDurationInMs.format(duration); }; return { diff --git a/catapult/tracing/tracing/base/units/time_duration_test.html b/catapult/tracing/tracing/base/units/time_duration_test.html index 12adfc4c..c257c741 100644 --- a/catapult/tracing/tracing/base/units/time_duration_test.html +++ b/catapult/tracing/tracing/base/units/time_duration_test.html @@ -5,15 +5,15 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> <link rel="import" href="/tracing/base/units/time_duration.html"> +<link rel="import" href="/tracing/base/units/units.html"> <script> 'use strict'; tr.b.unittest.testSuite(function() { - var Time = tr.b.units.Time; - var TimeDuration = tr.b.units.TimeDuration; + var Units = tr.b.u.Units; + var TimeDuration = tr.b.u.TimeDuration; function checkFormat(timestamp, expectedString) { assert.equal(TimeDuration.format(timestamp), expectedString); @@ -23,7 +23,7 @@ tr.b.unittest.testSuite(function() { test('format', function() { try { // Use milliseconds to display time (default behavior). - Time.currentDisplayUnit = Time.supportedUnits.ms; + Units.currentTimeDisplayMode = tr.b.u.TimeDisplayModes.ms; checkFormat(0, '0.000 ms'); checkFormat(0.02, '0.020 ms'); @@ -37,7 +37,7 @@ tr.b.unittest.testSuite(function() { checkFormat(-123456789, '-123,456,789.000 ms'); // Change the unit to nanoseconds. - Time.currentDisplayUnit = Time.supportedUnits.ns; + Units.currentTimeDisplayMode = tr.b.u.TimeDisplayModes.ns; checkFormat(0, '0 ns'); checkFormat(1, '1,000,000 ns'); @@ -48,7 +48,7 @@ tr.b.unittest.testSuite(function() { checkFormat(123.456, '123,456,000 ns'); checkFormat(-0.07, '-70,000 ns'); } finally { - Time.reset(); + Units.reset(); } }); }); diff --git a/catapult/tracing/tracing/base/units/time_stamp.html b/catapult/tracing/tracing/base/units/time_stamp.html index ecd9307c..27730aca 100644 --- a/catapult/tracing/tracing/base/units/time_stamp.html +++ b/catapult/tracing/tracing/base/units/time_stamp.html @@ -5,27 +5,30 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/scalar.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <script> 'use strict'; -tr.exportTo('tr.b.units', function() { +tr.exportTo('tr.b.u', function() { /** * Float wrapper, representing a time stamp, capable of pretty-printing. */ function TimeStamp(timestamp) { - this.timestamp = timestamp; + tr.b.u.Scalar.call(this, timestamp, tr.b.u.Units.timeStampInMs); }; TimeStamp.prototype = { - toString: function() { - return TimeStamp.format(this.timestamp); + __proto__: tr.b.u.Scalar.prototype, + + get timestamp() { + return this.value; } }; TimeStamp.format = function(timestamp) { - return tr.b.units.Time.currentDisplayUnit.format(timestamp); + return tr.b.u.Units.timeStampInMs.format(timestamp); }; return { diff --git a/catapult/tracing/tracing/base/units/time_stamp_test.html b/catapult/tracing/tracing/base/units/time_stamp_test.html index 84c2f2f0..9f5035aa 100644 --- a/catapult/tracing/tracing/base/units/time_stamp_test.html +++ b/catapult/tracing/tracing/base/units/time_stamp_test.html @@ -5,15 +5,15 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/units.html"> <link rel="import" href="/tracing/base/units/time_stamp.html"> <script> 'use strict'; tr.b.unittest.testSuite(function() { - var Time = tr.b.units.Time; - var TimeStamp = tr.b.units.TimeStamp; + var Units = tr.b.u.Units; + var TimeStamp = tr.b.u.TimeStamp; function checkFormat(timestamp, expectedString) { assert.equal(TimeStamp.format(timestamp), expectedString); @@ -23,7 +23,7 @@ tr.b.unittest.testSuite(function() { test('format', function() { try { // Use milliseconds to display time (default behavior). - Time.currentDisplayUnit = Time.supportedUnits.ms; + Units.currentTimeDisplayMode = tr.b.u.TimeDisplayModes.ms; checkFormat(0, '0.000 ms'); checkFormat(0.02, '0.020 ms'); @@ -37,7 +37,7 @@ tr.b.unittest.testSuite(function() { checkFormat(-123456789, '-123,456,789.000 ms'); // Change the unit to nanoseconds. - Time.currentDisplayUnit = Time.supportedUnits.ns; + Units.currentTimeDisplayMode = tr.b.u.TimeDisplayModes.ns; checkFormat(0, '0 ns'); checkFormat(1, '1,000,000 ns'); @@ -48,7 +48,7 @@ tr.b.unittest.testSuite(function() { checkFormat(123.456, '123,456,000 ns'); checkFormat(-0.07, '-70,000 ns'); } finally { - Time.reset(); + Units.reset(); } }); }); diff --git a/catapult/tracing/tracing/base/units/units.html b/catapult/tracing/tracing/base/units/units.html new file mode 100644 index 00000000..e6068317 --- /dev/null +++ b/catapult/tracing/tracing/base/units/units.html @@ -0,0 +1,159 @@ +<!DOCTYPE HTML> +<!-- +Copyright 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/base/base.html"> +<link rel="import" href="/tracing/base/event_target.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> + +<script> +'use strict'; + +tr.exportTo('tr.b.u', function() { + var TimeDisplayModes = tr.b.u.TimeDisplayModes; + + function max(a, b) { + if (a === undefined) + return b; + if (b === undefined) + return a; + return a.scale > b.scale ? a : b; + } + + var Units = { + reset: function() { + this.currentTimeDisplayMode = TimeDisplayModes.ms; + }, + + timestampFromUs: function(us) { + return us / 1000; + }, + + maybeTimestampFromUs: function(us) { + return us === undefined ? undefined : us / 1000; + }, + + get currentTimeDisplayMode() { + return this.currentTimeDisplayMode_; + }, + + // Use tr-ui-u-preferred-display-unit element instead of directly setting. + set currentTimeDisplayMode(value) { + if (this.currentTimeDisplayMode_ == value) + return; + + this.currentTimeDisplayMode_ = value; + this.dispatchEvent(new tr.b.Event('display-mode-changed')); + }, + + didPreferredTimeDisplayUnitChange: function() { + var largest = undefined; + var els = tr.b.findDeepElementsMatching(document.body, + 'tr-ui-u-preferred-display-unit'); + els.forEach(function(el) { + largest = max(largest, el.preferredTimeDisplayMode); + }); + + this.currentDisplayUnit = largest === undefined ? + TimeDisplayModes.ms : largest; + }, + + unitsByJSONName: {}, + + fromJSON: function(object) { + var u = this.unitsByJSONName[object]; + if (u) { + return u; + } + throw new Error('Unrecognized unit'); + } + }; + + tr.b.EventTarget.decorate(Units); + Units.reset(); + + // Known display units follow. + ////////////////////////////////////////////////////////////////////////////// + Units.timeDurationInMs = { + asJSON: function() { return 'ms'; }, + format: function(value) { + return Units.currentTimeDisplayMode_.format(value); + } + }; + Units.unitsByJSONName['ms'] = Units.timeDurationInMs; + + Units.timeStampInMs = { + asJSON: function() { return 'tsMs'; }, + format: function(value) { + return Units.currentTimeDisplayMode_.format(value); + } + }; + Units.unitsByJSONName['tsMs'] = Units.timeStampInMs; + + Units.normalizedPercentage = { + asJSON: function() { return 'n%'; }, + format: function(value) { + var tmp = new Number(Math.round(value * 100)); + return tmp.toLocaleString(undefined, {minimumFractionDigits: 3}) + '%'; + } + }; + Units.unitsByJSONName['n%'] = Units.normalizedPercentage; + + var SIZE_UNIT_PREFIXES = ['', 'Ki', 'Mi', 'Gi', 'Ti']; + Units.sizeInBytes = { + asJSON: function() { return 'sizeInBytes'; }, + format: function(value) { + var signPrefix = ''; + if (value < 0) { + signPrefix = '-'; + value = -value; + } + + var i = 0; + while (value >= 1024 && i < SIZE_UNIT_PREFIXES.length - 1) { + value /= 1024; + i++; + } + + return signPrefix + value.toFixed(1) + ' ' + SIZE_UNIT_PREFIXES[i] + 'B'; + } + }; + Units.unitsByJSONName['sizeInBytes'] = Units.sizeInBytes; + + Units.energyInJoules = { + asJSON: function() { return 'J'; }, + format: function(value) { + return value + .toLocaleString(undefined, { minimumFractionDigits: 3 }) + ' J'; + } + }; + Units.unitsByJSONName['J'] = Units.energyInJoules; + + Units.powerInWatts = { + asJSON: function() { return 'W'; }, + format: function(value) { + return (value * 1000.0) + .toLocaleString(undefined, { minimumFractionDigits: 3 }) + ' mW'; + } + }; + Units.unitsByJSONName['W'] = Units.powerInWatts; + + Units.unitlessNumber = { + asJSON: function() { return 'unitless'; }, + format: function(value) { + return value.toLocaleString( + undefined, { + minimumFractionDigits: 3, + maximumFractionDigits: 3}); + } + }; + Units.unitsByJSONName['unitless'] = Units.unitlessNumber; + + return { + Units: Units + }; +}); +</script>
\ No newline at end of file diff --git a/catapult/tracing/tracing/base/units/units_test.html b/catapult/tracing/tracing/base/units/units_test.html new file mode 100644 index 00000000..cb39a3c7 --- /dev/null +++ b/catapult/tracing/tracing/base/units/units_test.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<!-- +Copyright 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<link rel="import" href="/tracing/base/units/units.html"> +<script> +'use strict'; + +tr.b.unittest.testSuite(function() { + var Units = tr.b.u.Units; + + test('Units.display-mode-changed', function() { + var Units = tr.b.u.Units; + var TimeDisplayModes = tr.b.u.TimeDisplayModes; + + var listenerWasCalled = false; + function listener(e) { + listenerWasCalled = true; + } + + try { + Units.currentTimeDisplayMode = TimeDisplayModes.ms; + Units.addEventListener('display-mode-changed', listener); + + listenerWasCalled = false; + Units.currentTimeDisplayMode = TimeDisplayModes.ns; + assert.isTrue(listenerWasCalled); + assert.equal(Units.currentTimeDisplayMode, TimeDisplayModes.ns); + } finally { + Units.removeEventListener('display-mode-changed', listener); + Units.reset(); + } + }); + + test('sizeInBytes', function() { + function checkFormat(value, expectation) { + assert.equal(Units.sizeInBytes.format(value), expectation); + } + checkFormat(0, '0.0 B'); + checkFormat(1, '1.0 B'); + checkFormat(1536, '1.5 KiB'); + checkFormat(424.2 * 1024 * 1024, '424.2 MiB'); + checkFormat(5 * 1024 * 1024 * 1024, '5.0 GiB'); + checkFormat(1025 * 1024 * 1024 * 1024 * 1024, '1025.0 TiB'); + checkFormat(-2.5 * 1024 * 1024, '-2.5 MiB'); + }); + + test('energyInJoules', function() { + assert.equal(Units.energyInJoules.format(1000), '1,000.000 J'); + assert.equal(Units.energyInJoules.format(1), '1.000 J'); + assert.equal(Units.energyInJoules.format(.005), '0.005 J'); + assert.equal(Units.energyInJoules.format(.0005), '0.001 J'); + assert.equal(Units.energyInJoules.format(.0004), '0.000 J'); + }); + + test('powerInWatts', function() { + assert.equal(Units.powerInWatts.format(1000), '1,000,000.000 mW'); + assert.equal(Units.powerInWatts.format(1), '1,000.000 mW'); + assert.equal(Units.powerInWatts.format(.001), '1.000 mW'); + assert.equal(Units.powerInWatts.format(.001005), '1.005 mW'); + assert.equal(Units.powerInWatts.format(.0010005), '1.001 mW'); + assert.equal(Units.powerInWatts.format(.0010004), '1.000 mW'); + }); +}); +</script> diff --git a/catapult/tracing/tracing/core/filter_test.html b/catapult/tracing/tracing/core/filter_test.html index 288e6985..eb5406ca 100644 --- a/catapult/tracing/tracing/core/filter_test.html +++ b/catapult/tracing/tracing/core/filter_test.html @@ -25,14 +25,14 @@ tr.b.unittest.testSuite(function() { new TitleOrCategoryFilter(''); }); - var s0 = tr.c.test_utils.newSliceCategory('cat', 'a', 1, 3); + var s0 = tr.c.TestUtils.newSliceCategory('cat', 'a', 1, 3); assert.isTrue(new TitleOrCategoryFilter('a').matchSlice(s0)); assert.isTrue(new TitleOrCategoryFilter('cat').matchSlice(s0)); assert.isTrue(new TitleOrCategoryFilter('at').matchSlice(s0)); assert.isFalse(new TitleOrCategoryFilter('b').matchSlice(s0)); assert.isFalse(new TitleOrCategoryFilter('X').matchSlice(s0)); - var s1 = tr.c.test_utils.newSliceCategory('cat', 'abc', 1, 3); + var s1 = tr.c.TestUtils.newSliceCategory('cat', 'abc', 1, 3); assert.isTrue(new TitleOrCategoryFilter('abc').matchSlice(s1)); assert.isTrue(new TitleOrCategoryFilter('Abc').matchSlice(s1)); assert.isTrue(new TitleOrCategoryFilter('cat').matchSlice(s1)); @@ -49,12 +49,12 @@ tr.b.unittest.testSuite(function() { new ExactTitleFilter(''); }); - var s0 = tr.c.test_utils.newSliceNamed('a', 1, 3); + var s0 = tr.c.TestUtils.newSliceNamed('a', 1, 3); assert.isTrue(new ExactTitleFilter('a').matchSlice(s0)); assert.isFalse(new ExactTitleFilter('b').matchSlice(s0)); assert.isFalse(new ExactTitleFilter('A').matchSlice(s0)); - var s1 = tr.c.test_utils.newSliceNamed('abc', 1, 3); + var s1 = tr.c.TestUtils.newSliceNamed('abc', 1, 3); assert.isTrue(new ExactTitleFilter('abc').matchSlice(s1)); assert.isFalse(new ExactTitleFilter('Abc').matchSlice(s1)); assert.isFalse(new ExactTitleFilter('bc').matchSlice(s1)); @@ -69,7 +69,7 @@ tr.b.unittest.testSuite(function() { new FullTextFilter(''); }); - var s0 = tr.c.test_utils.newSliceCategory('cat', 'a', 1, 3); + var s0 = tr.c.TestUtils.newSliceCategory('cat', 'a', 1, 3); s0.args['key'] = 'value'; s0.args['anotherKey'] = 'anotherValue'; assert.isTrue(new FullTextFilter('cat').matchSlice(s0)); @@ -79,20 +79,20 @@ tr.b.unittest.testSuite(function() { assert.isTrue(new FullTextFilter('anotherValue').matchSlice(s0)); assert.isFalse(new FullTextFilter('not there').matchSlice(s0)); - var s1 = tr.c.test_utils.newSliceCategory('cat', 'a', 1, 3); + var s1 = tr.c.TestUtils.newSliceCategory('cat', 'a', 1, 3); s1.args['key'] = 123; assert.isTrue(new FullTextFilter('123').matchSlice(s1)); - var s2 = tr.c.test_utils.newSliceCategory('cat', 'a', 1, 3); + var s2 = tr.c.TestUtils.newSliceCategory('cat', 'a', 1, 3); s2.args['key'] = ['innerValue1', 'innerValue2']; assert.isTrue(new FullTextFilter('innerValue1').matchSlice(s2)); assert.isTrue(new FullTextFilter('innerValue2').matchSlice(s2)); - var s3 = tr.c.test_utils.newSliceCategory('cat', 'a', 1, 3); + var s3 = tr.c.TestUtils.newSliceCategory('cat', 'a', 1, 3); s3.args['key'] = ['one', 'two', 'three']; assert.isTrue(new FullTextFilter('two').matchSlice(s3)); - var s4 = tr.c.test_utils.newSliceCategory('cat', 'a', 1, 3); + var s4 = tr.c.TestUtils.newSliceCategory('cat', 'a', 1, 3); s4.args['key'] = undefined; assert.isFalse(new FullTextFilter('not there').matchSlice(s4)); }); diff --git a/catapult/tracing/tracing/core/test_utils.html b/catapult/tracing/tracing/core/test_utils.html index 1b73a8dc..d58cfe1b 100644 --- a/catapult/tracing/tracing/core/test_utils.html +++ b/catapult/tracing/tracing/core/test_utils.html @@ -19,7 +19,7 @@ found in the LICENSE file. /** * @fileoverview Helper functions for use in tracing tests. */ -tr.exportTo('tr.c.test_utils', function() { +tr.exportTo('tr.c', function() { function _getStartAndCpuDurationFromDict( options, required, startFieldName, durationFieldName, endFieldName) { @@ -54,21 +54,26 @@ tr.exportTo('tr.c.test_utils', function() { }; } - function getStartAndDurationFromDict(options) { + function _maybeGetCpuStartAndCpuDurationFromDict(options) { return _getStartAndCpuDurationFromDict( - options, true, 'start', 'duration', 'end'); + options, false, 'cpuStart', 'cpuDuration', 'cpuEnd'); + } + + function TestUtils() { } - function maybeGetCpuStartAndCpuDurationFromDict(options) { + TestUtils.getStartAndDurationFromDict = function(options) { return _getStartAndCpuDurationFromDict( - options, false, 'cpuStart', 'cpuDuration', 'cpuEnd'); + options, true, 'start', 'duration', 'end'); } - function newAsyncSlice(start, duration, startThread, endThread) { - return newAsyncSliceNamed('a', start, duration, startThread, endThread); + TestUtils.newAsyncSlice = function(start, duration, startThread, endThread) { + return TestUtils.newAsyncSliceNamed( + 'a', start, duration, startThread, endThread); } - function newAsyncSliceNamed(name, start, duration, startThread, endThread) { + TestUtils.newAsyncSliceNamed = function( + name, start, duration, startThread, endThread) { var asyncSliceConstructor = tr.model.AsyncSlice.getConstructor('', name); @@ -79,8 +84,8 @@ tr.exportTo('tr.c.test_utils', function() { return s; } - function newAsyncSliceEx(options) { - var sd = getStartAndDurationFromDict(options); + TestUtils.newAsyncSliceEx = function(options) { + var sd = TestUtils.getStartAndDurationFromDict(options); var cat = options.cat ? options.cat : 'cat'; var title = options.title ? options.title : 'a'; @@ -133,26 +138,26 @@ tr.exportTo('tr.c.test_utils', function() { return slice; } - function newCounter(parent) { - return newCounterNamed(parent, 'a'); + TestUtils.newCounter = function(parent) { + return TestUtils.newCounterNamed(parent, 'a'); } - function newCounterNamed(parent, name) { + TestUtils.newCounterNamed = function(parent, name) { var s = new tr.model.Counter(parent, name, null, name); return s; } - function newCounterCategory(parent, category, name) { + TestUtils.newCounterCategory = function(parent, category, name) { var s = new tr.model.Counter(parent, name, category, name); return s; } - function newCounterSeries() { + TestUtils.newCounterSeries = function() { var s = new tr.model.CounterSeries('a', 0); return s; } - function newFlowEventEx(options) { + TestUtils.newFlowEventEx = function(options) { if (options.start === undefined) throw new Error('Too little info'); @@ -160,7 +165,7 @@ tr.exportTo('tr.c.test_utils', function() { var colorId = options.colorId ? options.colorId : 0; - var sd = getStartAndDurationFromDict(options); + var sd = TestUtils.getStartAndDurationFromDict(options); var id; if (options.id !== undefined) @@ -194,16 +199,16 @@ tr.exportTo('tr.c.test_utils', function() { return event; } - function newSlice(start, duration) { - return newSliceNamed('a', start, duration); + TestUtils.newSlice = function(start, duration) { + return TestUtils.newSliceNamed('a', start, duration); } - function newSliceNamed(name, start, duration) { + TestUtils.newSliceNamed = function(name, start, duration) { var s = new tr.model.Slice('', name, 0, start, {}, duration); return s; } - function newThreadSlice(thread, state, start, duration, opt_cpu) { + TestUtils.newThreadSlice = function(thread, state, start, duration, opt_cpu) { var s = new tr.model.ThreadTimeSlice( thread, state, 'cat', start, {}, duration); if (opt_cpu) @@ -211,13 +216,14 @@ tr.exportTo('tr.c.test_utils', function() { return s; } - function newSampleNamed(thread, sampleName, category, frameNames, start) { + TestUtils.newSampleNamed = function( + thread, sampleName, category, frameNames, start) { var model; if (thread.parent) model = thread.parent.model; else model = undefined; - var sf = newStackTrace(model, category, frameNames); + var sf = TestUtils.newStackTrace(model, category, frameNames); var s = new tr.model.Sample(undefined, thread, sampleName, start, sf, @@ -225,20 +231,20 @@ tr.exportTo('tr.c.test_utils', function() { return s; } - function newSliceCategory(category, name, start, duration) { + TestUtils.newSliceCategory = function(category, name, start, duration) { var s = new tr.model.Slice( category, name, 0, start, {}, duration); return s; } - function newSliceEx(options) { - var sd = getStartAndDurationFromDict(options); + TestUtils.newSliceEx = function(options) { + var sd = TestUtils.getStartAndDurationFromDict(options); var title = options.title ? options.title : 'a'; var colorId = options.colorId ? options.colorId : 0; - var cpuSD = maybeGetCpuStartAndCpuDurationFromDict(options); + var cpuSD = _maybeGetCpuStartAndCpuDurationFromDict(options); var type; if (options.type) @@ -259,7 +265,7 @@ tr.exportTo('tr.c.test_utils', function() { return slice; } - function newStackTrace(model, category, titles) { + TestUtils.newStackTrace = function(model, category, titles) { var frame = undefined; for (var i = 0; i < titles.length; i++) { frame = new tr.model.StackFrame(frame, tr.b.GUID.allocate(), @@ -270,7 +276,7 @@ tr.exportTo('tr.c.test_utils', function() { return frame; } - function findSliceNamed(slices, name) { + TestUtils.findSliceNamed = function(slices, name) { if (slices instanceof tr.model.SliceGroup) slices = slices.slices; for (var i = 0; i < slices.length; i++) @@ -279,15 +285,15 @@ tr.exportTo('tr.c.test_utils', function() { return undefined; } - function newModel(customizeModelCallback) { - return newModelWithEvents([], { + TestUtils.newModel = function(customizeModelCallback) { + return TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneEmptyContainers: false, customizeModelCallback: customizeModelCallback }); } - function newModelWithEvents(events, opts) { + TestUtils.newModelWithEvents = function(events, opts) { if (!(events instanceof Array)) events = [events]; @@ -309,8 +315,8 @@ tr.exportTo('tr.c.test_utils', function() { return m; } - function newModelWithAuditor(customizeModelCallback, auditor) { - return newModelWithEvents([], { + TestUtils.newModelWithAuditor = function(customizeModelCallback, auditor) { + return TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneEmptyContainers: false, customizeModelCallback: customizeModelCallback, @@ -318,33 +324,13 @@ tr.exportTo('tr.c.test_utils', function() { }); } - function newFakeThread() { + TestUtils.newFakeThread = function() { var process = {model: {}}; return new tr.model.Thread(process); } return { - getStartAndDurationFromDict: getStartAndDurationFromDict, - newAsyncSlice: newAsyncSlice, - newAsyncSliceNamed: newAsyncSliceNamed, - newAsyncSliceEx: newAsyncSliceEx, - newCounter: newCounter, - newCounterNamed: newCounterNamed, - newCounterCategory: newCounterCategory, - newCounterSeries: newCounterSeries, - newFlowEventEx: newFlowEventEx, - newSlice: newSlice, - newFakeThread: newFakeThread, - newThreadSlice: newThreadSlice, - newSliceNamed: newSliceNamed, - newSliceEx: newSliceEx, - newSampleNamed: newSampleNamed, - newSliceCategory: newSliceCategory, - newStackTrace: newStackTrace, - newModel: newModel, - newModelWithAuditor: newModelWithAuditor, - newModelWithEvents: newModelWithEvents, - findSliceNamed: findSliceNamed + TestUtils: TestUtils }; }); </script> diff --git a/catapult/tracing/tracing/extras/android/android_auditor.html b/catapult/tracing/tracing/extras/android/android_auditor.html index aa041c8b..666a9683 100644 --- a/catapult/tracing/tracing/extras/android/android_auditor.html +++ b/catapult/tracing/tracing/extras/android/android_auditor.html @@ -30,7 +30,7 @@ tr.exportTo('tr.e.audits', function() { var InteractionRecord = tr.model.InteractionRecord; var Alert = tr.model.Alert; var EventInfo = tr.model.EventInfo; - var TimeDuration = tr.b.units.TimeDuration; + var TimeDuration = tr.b.u.TimeDuration; // TODO: extract from VSYNC, since not all devices have vsync near 60fps var EXPECTED_FRAME_TIME_MS = 16.67; diff --git a/catapult/tracing/tracing/extras/android/android_auditor_test.html b/catapult/tracing/tracing/extras/android/android_auditor_test.html index 14a4d0b9..475ffe2d 100644 --- a/catapult/tracing/tracing/extras/android/android_auditor_test.html +++ b/catapult/tracing/tracing/extras/android/android_auditor_test.html @@ -15,13 +15,13 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var SCHEDULING_STATE = tr.model.SCHEDULING_STATE; - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; var FRAME_PERF_CLASS = tr.model.FRAME_PERF_CLASS; - var newThreadSlice = tr.c.test_utils.newThreadSlice; - var TimeDuration = tr.b.units.TimeDuration; + var newThreadSlice = tr.c.TestUtils.newThreadSlice; + var TimeDuration = tr.b.u.TimeDuration; test('saveLayerAlert_badAlpha', function() { - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var renderThread = model.getOrCreateProcess(1).getOrCreateThread(2); renderThread.name = 'RenderThread'; renderThread.sliceGroup.pushSlice(newSliceEx( @@ -46,7 +46,7 @@ tr.b.unittest.testSuite(function() { }); test('saveLayerAlert_canvas', function() { - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var renderThread = model.getOrCreateProcess(1).getOrCreateThread(2); renderThread.name = 'RenderThread'; renderThread.sliceGroup.pushSlice(newSliceEx( @@ -63,7 +63,7 @@ tr.b.unittest.testSuite(function() { }); test('generatePathAlert', function() { - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var renderThread = model.getOrCreateProcess(1).getOrCreateThread(2); renderThread.name = 'RenderThread'; renderThread.sliceGroup.pushSlice(newSliceEx( @@ -82,7 +82,7 @@ tr.b.unittest.testSuite(function() { }); test('uploadAlert', function() { - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var renderThread = model.getOrCreateProcess(1).getOrCreateThread(2); renderThread.name = 'RenderThread'; renderThread.sliceGroup.pushSlice(newSliceEx( @@ -100,7 +100,7 @@ tr.b.unittest.testSuite(function() { }); test('listViewAlert', function() { - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1); uiThread.sliceGroup.pushSlice(newSliceEx( {title: 'obtainView', start: 0, duration: 5})); @@ -144,7 +144,7 @@ tr.b.unittest.testSuite(function() { }); test('measureLayoutAlert', function() { - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1); uiThread.sliceGroup.pushSlice(newSliceEx( {title: 'performTraversals', start: 0, duration: 20})); @@ -162,7 +162,7 @@ tr.b.unittest.testSuite(function() { }); test('viewDrawAlert', function() { - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1); // modern naming uiThread.sliceGroup.pushSlice(newSliceEx( @@ -183,7 +183,7 @@ tr.b.unittest.testSuite(function() { }); test('blockingGcAlert', function() { - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1); var sliceGroup = uiThread.sliceGroup; sliceGroup.pushSlice(newSliceEx( @@ -205,7 +205,7 @@ tr.b.unittest.testSuite(function() { }); test('lockContentionAlert', function() { - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1); var sliceGroup = uiThread.sliceGroup; sliceGroup.pushSlice(newSliceEx( @@ -220,7 +220,7 @@ tr.b.unittest.testSuite(function() { }); test('schedulingAlerts', function() { - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1); uiThread.sliceGroup.pushSlice(newSliceEx( {title: 'performTraversals', start: 0, duration: 20})); @@ -235,7 +235,7 @@ tr.b.unittest.testSuite(function() { assert.deepEqual(alert.args['Not scheduled, but runnable'], new TimeDuration(10)); - model = tr.c.test_utils.newModelWithAuditor(function(model) { + model = tr.c.TestUtils.newModelWithAuditor(function(model) { var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1); uiThread.sliceGroup.pushSlice(newSliceEx( {title: 'performTraversals', start: 0, duration: 20})); @@ -252,7 +252,7 @@ tr.b.unittest.testSuite(function() { test('addFramesToModel', function() { var process; - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { process = model.getOrCreateProcess(1); var uiThread = process.getOrCreateThread(1); @@ -283,7 +283,7 @@ tr.b.unittest.testSuite(function() { test('processRenameAndSort', function() { var appProcess; var sfProcess; - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { appProcess = model.getOrCreateProcess(1); var uiThread = appProcess.getOrCreateThread(1); uiThread.name = 'ndroid.systemui'; @@ -311,7 +311,7 @@ tr.b.unittest.testSuite(function() { var eventsExpectingInfo = []; var eventsNotExpectingInfo = []; - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var appProcess = model.getOrCreateProcess(1); var uiThread = appProcess.getOrCreateThread(1); uiThread.name = 'ndroid.systemui'; @@ -350,7 +350,7 @@ tr.b.unittest.testSuite(function() { var renderThread; var workerThread; var otherThread; - var model = tr.c.test_utils.newModelWithAuditor(function(model) { + var model = tr.c.TestUtils.newModelWithAuditor(function(model) { var appProcess = model.getOrCreateProcess(1); uiThread = appProcess.getOrCreateThread(1); @@ -382,7 +382,7 @@ tr.b.unittest.testSuite(function() { test('favicon', function() { var createModelWithJank = function(percentageJank) { - return tr.c.test_utils.newModelWithAuditor(function(model) { + return tr.c.TestUtils.newModelWithAuditor(function(model) { var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1); for (var i = 0; i < 100; i++) { var slice = newSliceEx({ diff --git a/catapult/tracing/tracing/extras/android/android_model_helper_test.html b/catapult/tracing/tracing/extras/android/android_model_helper_test.html index 490872f8..5b269dc4 100644 --- a/catapult/tracing/tracing/extras/android/android_model_helper_test.html +++ b/catapult/tracing/tracing/extras/android/android_model_helper_test.html @@ -14,10 +14,10 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var AndroidModelHelper = tr.e.audits.AndroidModelHelper; - var newAsyncSliceNamed = tr.c.test_utils.newAsyncSliceNamed; - var newSliceEx = tr.c.test_utils.newSliceEx; - var newCounterNamed = tr.c.test_utils.newCounterNamed; - var newCounterSeries = tr.c.test_utils.newCounterSeries; + var newAsyncSliceNamed = tr.c.TestUtils.newAsyncSliceNamed; + var newSliceEx = tr.c.TestUtils.newSliceEx; + var newCounterNamed = tr.c.TestUtils.newCounterNamed; + var newCounterSeries = tr.c.TestUtils.newCounterSeries; function createSurfaceFlingerWithVsyncs(model) { if (model.getProcess(2)) @@ -94,7 +94,7 @@ tr.b.unittest.testSuite(function() { test('getThreads', function() { SINGLE_FRAME_CUSTOM_MODELS.forEach(function(customizeModelCallback) { - var model = tr.c.test_utils.newModel(customizeModelCallback); + var model = tr.c.TestUtils.newModel(customizeModelCallback); var helper = new AndroidModelHelper(model); assert.equal(helper.apps[0].uiThread, model.uiThread); assert.equal(helper.apps[0].renderThread, model.renderThread); @@ -103,7 +103,7 @@ tr.b.unittest.testSuite(function() { test('iterateImportantSlices', function() { SINGLE_FRAME_CUSTOM_MODELS.forEach(function(customizeModelCallback) { - var model = tr.c.test_utils.newModel(customizeModelCallback); + var model = tr.c.TestUtils.newModel(customizeModelCallback); var helper = new AndroidModelHelper(model); var seen = 0; @@ -117,7 +117,7 @@ tr.b.unittest.testSuite(function() { test('getFrames', function() { SINGLE_FRAME_CUSTOM_MODELS.forEach(function(customizeModelCallback) { - var model = tr.c.test_utils.newModel(customizeModelCallback); + var model = tr.c.TestUtils.newModel(customizeModelCallback); var helper = new AndroidModelHelper(model); assert.equal(helper.apps.length, 1); @@ -131,7 +131,7 @@ tr.b.unittest.testSuite(function() { }); test('surfaceFlingerVsyncs', function() { - var model = tr.c.test_utils.newModel(createSurfaceFlingerWithVsyncs); + var model = tr.c.TestUtils.newModel(createSurfaceFlingerWithVsyncs); var helper = new AndroidModelHelper(model); assert.isTrue(helper.surfaceFlinger.hasVsyncs); @@ -148,7 +148,7 @@ tr.b.unittest.testSuite(function() { }); test('frameVsyncInterop', function() { - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { // app - 3 good, 3 bad frames var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1); uiThread.sliceGroup.pushSlice(newSliceEx( @@ -179,7 +179,7 @@ tr.b.unittest.testSuite(function() { }); test('appInputs', function() { - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { var process = model.getOrCreateProcess(120); var uiThread = process.getOrCreateThread(120); uiThread.sliceGroup.pushSlice(newSliceEx( @@ -207,7 +207,7 @@ tr.b.unittest.testSuite(function() { }); test('appAnimations', function() { - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { var process = model.getOrCreateProcess(120); var uiThread = process.getOrCreateThread(120); uiThread.sliceGroup.pushSlice(newSliceEx( diff --git a/catapult/tracing/tracing/extras/chrome/cc/display_item_list_test.html b/catapult/tracing/tracing/extras/chrome/cc/display_item_list_test.html index c0c71ae9..9bbab94f 100644 --- a/catapult/tracing/tracing/extras/chrome/cc/display_item_list_test.html +++ b/catapult/tracing/tracing/extras/chrome/cc/display_item_list_test.html @@ -19,7 +19,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('basic', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = tr.b.dictionaryValues(m.processes)[0]; var instance = p.objects.getAllInstancesNamed('cc::DisplayItemList')[0]; @@ -30,7 +30,7 @@ tr.b.unittest.testSuite(function() { }); test('getItems', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = tr.b.dictionaryValues(m.processes)[0]; var instance = p.objects.getAllInstancesNamed('cc::DisplayItemList')[0]; diff --git a/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice_test.html b/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice_test.html index 394c07c7..79bd809b 100644 --- a/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice_test.html +++ b/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice_test.html @@ -15,10 +15,10 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newAsyncSliceEx = tr.c.test_utils.newAsyncSliceEx; - var newSliceEx = tr.c.test_utils.newSliceEx; - var newFlowEventEx = tr.c.test_utils.newFlowEventEx; - var newModel = tr.c.test_utils.newModel; + var newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; + var newFlowEventEx = tr.c.TestUtils.newFlowEventEx; + var newModel = tr.c.TestUtils.newModel; var EventSet = tr.model.EventSet; test('matchByType_oldStyle', function() { diff --git a/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test.html b/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test.html index 7382b667..f9a165a8 100644 --- a/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test.html +++ b/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test.html @@ -18,7 +18,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('basic', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = tr.b.dictionaryValues(m.processes)[0]; var instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0]; diff --git a/catapult/tracing/tracing/extras/chrome/cc/picture_test.html b/catapult/tracing/tracing/extras/chrome/cc/picture_test.html index 4e8f5b43..25fe0544 100644 --- a/catapult/tracing/tracing/extras/chrome/cc/picture_test.html +++ b/catapult/tracing/tracing/extras/chrome/cc/picture_test.html @@ -19,7 +19,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('basic', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = tr.b.dictionaryValues(m.processes)[0]; var instance = p.objects.getAllInstancesNamed('cc::Picture')[0]; @@ -30,7 +30,7 @@ tr.b.unittest.testSuite(function() { }); test('getOps', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = tr.b.dictionaryValues(m.processes)[0]; var instance = p.objects.getAllInstancesNamed('cc::Picture')[0]; diff --git a/catapult/tracing/tracing/extras/chrome/cc/tile_test.html b/catapult/tracing/tracing/extras/chrome/cc/tile_test.html index 124572eb..c2997138 100644 --- a/catapult/tracing/tracing/extras/chrome/cc/tile_test.html +++ b/catapult/tracing/tracing/extras/chrome/cc/tile_test.html @@ -19,7 +19,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('basic', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = tr.b.dictionaryValues(m.processes)[0]; var instance = p.objects.getAllInstancesNamed('cc::Tile')[0]; var snapshot = instance.snapshots[0]; diff --git a/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html b/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html index cc2dcdf2..f343c864 100644 --- a/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html +++ b/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html @@ -15,7 +15,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function createModelWithChromeAuditor(customizeModelCallback) { - return tr.c.test_utils.newModelWithAuditor(function(m) { + return tr.c.TestUtils.newModelWithAuditor(function(m) { m.browserProcess = m.getOrCreateProcess(1); m.browserMain = m.browserProcess.getOrCreateThread(2); m.browserMain.name = 'CrBrowserMain'; diff --git a/catapult/tracing/tracing/extras/chrome/chrome_browser_helper_test.html b/catapult/tracing/tracing/extras/chrome/chrome_browser_helper_test.html index dc923b19..c10f85e9 100644 --- a/catapult/tracing/tracing/extras/chrome/chrome_browser_helper_test.html +++ b/catapult/tracing/tracing/extras/chrome/chrome_browser_helper_test.html @@ -17,7 +17,6 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var audits = tr.e.audits; var INPUT_TYPE = tr.e.cc.INPUT_EVENT_TYPE_NAMES; function getRange(min, max) { @@ -28,34 +27,35 @@ tr.b.unittest.testSuite(function() { } test('LoadingEvent', function() { - var model = tr.e.audits.newChromeModel(function() { }); + var model = tr.e.chrome.ChromeTestUtils.newChromeModel(function() { }); var modelHelper = new tr.e.audits.ChromeModelHelper(model); - audits.addLoadingEvent(model, {start: 1, end: 10}); + tr.e.chrome.ChromeTestUtils.addLoadingEvent(model, {start: 1, end: 10}); assert.equal(1, modelHelper.browserHelper.getLoadingEventsInRange( getRange(0, 100)).length); }); test('ProvisionalLoadEvent', function() { - var model = tr.e.audits.newChromeModel(function() { }); + var model = tr.e.chrome.ChromeTestUtils.newChromeModel(function() { }); var modelHelper = new tr.e.audits.ChromeModelHelper(model); - audits.addCommitLoadEvent(model, {start: 1, end: 10}); + tr.e.chrome.ChromeTestUtils.addCommitLoadEvent(model, {start: 1, end: 10}); assert.equal(1, modelHelper.browserHelper.getCommitProvisionalLoadEventsInRange( getRange(0, 100)).length); }); test('LatencyEvent', function() { - var model = tr.e.audits.newChromeModel(function() { }); + var model = tr.e.chrome.ChromeTestUtils.newChromeModel(function() { }); var modelHelper = new tr.e.audits.ChromeModelHelper(model); - audits.addInputEvent(model, INPUT_TYPE.UNKNOWN, {start: 1, end: 10}); + tr.e.chrome.ChromeTestUtils.addInputEvent( + model, INPUT_TYPE.UNKNOWN, {start: 1, end: 10}); assert.equal(1, modelHelper.browserHelper.getLatencyEventsInRange( getRange(0, 100)).length); }); test('NetworkEvent', function() { - var model = tr.e.audits.newChromeModel(function() { }); + var model = tr.e.chrome.ChromeTestUtils.newChromeModel(function() { }); var modelHelper = new tr.e.audits.ChromeModelHelper(model); - audits.addNetworkEvent(model, {start: 1, end: 10}); + tr.e.chrome.ChromeTestUtils.addNetworkEvent(model, {start: 1, end: 10}); assert.equal(1, modelHelper.browserHelper.getAllNetworkEventsInRange( getRange(0, 100)).length); }); diff --git a/catapult/tracing/tracing/extras/chrome/chrome_model_helper_test.html b/catapult/tracing/tracing/extras/chrome/chrome_model_helper_test.html index da74092c..32149edd 100644 --- a/catapult/tracing/tracing/extras/chrome/chrome_model_helper_test.html +++ b/catapult/tracing/tracing/extras/chrome/chrome_model_helper_test.html @@ -16,10 +16,10 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newAsyncSliceEx = tr.c.test_utils.newAsyncSliceEx; + var newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx; test('getLatencyData', function() { - var m = tr.e.audits.newChromeModel(function(m) { + var m = tr.e.chrome.ChromeTestUtils.newChromeModel(function(m) { m.browserMain.asyncSliceGroup.push(newAsyncSliceEx({ title: 'InputLatency::GestureScrollUpdate', cat: 'benchmark', @@ -82,7 +82,7 @@ tr.b.unittest.testSuite(function() { frame_ts += 16000 + 1000 * (i % 2); } - var m = tr.c.test_utils.newModelWithEvents([events]); + var m = tr.c.TestUtils.newModelWithEvents([events]); var modelHelper = new tr.e.audits.ChromeModelHelper(m); // Testing browser impl and main rendering stats. diff --git a/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html b/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html index 2929fa60..08396d55 100644 --- a/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html +++ b/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html @@ -15,9 +15,12 @@ found in the LICENSE file. /** * @fileoverview Base class for trace data Auditors. */ -tr.exportTo('tr.e.audits', function() { - function newChromeModel(customizeModelCallback) { - return tr.c.test_utils.newModel(function(model) { +tr.exportTo('tr.e.chrome', function() { + function ChromeTestUtils() { + } + + ChromeTestUtils.newChromeModel = function(customizeModelCallback) { + return tr.c.TestUtils.newModel(function(model) { console.log(model); model.browserProcess = model.getOrCreateProcess(1); model.browserMain = model.browserProcess.getOrCreateThread(2); @@ -37,90 +40,80 @@ tr.exportTo('tr.e.audits', function() { }); } - function addEvent(thread, dict) { - var slice = tr.c.test_utils.newAsyncSliceEx(dict); + ChromeTestUtils.addEvent = function(thread, dict) { + var slice = tr.c.TestUtils.newAsyncSliceEx(dict); thread.asyncSliceGroup.push(slice); return slice; } - function addInputEvent(model, typeName, dict) { + ChromeTestUtils.addInputEvent = function(model, typeName, dict) { dict.title = 'InputLatency::' + typeName; dict.isTopLevel = (dict.isTopLevel === undefined); dict.startThread = model.browserMain; - var slice = tr.c.test_utils.newAsyncSliceEx(dict); + var slice = tr.c.TestUtils.newAsyncSliceEx(dict); model.rendererMain.asyncSliceGroup.push(slice); return slice; } - function addFlingAnimationEvent(model, dict) { + ChromeTestUtils.addFlingAnimationEvent = function(model, dict) { dict.title = 'InputHandlerProxy::HandleGestureFling::started'; - var slice = tr.c.test_utils.newAsyncSliceEx(dict); + var slice = tr.c.TestUtils.newAsyncSliceEx(dict); model.rendererCompositor.asyncSliceGroup.push(slice); return slice; } - function addFrameEvent(model, dict) { + ChromeTestUtils.addFrameEvent = function(model, dict) { dict.title = tr.e.audits.IMPL_RENDERING_STATS; dict.type = tr.model.ThreadSlice; - var slice = tr.c.test_utils.newSliceEx(dict); + var slice = tr.c.TestUtils.newSliceEx(dict); model.rendererMain.asyncSliceGroup.push(slice); return slice; } - function addLoadingEvent(model, dict) { + ChromeTestUtils.addLoadingEvent = function(model, dict) { dict.title = 'WebContentsImpl Loading'; - var slice = tr.c.test_utils.newAsyncSliceEx(dict); + var slice = tr.c.TestUtils.newAsyncSliceEx(dict); model.rendererMain.asyncSliceGroup.push(slice); return slice; } - function addNetworkEvent(model, dict) { + ChromeTestUtils.addNetworkEvent = function(model, dict) { dict.cat = 'netlog'; dict.title = 'Generic Network event'; - var slice = tr.c.test_utils.newAsyncSliceEx(dict); + var slice = tr.c.TestUtils.newAsyncSliceEx(dict); model.browserMain.asyncSliceGroup.push(slice); return slice; } - function addCommitLoadEvent(model, dict) { + ChromeTestUtils.addCommitLoadEvent = function(model, dict) { dict.title = 'RenderFrameImpl::didCommitProvisionalLoad'; - var slice = tr.c.test_utils.newAsyncSliceEx(dict); + var slice = tr.c.TestUtils.newAsyncSliceEx(dict); model.rendererMain.asyncSliceGroup.push(slice); return slice; } - function addStartProvisionalLoadEvent(model, dict) { + ChromeTestUtils.addStartProvisionalLoadEvent = function(model, dict) { dict.title = 'RenderFrameImpl::didStartProvisionalLoad'; - var slice = tr.c.test_utils.newAsyncSliceEx(dict); + var slice = tr.c.TestUtils.newAsyncSliceEx(dict); model.rendererMain.asyncSliceGroup.push(slice); return slice; } - function addFailProvisionalLoadEvent(model, dict) { + ChromeTestUtils.addFailProvisionalLoadEvent = function(model, dict) { dict.title = 'RenderFrameImpl::didFailProvisionalLoad'; - var slice = tr.c.test_utils.newAsyncSliceEx(dict); + var slice = tr.c.TestUtils.newAsyncSliceEx(dict); model.rendererMain.asyncSliceGroup.push(slice); return slice; } - function addMainRunnerEvent(model, dict) { + ChromeTestUtils.addMainRunnerEvent = function(model, dict) { dict.title = 'ContentMainRunnerImpl::Initialize'; - var slice = tr.c.test_utils.newAsyncSliceEx(dict); + var slice = tr.c.TestUtils.newAsyncSliceEx(dict); model.rendererMain.asyncSliceGroup.push(slice); } return { - newChromeModel: newChromeModel, - addEvent: addEvent, - addInputEvent: addInputEvent, - addFlingAnimationEvent: addFlingAnimationEvent, - addFrameEvent: addFrameEvent, - addLoadingEvent: addLoadingEvent, - addNetworkEvent: addNetworkEvent, - addCommitLoadEvent: addCommitLoadEvent, - addStartProvisionalLoadEvent: addStartProvisionalLoadEvent, - addFailProvisionalLoadEvent: addFailProvisionalLoadEvent, - addMainRunnerEvent: addMainRunnerEvent + ChromeTestUtils: ChromeTestUtils }; }); </script> diff --git a/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice_test.html b/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice_test.html index 7d2a530d..24bd98cc 100644 --- a/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice_test.html +++ b/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice_test.html @@ -52,7 +52,7 @@ tr.b.unittest.testSuite(function() { {name: 'trace3', args: {'channel': 'test_channel'}, pid: 1, ts: 200, cat: 'disabled-by-default-gpu.device', tid: 2, ph: 'e', id: 73} ]; - var m = tr.c.test_utils.newModelWithEvents([events]); + var m = tr.c.TestUtils.newModelWithEvents([events]); var t2 = m.getOrCreateProcess(1).getOrCreateThread(2); assert.equal(t2.asyncSliceGroup.length, 3); diff --git a/catapult/tracing/tracing/extras/chrome/gpu/state_test.html b/catapult/tracing/tracing/extras/chrome/gpu/state_test.html index 7883d498..4ddfe1e4 100644 --- a/catapult/tracing/tracing/extras/chrome/gpu/state_test.html +++ b/catapult/tracing/tracing/extras/chrome/gpu/state_test.html @@ -17,7 +17,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('basic', function() { - var m = tr.c.test_utils.newModelWithEvents([g_gpu_state_trace]); + var m = tr.c.TestUtils.newModelWithEvents([g_gpu_state_trace]); var p = tr.b.dictionaryValues(m.processes)[0]; var instance = p.objects.getAllInstancesNamed('gpu::State')[0]; diff --git a/catapult/tracing/tracing/extras/importer/battor_importer_test.html b/catapult/tracing/tracing/extras/importer/battor_importer_test.html index f37c8b06..f25d9769 100644 --- a/catapult/tracing/tracing/extras/importer/battor_importer_test.html +++ b/catapult/tracing/tracing/extras/importer/battor_importer_test.html @@ -55,7 +55,7 @@ tr.b.unittest.testSuite(function() { }); test('importPowerSamplesAndTrace', function() { - var m = tr.c.test_utils.newModelWithEvents( + var m = tr.c.TestUtils.newModelWithEvents( [SYSTRACE_LINES.join('\n'), BATTOR_LINES.join('\n')]); assert.isDefined(m.device.powerSeries); @@ -70,12 +70,12 @@ tr.b.unittest.testSuite(function() { }); test('importMissingLinuxTrace', function() { - var m = tr.c.test_utils.newModelWithEvents(BATTOR_LINES.join('\n')); + var m = tr.c.TestUtils.newModelWithEvents(BATTOR_LINES.join('\n')); assert.isTrue(m.hasImportWarnings); }); test('importNotEnoughSamples', function() { - var m = tr.c.test_utils.newModelWithEvents( + var m = tr.c.TestUtils.newModelWithEvents( BATTOR_LINES.slice(0, 5).join('\n')); assert.isTrue(m.hasImportWarnings); }); diff --git a/catapult/tracing/tracing/extras/importer/ddms_importer_test.html b/catapult/tracing/tracing/extras/importer/ddms_importer_test.html index 4eb5a4b1..c741aa12 100644 --- a/catapult/tracing/tracing/extras/importer/ddms_importer_test.html +++ b/catapult/tracing/tracing/extras/importer/ddms_importer_test.html @@ -19,7 +19,7 @@ tr.b.unittest.testSuite(function() { }); test('parseThreads', function() { - var m = tr.c.test_utils.newModelWithEvents(TEST_DATA, { + var m = tr.c.TestUtils.newModelWithEvents(TEST_DATA, { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); @@ -33,7 +33,7 @@ tr.b.unittest.testSuite(function() { }); test('parseMethods', function() { - var m = tr.c.test_utils.newModelWithEvents(TEST_DATA, { + var m = tr.c.TestUtils.newModelWithEvents(TEST_DATA, { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/gzip_importer_test.html b/catapult/tracing/tracing/extras/importer/gzip_importer_test.html index 31b9d1f3..2b354eb1 100644 --- a/catapult/tracing/tracing/extras/importer/gzip_importer_test.html +++ b/catapult/tracing/tracing/extras/importer/gzip_importer_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var findSliceNamed = tr.c.test_utils.findSliceNamed; + var findSliceNamed = tr.c.TestUtils.findSliceNamed; var original_data = '[{"name":"a","args":{},"pid":52,"ts":520,"cat":"foo","tid":53,' + '"ph":"B"},{"name":"a","args":{},"pid":52,"ts":520,"cat":"foo",' + @@ -52,7 +52,7 @@ tr.b.unittest.testSuite(function() { var gzip_data = atob(gzip_data_base64); assert.isTrue(tr.e.importer.GzipImporter.canImport(gzip_data)); - var model = tr.c.test_utils.newModelWithEvents(gzip_data); + var model = tr.c.TestUtils.newModelWithEvents(gzip_data); var threads = model.getAllThreads(); assert.equal(threads.length, 1); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/android_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/android_parser_test.html index 07cb9c02..ddc5ba99 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/android_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/android_parser_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function newModel(events) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false }); } @@ -212,7 +212,7 @@ tr.b.unittest.testSuite(function() { 'RenderThread-3894 [001] .n.1 253.780671: tracing_mark_write: E', // @suppress longLineCheck 'RenderThread-3894 [001] ...1 253.780671: tracing_mark_write: B|3586|waitForTask', // @suppress longLineCheck 'RenderThread-3894 [001] .p.1 253.780671: tracing_mark_write: E', // @suppress longLineCheck - 'RenderThread-3894 [001] ...1 253.780686: tracing_mark_write: E', // @suppress longLineCheck + 'RenderThread-3894 [001] ...1 253.780686: tracing_mark_write: E' // @suppress longLineCheck ]; var m = newModel(lines.join('\n')); assert.isFalse(m.hasImportWarnings, 'hasImportWarnings'); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser_test.html index d053bac6..513279ad 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser_test.html @@ -48,7 +48,7 @@ tr.b.unittest.testSuite(function() { ' trace_event_clock_sync: parent_ts=25196.050781' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shfitWorldToZero: false }); assert.isFalse(m.hasImportWarnings); @@ -94,7 +94,7 @@ tr.b.unittest.testSuite(function() { ' trace_event_clock_sync: parent_ts=25196.050781' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shfitWorldToZero: false }); var threads = m.getAllThreads(); @@ -190,7 +190,7 @@ tr.b.unittest.testSuite(function() { ' binder_transaction_received: transaction=923419' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shfitWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser_test.html index 8905fa64..ac733f44 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser_test.html @@ -53,7 +53,7 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck 'cycles=6690156 ns=16725375' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser_test.html index 5cea3145..71166a1a 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser_test.html @@ -45,7 +45,7 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck 'fout_apll state=500000000 cpu_id=0' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser_test.html index 229b3c87..114b8aa4 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function newModel(events) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser_test.html index 7b5816b8..6649f0e4 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser_test.html @@ -45,7 +45,7 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck 'ContactsProvide-1184 [000] ...1 66.613733: f2fs_write_end: ' + 'dev = (253,2), ino = 3342, pos = 0, len = 75, copied = 75' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser_test.html index 5181031f..61fa7d96 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser_test.html @@ -17,7 +17,7 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck ' chrome-2465 [000] 71.653157: drm_vblank_event: crtc=0, seq=4233', ' <idle>-0 [000] 71.669851: drm_vblank_event: crtc=0, seq=4234' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser_test.html index f7fa47f4..c27e7c65 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function newModel(events) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer_test.html index becc14d3..bfafb638 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer_test.html @@ -18,7 +18,7 @@ tr.b.unittest.testSuite(function() { tr.e.importer.linux_perf._LinuxPerfImporterTestExports; function newModel(events) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser_test.html index 8c678825..002844dc 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function newModel(events) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser_test.html index eb6adb82..c88ca84b 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser_test.html @@ -46,7 +46,7 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck 'intel_gpu_freq_change: new_freq=350' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser_test.html index c77b14aa..afd88ba8 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser_test.html @@ -23,7 +23,7 @@ tr.b.unittest.testSuite(function() { ' kworker/u4:2-31908 (31908) [000] ..s3 14063.477246: ' + 'softirq_exit: vec=9 [action=RCU]' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser_test.html index f685e70f..64b1aebd 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser_test.html @@ -26,7 +26,7 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck 'Binder_2-127 ( 127) [001] .... 3431.906896: graph_ent: func=sys_write', 'Binder_2-127 ( 127) [001] .... 3431.906906: graph_ret: func=sys_write' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser_test.html index 6688e5fc..be19c738 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function newModel(events) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser_test.html index ac61ca03..f6a10ecf 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function newModel(events) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/power_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/power_parser_test.html index 166cbcfb..9dae21dc 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/power_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/power_parser_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function newModel(events) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser_test.html index 5e19f2c2..328bf7c3 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser_test.html @@ -33,7 +33,7 @@ tr.b.unittest.testSuite(function() { 'kworker/0:1-30321 [000] ...1 144568.654785: ' + 'regulator_disable_complete: name=8941_smbb_boost' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser_test.html index 92ce7ab6..3548b757 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function newModel(events) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser_test.html index 8ae74cff..7d6902e0 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser_test.html @@ -32,7 +32,7 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck 's3c-fb-92 ( 0) [000] ...1 7206.591244: sync_wait: end name=vb2 state=1' // @suppress longLineCheck ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser_test.html b/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser_test.html index b1f5f534..4749b8f6 100644 --- a/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser_test.html +++ b/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser_test.html @@ -23,7 +23,7 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck ' kworker/1:2-7269 [001] 2784.805975: workqueue_execute_end: ' + 'work struct ffff88014fb0f158' ]; - var m = tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + var m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); assert.isFalse(m.hasImportWarnings); diff --git a/catapult/tracing/tracing/extras/importer/trace_event_importer.html b/catapult/tracing/tracing/extras/importer/trace_event_importer.html index 6aa46c1b..cc605c30 100644 --- a/catapult/tracing/tracing/extras/importer/trace_event_importer.html +++ b/catapult/tracing/tracing/extras/importer/trace_event_importer.html @@ -8,7 +8,7 @@ found in the LICENSE file. <link rel="import" href="/tracing/base/quad.html"> <link rel="import" href="/tracing/base/range.html"> <link rel="import" href="/tracing/base/utils.html"> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/units.html"> <link rel="import" href="/tracing/extras/importer/trace_code_entry.html"> <link rel="import" href="/tracing/extras/importer/v8/codemap.html"> <link rel="import" href="/tracing/importer/importer.html"> @@ -45,8 +45,8 @@ tr.exportTo('tr.e.importer', function() { } } - var timestampFromUs = tr.b.units.Time.timestampFromUs; - var maybeTimestampFromUs = tr.b.units.Time.maybeTimestampFromUs; + var timestampFromUs = tr.b.u.Units.timestampFromUs; + var maybeTimestampFromUs = tr.b.u.Units.maybeTimestampFromUs; var PRODUCER = 'producer'; var CONSUMER = 'consumer'; @@ -120,7 +120,7 @@ tr.exportTo('tr.e.importer', function() { // Some implementations specify displayTimeUnit if (container.displayTimeUnit) { var unitName = container.displayTimeUnit; - var unit = tr.b.units.Time.supportedUnits[unitName]; + var unit = tr.b.u.TimeDisplayModes[unitName]; if (unit === undefined) { throw new Error('Unit ' + unitName + ' is not supported.'); } diff --git a/catapult/tracing/tracing/extras/importer/trace_event_importer_perf_test.html b/catapult/tracing/tracing/extras/importer/trace_event_importer_perf_test.html index 0a85f25b..b7a7c57b 100644 --- a/catapult/tracing/tracing/extras/importer/trace_event_importer_perf_test.html +++ b/catapult/tracing/tracing/extras/importer/trace_event_importer_perf_test.html @@ -50,7 +50,7 @@ tr.b.unittest.testSuite(function() { n110100.forEach(function(val) { timedPerfTestWithEvents(TEST_NAMES[0] + '_' + val, function() { var events = getEvents(TEST_FILES_PATHS[0]); - var m = tr.c.test_utils.newModelWithEvents([events], { + var m = tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false, pruneContainers: false }); @@ -59,7 +59,7 @@ tr.b.unittest.testSuite(function() { timedPerfTestWithEvents(TEST_NAMES[1] + '_1', function() { var events = getEvents(TEST_FILES_PATHS[1]); - var m = tr.c.test_utils.newModelWithEvents([events], { + var m = tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false, pruneContainers: false }); diff --git a/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html b/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html index 64a49dff..434f4b83 100644 --- a/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html +++ b/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html @@ -5,7 +5,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <link rel="import" href="/tracing/core/test_utils.html"> <link rel="import" href="/tracing/extras/importer/trace_event_importer.html"> <link rel="import" href="/tracing/importer/import.html"> @@ -14,10 +14,10 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var findSliceNamed = tr.c.test_utils.findSliceNamed; + var findSliceNamed = tr.c.TestUtils.findSliceNamed; var makeModel = function(events, opt_shift, opt_prune) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: opt_shift, pruneEmptyContainers: opt_prune }); @@ -3682,7 +3682,7 @@ tr.b.unittest.testSuite(function() { displayTimeUnit: 'ns' }; var m = makeModel(JSON.stringify(eventData)); - assert.equal(m.intrinsicTimeUnit, tr.b.units.Time.supportedUnits.ns); + assert.equal(m.intrinsicTimeUnit, tr.b.u.TimeDisplayModes.ns); }); test('extractBattorSubTraces', function() { diff --git a/catapult/tracing/tracing/extras/importer/v8/v8_log_importer_test.html b/catapult/tracing/tracing/extras/importer/v8/v8_log_importer_test.html index d1a4d1c7..85cb3d97 100644 --- a/catapult/tracing/tracing/extras/importer/v8/v8_log_importer_test.html +++ b/catapult/tracing/tracing/extras/importer/v8/v8_log_importer_test.html @@ -16,7 +16,7 @@ tr.b.unittest.testSuite(function() { var V8LogImporter = tr.e.importer.v8.V8LogImporter; function newModel(events) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/extras/net/net_async_slice_test.html b/catapult/tracing/tracing/extras/net/net_async_slice_test.html index 31476108..4ef9fc80 100644 --- a/catapult/tracing/tracing/extras/net/net_async_slice_test.html +++ b/catapult/tracing/tracing/extras/net/net_async_slice_test.html @@ -31,7 +31,7 @@ tr.b.unittest.testSuite(function() { {name: 'HTTP_STREAM_JOB', args: {}, pid: 1, ts: 100, cat: 'netlog', tid: 2, ph: 'b', id: 71}, // @suppress longLineCheck {name: 'HTTP_STREAM_JOB', args: {}, pid: 1, ts: 200, cat: 'netlog', tid: 2, ph: 'e', id: 71} // @suppress longLineCheck ]; - var m = tr.c.test_utils.newModelWithEvents([events]); + var m = tr.c.TestUtils.newModelWithEvents([events]); var t2 = m.getOrCreateProcess(1).getOrCreateThread(2); assert.equal(t2.asyncSliceGroup.length, 1); assert.instanceOf(t2.asyncSliceGroup.slices[0], NetAsyncSlice); diff --git a/catapult/tracing/tracing/extras/rail/animation_interaction_record_test.html b/catapult/tracing/tracing/extras/rail/animation_interaction_record_test.html index a43a8ffa..7111b2ff 100644 --- a/catapult/tracing/tracing/extras/rail/animation_interaction_record_test.html +++ b/catapult/tracing/tracing/extras/rail/animation_interaction_record_test.html @@ -12,12 +12,12 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('OneHundredFPS', function() { var animationIR = new tr.e.rail.AnimationInteractionRecord(0, 100); for (var i = 1; i < 10; ++i) { - animationIR.associatedEvents.push(tr.c.test_utils.newAsyncSliceEx({ + animationIR.associatedEvents.push(tr.c.TestUtils.newAsyncSliceEx({ title: tr.e.audits.IMPL_RENDERING_STATS, start: i * 10, end: (i * 10) + 1 @@ -30,17 +30,17 @@ tr.b.unittest.testSuite(function() { // Maximum pain is when at least max(2, frameCount/10) frames are longer // than 50ms, and avgFPS <= 10. var animationIR = new tr.e.rail.AnimationInteractionRecord(0, 2000); - animationIR.associatedEvents.push(tr.c.test_utils.newAsyncSliceEx({ + animationIR.associatedEvents.push(tr.c.TestUtils.newAsyncSliceEx({ title: tr.e.audits.IMPL_RENDERING_STATS, start: 0, end: 1 })); - animationIR.associatedEvents.push(tr.c.test_utils.newAsyncSliceEx({ + animationIR.associatedEvents.push(tr.c.TestUtils.newAsyncSliceEx({ title: tr.e.audits.IMPL_RENDERING_STATS, start: 999, end: 1000 })); - animationIR.associatedEvents.push(tr.c.test_utils.newAsyncSliceEx({ + animationIR.associatedEvents.push(tr.c.TestUtils.newAsyncSliceEx({ title: tr.e.audits.IMPL_RENDERING_STATS, start: 1999, end: 2000 diff --git a/catapult/tracing/tracing/extras/rail/idle_interaction_record_test.html b/catapult/tracing/tracing/extras/rail/idle_interaction_record_test.html index b264209c..166481a5 100644 --- a/catapult/tracing/tracing/extras/rail/idle_interaction_record_test.html +++ b/catapult/tracing/tracing/extras/rail/idle_interaction_record_test.html @@ -12,7 +12,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('optimalEfficiency', function() { var idleIR = new tr.e.rail.IdleInteractionRecord(0, 150); @@ -21,7 +21,7 @@ tr.b.unittest.testSuite(function() { }); test('pessimalEfficiency', function() { - var slice = tr.c.test_utils.newSliceEx({ + var slice = tr.c.TestUtils.newSliceEx({ title: 'foo', start: 0, end: 150, diff --git a/catapult/tracing/tracing/extras/rail/ir_verifier.html b/catapult/tracing/tracing/extras/rail/ir_verifier.html index fa3435aa..81da2374 100644 --- a/catapult/tracing/tracing/extras/rail/ir_verifier.html +++ b/catapult/tracing/tracing/extras/rail/ir_verifier.html @@ -87,7 +87,8 @@ tr.exportTo('tr.e.rail', function() { }, verify: function() { - var model = tr.e.audits.newChromeModel(this.customizeModelCallback_); + var model = tr.e.chrome.ChromeTestUtils.newChromeModel( + this.customizeModelCallback_); var modelHelper = new tr.e.audits.ChromeModelHelper(model); var rirf = new tr.e.rail.RAILIRFinder(model, modelHelper); var actualIRs = rirf.findAllInteractionRecords(); diff --git a/catapult/tracing/tracing/extras/rail/rail_interaction_record_test.html b/catapult/tracing/tracing/extras/rail/rail_interaction_record_test.html index 482ba3c3..1ee5c9be 100644 --- a/catapult/tracing/tracing/extras/rail/rail_interaction_record_test.html +++ b/catapult/tracing/tracing/extras/rail/rail_interaction_record_test.html @@ -15,10 +15,10 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('layoutInfo', function() { - var model = tr.e.audits.newChromeModel(function(model) { + var model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) { // TODO(benjhayden): Create model.rendererMain.sliceGroup.pushSlice(test_utils.newSliceEx({ title: 'FrameView::layout', diff --git a/catapult/tracing/tracing/extras/rail/rail_ir_finder_test.html b/catapult/tracing/tracing/extras/rail/rail_ir_finder_test.html index bf39fa30..414d3350 100644 --- a/catapult/tracing/tracing/extras/rail/rail_ir_finder_test.html +++ b/catapult/tracing/tracing/extras/rail/rail_ir_finder_test.html @@ -14,13 +14,13 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var INPUT_TYPE = tr.e.cc.INPUT_EVENT_TYPE_NAMES; - var audits = tr.e.audits; + var chrome_test_utils = tr.e.chrome.ChromeTestUtils; var IRVerifier = tr.e.rail.IRVerifier; function addFrameEventForInput(model, event) { - var frame = audits.addFrameEvent(model, + var frame = chrome_test_utils.addFrameEvent(model, {start: event.start, end: event.end, isTopLevel: true}); - model.flowEvents.push(tr.c.test_utils.newFlowEventEx({ + model.flowEvents.push(tr.c.TestUtils.newFlowEventEx({ id: event.id, start: event.start, end: event.end, @@ -41,18 +41,18 @@ tr.b.unittest.testSuite(function() { test('slowMouseMoveResponses', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN, - {start: 0, end: 10}); - var mouseMove = audits.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, - {start: 10, end: 20, id: '0x100'}); + chrome_test_utils.addInputEvent( + model, INPUT_TYPE.MOUSE_DOWN, {start: 0, end: 10}); + var mouseMove = chrome_test_utils.addInputEvent( + model, INPUT_TYPE.MOUSE_MOVE, {start: 10, end: 20, id: '0x100'}); addFrameEventForInput(model, mouseMove); - mouseMove = audits.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, - {start: 70, end: 80, id: '0x101'}); + mouseMove = chrome_test_utils.addInputEvent( + model, INPUT_TYPE.MOUSE_MOVE, {start: 70, end: 80, id: '0x101'}); addFrameEventForInput(model, mouseMove); - mouseMove = audits.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, - {start: 130, end: 140, id: '0x102'}); + mouseMove = chrome_test_utils.addInputEvent( + model, INPUT_TYPE.MOUSE_MOVE, {start: 130, end: 140, id: '0x102'}); addFrameEventForInput(model, mouseMove); }; verifier.expectedIRs = [ @@ -69,16 +69,16 @@ tr.b.unittest.testSuite(function() { test('MouseEventResponses', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - var mouseDown = audits.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN, - {start: 0, end: 50, id: '0x100'}); + var mouseDown = chrome_test_utils.addInputEvent( + model, INPUT_TYPE.MOUSE_DOWN, {start: 0, end: 50, id: '0x100'}); addFrameEventForInput(model, mouseDown); - var mouseUp = audits.addInputEvent(model, INPUT_TYPE.MOUSE_UP, + var mouseUp = chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_UP, {start: 50, end: 100, id: '0x101'}); addFrameEventForInput(model, mouseUp); - var mouseMove = audits.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, - {start: 200, end: 250, id: '0x102'}); + var mouseMove = chrome_test_utils.addInputEvent( + model, INPUT_TYPE.MOUSE_MOVE, {start: 200, end: 250, id: '0x102'}); addFrameEventForInput(model, mouseMove); }; verifier.expectedIRs = [ @@ -93,9 +93,9 @@ tr.b.unittest.testSuite(function() { test('MouseEventsIgnored', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, {start: 0, end: 50}); - audits.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN, {start: 50, end: 100}); }; verifier.expectedIRs = [ @@ -110,12 +110,12 @@ tr.b.unittest.testSuite(function() { // ThreadSlices in the model. var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - var start = tr.c.test_utils.newSliceEx( + var start = tr.c.TestUtils.newSliceEx( {title: 'model start', start: 0, end: 1, type: tr.model.ThreadSlice}); start.isTopLevel = true; model.browserMain.sliceGroup.pushSlice(start); - var end = tr.c.test_utils.newSliceEx( + var end = tr.c.TestUtils.newSliceEx( {title: 'model end', start: 9, end: 10, type: tr.model.ThreadSlice}); end.isTopLevel = true; model.browserMain.sliceGroup.pushSlice(end); @@ -132,56 +132,56 @@ tr.b.unittest.testSuite(function() { // measurmt-traces/mobile/cnet_fling_up_fling_down_motox_2013.json var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addFrameEvent(model, {start: 0, end: 10}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_START, + chrome_test_utils.addFrameEvent(model, {start: 0, end: 10}); + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, {start: 919, end: 998}); - audits.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, {start: 919, end: 1001}); - audits.addInputEvent(model, INPUT_TYPE.TAP_DOWN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, {start: 919, end: 1001}); - audits.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, {start: 974, end: 1020}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, {start: 974, end: 1020}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 974, end: 1040}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 974, end: 1054}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 990, end: 1021}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 990, end: 1052}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 1006, end: 1021}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 1022, end: 1036}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 1022, end: 1052}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 1038, end: 1049}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 1038, end: 1068}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, {start: 1046, end: 1050}); - audits.addInputEvent(model, INPUT_TYPE.FLING_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, {start: 1046, end: 1077}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, {start: 1432, end: 2238}); - audits.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, {start: 1432, end: 2241}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 1516, end: 2605}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, {start: 1532, end: 2274}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 1532, end: 2294}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 1549, end: 2310}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, {start: 1627, end: 2275}); - audits.addInputEvent(model, INPUT_TYPE.FLING_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, {start: 1627, end: 2310}); - audits.addFrameEvent(model, {start: 2990, end: 3000}); + chrome_test_utils.addFrameEvent(model, {start: 2990, end: 3000}); }; verifier.expectedIRs = [ {title: 'Idle', start: 0, end: 919, eventCount: 0}, @@ -204,9 +204,9 @@ tr.b.unittest.testSuite(function() { test('keyboardEvents', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.KEY_DOWN_RAW, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.KEY_DOWN_RAW, {start: 0, end: 45}); - audits.addInputEvent(model, INPUT_TYPE.CHAR, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.CHAR, {start: 10, end: 50}); }; verifier.expectedIRs = [ @@ -218,11 +218,11 @@ tr.b.unittest.testSuite(function() { test('mouseResponses', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.CLICK, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.CLICK, {start: 0, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.CONTEXT_MENU, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.CONTEXT_MENU, {start: 200, end: 300}); - audits.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, {start: 400, end: 500}); }; verifier.expectedIRs = [ @@ -239,19 +239,19 @@ tr.b.unittest.testSuite(function() { test('mouseWheelAnimation', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, {start: 0, end: 20}); - audits.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, {start: 16, end: 36}); - audits.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, {start: 55, end: 75}); // This threshold uses both events' start times, not end...start. - audits.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, {start: 100, end: 150}); - audits.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, {start: 141, end: 191}); - audits.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, {start: 182, end: 200}); }; verifier.expectedIRs = [ @@ -272,9 +272,9 @@ tr.b.unittest.testSuite(function() { test('mouseDownUpResponse', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN, {start: 0, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.MOUSE_UP, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_UP, {start: 200, end: 210}); }; verifier.expectedIRs = [ @@ -287,7 +287,7 @@ tr.b.unittest.testSuite(function() { test('ignoreLoneMouseMoves', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, {start: 0, end: 100}); }; verifier.expectedIRs = [ @@ -299,16 +299,16 @@ tr.b.unittest.testSuite(function() { test('mouseDrags', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN, - {start: 0, end: 100}); - var mouseMove = audits.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, - {start: 200, end: 215}); + chrome_test_utils.addInputEvent( + model, INPUT_TYPE.MOUSE_DOWN, {start: 0, end: 100}); + var mouseMove = chrome_test_utils.addInputEvent( + model, INPUT_TYPE.MOUSE_MOVE, {start: 200, end: 215}); addFrameEventForInput(model, mouseMove); - mouseMove = audits.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, - {start: 210, end: 220}); + mouseMove = chrome_test_utils.addInputEvent( + model, INPUT_TYPE.MOUSE_MOVE, {start: 210, end: 220}); addFrameEventForInput(model, mouseMove); - mouseMove = audits.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, - {start: 221, end: 240}); + mouseMove = chrome_test_utils.addInputEvent( + model, INPUT_TYPE.MOUSE_MOVE, {start: 221, end: 240}); addFrameEventForInput(model, mouseMove); }; verifier.expectedIRs = [ @@ -322,29 +322,29 @@ tr.b.unittest.testSuite(function() { test('twoScrollsNoFling', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, {start: 0, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 20, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 40, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 60, end: 150}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 70, end: 150}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_END, {start: 80, end: 150}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, {start: 300, end: 400}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 320, end: 400}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 330, end: 450}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 340, end: 450}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 350, end: 500}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_END, {start: 360, end: 500}); }; verifier.expectedIRs = [ @@ -363,13 +363,13 @@ tr.b.unittest.testSuite(function() { // They are merged with other kinds of animations. var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addEvent(model.rendererMain, { + chrome_test_utils.addEvent(model.rendererMain, { title: 'Animation', start: 0, end: 100}); - audits.addEvent(model.rendererMain, { + chrome_test_utils.addEvent(model.rendererMain, { title: 'Animation', start: 99, end: 200}); - audits.addInputEvent(model, INPUT_TYPE.FLING_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, {start: 150, end: 180}); - audits.addFrameEvent(model, {start: 290, end: 300}); + chrome_test_utils.addFrameEvent(model, {start: 290, end: 300}); }; verifier.expectedIRs = [ {title: 'Animation', name: 'CSS', start: 0, end: 200, eventCount: 2}, @@ -381,10 +381,10 @@ tr.b.unittest.testSuite(function() { test('flingThatIsntstopped', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.FLING_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, {start: 32, end: 100}); - audits.addFlingAnimationEvent(model, {start: 38, end: 200}); - audits.addFrameEvent(model, {start: 290, end: 300}); + chrome_test_utils.addFlingAnimationEvent(model, {start: 38, end: 200}); + chrome_test_utils.addFrameEvent(model, {start: 290, end: 300}); }; verifier.expectedIRs = [ {title: 'Animation', name: 'Fling', start: 32, end: 200, eventCount: 2}, @@ -396,9 +396,9 @@ tr.b.unittest.testSuite(function() { test('flingThatIsStopped', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.FLING_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, {start: 32, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, {start: 105, end: 150}); }; verifier.expectedIRs = [ @@ -412,21 +412,21 @@ tr.b.unittest.testSuite(function() { // measurmt-traces/mobile/facebook_obama_scroll_dialog_box.html var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.FLING_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, {start: 0, end: 30}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, {start: 100, end: 130}); - audits.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, {start: 100, end: 130}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 110, end: 140}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 170, end: 180}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, {start: 200, end: 210}); - audits.addInputEvent(model, INPUT_TYPE.FLING_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, {start: 200, end: 220}); - audits.addFrameEvent(model, {start: 230, end: 240}); + chrome_test_utils.addFrameEvent(model, {start: 230, end: 240}); }; verifier.expectedIRs = [ {title: 'Animation', name: 'Fling', start: 0, end: 100, eventCount: 2}, @@ -440,8 +440,8 @@ tr.b.unittest.testSuite(function() { test('Load', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addCommitLoadEvent(model, {start: 0, end: 10}); - audits.addFrameEvent(model, {start: 11, end: 20}); + chrome_test_utils.addCommitLoadEvent(model, {start: 0, end: 10}); + chrome_test_utils.addFrameEvent(model, {start: 11, end: 20}); }; verifier.expectedIRs = [ {title: 'Load', name: 'Succeeded', start: 0, end: 20, eventCount: 2} @@ -452,8 +452,10 @@ tr.b.unittest.testSuite(function() { test('LoadFailed', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addStartProvisionalLoadEvent(model, {start: 0, end: 10}); - audits.addFailProvisionalLoadEvent(model, {start: 11, end: 20}); + chrome_test_utils.addStartProvisionalLoadEvent( + model, {start: 0, end: 10}); + chrome_test_utils.addFailProvisionalLoadEvent( + model, {start: 11, end: 20}); }; verifier.expectedIRs = [ {title: 'Load', name: 'Failed', start: 0, end: 20, eventCount: 2} @@ -464,8 +466,8 @@ tr.b.unittest.testSuite(function() { test('LoadMainRunner', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addMainRunnerEvent(model, {start: 0, end: 10}); - audits.addFrameEvent(model, {start: 11, end: 20}); + chrome_test_utils.addMainRunnerEvent(model, {start: 0, end: 10}); + chrome_test_utils.addFrameEvent(model, {start: 11, end: 20}); }; verifier.expectedIRs = [ {title: 'Load', name: 'Startup', start: 0, end: 20, eventCount: 2} @@ -476,7 +478,7 @@ tr.b.unittest.testSuite(function() { test('totalIdle', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addFrameEvent(model, {start: 0, end: 10}); + chrome_test_utils.addFrameEvent(model, {start: 0, end: 10}); }; verifier.expectedIRs = [ {title: 'Idle', start: 0, end: 10, eventCount: 0} @@ -487,14 +489,14 @@ tr.b.unittest.testSuite(function() { test('MultipleIdles', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addFrameEvent(model, {start: 0, end: 1}); - audits.addCommitLoadEvent(model, {start: 1, end: 2}); - audits.addFrameEvent(model, {start: 3, end: 4}); - audits.addCommitLoadEvent(model, {start: 5, end: 6}); - audits.addFrameEvent(model, {start: 7, end: 8}); - audits.addCommitLoadEvent(model, {start: 9, end: 10}); - audits.addFrameEvent(model, {start: 11, end: 12}); - audits.addFrameEvent(model, {start: 12, end: 13}); + chrome_test_utils.addFrameEvent(model, {start: 0, end: 1}); + chrome_test_utils.addCommitLoadEvent(model, {start: 1, end: 2}); + chrome_test_utils.addFrameEvent(model, {start: 3, end: 4}); + chrome_test_utils.addCommitLoadEvent(model, {start: 5, end: 6}); + chrome_test_utils.addFrameEvent(model, {start: 7, end: 8}); + chrome_test_utils.addCommitLoadEvent(model, {start: 9, end: 10}); + chrome_test_utils.addFrameEvent(model, {start: 11, end: 12}); + chrome_test_utils.addFrameEvent(model, {start: 12, end: 13}); }; verifier.expectedIRs = [ {title: 'Idle', start: 0, end: 1, eventCount: 0}, @@ -511,9 +513,9 @@ tr.b.unittest.testSuite(function() { test('TouchStartTouchEndTap', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.TOUCH_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, {start: 0, end: 10}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, {start: 200, end: 210}); }; verifier.expectedIRs = [ @@ -525,13 +527,13 @@ tr.b.unittest.testSuite(function() { test('TouchMoveResponseAnimation', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.TOUCH_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, {start: 0, end: 10}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 50, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 70, end: 150}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, {start: 200, end: 300}); }; verifier.expectedIRs = [ @@ -544,11 +546,11 @@ tr.b.unittest.testSuite(function() { test('TapEvents', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.TAP, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP, {start: 0, end: 50}); - audits.addInputEvent(model, INPUT_TYPE.TAP_DOWN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, {start: 300, end: 310}); - audits.addInputEvent(model, INPUT_TYPE.TAP, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP, {start: 320, end: 350}); }; verifier.expectedIRs = [ @@ -562,9 +564,9 @@ tr.b.unittest.testSuite(function() { test('TapAndTapCancelResponses', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.TAP_DOWN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, {start: 0, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, {start: 300, end: 350}); }; verifier.expectedIRs = [ @@ -578,9 +580,9 @@ tr.b.unittest.testSuite(function() { test('TapCancelResponse', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.TAP_DOWN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, {start: 0, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, {start: 150, end: 200}); }; verifier.expectedIRs = [ @@ -592,21 +594,21 @@ tr.b.unittest.testSuite(function() { test('PinchResponseAnimation', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addFrameEvent(model, {start: 0, end: 10}); - audits.addInputEvent(model, INPUT_TYPE.PINCH_BEGIN, + chrome_test_utils.addFrameEvent(model, {start: 0, end: 10}); + chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_BEGIN, {start: 100, end: 150}); - audits.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, {start: 130, end: 160}); - audits.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, {start: 140, end: 200}); - audits.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, {start: 150, end: 205}); - audits.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, {start: 210, end: 220}); // pause > 200ms - audits.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, {start: 421, end: 470}); - audits.addInputEvent(model, INPUT_TYPE.PINCH_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_END, {start: 460, end: 500}); }; verifier.expectedIRs = [ @@ -623,15 +625,15 @@ tr.b.unittest.testSuite(function() { // measurmt-traces/mobile/google_io_instrument_strumming.json var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.TOUCH_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, {start: 0, end: 20}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, {start: 40, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, {start: 50, end: 120}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 80, end: 150}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 180, end: 200}); }; verifier.expectedIRs = [ @@ -645,50 +647,50 @@ tr.b.unittest.testSuite(function() { test('PinchFlingTapTouchEventsOverlap', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addFrameEvent(model, {start: 0, end: 10}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_START, + chrome_test_utils.addFrameEvent(model, {start: 0, end: 10}); + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, {start: 20, end: 50}); - audits.addInputEvent(model, INPUT_TYPE.TAP_DOWN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, {start: 20, end: 30}); - audits.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, {start: 20, end: 50}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 60, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, {start: 60, end: 110}); - audits.addInputEvent(model, INPUT_TYPE.PINCH_BEGIN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_BEGIN, {start: 60, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, {start: 65, end: 75}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 70, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, {start: 70, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 75, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 80, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 85, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, {start: 75, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 150, end: 200}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 150, end: 200}); - audits.addInputEvent(model, INPUT_TYPE.FLING_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, {start: 180, end: 210}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, {start: 190, end: 210}); - audits.addFrameEvent(model, {start: 215, end: 220}); + chrome_test_utils.addFrameEvent(model, {start: 215, end: 220}); }; verifier.expectedIRs = [ {title: 'Idle', start: 0, end: 20, eventCount: 0}, - {title: 'Response', name:'Pinch,Scroll,Tap,Touch', start: 20, end: 110, + {title: 'Response', name: 'Pinch,Scroll,Tap,Touch', start: 20, end: 110, eventCount: 9}, - {title: 'Animation', name:'Scroll,Touch', start: 110, end: 210, + {title: 'Animation', name: 'Scroll,Touch', start: 110, end: 210, eventCount: 6}, - {title: 'Animation', name:'Fling', start: 180, end: 220, eventCount: 1} + {title: 'Animation', name: 'Fling', start: 180, end: 220, eventCount: 1} ]; verifier.verify(); }); @@ -696,13 +698,13 @@ tr.b.unittest.testSuite(function() { test('ScrollThenFling', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 0, end: 40}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 50, end: 100}); - audits.addInputEvent(model, INPUT_TYPE.FLING_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, {start: 80, end: 100}); - audits.addFrameEvent(model, {start: 190, end: 200}); + chrome_test_utils.addFrameEvent(model, {start: 190, end: 200}); }; verifier.expectedIRs = [ {title: 'Animation', name: 'Scroll', start: 0, end: 100, eventCount: 2}, @@ -718,44 +720,44 @@ tr.b.unittest.testSuite(function() { test('fling_HN_to_rest', function() { var verifier = new IRVerifier(); verifier.customizeModelCallback = function(model) { - audits.addEvent(model.browserMain, + chrome_test_utils.addEvent(model.browserMain, {title: 'model start', start: 0, end: 1}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, {start: 1274, end: 1297}); - audits.addInputEvent(model, INPUT_TYPE.TAP_DOWN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, {start: 1274, end: 1305}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 1343, end: 1350}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 1359, end: 1366}); - audits.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, {start: 1359, end: 1366}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, {start: 1359, end: 1367}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 1359, end: 1387}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 1375, end: 1385}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 1375, end: 1416}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 1389, end: 1404}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 1389, end: 1429}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 1405, end: 1418}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 1405, end: 1449}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, {start: 1419, end: 1432}); - audits.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, {start: 1419, end: 1474}); - audits.addInputEvent(model, INPUT_TYPE.TOUCH_END, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, {start: 1427, end: 1435}); - audits.addInputEvent(model, INPUT_TYPE.FLING_START, + chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, {start: 1427, end: 1474}); - audits.addFlingAnimationEvent(model, {start: 1440, end: 2300}); - audits.addEvent(model.browserMain, + chrome_test_utils.addFlingAnimationEvent(model, {start: 1440, end: 2300}); + chrome_test_utils.addEvent(model.browserMain, {title: 'model end', start: 3184, end: 3185}); }; verifier.expectedIRs = [ diff --git a/catapult/tracing/tracing/extras/rail/rail_score.html b/catapult/tracing/tracing/extras/rail/rail_score.html index 253c83ac..57bef096 100644 --- a/catapult/tracing/tracing/extras/rail/rail_score.html +++ b/catapult/tracing/tracing/extras/rail/rail_score.html @@ -61,6 +61,12 @@ tr.exportTo('tr.e.rail', function() { denominator += weight; }); return numerator / denominator; + }, + + asDict: function() { + return { + overallScore: this.overallScore + }; } }; diff --git a/catapult/tracing/tracing/extras/rail/rail_score_test.html b/catapult/tracing/tracing/extras/rail/rail_score_test.html index 2713b8dd..fd9d9235 100644 --- a/catapult/tracing/tracing/extras/rail/rail_score_test.html +++ b/catapult/tracing/tracing/extras/rail/rail_score_test.html @@ -137,7 +137,7 @@ tr.b.unittest.testSuite(function() { }); test('fromModel', function() { - var model = tr.e.audits.newChromeModel(function(model) { + var model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) { model.addInteractionRecord(new tr.e.rail.RAILInteractionRecord( 'Idle', 'rail_idle', 0, 1)); }); @@ -146,7 +146,7 @@ tr.b.unittest.testSuite(function() { }); test('fromEmptyModel', function() { - var model = tr.e.audits.newChromeModel(function(model) { + var model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) { }); assert.isUndefined(tr.e.rail.RAILScore.fromModel(model)); }); diff --git a/catapult/tracing/tracing/extras/rail/response_interaction_record_test.html b/catapult/tracing/tracing/extras/rail/response_interaction_record_test.html index 276407e8..6818cf1b 100644 --- a/catapult/tracing/tracing/extras/rail/response_interaction_record_test.html +++ b/catapult/tracing/tracing/extras/rail/response_interaction_record_test.html @@ -11,7 +11,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('instantiate', function() { var responseIR = new tr.e.rail.ResponseInteractionRecord(0, 150); diff --git a/catapult/tracing/tracing/extras/rail/stub_rail_interaction_record.html b/catapult/tracing/tracing/extras/rail/stub_rail_interaction_record.html index 45e83733..d2cfa53b 100644 --- a/catapult/tracing/tracing/extras/rail/stub_rail_interaction_record.html +++ b/catapult/tracing/tracing/extras/rail/stub_rail_interaction_record.html @@ -16,7 +16,7 @@ found in the LICENSE file. */ tr.exportTo('tr.e.rail', function() { function StubRAILInteractionRecord(args) { - var sd = tr.c.test_utils.getStartAndDurationFromDict(args); + var sd = tr.c.TestUtils.getStartAndDurationFromDict(args); tr.e.rail.RAILInteractionRecord.call( this, args.railTypeName, args.railTypeName, sd.start, sd.duration); diff --git a/catapult/tracing/tracing/extras/systrace_config.html b/catapult/tracing/tracing/extras/systrace_config.html index 66bea8ef..54efc9b8 100644 --- a/catapult/tracing/tracing/extras/systrace_config.html +++ b/catapult/tracing/tracing/extras/systrace_config.html @@ -14,3 +14,4 @@ found in the LICENSE file. <link rel="import" href="/tracing/extras/importer/ddms_importer.html"> <link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html"> <link rel="import" href="/tracing/extras/android/android_auditor.html"> +<link rel="import" href="/tracing/extras/vsync/vsync_auditor.html"> diff --git a/catapult/tracing/tracing/extras/vsync/vsync_auditor.html b/catapult/tracing/tracing/extras/vsync/vsync_auditor.html index 47711c54..d365fd2b 100644 --- a/catapult/tracing/tracing/extras/vsync/vsync_auditor.html +++ b/catapult/tracing/tracing/extras/vsync/vsync_auditor.html @@ -30,6 +30,10 @@ tr.exportTo('tr.e.audits', function() { 'DisplayLinkMac::GetVSyncParameters': 5 }; + var BEGIN_FRAME_SLICE_PRECISION = { + 'Scheduler::BeginFrame': 10 + }; + /** * Auditor that analyzes the model and, if possible, adds data to it * indicating when vertical sync events took place. @@ -59,11 +63,14 @@ tr.exportTo('tr.e.audits', function() { var maxTitle = undefined; function useInstead(title, precisions) { + var precision = precisions[title]; + if (precision === undefined) + return false; + if (title === maxTitle) return true; - var precision = precisions[title]; - if (precision === undefined || precision <= maxPrecision) { + if (precision <= maxPrecision) { if (precision === maxPrecision) { console.warn('Encountered two different VSync events (' + maxTitle + ', ' + title + ') with the same precision, ' + @@ -98,6 +105,8 @@ tr.exportTo('tr.e.audits', function() { var slice = thread.sliceGroup.slices[i]; if (useInstead(slice.title, VSYNC_SLICE_PRECISIONS)) times.push(slice.start); + else if (useInstead(slice.title, BEGIN_FRAME_SLICE_PRECISION)) + times.push(slice.args.frame_time_us / 1000.0); } } } diff --git a/catapult/tracing/tracing/extras/vsync/vsync_auditor_test.html b/catapult/tracing/tracing/extras/vsync/vsync_auditor_test.html index 6644363c..a06e423c 100644 --- a/catapult/tracing/tracing/extras/vsync/vsync_auditor_test.html +++ b/catapult/tracing/tracing/extras/vsync/vsync_auditor_test.html @@ -111,5 +111,13 @@ tr.b.unittest.testSuite(function() { buildSlice('RenderWidgetHostViewAndroid::OnVSync', 3)] ], [], [2]); }); + + test('findBeginFrame', function() { + var title = 'Scheduler::BeginFrame'; + testFindVSyncTimestamps([[ + new ThreadSlice('', title, 0, 2, { frame_time_us: 1000 }), + new ThreadSlice('', title, 0, 4, { frame_time_us: 3000 }) + ]], [], [1, 3]); + }); }); </script> diff --git a/catapult/tracing/tracing/importer/import_test.html b/catapult/tracing/tracing/importer/import_test.html index 4e3d3294..c4a03ccf 100644 --- a/catapult/tracing/tracing/importer/import_test.html +++ b/catapult/tracing/tracing/importer/import_test.html @@ -17,7 +17,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('canImportEmpty', function() { - var m = tr.c.test_utils.newModelWithEvents([]); + var m = tr.c.TestUtils.newModelWithEvents([]); assert.isDefined(m.modelIndices); m = new tr.Model(''); }); @@ -41,7 +41,7 @@ tr.b.unittest.testSuite(function() { systemTraceEvents: systraceLines.join('\n') }); - var m = tr.c.test_utils.newModelWithEvents([combined]); + var m = tr.c.TestUtils.newModelWithEvents([combined]); assert.equal(tr.b.dictionaryValues(m.processes).length, 1); var p1 = m.processes[1]; @@ -62,7 +62,7 @@ tr.b.unittest.testSuite(function() { test('canImportCompressedSingleSubtrace', function() { var compressedTrace = atob('H4sIACKfFVUC/wsuLUpLTE51y8nMS08t0jVSUIg2MDCMV' + 'dDT0zNUMDQwMNAzsFIAIqcaw5qSxOJsR65gfDqMEDpcATiC61ZbAAAA'); - var m = tr.c.test_utils.newModelWithEvents([compressedTrace]); + var m = tr.c.TestUtils.newModelWithEvents([compressedTrace]); assert.equal(1, tr.b.dictionaryValues(m.processes).length); var p1 = m.processes[1]; @@ -102,7 +102,7 @@ tr.b.unittest.testSuite(function() { systemTraceEvents: innerTrace }); - var m = tr.c.test_utils.newModelWithEvents([outerTrace]); + var m = tr.c.TestUtils.newModelWithEvents([outerTrace]); assert.equal(tr.b.dictionaryValues(m.processes).length, 1); var p1 = m.processes[1]; @@ -122,12 +122,12 @@ tr.b.unittest.testSuite(function() { test('withImportFailure', function() { assert.throw(function() { - tr.c.test_utils.newModelWithEvents([malformed]); + tr.c.TestUtils.newModelWithEvents([malformed]); }); }); test('customizeCallback', function() { - var m = tr.c.test_utils.newModelWithEvents([], { + var m = tr.c.TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: function(m) { @@ -151,7 +151,7 @@ tr.b.unittest.testSuite(function() { // and irrespective of the order // in which the lines appear in the trace, // the samples should always be sorted by sampling time. - var m = tr.c.test_utils.newModelWithEvents([ + var m = tr.c.TestUtils.newModelWithEvents([ 'tick,0x9a,184,0,0x0,5', 'tick,0x9b,0,0,0x0,5', 'tick,0x9c,185,0,0x0,5']); @@ -161,7 +161,7 @@ tr.b.unittest.testSuite(function() { }); test('sortsGlobalMemoryDumps', function() { - var m = tr.c.test_utils.newModelWithEvents([], { + var m = tr.c.TestUtils.newModelWithEvents([], { pruneContainers: false, customizeModelCallback: function(m) { m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 1)); @@ -176,7 +176,7 @@ tr.b.unittest.testSuite(function() { test('finalizesProcessMemoryDumps', function() { var p; - var m = tr.c.test_utils.newModelWithEvents([], { + var m = tr.c.TestUtils.newModelWithEvents([], { pruneContainers: false, customizeModelCallback: function(m) { p = m.getOrCreateProcess(1); diff --git a/catapult/tracing/tracing/model/alert.html b/catapult/tracing/tracing/model/alert.html index 66ed4b92..9f5b7845 100644 --- a/catapult/tracing/tracing/model/alert.html +++ b/catapult/tracing/tracing/model/alert.html @@ -38,7 +38,7 @@ tr.exportTo('tr.model', function() { get userFriendlyName() { return 'Alert ' + this.title + ' at ' + - tr.b.units.TimeStamp.format(this.start); + tr.b.u.TimeStamp.format(this.start); } }; diff --git a/catapult/tracing/tracing/model/async_slice.html b/catapult/tracing/tracing/model/async_slice.html index 2baed497..4da1723c 100644 --- a/catapult/tracing/tracing/model/async_slice.html +++ b/catapult/tracing/tracing/model/async_slice.html @@ -78,7 +78,7 @@ tr.exportTo('tr.model', function() { get userFriendlyName() { return 'Async slice ' + this.title + ' at ' + - tr.b.units.TimeStamp.format(this.start); + tr.b.u.TimeStamp.format(this.start); }, findDescendentSlice: function(targetTitle) { diff --git a/catapult/tracing/tracing/model/async_slice_group_test.html b/catapult/tracing/tracing/model/async_slice_group_test.html index 58d5beec..739e6f7e 100644 --- a/catapult/tracing/tracing/model/async_slice_group_test.html +++ b/catapult/tracing/tracing/model/async_slice_group_test.html @@ -16,9 +16,9 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck var Thread = tr.model.Thread; var AsyncSlice = tr.model.AsyncSlice; var AsyncSliceGroup = tr.model.AsyncSliceGroup; - var newAsyncSlice = tr.c.test_utils.newAsyncSlice; - var newAsyncSliceEx = tr.c.test_utils.newAsyncSliceEx; - var newModel = tr.c.test_utils.newModel; + var newAsyncSlice = tr.c.TestUtils.newAsyncSlice; + var newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx; + var newModel = tr.c.TestUtils.newModel; test('asyncSliceGroupBounds_Empty', function() { var thread = {}; diff --git a/catapult/tracing/tracing/model/counter_sample.html b/catapult/tracing/tracing/model/counter_sample.html index 878cdaef..e8e51a4e 100644 --- a/catapult/tracing/tracing/model/counter_sample.html +++ b/catapult/tracing/tracing/model/counter_sample.html @@ -83,7 +83,7 @@ tr.exportTo('tr.model', function() { get userFriendlyName() { return 'Counter sample from ' + this.series_.title + ' at ' + - tr.b.units.TimeStamp.format(this.timestamp); + tr.b.u.TimeStamp.format(this.timestamp); } }; diff --git a/catapult/tracing/tracing/model/cpu_test.html b/catapult/tracing/tracing/model/cpu_test.html index d4ba61d9..49be00df 100644 --- a/catapult/tracing/tracing/model/cpu_test.html +++ b/catapult/tracing/tracing/model/cpu_test.html @@ -14,7 +14,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var Cpu = tr.model.Cpu; - var newThreadSlice = tr.c.test_utils.newThreadSlice; + var newThreadSlice = tr.c.TestUtils.newThreadSlice; test('cpuBounds_Empty', function() { var cpu = new Cpu({}, 1); @@ -25,7 +25,7 @@ tr.b.unittest.testSuite(function() { test('cpuBounds_OneSlice', function() { var cpu = new Cpu({}, 1); - cpu.slices.push(tr.c.test_utils.newSlice(1, 3)); + cpu.slices.push(tr.c.TestUtils.newSlice(1, 3)); cpu.updateBounds(); assert.equal(cpu.bounds.min, 1); assert.equal(cpu.bounds.max, 4); @@ -41,13 +41,13 @@ tr.b.unittest.testSuite(function() { test('shiftTimestampsForward', function() { var cpu = new Cpu({}, 1); var ctr = cpu.getOrCreateCounter('foo', 'bar'); - cpu.slices.push(tr.c.test_utils.newSlice(1, 3)); + cpu.slices.push(tr.c.TestUtils.newSlice(1, 3)); var shiftCount = 0; ctr.shiftTimestampsForward = function(ts) { if (ts == 0.32) shiftCount++; }; - cpu.slices.push(tr.c.test_utils.newSlice(1, 3)); + cpu.slices.push(tr.c.TestUtils.newSlice(1, 3)); cpu.shiftTimestampsForward(0.32); assert.equal(1, shiftCount); assert.equal(cpu.slices[0].start, 1.32); diff --git a/catapult/tracing/tracing/model/event_set_test.html b/catapult/tracing/tracing/model/event_set_test.html index 3324dff1..3c83e53f 100644 --- a/catapult/tracing/tracing/model/event_set_test.html +++ b/catapult/tracing/tracing/model/event_set_test.html @@ -13,8 +13,8 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newModel = tr.c.test_utils.newModel; - var newSliceEx = tr.c.test_utils.newSliceEx; + var newModel = tr.c.TestUtils.newModel; + var newSliceEx = tr.c.TestUtils.newSliceEx; test('eventSetObject', function() { var model = new tr.Model(); diff --git a/catapult/tracing/tracing/model/flow_event.html b/catapult/tracing/tracing/model/flow_event.html index c3a7dc1a..861bcab0 100644 --- a/catapult/tracing/tracing/model/flow_event.html +++ b/catapult/tracing/tracing/model/flow_event.html @@ -47,7 +47,7 @@ tr.exportTo('tr.model', function() { get userFriendlyName() { return 'Flow event named ' + this.title + ' at ' + - tr.b.units.TimeStamp.format(this.timestamp); + tr.b.u.TimeStamp.format(this.timestamp); } }; diff --git a/catapult/tracing/tracing/model/global_memory_dump.html b/catapult/tracing/tracing/model/global_memory_dump.html index 1f6e1a68..7a01c96f 100644 --- a/catapult/tracing/tracing/model/global_memory_dump.html +++ b/catapult/tracing/tracing/model/global_memory_dump.html @@ -5,7 +5,6 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/size_in_bytes.html"> <link rel="import" href="/tracing/base/units/time_stamp.html"> <link rel="import" href="/tracing/model/attribute.html"> <link rel="import" href="/tracing/model/container_memory_dump.html"> @@ -50,7 +49,7 @@ tr.exportTo('tr.model', function() { } function ownershipToUserFriendlyString(dump, importance) { - return dump.quantifiedName + ' (sharing importance ' + + return dump.quantifiedName + ' (importance: ' + optional(importance, 0) + ')'; } @@ -58,7 +57,7 @@ tr.exportTo('tr.model', function() { __proto__: tr.model.ContainerMemoryDump.prototype, get userFriendlyName() { - return 'Global memory dump at ' + tr.b.units.TimeStamp.format(this.start); + return 'Global memory dump at ' + tr.b.u.TimeStamp.format(this.start); }, get containerName() { @@ -66,9 +65,23 @@ tr.exportTo('tr.model', function() { }, calculateGraphAttributes: function() { + // 1. Calculate the sizes of all memory allocator dumps (MADs). this.calculateSizes(); + + // 2. Calculate the effective sizes of all MADs. This step requires that + // the sizes of all MADs have already been calculated (step 1). this.calculateEffectiveSizes(); + + // 3. Aggregate all other attributes of all MADs. This step must be + // carried out after the sizes of all MADs were calculated (step 1). + // Otherwise, the sizes of all MADs would be aggregated as a direct sums + // of their children, which would most likely lead to double-counting. this.aggregateAttributes(); + + // 4. Discount tracing from VM regions stats and malloc or winheap + // allocator stats. This steps requires that the sizes (step 1), + // effective sizes (step 2), and resident sizes (step 3) of the relevant + // MADs have already been calculated. this.discountTracingOverhead(); }, @@ -135,9 +148,9 @@ tr.exportTo('tr.model', function() { dependentName) { if (size >= dependentSize) return; - var messageSuffix = ' (' + tr.b.units.SizeInBytes.format(size) + + var messageSuffix = ' (' + tr.b.u.Units.sizeInBytes.format(size) + ') is less than ' + dependentName + ' (' + - tr.b.units.SizeInBytes.format(dependentSize) + ').'; + tr.b.u.Units.sizeInBytes.format(dependentSize) + ').'; this.model.importWarning({ type: 'memory_dump_parse_error', message: 'Size provided by memory allocator dump \'' + @@ -209,9 +222,8 @@ tr.exportTo('tr.model', function() { var message = tr.b.dictionaryValues(tr.b.mapItems(childOverlaps, function(ownerChildName, overlap) { - return 'This memory allocator dump overlaps with its sibling \'' + - ownerChildName + '\' (' + - tr.b.units.SizeInBytes.format(overlap) + ').'; + return 'overlaps with its sibling \'' + ownerChildName + '\' (' + + tr.b.u.Units.sizeInBytes.format(overlap) + ')'; })).join(' '); childDump.attributes[SIZE_ATTRIBUTE_NAME].infos.push( @@ -621,19 +633,36 @@ tr.exportTo('tr.model', function() { dump.attributes[EFFECTIVE_SIZE_ATTRIBUTE_NAME] = attribute; // Add attribute infos regarding ownership (if applicable). + // TODO(petrcermak): This belongs to the corresponding analysis UI code. if (dump.ownedBy.length > 0) { - var message = 'This memory allocator dump is shared by ' + + var message = 'shared by:' + dump.ownedBy.map(function(ownershipLink) { - return ownershipToUserFriendlyString( + return '\n - ' + ownershipToUserFriendlyString( ownershipLink.source, ownershipLink.importance); - }).join(', ') + '.'; + }).join(); attribute.infos.push(new tr.model.AttributeInfo( tr.model.AttributeInfoType.MEMORY_OWNED, message)); } if (dump.owns !== undefined) { - var message = 'This memory allocator dump shares ' + - ownershipToUserFriendlyString( - dump.owns.target, dump.owns.importance) + '.'; + var target = dump.owns.target; + var message = 'shares ' + + ownershipToUserFriendlyString(target, dump.owns.importance) + + ' with'; + + var otherOwnershipLinks = target.ownedBy.filter( + function(ownershipLink) { + return ownershipLink.source !== dump; + }); + if (otherOwnershipLinks.length > 0) { + message += ':'; + message += otherOwnershipLinks.map(function(ownershipLink) { + return '\n - ' + ownershipToUserFriendlyString( + ownershipLink.source, ownershipLink.importance); + }).join(); + } else { + message += ' no other dumps'; + } + attribute.infos.push(new tr.model.AttributeInfo( tr.model.AttributeInfoType.MEMORY_OWNER, message)); } diff --git a/catapult/tracing/tracing/model/global_memory_dump_test.html b/catapult/tracing/tracing/model/global_memory_dump_test.html index 8e611ffb..3024e0f5 100644 --- a/catapult/tracing/tracing/model/global_memory_dump_test.html +++ b/catapult/tracing/tracing/model/global_memory_dump_test.html @@ -480,28 +480,47 @@ tr.b.unittest.testSuite(function() { return genericInfo(AttributeInfoType.WARNING, regex); } - function ownershipInfo(type, prefix, entries) { - assert(entries.length % 3 === 0); // Test sanity check. + function ownershipInfo(/* type, prefix1, entries1, ... */) { + // Test sanity checks. + assert(arguments.length >= 3); + assert(arguments.length % 2 === 1); - var regExpString = '\\b' + prefix + '\\b'; + var type = arguments[0]; + var regExpString = ''; - for (var i = 0; i < entries.length; i += 3) { - regExpString += '.*\'' + entries[i] + '\''; - regExpString += '.*\\b' + entries[i + 1] + '\\b'; - regExpString += '.*\\bimportance ' + entries[i + 2] + '\\b'; + for (var i = 1; i < arguments.length; i += 2) { + var prefix = arguments[i]; + var entries = arguments[i + 1]; + assert(entries.length % 3 === 0); // Test sanity check. + + regExpString += '.*' + prefix; + + for (var j = 0; j < entries.length; j += 3) { + regExpString += '[\\s\\S]*\'' + entries[j] + '\''; + regExpString += '.*\\b' + entries[j + 1] + '\\b'; + regExpString += '.*\\bimportance: ' + entries[j + 2] + '\\b'; + } } return genericInfo(type, new RegExp(regExpString)); } - function ownerInfo(/* fullName1, containerName1, importance1, ... */) { - return ownershipInfo(AttributeInfoType.MEMORY_OWNER, 'shares', - Array.prototype.slice.call(arguments)); + function ownerInfo(/* ownedFullName, ownedContainerName, ownedImportance, + otherOwnerFullName1, otherOwnerContainerName1, + otherOwnerImportance1, ... */) { + var ownedEntries = Array.prototype.slice.call(arguments, 0, 3); + var otherOwnerEntries = Array.prototype.slice.call(arguments, 3); + return ownershipInfo(AttributeInfoType.MEMORY_OWNER, + '\\bshares\\b', ownedEntries, + '\\bwith' + (otherOwnerEntries.length === 0 ? ' no other\\b' : ':\\n'), + otherOwnerEntries); } - function ownedInfo(/* fullName1, containerName1, importance1, ... */) { - return ownershipInfo(AttributeInfoType.MEMORY_OWNED, 'shared by', - Array.prototype.slice.call(arguments)); + function ownedInfo(/* ownerFullName1, ownerContainerName1, ownerImportance1, + ... */) { + var ownerEntries = Array.prototype.slice.call(arguments); + return ownershipInfo(AttributeInfoType.MEMORY_OWNED, '\\bshared by\\b', + ownerEntries); } // Check that the checkDumpTrees testing helper method above actually @@ -1538,7 +1557,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 5, 'expected_effective_size': 2.5, 'expected_effective_size_infos': [ - ownerInfo('bitmap', 'global space', 0) + ownerInfo('bitmap', 'global space', 0, 'chunk', 'Process 1', 0) ], 'owns': 7 } @@ -1550,7 +1569,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 9, 'expected_effective_size': 6.5, 'expected_effective_size_infos': [ - ownerInfo('bitmap', 'global space', 0) + ownerInfo('bitmap', 'global space', 0, 'tile', 'Process 0', 0) ], 'owns': 7 } @@ -1576,7 +1595,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 16, 'expected_effective_size': 16, 'expected_effective_size_infos': [ - ownerInfo('bitmap', 'global space', 0) + ownerInfo('bitmap', 'global space', 0, 'chunk', 'Process 1', 0) ], 'owns': 7 } @@ -1615,7 +1634,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 18, 'expected_effective_size': 18, 'expected_effective_size_infos': [ - ownerInfo('bitmap', 'global space', 0) + ownerInfo('bitmap', 'global space', 0, 'tile', 'Process 0', 0) ], 'owns': 7 } @@ -1642,7 +1661,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 29, 'expected_effective_size': 19.5, 'expected_effective_size_infos': [ - ownerInfo('bitmap', 'global space', 0) + ownerInfo('bitmap', 'global space', 0, 'chunk', 'Process 1', 0) ], 'owns': 7 } @@ -1654,7 +1673,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 19, 'expected_effective_size': 9.5, 'expected_effective_size_infos': [ - ownerInfo('bitmap', 'global space', 0) + ownerInfo('bitmap', 'global space', 0, 'tile', 'Process 0', 0) ], 'owns': 7 } @@ -1681,7 +1700,7 @@ tr.b.unittest.testSuite(function() { 'expected_effective_size_infos': [ ownedInfo('object1', 'Process 0', 0, 'object2', 'Process 0', 0, 'object3', 'Process 0', 0), - ownerInfo('bitmap', 'global space', 0) + ownerInfo('bitmap', 'global space', 0, 'chunk', 'Process 1', 0) ], 'owns': 7, 'guid': 0 @@ -1693,7 +1712,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 30, 'expected_effective_size': 9, 'expected_effective_size_infos': [ - ownerInfo('tile', 'Process 0', 0) + ownerInfo('tile', 'Process 0', 0, 'object2', 'Process 0', 0, + 'object3', 'Process 0', 0) ] }, { @@ -1707,7 +1727,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 50, 'expected_effective_size': 21, 'expected_effective_size_infos': [ - ownerInfo('tile', 'Process 0', 0) + ownerInfo('tile', 'Process 0', 0, 'object1', 'Process 0', 0, + 'object2', 'Process 0', 0) ] } ], @@ -1718,7 +1739,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 40, 'expected_effective_size': 20, 'expected_effective_size_infos': [ - ownerInfo('bitmap', 'global space', 0) + ownerInfo('bitmap', 'global space', 0, 'tile', 'Process 0', 0) ], 'owns': 7 } @@ -2428,7 +2449,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 6, 'expected_effective_size': 3, 'expected_effective_size_infos': [ - ownerInfo('owned', 'global space', 0) + ownerInfo('owned', 'global space', 0, 'owner2', 'global space', 0) ] }, { @@ -2438,7 +2459,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 6, 'expected_effective_size': 3, 'expected_effective_size_infos': [ - ownerInfo('owned', 'global space', 0) + ownerInfo('owned', 'global space', 0, 'owner1', 'global space', 0) ] } ], @@ -2461,7 +2482,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 15, 'expected_effective_size': 10 / 2 + 5, 'expected_effective_size_infos': [ - ownerInfo('owned', 'Process 0', 0) + ownerInfo('owned', 'Process 0', 0, 'owner2', 'Process 0', 0) ] }, { @@ -2471,7 +2492,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 10, 'expected_effective_size': 10 / 2, 'expected_effective_size_infos': [ - ownerInfo('owned', 'Process 0', 0) + ownerInfo('owned', 'Process 0', 0, 'owner1', 'Process 0', 0) ] } ], @@ -2495,7 +2516,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 8, 'expected_effective_size': 8 / 3, 'expected_effective_size_infos': [ - ownerInfo('owned', 'Process 1', 3) + ownerInfo('owned', 'Process 1', 3, 'owner2', 'Process 1', 3, + 'owner3', 'Process 1', 3) ] }, { @@ -2506,7 +2528,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 9, 'expected_effective_size': 8 / 3 + 1 / 2, 'expected_effective_size_infos': [ - ownerInfo('owned', 'Process 1', 3) + ownerInfo('owned', 'Process 1', 3, 'owner1', 'Process 1', 3, + 'owner3', 'Process 1', 3) ] }, { @@ -2517,7 +2540,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 10, 'expected_effective_size': 8 / 3 + 1 / 2 + 1, 'expected_effective_size_infos': [ - ownerInfo('owned', 'Process 1', 3) + ownerInfo('owned', 'Process 1', 3, 'owner1', 'Process 1', 3, + 'owner2', 'Process 1', 3) ] } ] @@ -2542,7 +2566,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 6, 'expected_effective_size': 0, 'expected_effective_size_infos': [ - ownerInfo('owned', 'global space', 0) + ownerInfo('owned', 'global space', 0, 'owner2', 'global space', 1) ] }, { @@ -2553,7 +2577,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 6, 'expected_effective_size': 6, 'expected_effective_size_infos': [ - ownerInfo('owned', 'global space', 1) + ownerInfo('owned', 'global space', 1, 'owner1', 'global space', 0) ] } ], @@ -2576,7 +2600,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 16, 'expected_effective_size': 6, 'expected_effective_size_infos': [ - ownerInfo('owned', 'Process 0', -1) + ownerInfo('owned', 'Process 0', -1, 'owner2', 'Process 0', 0) ] }, { @@ -2586,7 +2610,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 10, 'expected_effective_size': 10, 'expected_effective_size_infos': [ - ownerInfo('owned', 'Process 0', 0) + ownerInfo('owned', 'Process 0', 0, 'owner1', 'Process 0', -1) ] } ], @@ -2610,7 +2634,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 8, 'expected_effective_size': 8, 'expected_effective_size_infos': [ - ownerInfo('owned', 'Process 1', 4) + ownerInfo('owned', 'Process 1', 4, 'owner2', 'Process 1', 3, + 'owner3', 'Process 1', 2) ] }, { @@ -2621,7 +2646,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 6, 'expected_effective_size': 0, 'expected_effective_size_infos': [ - ownerInfo('owned', 'Process 1', 3) + ownerInfo('owned', 'Process 1', 3, 'owner1', 'Process 1', 4, + 'owner3', 'Process 1', 2) ] }, { @@ -2632,7 +2658,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 10, 'expected_effective_size': 2, 'expected_effective_size_infos': [ - ownerInfo('owned', 'Process 1', 2) + ownerInfo('owned', 'Process 1', 2, 'owner1', 'Process 1', 4, + 'owner2', 'Process 1', 3) ] } ] @@ -2664,7 +2691,9 @@ tr.b.unittest.testSuite(function() { 'expected_size': 6, 'expected_effective_size': 6 / 2, 'expected_effective_size_infos': [ - ownerInfo('owned', 'global space', 2) + ownerInfo('owned', 'global space', 2, + 'some_parent/owner2', 'Process 1', 2, 'owner3', 'Process 2', 1, + 'owner4', 'Process 2', 0) ] } ], @@ -2682,7 +2711,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 7, 'expected_effective_size': 6 / 2 + 1, 'expected_effective_size_infos': [ - ownerInfo('owned', 'global space', 2) + ownerInfo('owned', 'global space', 2, 'owner1', 'Process 0', 2, + 'owner3', 'Process 2', 1, 'owner4', 'Process 2', 0) ] } ] @@ -2697,7 +2727,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 5, 'expected_effective_size': 0, 'expected_effective_size_infos': [ - ownerInfo('owned', 'global space', 1) + ownerInfo('owned', 'global space', 1, 'owner1', 'Process 0', 2, + 'some_parent/owner2', 'Process 1', 2, 'owner4', 'Process 2', 0) ] }, { @@ -2708,7 +2739,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 8, 'expected_effective_size': 1, 'expected_effective_size_infos': [ - ownerInfo('owned', 'global space', 0) + ownerInfo('owned', 'global space', 0, 'owner1', 'Process 0', 2, + 'some_parent/owner2', 'Process 1', 2, 'owner3', 'Process 2', 1) ] } ] @@ -2723,7 +2755,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 10, 'expected_effective_size': 2, 'expected_effective_size_infos': [ - ownedInfo('owner1', 'Process 0', 2) + ownedInfo('owner1', 'Process 0', 2, 'owner2', 'Process 1', 1) ] } ], @@ -2738,7 +2770,7 @@ tr.b.unittest.testSuite(function() { 'expected_effective_size': 2, 'expected_effective_size_infos': [ ownedInfo('subowner1', 'Process 0', 0), - ownerInfo('owned', 'global space', 2) + ownerInfo('owned', 'global space', 2, 'owner2', 'Process 1', 1) ] }, { @@ -2763,7 +2795,7 @@ tr.b.unittest.testSuite(function() { 'expected_effective_size': 2 - 2 / 4, 'expected_effective_size_infos': [ ownedInfo('subowner2', 'Process 1', 0), - ownerInfo('owned', 'global space', 1) + ownerInfo('owned', 'global space', 1, 'owner1', 'Process 0', 2) ] }, { @@ -2801,7 +2833,7 @@ tr.b.unittest.testSuite(function() { 'expected_effective_size': 1, 'expected_effective_size_infos': [ ownedInfo('red', 'global space', 0), - ownerInfo('grey', 'global space', 1) + ownerInfo('grey', 'global space', 1, 'purple', 'global space', 2) ] }, { @@ -2812,7 +2844,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 7, 'expected_effective_size': 7, 'expected_effective_size_infos': [ - ownerInfo('grey', 'global space', 2) + ownerInfo('grey', 'global space', 2, 'blue', 'global space', 1) ] }, { @@ -2823,7 +2855,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 10, 'expected_effective_size': 3, 'expected_effective_size_infos': [ - ownerInfo('red', 'global space', 3) + ownerInfo('red', 'global space', 3, 'green', 'global space', 3) ] }, { @@ -2846,7 +2878,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 8, 'expected_effective_size': 2, 'expected_effective_size_infos': [ - ownerInfo('red', 'global space', 3) + ownerInfo('red', 'global space', 3, 'yellow', 'global space', 3) ] } ] @@ -2964,7 +2996,7 @@ tr.b.unittest.testSuite(function() { 'expected_size': 12, 'expected_effective_size': 5 + 2, 'expected_effective_size_infos': [ - ownerInfo('shared_bitmap', 'global space', 2) + ownerInfo('shared_bitmap', 'global space', 2, 'gpu', 'Process 1', 1) ], 'children': [ { @@ -2981,7 +3013,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 7, 'expected_effective_size': 2, 'expected_effective_size_infos': [ - ownerInfo('shared_bitmap/bitmap0x7', 'global space', 1) + ownerInfo('shared_bitmap/bitmap0x7', 'global space', 1, + 'gpu/chunk-3\\.14', 'Process 1', 2) ] } ] @@ -2996,7 +3029,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 16, 'expected_effective_size': 6 + 5, 'expected_effective_size_infos': [ - ownerInfo('shared_bitmap', 'global space', 1) + ownerInfo('shared_bitmap', 'global space', 1, + 'tile_manager', 'Process 0', 2) ], 'children': [ { @@ -3013,7 +3047,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 5, 'expected_effective_size': 5, 'expected_effective_size_infos': [ - ownerInfo('shared_bitmap/bitmap0x7', 'global space', 2) + ownerInfo('shared_bitmap/bitmap0x7', 'global space', 2, + 'tile_manager/tile42', 'Process 0', 1) ] } ] @@ -3054,7 +3089,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 16, 'expected_effective_size': 8, 'expected_effective_size_infos': [ - ownerInfo('unknown', 'global space', 1) + ownerInfo('unknown', 'global space', 1, + 'v8/heaps/1', 'Process 1', 2) ], 'owns': 2, 'importance': 1, @@ -3097,7 +3133,8 @@ tr.b.unittest.testSuite(function() { 'expected_size': 8, 'expected_effective_size': 2, 'expected_effective_size_infos': [ - ownerInfo('unknown', 'global space', 2) + ownerInfo('unknown', 'global space', 2, + 'sharedbitmap/0x7', 'Process 0', 1) ], 'owns': 2, 'importance': 2 @@ -3244,7 +3281,9 @@ tr.b.unittest.testSuite(function() { 'expected_size': 9, 'expected_effective_size': 7 / 3 + 1 / 2 + 1, 'expected_effective_size_infos': [ - ownerInfo('root/parent1/child', 'global space', 0) + ownerInfo('root/parent1/child', 'global space', 0, + 'root/parent2/child2', 'global space', 0, + 'root/parent3', 'global space', 0) ] }, { @@ -3254,7 +3293,9 @@ tr.b.unittest.testSuite(function() { 'expected_size': 8, 'expected_effective_size': 7 / 3 + 1 / 2, 'expected_effective_size_infos': [ - ownerInfo('root/parent1/child', 'global space', 0) + ownerInfo('root/parent1/child', 'global space', 0, + 'root/parent2/child1', 'global space', 0, + 'root/parent3', 'global space', 0) ] } ] @@ -3265,7 +3306,9 @@ tr.b.unittest.testSuite(function() { 'expected_size': 7, 'expected_effective_size': 7 / 3, 'expected_effective_size_infos': [ - ownerInfo('root/parent1/child', 'global space', 0) + ownerInfo('root/parent1/child', 'global space', 0, + 'root/parent2/child1', 'global space', 0, + 'root/parent2/child2', 'global space', 0) ], 'owns': 3 } @@ -3277,7 +3320,7 @@ tr.b.unittest.testSuite(function() { // Check that size calculation is NOT preceded by attribute // aggregation, which would recursively sum up size attributes. test('calculateGraphAttributes', function() { - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { buildDumpTrees([ undefined, // GMD. [ // PMD. diff --git a/catapult/tracing/tracing/model/instant_event.html b/catapult/tracing/tracing/model/instant_event.html index 014c7a0b..aa071cc2 100644 --- a/catapult/tracing/tracing/model/instant_event.html +++ b/catapult/tracing/tracing/model/instant_event.html @@ -45,7 +45,7 @@ tr.exportTo('tr.model', function() { __proto__: InstantEvent.prototype, get userFriendlyName() { return 'Global instant event ' + this.title + ' @ ' + - tr.b.units.TimeStamp.format(start); + tr.b.u.TimeStamp.format(start); } }; @@ -59,7 +59,7 @@ tr.exportTo('tr.model', function() { get userFriendlyName() { return 'Process-level instant event ' + this.title + ' @ ' + - tr.b.units.TimeStamp.format(start); + tr.b.u.TimeStamp.format(start); } }; diff --git a/catapult/tracing/tracing/model/interaction_record.html b/catapult/tracing/tracing/model/interaction_record.html index 958deb52..087bd2d1 100644 --- a/catapult/tracing/tracing/model/interaction_record.html +++ b/catapult/tracing/tracing/model/interaction_record.html @@ -37,7 +37,7 @@ tr.exportTo('tr.model', function() { get userFriendlyName() { return this.title + ' interaction at ' + - tr.b.units.TimeStamp.format(this.start); + tr.b.u.TimeStamp.format(this.start); }, computeCompoundEvenSelectionState: function(selection) { diff --git a/catapult/tracing/tracing/model/interaction_record_test.html b/catapult/tracing/tracing/model/interaction_record_test.html index d0bc5713..f31d1a9d 100644 --- a/catapult/tracing/tracing/model/interaction_record_test.html +++ b/catapult/tracing/tracing/model/interaction_record_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; var CompoundEventSelectionState = tr.model.CompoundEventSelectionState; function createModel(opt_customizeModelCallback) { diff --git a/catapult/tracing/tracing/model/ir_coverage_test.html b/catapult/tracing/tracing/model/ir_coverage_test.html index 8ccdf689..3e7a3ec9 100644 --- a/catapult/tracing/tracing/model/ir_coverage_test.html +++ b/catapult/tracing/tracing/model/ir_coverage_test.html @@ -12,10 +12,10 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; test('computeCoverage', function() { - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { var process = model.getOrCreateProcess(1); var thread = process.getOrCreateThread(2); var s0 = thread.sliceGroup.pushSlice(newSliceEx( @@ -30,7 +30,7 @@ tr.b.unittest.testSuite(function() { {title: 's2', start: 2.0, duration: 1.0})); s2.cpuDuration = 0.4; s2.isTopLevel = true; - var f0 = tr.c.test_utils.newFlowEventEx({ + var f0 = tr.c.TestUtils.newFlowEventEx({ title: 'test1', start: 0, end: 10, @@ -39,7 +39,7 @@ tr.b.unittest.testSuite(function() { id: '0x100' }); model.flowEvents.push(f0); - var as1 = tr.c.test_utils.newAsyncSliceEx({ + var as1 = tr.c.TestUtils.newAsyncSliceEx({ title: 'InputLatency::GestureTap', cat: 'benchmark,latencyInfo', start: 2, diff --git a/catapult/tracing/tracing/model/kernel_test.html b/catapult/tracing/tracing/model/kernel_test.html index 994fec83..c4ca0ca8 100644 --- a/catapult/tracing/tracing/model/kernel_test.html +++ b/catapult/tracing/tracing/model/kernel_test.html @@ -14,7 +14,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function newModel(events, callback) { - return tr.c.test_utils.newModelWithEvents([events], { + return tr.c.TestUtils.newModelWithEvents([events], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: callback diff --git a/catapult/tracing/tracing/model/model.html b/catapult/tracing/tracing/model/model.html index b77c98a9..0d01b29f 100644 --- a/catapult/tracing/tracing/model/model.html +++ b/catapult/tracing/tracing/model/model.html @@ -10,7 +10,7 @@ found in the LICENSE file. <link rel="import" href="/tracing/base/interval_tree.html"> <link rel="import" href="/tracing/base/range.html"> <link rel="import" href="/tracing/base/task.html"> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/units.html"> <link rel="import" href="/tracing/core/auditor.html"> <link rel="import" href="/tracing/core/filter.html"> <link rel="import" href="/tracing/model/alert.html"> @@ -178,7 +178,7 @@ tr.exportTo('tr', function() { convertTimestampToModelTime: function(sourceClockDomainName, ts) { if (sourceClockDomainName !== 'traceEventClock') throw new Error('Only traceEventClock is supported.'); - return tr.b.units.Time.timestampFromUs(ts) + + return tr.b.u.Units.timestampFromUs(ts) + this.timestampShiftToZeroAmount_; }, @@ -336,7 +336,7 @@ tr.exportTo('tr', function() { */ get intrinsicTimeUnit() { if (this.intrinsicTimeUnit_ === undefined) - return tr.b.units.Time.supportedUnits.ms; + return tr.b.u.TimeDisplayModes.ms; return this.intrinsicTimeUnit_; }, diff --git a/catapult/tracing/tracing/model/model_indices_test.html b/catapult/tracing/tracing/model/model_indices_test.html index 77f07bc5..750e0b02 100644 --- a/catapult/tracing/tracing/model/model_indices_test.html +++ b/catapult/tracing/tracing/model/model_indices_test.html @@ -12,8 +12,8 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newFlowEventEx = tr.c.test_utils.newFlowEventEx; - var newModel = tr.c.test_utils.newModel; + var newFlowEventEx = tr.c.TestUtils.newFlowEventEx; + var newModel = tr.c.TestUtils.newModel; test('getCorrectModelIndices', function() { var m = newModel(function(m) { diff --git a/catapult/tracing/tracing/model/model_test.html b/catapult/tracing/tracing/model/model_test.html index e0fe23ea..a3845248 100644 --- a/catapult/tracing/tracing/model/model_test.html +++ b/catapult/tracing/tracing/model/model_test.html @@ -5,7 +5,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <link rel="import" href="/tracing/core/test_utils.html"> <link rel="import" href="/tracing/extras/importer/trace_event_importer.html"> <link rel="import" href="/tracing/importer/import.html"> @@ -23,13 +23,13 @@ tr.b.unittest.testSuite(function() { var createModelWithOneOfEverything = function() { var m = new tr.Model(); var cpu = m.kernel.getOrCreateCpu(1); - cpu.slices.push(tr.c.test_utils.newSlice(1, 3)); + cpu.slices.push(tr.c.TestUtils.newSlice(1, 3)); var p = m.getOrCreateProcess(1); var t = p.getOrCreateThread(1); var slice = new ThreadSlice('', 'a', 0, 1, {}, 4); t.sliceGroup.pushSlice(slice); - t.asyncSliceGroup.push(tr.c.test_utils.newAsyncSlice(0, 1, t, t)); + t.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSlice(0, 1, t, t)); var c = p.getOrCreateCounter('', 'ProcessCounter'); var aSeries = new tr.model.CounterSeries('a', 0); @@ -114,7 +114,7 @@ tr.b.unittest.testSuite(function() { test('modelBounds_OneCpu', function() { var m = new tr.Model(); var cpu = m.kernel.getOrCreateCpu(1); - cpu.slices.push(tr.c.test_utils.newSlice(1, 3)); + cpu.slices.push(tr.c.TestUtils.newSlice(1, 3)); m.updateBounds(); assert.equal(m.bounds.min, 1); assert.equal(m.bounds.max, 4); @@ -123,7 +123,7 @@ tr.b.unittest.testSuite(function() { test('modelBounds_OneCpuOneThread', function() { var m = new tr.Model(); var cpu = m.kernel.getOrCreateCpu(1); - cpu.slices.push(tr.c.test_utils.newSlice(1, 3)); + cpu.slices.push(tr.c.TestUtils.newSlice(1, 3)); var t = m.getOrCreateProcess(1).getOrCreateThread(1); t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 4)); @@ -171,11 +171,11 @@ tr.b.unittest.testSuite(function() { }); test('TitleOrCategoryFilter', function() { - var s0 = tr.c.test_utils.newSlice(1, 3); + var s0 = tr.c.TestUtils.newSlice(1, 3); assert.isTrue(new TitleOrCategoryFilter('a').matchSlice(s0)); assert.isFalse(new TitleOrCategoryFilter('x').matchSlice(s0)); - var s1 = tr.c.test_utils.newSliceEx({title: 'ba', start: 1, duration: 3}); + var s1 = tr.c.TestUtils.newSliceEx({title: 'ba', start: 1, duration: 3}); assert.isTrue(new TitleOrCategoryFilter('a').matchSlice(s1)); assert.isTrue(new TitleOrCategoryFilter('ba').matchSlice(s1)); assert.isFalse(new TitleOrCategoryFilter('x').matchSlice(s1)); @@ -236,7 +236,7 @@ tr.b.unittest.testSuite(function() { }); test('model_intrinsicTimeUnit', function() { - var unit = tr.b.units.Time.supportedUnits; + var unit = tr.b.u.TimeDisplayModes; var m = new tr.Model(); // by default it should be milliseconds diff --git a/catapult/tracing/tracing/model/object_snapshot.html b/catapult/tracing/tracing/model/object_snapshot.html index 8ab33ceb..54d868a1 100644 --- a/catapult/tracing/tracing/model/object_snapshot.html +++ b/catapult/tracing/tracing/model/object_snapshot.html @@ -65,7 +65,7 @@ tr.exportTo('tr.model', function() { return 'Snapshot of ' + this.objectInstance.typeName + ' ' + this.objectInstance.id + ' @ ' + - tr.b.units.TimeStamp.format(this.ts); + tr.b.u.TimeStamp.format(this.ts); } }; diff --git a/catapult/tracing/tracing/model/process_memory_dump.html b/catapult/tracing/tracing/model/process_memory_dump.html index 8d6a70e9..b92231c5 100644 --- a/catapult/tracing/tracing/model/process_memory_dump.html +++ b/catapult/tracing/tracing/model/process_memory_dump.html @@ -42,7 +42,7 @@ tr.exportTo('tr.model', function() { get userFriendlyName() { return 'Process memory dump at ' + - tr.b.units.TimeStamp.format(this.start); + tr.b.u.TimeStamp.format(this.start); }, get containerName() { @@ -87,53 +87,81 @@ tr.exportTo('tr.model', function() { if (tracingDump === undefined) return; - // Subtract 'resident_size' from totals and VM regions stats. - var tracingResidentSizeAttr = - tracingDump.getValidSizeAttributeOrUndefined( - 'resident_size', opt_model); - if (tracingResidentSizeAttr !== undefined) { - var tracingResidentSize = tracingResidentSizeAttr.value; + function getDiscountedSize(sizeAttrName) { + var sizeAttr = tracingDump.getValidSizeAttributeOrUndefined( + sizeAttrName, opt_model); + if (sizeAttr === undefined) + return 0; + return sizeAttr.value; + } + var discountedSize = getDiscountedSize('size'); + var discountedEffectiveSize = getDiscountedSize('effective_size'); + var discountedResidentSize = getDiscountedSize('resident_size'); + + // Subtract 'resident_size' from totals and VM regions stats. + if (discountedResidentSize > 0) { // Subtract the tracing size from the total. if (this.totalResidentBytes !== undefined) - this.totalResidentBytes -= tracingResidentSize; + this.totalResidentBytes -= discountedResidentSize; // Subtract the tracing size from VM regions. if (this.vmRegions_ !== undefined) { this.vmRegions_.push(VMRegion.fromDict({ mappedFile: '[discounted tracing overhead]', byteStats: { - privateDirtyResident: -tracingResidentSize, - proportionalResident: -tracingResidentSize + privateDirtyResident: -discountedResidentSize, + proportionalResident: -discountedResidentSize } })); } } - // Subtract 'size' from the 'winheap' or 'malloc' MemoryAllocatorDump. - var tracingSizeAttr = tracingDump.getValidSizeAttributeOrUndefined( - 'size', opt_model); - if (tracingSizeAttr !== undefined) { - var tracingSize = tracingSizeAttr.value; - - var hasDiscountedFromAllocatorDumps = DISCOUNTED_ALLOCATOR_NAMES.some( - function(allocatorName) { - var dump = this.getMemoryAllocatorDumpByFullName(allocatorName); - if (dump === undefined) - return false; - - var overheadSizeAttribute = new tr.model.ScalarAttribute( - 'bytes', -tracingSize); - var overheadDump = new tr.model.MemoryAllocatorDump( - this, allocatorName + '/discounted_tracing_overhead'); - overheadDump.parent = dump; - overheadDump.addAttribute('size', overheadSizeAttribute); - dump.children.push(overheadDump); - + // Subtract 'size' and 'effective_size' from the 'winheap' or 'malloc' + // MemoryAllocatorDump. + if (discountedSize > 0 || discountedEffectiveSize > 0) { + function discountSizeAndEffectiveSize(dump) { var dumpSizeAttr = dump.getValidSizeAttributeOrUndefined( 'size', opt_model); if (dumpSizeAttr !== undefined) - dumpSizeAttr.value -= tracingSize; + dumpSizeAttr.value -= discountedSize; + + var dumpEffectiveSizeAttr = dump.getValidSizeAttributeOrUndefined( + 'effective_size', opt_model); + if (dumpEffectiveSizeAttr !== undefined) + dumpEffectiveSizeAttr.value -= discountedEffectiveSize; + } + + var hasDiscountedFromAllocatorDumps = DISCOUNTED_ALLOCATOR_NAMES.some( + function(allocatorName) { + // Discount 'size' and 'effective_size' from the allocator root. + var allocatorDump = this.getMemoryAllocatorDumpByFullName( + allocatorName); + if (allocatorDump === undefined) + return false; // Allocator doesn't exist, try another one. + discountSizeAndEffectiveSize(allocatorDump); + + // Discount 'size' and 'effective_size' from allocated objects of the + // allocator ('<ALLOCATOR>/allocated_objects'). + var allocatedObjectsDumpName = allocatorName + '/allocated_objects'; + var allocatedObjectsDump = this.getMemoryAllocatorDumpByFullName( + allocatedObjectsDumpName); + if (allocatedObjectsDump === undefined) + return true; // Allocator has unexpected structure, good enough. + discountSizeAndEffectiveSize(allocatedObjectsDump); + + // Add a child MAD representing the discounted tracing overhead + // ('<ALLOCATOR>/allocated_objects/discounted_tracing_overhead'). + var discountDumpName = + allocatedObjectsDumpName + '/discounted_tracing_overhead'; + var discountDump = new tr.model.MemoryAllocatorDump( + this, discountDumpName); + discountDump.parent = allocatedObjectsDump; + discountDump.addAttribute('size', + new tr.model.ScalarAttribute('bytes', -discountedSize)); + discountDump.addAttribute('effective_size', + new tr.model.ScalarAttribute('bytes', -discountedEffectiveSize)); + allocatedObjectsDump.children.push(discountDump); return true; }, this); diff --git a/catapult/tracing/tracing/model/process_memory_dump_test.html b/catapult/tracing/tracing/model/process_memory_dump_test.html index 7e86e0c8..e3b4b3a9 100644 --- a/catapult/tracing/tracing/model/process_memory_dump_test.html +++ b/catapult/tracing/tracing/model/process_memory_dump_test.html @@ -19,6 +19,7 @@ tr.b.unittest.testSuite(function() { var GlobalMemoryDump = tr.model.GlobalMemoryDump; var ProcessMemoryDump = tr.model.ProcessMemoryDump; var MemoryAllocatorDump = tr.model.MemoryAllocatorDump; + var MemoryAllocatorDumpLink = tr.model.MemoryAllocatorDumpLink; var VMRegion = tr.model.VMRegion; var ScalarAttribute = tr.model.ScalarAttribute; @@ -39,7 +40,7 @@ tr.b.unittest.testSuite(function() { } function createFinalizedProcessMemoryDumps(timestamps, createdCallback) { - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { var pmds = timestamps.map(function(timestamp) { return createProcessMemoryDump(timestamp, model); }); @@ -282,13 +283,27 @@ tr.b.unittest.testSuite(function() { var mallocDump = new MemoryAllocatorDump(pmd, 'malloc'); mallocDump.addAttribute('size', new ScalarAttribute('bytes', 3072)); + var allocatedObjectsDump = new MemoryAllocatorDump( + pmd, 'malloc/allocated_objects'); + allocatedObjectsDump.addAttribute( + 'size', new ScalarAttribute('bytes', 2560)); + allocatedObjectsDump.parent = mallocDump; + mallocDump.children.push(allocatedObjectsDump); var tracingDump = new MemoryAllocatorDump(pmd, 'tracing'); tracingDump.addAttribute('size', new ScalarAttribute('bytes', 1024)); tracingDump.addAttribute( 'resident_size', new ScalarAttribute('bytes', 1000)); - pmd.memoryAllocatorDumps = [mallocDump, tracingDump]; + // We need to inject a fake owner of the 'tracing' dump so that we alter + // its effective size. + var ownerDump = new MemoryAllocatorDump(pmd, 'owner'); + ownerDump.addAttribute('size', new ScalarAttribute('bytes', 256)); + var ownershipLink = new MemoryAllocatorDumpLink(ownerDump, tracingDump); + ownerDump.owns = ownershipLink; + tracingDump.ownedBy.push(ownershipLink); + + pmd.memoryAllocatorDumps = [mallocDump, tracingDump, ownerDump]; }); assert.equal(pmd.totalResidentBytes, 9240); @@ -301,15 +316,27 @@ tr.b.unittest.testSuite(function() { var mallocDump = pmd.getMemoryAllocatorDumpByFullName('malloc'); assert.equal(mallocDump.attributes['size'].value, 2048); + assert.equal(mallocDump.attributes['effective_size'].value, 2304); + assert.lengthOf( + mallocDump.children, 2 /* 'allocated_objects' and '<unspecified>' */); + + var allocatedObjectsDump = pmd.getMemoryAllocatorDumpByFullName( + 'malloc/allocated_objects'); + assert.equal(allocatedObjectsDump.attributes['size'].value, 1536); + assert.equal(allocatedObjectsDump.attributes['effective_size'].value, 1792); + assert.lengthOf( + allocatedObjectsDump.children, 1 /* 'discounted_tracing_overhead' */); var discountDump = pmd.getMemoryAllocatorDumpByFullName( - 'malloc/discounted_tracing_overhead'); - assert.strictEqual(discountDump.parent, mallocDump); - assert.include(mallocDump.children, discountDump); + 'malloc/allocated_objects/discounted_tracing_overhead'); + assert.strictEqual(discountDump.parent, allocatedObjectsDump); + assert.include(allocatedObjectsDump.children, discountDump); assert.equal(discountDump.attributes['size'].value, -1024); + assert.equal(discountDump.attributes['effective_size'].value, -768); var tracingDump = pmd.getMemoryAllocatorDumpByFullName('tracing'); assert.equal(tracingDump.attributes['size'].value, 1024); + assert.equal(tracingDump.attributes['effective_size'].value, 768); assert.equal(tracingDump.attributes['resident_size'].value, 1000); }); @@ -334,15 +361,12 @@ tr.b.unittest.testSuite(function() { var winheapDump = pmd.getMemoryAllocatorDumpByFullName('winheap'); assert.equal(winheapDump.attributes['size'].value, 3072); - - var discountDump = pmd.getMemoryAllocatorDumpByFullName( - 'winheap/discounted_tracing_overhead'); - assert.strictEqual(discountDump.parent, winheapDump); - assert.include(winheapDump.children, discountDump); - assert.equal(discountDump.attributes['size'].value, -2048); + assert.equal(winheapDump.attributes['effective_size'].value, 3072); + assert.lengthOf(winheapDump.children, 0); var tracingDump = pmd.getMemoryAllocatorDumpByFullName('tracing'); assert.equal(tracingDump.attributes['size'].value, 2048); + assert.equal(tracingDump.attributes['effective_size'].value, 2048); }); test('checkDiscountTracingOverhead_withMostRecentVmRegionsLinks', function() { diff --git a/catapult/tracing/tracing/model/sample.html b/catapult/tracing/tracing/model/sample.html index 2d45c6fd..f31ad19d 100644 --- a/catapult/tracing/tracing/model/sample.html +++ b/catapult/tracing/tracing/model/sample.html @@ -49,7 +49,7 @@ tr.exportTo('tr.model', function() { }, get userFriendlyName() { - return 'Sample at ' + tr.b.units.TimeStamp.format(this.start); + return 'Sample at ' + tr.b.u.TimeStamp.format(this.start); } }; diff --git a/catapult/tracing/tracing/model/sample_test.html b/catapult/tracing/tracing/model/sample_test.html index 1d2e9954..61ecdaff 100644 --- a/catapult/tracing/tracing/model/sample_test.html +++ b/catapult/tracing/tracing/model/sample_test.html @@ -17,10 +17,10 @@ tr.b.unittest.testSuite(function() { var Thread = tr.model.Thread; test('sampleStackTrace', function() { - var thread = tr.c.test_utils.newFakeThread(); + var thread = tr.c.TestUtils.newFakeThread(); var model = new tr.Model(); - var fABC = tr.c.test_utils.newStackTrace(model, 'cat', ['a', 'b', 'c']); + var fABC = tr.c.TestUtils.newStackTrace(model, 'cat', ['a', 'b', 'c']); var s = new Sample(undefined, thread, 'instructions_retired', 10, fABC, 10); diff --git a/catapult/tracing/tracing/model/slice.html b/catapult/tracing/tracing/model/slice.html index 8f32328b..ebe97d65 100644 --- a/catapult/tracing/tracing/model/slice.html +++ b/catapult/tracing/tracing/model/slice.html @@ -73,7 +73,7 @@ tr.exportTo('tr.model', function() { get userFriendlyName() { return 'Slice ' + this.title + ' at ' + - tr.b.units.TimeStamp.format(this.start); + tr.b.u.TimeStamp.format(this.start); }, findDescendentSlice: function(targetTitle) { diff --git a/catapult/tracing/tracing/model/slice_group_test.html b/catapult/tracing/tracing/model/slice_group_test.html index f20ba54c..85ea6311 100644 --- a/catapult/tracing/tracing/model/slice_group_test.html +++ b/catapult/tracing/tracing/model/slice_group_test.html @@ -15,11 +15,11 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var Slice = tr.model.Slice; var SliceGroup = tr.model.SliceGroup; - var newSlice = tr.c.test_utils.newSlice; - var newSliceEx = tr.c.test_utils.newSliceEx; - var newThreadSlice = tr.c.test_utils.newThreadSlice; - var newModel = tr.c.test_utils.newModel; - var newFakeThread = tr.c.test_utils.newFakeThread; + var newSlice = tr.c.TestUtils.newSlice; + var newSliceEx = tr.c.TestUtils.newSliceEx; + var newThreadSlice = tr.c.TestUtils.newThreadSlice; + var newModel = tr.c.TestUtils.newModel; + var newFakeThread = tr.c.TestUtils.newFakeThread; test('basicBeginEnd', function() { var group = new SliceGroup(newFakeThread()); diff --git a/catapult/tracing/tracing/model/slice_test.html b/catapult/tracing/tracing/model/slice_test.html index 44929335..4eb9f341 100644 --- a/catapult/tracing/tracing/model/slice_test.html +++ b/catapult/tracing/tracing/model/slice_test.html @@ -14,10 +14,10 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var Slice = tr.model.Slice; var SliceGroup = tr.model.SliceGroup; - var newSlice = tr.c.test_utils.newSlice; - var newSliceEx = tr.c.test_utils.newSliceEx; - var newSliceNamed = tr.c.test_utils.newSliceNamed; - var newFakeThread = tr.c.test_utils.newFakeThread; + var newSlice = tr.c.TestUtils.newSlice; + var newSliceEx = tr.c.TestUtils.newSliceEx; + var newSliceNamed = tr.c.TestUtils.newSliceNamed; + var newFakeThread = tr.c.TestUtils.newFakeThread; test('findDescendentSlice', function() { var group = new SliceGroup(newFakeThread()); diff --git a/catapult/tracing/tracing/model/thread_test.html b/catapult/tracing/tracing/model/thread_test.html index b23017e0..fc88dda7 100644 --- a/catapult/tracing/tracing/model/thread_test.html +++ b/catapult/tracing/tracing/model/thread_test.html @@ -16,9 +16,9 @@ tr.b.unittest.testSuite(function() { var ThreadSlice = tr.model.ThreadSlice; var Process = tr.model.Process; var Thread = tr.model.Thread; - var newSliceEx = tr.c.test_utils.newSliceEx; - var newAsyncSlice = tr.c.test_utils.newAsyncSlice; - var newThreadSlice = tr.c.test_utils.newThreadSlice; + var newSliceEx = tr.c.TestUtils.newSliceEx; + var newAsyncSlice = tr.c.TestUtils.newAsyncSlice; + var newThreadSlice = tr.c.TestUtils.newThreadSlice; var SCHEDULING_STATE = tr.model.SCHEDULING_STATE; test('threadBounds_Empty', function() { @@ -98,7 +98,7 @@ tr.b.unittest.testSuite(function() { test('getSchedulingStatsForRange', function() { var scheduledThread = undefined; var unscheduledThread = undefined; - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { unscheduledThread = model.getOrCreateProcess(1).getOrCreateThread(1); unscheduledThread.sliceGroup.pushSlice(newSliceEx( {title: 'work', start: 0, duration: 20})); @@ -138,7 +138,7 @@ tr.b.unittest.testSuite(function() { }); test('getCpuStatsForRange', function() { - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { var cpu0 = model.kernel.getOrCreateCpu(0); var cpu1 = model.kernel.getOrCreateCpu(1); var thread = model.getOrCreateProcess(1).getOrCreateThread(1); @@ -158,7 +158,7 @@ tr.b.unittest.testSuite(function() { }); test('getCpuStatsForRange_excludesNotRunningThreads', function() { - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { var cpu0 = model.kernel.getOrCreateCpu(0); var cpu1 = model.kernel.getOrCreateCpu(1); var thread = model.getOrCreateProcess(1).getOrCreateThread(1); diff --git a/catapult/tracing/tracing/model/timed_event.html b/catapult/tracing/tracing/model/timed_event.html index 2060b480..c5675e7a 100644 --- a/catapult/tracing/tracing/model/timed_event.html +++ b/catapult/tracing/tracing/model/timed_event.html @@ -5,7 +5,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <link rel="import" href="/tracing/model/event.html"> <link rel="import" href="/tracing/base/guid.html"> @@ -45,7 +45,7 @@ tr.exportTo('tr.model', function() { // bounds returns whether that TimedEvent happens within this timed event bounds: function(that, precisionUnit) { if (precisionUnit === undefined) { - precisionUnit = tr.b.units.Time.supportedUnits.ms; + precisionUnit = tr.b.u.TimeDisplayModes.ms; } var startsBefore = precisionUnit.roundedLess(that.start, this.start); var endsAfter = precisionUnit.roundedLess(this.end, that.end); diff --git a/catapult/tracing/tracing/model/timed_event_test.html b/catapult/tracing/tracing/model/timed_event_test.html index e69f5893..9288c50f 100644 --- a/catapult/tracing/tracing/model/timed_event_test.html +++ b/catapult/tracing/tracing/model/timed_event_test.html @@ -6,7 +6,7 @@ found in the LICENSE file. --> <link rel="import" href="/tracing/core/test_utils.html"> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <link rel="import" href="/tracing/model/timed_event.html"> <script> @@ -14,7 +14,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('bounds_startPrecision', function() { - var unit = tr.b.units.Time.supportedUnits; + var unit = tr.b.u.TimeDisplayModes; var outer = new tr.model.TimedEvent(10.0001); outer.duration = 0.9999; @@ -28,7 +28,7 @@ tr.b.unittest.testSuite(function() { }); test('bounds_endPrecision', function() { - var unit = tr.b.units.Time.supportedUnits; + var unit = tr.b.u.TimeDisplayModes; var outer = new tr.model.TimedEvent(10.0000); outer.duration = 0.9999; diff --git a/catapult/tracing/tracing/trace2html.html b/catapult/tracing/tracing/trace2html.html index b6347d05..f26ab629 100644 --- a/catapult/tracing/tracing/trace2html.html +++ b/catapult/tracing/tracing/trace2html.html @@ -53,7 +53,8 @@ document.addEventListener('DOMContentLoaded', function() { } var m = new tr.Model(); - var p = m.importTracesWithProgressDialog(traces, true); + var i = new tr.importer.Import(m); + var p = i.importTracesWithProgressDialog(traces); p.then( function() { g_timelineViewEl.model = m; diff --git a/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html index 7b7f2f01..25a8fc58 100644 --- a/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html @@ -15,7 +15,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; test('instantiate', function() { var slice = newSliceEx({title: 'b', start: 0, duration: 0.002}); diff --git a/catapult/tracing/tracing/ui/analysis/analysis_view_test.html b/catapult/tracing/tracing/ui/analysis/analysis_view_test.html index ed65f4c4..306705d2 100644 --- a/catapult/tracing/tracing/ui/analysis/analysis_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/analysis_view_test.html @@ -24,7 +24,7 @@ tr.b.unittest.testSuite(function() { var Counter = tr.model.Counter; var CounterSeries = tr.model.CounterSeries; var CounterSample = tr.model.CounterSample; - var newThreadSlice = tr.c.test_utils.newThreadSlice; + var newThreadSlice = tr.c.TestUtils.newThreadSlice; var SCHEDULING_STATE = tr.model.SCHEDULING_STATE; var InteractionRecord = tr.model.InteractionRecord; diff --git a/catapult/tracing/tracing/ui/analysis/flow_classifier_test.html b/catapult/tracing/tracing/ui/analysis/flow_classifier_test.html index f8a529bd..b200fb51 100644 --- a/catapult/tracing/tracing/ui/analysis/flow_classifier_test.html +++ b/catapult/tracing/tracing/ui/analysis/flow_classifier_test.html @@ -13,7 +13,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newFlowEventEx = tr.c.test_utils.newFlowEventEx; + var newFlowEventEx = tr.c.TestUtils.newFlowEventEx; test('basic', function() { var a = newFlowEventEx({ diff --git a/catapult/tracing/tracing/ui/analysis/generic_object_view.html b/catapult/tracing/tracing/ui/analysis/generic_object_view.html index 8ccc7ced..a1bf70c1 100644 --- a/catapult/tracing/tracing/ui/analysis/generic_object_view.html +++ b/catapult/tracing/tracing/ui/analysis/generic_object_view.html @@ -6,7 +6,6 @@ found in the LICENSE file. --> <link rel="import" href="/tracing/base/rect.html"> -<link rel="import" href="/tracing/base/units/size_in_bytes.html"> <link rel="import" href="/tracing/base/units/time_duration.html"> <link rel="import" href="/tracing/base/units/time_stamp.html"> <link rel="import" href="/tracing/base/utils.html"> @@ -16,7 +15,7 @@ found in the LICENSE file. <link rel="import" href="/tracing/ui/analysis/analysis_link.html"> <link rel="import" href="/tracing/ui/base/table.html"> <link rel="import" href="/tracing/ui/base/ui.html"> -<link rel="import" href="/tracing/ui/units/size_in_bytes_span.html"> +<link rel="import" href="/tracing/ui/units/scalar_span.html"> <link rel="import" href="/tracing/ui/units/time_duration_span.html"> <link rel="import" href="/tracing/ui/units/time_stamp_span.html"> @@ -168,23 +167,9 @@ found in the LICENSE file. return; } - if (object instanceof tr.b.units.SizeInBytes) { - var el = this.ownerDocument.createElement('tr-ui-u-size-in-bytes-span'); - el.numBytes = object.numBytes; - this.appendElementWithLabel_(label, indent, el, suffix); - return; - } - - if (object instanceof tr.b.units.TimeDuration) { - var el = this.ownerDocument.createElement('tr-ui-u-time-duration-span'); - el.duration = object.duration; - this.appendElementWithLabel_(label, indent, el, suffix); - return; - } - - if (object instanceof tr.b.units.TimeStamp) { - var el = this.ownerDocument.createElement('tr-ui-u-time-stamp-span'); - el.timestamp = object.timestamp; + if (object instanceof tr.b.u.Scalar) { + var el = this.ownerDocument.createElement('tr-ui-u-scalar-span'); + el.value = object; this.appendElementWithLabel_(label, indent, el, suffix); return; } diff --git a/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html b/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html index f6b3010d..ca7a28fe 100644 --- a/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html @@ -170,25 +170,27 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck test('timeDurationValue', function() { var view = document.createElement('tr-ui-a-generic-object-view'); - view.object = new tr.b.units.TimeDuration(3); + view.object = new tr.b.u.TimeDuration(3); assert.isDefined(tr.b.findDeepElementMatching( - view.$.content, 'tr-ui-u-time-duration-span')); + view.$.content, 'tr-ui-u-scalar-span')); }); test('timeStampValue', function() { var view = document.createElement('tr-ui-a-generic-object-view'); - view.object = new tr.b.units.TimeStamp(3); + view.object = new tr.b.u.TimeStamp(3); assert.isDefined(tr.b.findDeepElementMatching( - view.$.content, 'tr-ui-u-time-stamp-span')); + view.$.content, 'tr-ui-u-scalar-span')); }); - test('sizeInBytesValue', function() { + test('scalarValue', function() { var view = document.createElement('tr-ui-a-generic-object-view'); - view.object = new tr.b.units.SizeInBytes(3); - assert.isDefined(tr.b.findDeepElementMatching( - view.$.content, 'tr-ui-u-size-in-bytes-span')); + view.object = new tr.b.u.Scalar(.3, tr.b.u.Units.normalizedPercentage); + var m = tr.b.findDeepElementMatching( + view.$.content, 'tr-ui-u-scalar-span'); + assert.isDefined(m); + assert.equal(m.value, .3); + assert.equal(m.unit, tr.b.u.Units.normalizedPercentage); }); - }); </script> diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html b/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html index 30d3ac12..57f3c09f 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html @@ -6,10 +6,12 @@ found in the LICENSE file. --> <link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html"> +<link rel="import" href="/tracing/ui/analysis/stacked_pane.html"> <link rel="import" href="/tracing/ui/base/dom_helpers.html"> <link rel="import" href="/tracing/ui/base/table.html"> -<polymer-element name="tr-ui-a-memory-dump-allocator-details-pane"> +<polymer-element name="tr-ui-a-memory-dump-allocator-details-pane" + extends="tr-ui-a-stacked-pane"> <template> <style> :host { @@ -68,29 +70,20 @@ found in the LICENSE file. ]; Polymer({ - // TODO(petrcermak): Consider sharing more code between - // tr-ui-a-memory-dump-overview-pane and - // tr-ui-a-memory-dump-allocator-details-pane (e.g. by defining a common - // base class tr-c-memory-dump-pane). - created: function() { this.memoryAllocatorDump_ = undefined; }, - ready: function() { - this.updateContents_(); - }, - set memoryAllocatorDump(memoryAllocatorDump) { this.memoryAllocatorDump_ = memoryAllocatorDump; - this.updateContents_(); + this.scheduleRebuildPane_(); }, get memoryAllocatorDump() { return this.memoryAllocatorDump_; }, - updateContents_: function() { + rebuildPane_: function() { this.$.contents.textContent = ''; if (this.memoryAllocatorDump_ === undefined) { diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane_test.html b/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane_test.html index 207568d1..b33958e6 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane_test.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane_test.html @@ -55,6 +55,7 @@ tr.b.unittest.testSuite(function() { test('instantiate_empty', function() { var viewEl = document.createElement( 'tr-ui-a-memory-dump-allocator-details-pane'); + viewEl.rebuild(); this.addHTMLOutput(viewEl); }); @@ -64,6 +65,7 @@ tr.b.unittest.testSuite(function() { var viewEl = document.createElement( 'tr-ui-a-memory-dump-allocator-details-pane'); viewEl.memoryAllocatorDump = memoryAllocatorDump; + viewEl.rebuild(); this.addHTMLOutput(viewEl); var table = tr.b.findDeepElementMatching( @@ -82,14 +84,14 @@ tr.b.unittest.testSuite(function() { // Check the rows of the table. var rootRow = rows[0]; assert.equal(titleColumn.value(rootRow), 'v8'); - assert.equal(sizeColumn.value(rootRow).numBytes, 1073741824); - assert.equal(innerSizeColumn.value(rootRow).numBytes, 2097152); + assert.equal(sizeColumn.value(rootRow).value, 1073741824); + assert.equal(innerSizeColumn.value(rootRow).value, 2097152); assert.equal(objectsCountColumn.value(rootRow), 204); assert.lengthOf(rootRow.subRows, 2); var subRow1 = rootRow.subRows[0]; assert.equal(titleColumn.value(subRow1), 'heaps'); - assert.equal(sizeColumn.value(subRow1).numBytes, 805306368); + assert.equal(sizeColumn.value(subRow1).value, 805306368); assert.equal(innerSizeColumn.value(subRow1), ''); assert.equal(objectsCountColumn.value(subRow1), ''); assert.isUndefined(subRow1.subRows); @@ -99,7 +101,7 @@ tr.b.unittest.testSuite(function() { titleColumn.value(subRow2).textContent, 'suballocation by oilpan/cow'); assert.equal( titleColumn.value(subRow2).title, 'Suballocation name: v8/__42BEEF'); - assert.equal(sizeColumn.value(subRow2).numBytes, 268435456); + assert.equal(sizeColumn.value(subRow2).value, 268435456); assert.equal(innerSizeColumn.value(subRow2), ''); assert.equal(objectsCountColumn.value(subRow2), ''); assert.isUndefined(subRow2.subRows); diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane.html b/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane.html index 515794e5..e05b8f9d 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane.html @@ -12,13 +12,14 @@ found in the LICENSE file. <link rel="import" href="/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html"> <link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html"> -<link rel="import" href="/tracing/ui/units/size_in_bytes_span.html"> +<link rel="import" href="/tracing/ui/analysis/stacked_pane.html"> <link rel="import" href="/tracing/ui/base/dom_helpers.html"> <link rel="import" href="/tracing/ui/base/table.html"> <link rel="import" href="/tracing/ui/view_specific_brushing_state.html"> <link rel="import" href="/tracing/model/attribute.html"> -<polymer-element name="tr-ui-a-memory-dump-overview-pane"> +<polymer-element name="tr-ui-a-memory-dump-overview-pane" + extends="tr-ui-a-stacked-pane"> <template> <style> :host { @@ -67,10 +68,6 @@ found in the LICENSE file. var LINK_SYMBOL = String.fromCharCode(9903); Polymer({ - // TODO(petrcermak): Consider sharing more code between - // tr-ui-a-memory-dump-overview-pane and tr-c-memory-dump-process pane - // (e.g. by defining a common base class tr-c-memory-dump-pane). - created: function() { this.processMemoryDumps_ = undefined; }, @@ -82,15 +79,13 @@ found in the LICENSE file. this.$.table.addEventListener('selection-changed', function(tableEvent) { tableEvent.stopPropagation(); - var paneEvent = new tr.b.Event('selected-memory-cell-changed'); - this.dispatchEvent(paneEvent); - this.storeSelection_(); + this.changeChildPane_(); }.bind(this)); }, set processMemoryDumps(processMemoryDumps) { this.processMemoryDumps_ = processMemoryDumps; - this.updateContents_(); + this.scheduleRebuildPane_(); }, get processMemoryDumps() { @@ -111,7 +106,15 @@ found in the LICENSE file. return selectedMemoryCell; }, - updateContents_: function() { + changeChildPane_: function() { + this.storeSelection_(); + var builder = undefined; + if (this.selectedMemoryCell !== undefined) + builder = this.selectedMemoryCell.buildDetailsPane; + this.childPaneBuilder = builder; + }, + + rebuildPane_: function() { var processMemoryDumps = this.processMemoryDumps_ || []; var rows = processMemoryDumps.map(function(processMemoryDump) { diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane_test.html b/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane_test.html index e9e77c6d..d3418cba 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane_test.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane_test.html @@ -23,6 +23,7 @@ tr.b.unittest.testSuite(function() { test('instantiate_zeroDumps', function() { var viewEl = document.createElement('tr-ui-a-memory-dump-overview-pane'); viewEl.processMemoryDumps = []; + viewEl.rebuild(); this.addHTMLOutput(viewEl); var table = tr.b.findDeepElementMatching(viewEl, 'tr-ui-b-table'); @@ -40,6 +41,7 @@ tr.b.unittest.testSuite(function() { var viewEl = document.createElement('tr-ui-a-memory-dump-overview-pane'); viewEl.processMemoryDumps = processMemoryDumps.slice(1, 2); + viewEl.rebuild(); this.addHTMLOutput(viewEl); var table = tr.b.findDeepElementMatching(viewEl, 'tr-ui-b-table'); @@ -61,16 +63,16 @@ tr.b.unittest.testSuite(function() { var tracingColumn = columns[7]; assert.equal(titleColumn.value(rows[0]).label, 'Process 2'); - assert.equal(totalColumn.value(rows[0]).children[0].numBytes, 19398656); + assert.equal(totalColumn.value(rows[0]).children[0].value, 19398656); assert.equal( - proportionalColumn.value(rows[0]).children[0].numBytes, 14155776); + proportionalColumn.value(rows[0]).children[0].value, 14155776); assert.equal( - privateDirtyColumn.value(rows[0]).children[0].numBytes, 0); + privateDirtyColumn.value(rows[0]).children[0].value, 0); assert.equal( - swappedColumn.value(rows[0]).children[0].numBytes, 32); - assert.equal(mallocColumn.value(rows[0]).numBytes, 2097152); - assert.equal(v8Column.value(rows[0]).numBytes, 5242880); - assert.equal(tracingColumn.value(rows[0]).children[0].numBytes, 1048576); + swappedColumn.value(rows[0]).children[0].value, 32); + assert.equal(mallocColumn.value(rows[0]).value, 2097152); + assert.equal(v8Column.value(rows[0]).value, 5242880); + assert.equal(tracingColumn.value(rows[0]).children[0].value, 1048576); }); test('instantiate_multipleDumps', function() { @@ -78,6 +80,7 @@ tr.b.unittest.testSuite(function() { var viewEl = document.createElement('tr-ui-a-memory-dump-overview-pane'); viewEl.processMemoryDumps = processMemoryDumps; + viewEl.rebuild(); this.addHTMLOutput(viewEl); var table = tr.b.findDeepElementMatching(viewEl, 'tr-ui-b-table'); @@ -95,34 +98,34 @@ tr.b.unittest.testSuite(function() { var privateDirtyColumn = columns[3]; var swappedColumn = columns[4]; var mallocColumn = columns[5]; - var v8Column = columns[6]; - var oilpanColumn = columns[7]; + var oilpanColumn = columns[6]; + var v8Column = columns[7]; var tracingColumn = columns[8]; // Check the rows of the table. assert.equal(titleColumn.value(rows[0]).label, 'Process 1'); - assert.equal(totalColumn.value(rows[0]).children[0].numBytes, 31457280); + assert.equal(totalColumn.value(rows[0]).children[0].value, 31457280); assert.equal( - proportionalColumn.value(rows[0]).children[0].numBytes, 10485760); + proportionalColumn.value(rows[0]).children[0].value, 10485760); assert.equal( - privateDirtyColumn.value(rows[0]).children[0].numBytes, 8388608); - assert.equal(swappedColumn.value(rows[0]).children[0].numBytes, 0); + privateDirtyColumn.value(rows[0]).children[0].value, 8388608); + assert.equal(swappedColumn.value(rows[0]).children[0].value, 0); assert.equal(mallocColumn.value(rows[0]), ''); assert.equal(v8Column.value(rows[0]), ''); assert.equal(oilpanColumn.value(rows[0]), ''); assert.equal(tracingColumn.value(rows[0]), ''); assert.equal(titleColumn.value(rows[1]).label, 'Process 2'); - assert.equal(totalColumn.value(rows[1]).children[0].numBytes, 19398656); + assert.equal(totalColumn.value(rows[1]).children[0].value, 19398656); assert.equal( - proportionalColumn.value(rows[1]).children[0].numBytes, 14155776); + proportionalColumn.value(rows[1]).children[0].value, 14155776); assert.equal( - privateDirtyColumn.value(rows[1]).children[0].numBytes, 0); - assert.equal(swappedColumn.value(rows[1]).children[0].numBytes, 32); - assert.equal(mallocColumn.value(rows[1]).numBytes, 2097152); - assert.equal(v8Column.value(rows[1]).numBytes, 5242880); + privateDirtyColumn.value(rows[1]).children[0].value, 0); + assert.equal(swappedColumn.value(rows[1]).children[0].value, 32); + assert.equal(mallocColumn.value(rows[1]).value, 2097152); + assert.equal(v8Column.value(rows[1]).value, 5242880); assert.equal(oilpanColumn.value(rows[1]), ''); - assert.equal(tracingColumn.value(rows[1]).children[0].numBytes, 1048576); + assert.equal(tracingColumn.value(rows[1]).children[0].value, 1048576); assert.equal(titleColumn.value(rows[2]).label, 'Process 3'); assert.equal(totalColumn.value(rows[2]), ''); @@ -130,24 +133,24 @@ tr.b.unittest.testSuite(function() { assert.equal(privateDirtyColumn.value(rows[2]), ''); assert.equal(swappedColumn.value(rows[2]), ''); assert.equal(mallocColumn.value(rows[2]), ''); - assert.equal(v8Column.value(rows[2]).numBytes, 1073741824); - assert.equal(oilpanColumn.value(rows[2]).numBytes, 2147483648); + assert.equal(v8Column.value(rows[2]).value, 1073741824); + assert.equal(oilpanColumn.value(rows[2]).value, 2147483648); assert.equal(tracingColumn.value(rows[2]), ''); // Check the footer row. assert.equal(titleColumn.value(footerRows[0]), 'Total'); assert.equal( - totalColumn.value(footerRows[0]).children[0].numBytes, 50855936); + totalColumn.value(footerRows[0]).children[0].value, 50855936); assert.equal( - proportionalColumn.value(footerRows[0]).children[0].numBytes, 24641536); + proportionalColumn.value(footerRows[0]).children[0].value, 24641536); assert.equal( - privateDirtyColumn.value(footerRows[0]).children[0].numBytes, 8388608); - assert.equal(swappedColumn.value(footerRows[0]).children[0].numBytes, 32); - assert.equal(mallocColumn.value(footerRows[0]).numBytes, 2097152); - assert.equal(v8Column.value(footerRows[0]).numBytes, 1078984704); - assert.equal(oilpanColumn.value(footerRows[0]).numBytes, 2147483648); + privateDirtyColumn.value(footerRows[0]).children[0].value, 8388608); + assert.equal(swappedColumn.value(footerRows[0]).children[0].value, 32); + assert.equal(mallocColumn.value(footerRows[0]).value, 2097152); + assert.equal(v8Column.value(footerRows[0]).value, 1078984704); + assert.equal(oilpanColumn.value(footerRows[0]).value, 2147483648); assert.equal( - tracingColumn.value(footerRows[0]).children[0].numBytes, 1048576); + tracingColumn.value(footerRows[0]).children[0].value, 1048576); }); test('selection', function() { @@ -155,31 +158,33 @@ tr.b.unittest.testSuite(function() { var viewEl = document.createElement('tr-ui-a-memory-dump-overview-pane'); viewEl.processMemoryDumps = processMemoryDumps; + viewEl.rebuild(); this.addHTMLOutput(viewEl); - var didFireSelectedDumpChanged; - viewEl.addEventListener('selected-memory-cell-changed', + var didFireRequestChildDumpChange; + viewEl.addEventListener('request-child-pane-change', function(e) { - didFireSelectedDumpChanged = true; + didFireRequestChildDumpChange = true; }); var table = tr.b.findDeepElementMatching( viewEl, 'tr-ui-b-table'); // Simulate clicking on the 'oilpan' cell of the second process. - didFireSelectedDumpChanged = false; + didFireRequestChildDumpChange = false; table.selectedTableRow = table.tableRows[2]; table.selectedColumnIndex = 7; - assert.isTrue(didFireSelectedDumpChanged); + assert.isTrue(didFireRequestChildDumpChange); assert.isDefined(viewEl.selectedMemoryCell); - assert.isDefined(viewEl.selectedMemoryCell.buildDetailsPane); + assert.isDefined(viewEl.childPaneBuilder); // Simulate clicking on the 'Proportional used memory (mmaps)' cell of the // second process. - didFireSelectedDumpChanged = false; + didFireRequestChildDumpChange = false; table.selectedColumnIndex = 2; - assert.isTrue(didFireSelectedDumpChanged); + assert.isTrue(didFireRequestChildDumpChange); assert.isUndefined(viewEl.selectedMemoryCell); + assert.isUndefined(viewEl.childPaneBuilder); }); test('memory', function() { @@ -193,14 +198,15 @@ tr.b.unittest.testSuite(function() { containerEl.textContent = ''; containerEl.appendChild(view); - var didFireSelectedDumpChanged = false; - view.addEventListener('selected-memory-cell-changed', function(e) { - didFireSelectedDumpChanged = true; + var didFireRequestChildDumpChange = false; + view.addEventListener('request-child-pane-change', function(e) { + didFireRequestChildDumpChange = true; }); view.processMemoryDumps = dumps; + view.rebuild(); - assert.equal(didFireSelectedDumpChanged, expectSelectionEventFires); + assert.equal(didFireRequestChildDumpChange, expectSelectionEventFires); var table = tr.b.findDeepElementMatching(view, 'tr-ui-b-table'); callback(view, table); @@ -210,6 +216,7 @@ tr.b.unittest.testSuite(function() { simulateView(processMemoryDumps, false, function(view, table) { // No cell should be selected. assert.isUndefined(view.selectedMemoryCell); + assert.isUndefined(view.childPaneBuilder); assert.isUndefined(table.selectedTableRow); assert.isUndefined(table.selectedColumnIndex); @@ -232,6 +239,7 @@ tr.b.unittest.testSuite(function() { simulateView(processMemoryDumps.slice(2, 3), false, function(view, table) { // No cell should be selected (the second process is not shown). assert.isUndefined(view.selectedMemoryCell); + assert.isUndefined(view.childPaneBuilder); assert.isUndefined(table.selectedTableRow); assert.isUndefined(table.selectedColumnIndex); }); @@ -240,6 +248,7 @@ tr.b.unittest.testSuite(function() { simulateView(processMemoryDumps, true, function(view, table) { // The 'PSS' column of the second process should be selected again. assert.equal(view.selectedMemoryCell.attr.value, 14155776); + assert.isDefined(view.childPaneBuilder); assert.strictEqual(table.selectedTableRow.title, 'Process 2'); assert.strictEqual( table.tableColumns[table.selectedColumnIndex].name, 'PSS'); @@ -254,6 +263,7 @@ tr.b.unittest.testSuite(function() { // Nothing should be selected (no process with a 'v8' column value is // shown). assert.isUndefined(view.selectedMemoryCell); + assert.isUndefined(view.childPaneBuilder); assert.isUndefined(table.selectedTableRow); assert.isUndefined(table.selectedColumnIndex); @@ -268,6 +278,7 @@ tr.b.unittest.testSuite(function() { // The 'Total resident' column of the first process should still be // selected. assert.equal(view.selectedMemoryCell.attr.value, 31457280); + assert.isDefined(view.childPaneBuilder); assert.strictEqual(table.selectedTableRow.title, 'Process 1'); assert.strictEqual( table.tableColumns[table.selectedColumnIndex].name, 'Total resident'); diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_test_utils.html b/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_test_utils.html index 0edf12f3..5969867f 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_test_utils.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_test_utils.html @@ -26,7 +26,7 @@ tr.exportTo('tr.ui.analysis', function() { var ScalarAttribute = tr.model.ScalarAttribute; function createTestGlobalMemoryDump() { - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { var p1 = model.getOrCreateProcess(1); var p2 = model.getOrCreateProcess(2); var p3 = model.getOrCreateProcess(3); diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util.html b/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util.html index 94869673..e05f0279 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util.html @@ -8,7 +8,7 @@ found in the LICENSE file. <link rel="import" href="/tracing/base/base.html"> <link rel="import" href="/tracing/model/attribute.html"> <link rel="import" href="/tracing/ui/base/dom_helpers.html"> -<link rel="import" href="/tracing/ui/units/size_in_bytes_span.html"> +<link rel="import" href="/tracing/ui/units/scalar_span.html"> <script> 'use strict'; @@ -132,22 +132,20 @@ tr.exportTo('tr.ui.analysis', function() { * 3. columns whose name is 'page_size'. * [least important, right in the resulting table] * - * where the order within each group is unmodified (stable sort). + * where columns are sorted alphabetically within each group. */ MemoryColumn.sortByImportance = function(columns, importanceRules) { var positions = columns.map(function(column, srcIndex) { return { importance: column.getImportance(importanceRules), - srcIndex: srcIndex, column: column }; }); positions.sort(function(a, b) { - // Keep existing order of columns if they have the same importance - // (stable sort). + // Sort columns with the same importance alphabetically. if (a.importance === b.importance) - return a.srcIndex - b.srcIndex; + return a.column.name.localeCompare(b.column.name); // Sort columns in descending order of importance. return b.importance - a.importance; @@ -321,8 +319,8 @@ tr.exportTo('tr.ui.analysis', function() { formatDefinedAttributeValue: function(attr) { if (this.units === 'bytes') { - var sizeEl = document.createElement('tr-ui-u-size-in-bytes-span'); - sizeEl.numBytes = attr.value; + var sizeEl = document.createElement('tr-ui-u-scalar-span'); + sizeEl.setValueAndUnit(attr.value, tr.b.u.Units.sizeInBytes); return sizeEl; } return MemoryColumn.prototype.formatDefinedAttributeValue.call( diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util_test.html b/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util_test.html index 80bda8af..cc43b1eb 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util_test.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util_test.html @@ -151,7 +151,7 @@ tr.b.unittest.testSuite(function() { assert.equal(column.name, 'second_column'); assert.equal(column.title, 'Second Column'); assert.isUndefined(column.width); - assert.equal(column.value({x: buildScalarCell('bytes', 1024)}).numBytes, + assert.equal(column.value({x: buildScalarCell('bytes', 1024)}).value, 1024); assert.isAbove(column.cmp({x: buildScalarCell('bytes', 100)}, {x: buildScalarCell('bytes', 99.99)}), 0); @@ -217,8 +217,8 @@ tr.b.unittest.testSuite(function() { MemoryColumn.sortByImportance(columns, rules); assert.lengthOf(columns, 4); - assert.equal(columns[0].name, 'resident_size'); - assert.equal(columns[1].name, 'proportional_size'); + assert.equal(columns[0].name, 'proportional_size'); + assert.equal(columns[1].name, 'resident_size'); assert.equal(columns[2].name, 'object_count'); assert.equal(columns[3].name, 'page_size'); }); @@ -441,7 +441,7 @@ tr.b.unittest.testSuite(function() { // Defined cell. var value = c.value({x: buildScalarCell('bytes', 1024)}); - assert.equal(value.numBytes, 1024); + assert.equal(value.value, 1024); this.addHTMLOutput(value); // Attribute with infos. @@ -453,7 +453,7 @@ tr.b.unittest.testSuite(function() { var value = c.value({x: cell}); assert.lengthOf(value.childNodes, 3); assert.equal(value.style.color, ''); - assert.equal(value.childNodes[0].numBytes, 2048); + assert.equal(value.childNodes[0].value, 2048); assert.equal(value.childNodes[1].textContent, String.fromCharCode(9888)); assert.equal(value.childNodes[1].title, 'This value is too cool'); assert.equal(value.childNodes[2].textContent, String.fromCharCode(9903)); @@ -473,7 +473,7 @@ tr.b.unittest.testSuite(function() { // Defined cell. var value = c.value({x: buildScalarCell('bytes', 1024)}); assert.lengthOf(value.childNodes, 1); - assert.equal(value.childNodes[0].numBytes, 1024); + assert.equal(value.childNodes[0].value, 1024); assert.equal(value.style.color, 'rgb(0, 153, 153)'); this.addHTMLOutput(value); @@ -486,7 +486,7 @@ tr.b.unittest.testSuite(function() { var value = c.value({x: cell}); assert.lengthOf(value.childNodes, 3); assert.equal(value.style.color, 'rgb(0, 153, 153)'); - assert.equal(value.childNodes[0].numBytes, 2048); + assert.equal(value.childNodes[0].value, 2048); assert.equal(value.childNodes[1].textContent, String.fromCharCode(9888)); assert.equal(value.childNodes[1].title, 'This value is too cool'); assert.equal(value.childNodes[2].textContent, String.fromCharCode(9903)); @@ -507,12 +507,12 @@ tr.b.unittest.testSuite(function() { // Defined cell. var value = c.value({x: buildScalarCell('bytes', 1024)}); - assert.equal(value.numBytes, 1024); + assert.equal(value.value, 1024); this.addHTMLOutput(value); var value = c.value({x: buildScalarCell('bytes', -1024)}); assert.lengthOf(value.childNodes, 1); - assert.equal(value.childNodes[0].numBytes, -1024); + assert.equal(value.childNodes[0].value, -1024); assert.equal(value.style.color, 'green'); this.addHTMLOutput(value); @@ -525,7 +525,7 @@ tr.b.unittest.testSuite(function() { var value = c.value({x: cell}); assert.lengthOf(value.childNodes, 3); assert.equal(value.style.color, ''); - assert.equal(value.childNodes[0].numBytes, 2048); + assert.equal(value.childNodes[0].value, 2048); assert.equal(value.childNodes[1].textContent, String.fromCharCode(9888)); assert.equal(value.childNodes[1].title, 'This value is too cool'); assert.equal(value.childNodes[2].textContent, String.fromCharCode(9903)); @@ -540,7 +540,7 @@ tr.b.unittest.testSuite(function() { var value = c.value({x: cell}); assert.lengthOf(value.childNodes, 2); assert.equal(value.style.color, 'green'); - assert.equal(value.childNodes[0].numBytes, -2048); + assert.equal(value.childNodes[0].value, -2048); assert.equal(value.childNodes[1].textContent, String.fromCharCode(9432)); assert.equal(value.childNodes[1].title, 'This value is impossibly cool'); this.addHTMLOutput(value); diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_view.html b/catapult/tracing/tracing/ui/analysis/memory_dump_view.html index 098dd615..875d858d 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_view.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_view.html @@ -6,25 +6,10 @@ found in the LICENSE file. --> <link rel="import" href="/tracing/ui/analysis/memory_dump_overview_pane.html"> +<link rel="import" href="/tracing/ui/analysis/stacked_pane_view.html"> -<polymer-element name="tr-ui-a-memory-dump-view"> - <template> - <style> - :host { - display: flex; - flex-direction: column; - } - - #overview_pane, - #details_pane_container { - flex: 0 0 auto; - } - </style> - <tr-ui-a-memory-dump-overview-pane id="overview_pane"> - </tr-ui-a-memory-dump-overview-pane> - <div id="details_pane_container"> - </div> - </template> +<polymer-element name="tr-ui-a-memory-dump-view" + extends="tr-ui-a-stacked-pane-view"> <script> 'use strict'; @@ -33,28 +18,18 @@ found in the LICENSE file. this.processMemoryDumps_ = undefined; }, - ready: function() { - this.$.overview_pane.addEventListener( - 'selected-memory-cell-changed', this.updateDetailsPane_.bind(this)); - }, - set processMemoryDumps(processMemoryDumps) { this.processMemoryDumps_ = processMemoryDumps; - this.$.overview_pane.processMemoryDumps = this.processMemoryDumps_; - this.updateDetailsPane_(); + this.setPaneBuilder(function() { + var overviewPane = document.createElement( + 'tr-ui-a-memory-dump-overview-pane'); + overviewPane.processMemoryDumps = this.processMemoryDumps_; + return overviewPane; + }.bind(this)); }, get processMemoryDumps() { return this.processMemoryDumps_; - }, - - updateDetailsPane_: function() { - this.$.details_pane_container.textContent = ''; - var selectedMemoryCell = this.$.overview_pane.selectedMemoryCell; - if (!selectedMemoryCell || !selectedMemoryCell.buildDetailsPane) - return; - this.$.details_pane_container.appendChild( - selectedMemoryCell.buildDetailsPane()); } }); </script> diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_view_test.html b/catapult/tracing/tracing/ui/analysis/memory_dump_view_test.html index 88088ca2..57be37e4 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_view_test.html @@ -22,6 +22,7 @@ tr.b.unittest.testSuite(function() { var viewEl = document.createElement('tr-ui-a-memory-dump-view'); viewEl.processMemoryDumps = processMemoryDumps; + viewEl.rebuild(); this.addHTMLOutput(viewEl); var overviewPane = tr.b.findDeepElementMatching( @@ -34,6 +35,7 @@ tr.b.unittest.testSuite(function() { // Select totals of first process. overviewTable.selectedTableRow = overviewTable.tableRows[0]; overviewTable.selectedColumnIndex = 1; + viewEl.rebuild(); var detailsPane = tr.b.findDeepElementMatching( viewEl, 'tr-ui-a-memory-dump-vm-regions-details-pane'); assert.strictEqual( @@ -41,6 +43,7 @@ tr.b.unittest.testSuite(function() { // Select PSS of first process. overviewTable.selectedColumnIndex = 2; + viewEl.rebuild(); var detailsPane = tr.b.findDeepElementMatching( viewEl, 'tr-ui-a-memory-dump-vm-regions-details-pane'); assert.strictEqual( @@ -48,12 +51,14 @@ tr.b.unittest.testSuite(function() { // Select PSS of third process. overviewTable.selectedTableRow = overviewTable.tableRows[2]; + viewEl.rebuild(); var detailsPane = tr.b.findDeepElementMatching( viewEl, 'tr-ui-a-memory-dump-vm-regions-details-pane'); assert.isUndefined(detailsPane); // Select oilpan dump of second process. overviewTable.selectedColumnIndex = 7; + viewEl.rebuild(); var detailsPane = tr.b.findDeepElementMatching( viewEl, 'tr-ui-a-memory-dump-allocator-details-pane'); var detailsTable = tr.b.findDeepElementMatching( diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html b/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html index 725130f0..3ba514db 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html @@ -6,10 +6,12 @@ found in the LICENSE file. --> <link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html"> +<link rel="import" href="/tracing/ui/analysis/stacked_pane.html"> <link rel="import" href="/tracing/ui/base/table.html"> <link rel="import" href="/tracing/model/attribute.html"> -<polymer-element name="tr-ui-a-memory-dump-vm-regions-details-pane"> +<polymer-element name="tr-ui-a-memory-dump-vm-regions-details-pane" + extends="tr-ui-a-stacked-pane"> <template> <style> :host { @@ -115,7 +117,7 @@ found in the LICENSE file. }, { name: 'Native heap', - file: /^((\[heap\])|(\[anon:)|(\/dev\/ashmem\/libc malloc)|$)/ + file: /^((\[heap\])|(\[anon:)|(\/dev\/ashmem\/libc malloc)|(\[discounted tracing overhead\])|$)/ // @suppress longLineCheck }, { name: 'Stack', @@ -168,12 +170,6 @@ found in the LICENSE file. file: /anon_inode:dmabuf/ } ] - }, - { - // Add a separate category for the discounted tracing overhead to - // avoid negative 'Total/Other' sizes. - name: 'Discounted tracing overhead', - file: /\[discounted tracing overhead\]/ } ] }; @@ -275,29 +271,20 @@ found in the LICENSE file. } Polymer({ - // TODO(petrcermak): Consider sharing more code between - // tr-ui-a-memory-dump-allocator-details-pane and - // tr-ui-a-memory-dump-vm-regions-details-pane (e.g. by defining a common - // base class tr-c-memory-dump-details-pane). - created: function() { this.vmRegions_ = undefined; }, - ready: function() { - this.updateContents_(); - }, - set vmRegions(vmRegions) { this.vmRegions_ = vmRegions; - this.updateContents_(); + this.scheduleRebuildPane_(); }, get vmRegions() { return this.vmRegions_; }, - updateContents_: function() { + rebuildPane_: function() { this.$.contents.textContent = ''; if (this.vmRegions_ === undefined) { diff --git a/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane_test.html b/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane_test.html index b94238a7..a8983406 100644 --- a/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane_test.html +++ b/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane_test.html @@ -6,7 +6,10 @@ found in the LICENSE file. --> <link rel="import" href="/tracing/core/test_utils.html"> +<link rel="import" href="/tracing/model/attribute.html"> <link rel="import" href="/tracing/model/event_set.html"> +<link rel="import" href="/tracing/model/global_memory_dump.html"> +<link rel="import" href="/tracing/model/memory_allocator_dump.html"> <link rel="import" href="/tracing/model/process_memory_dump.html"> <link rel="import" href="/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html"> @@ -16,80 +19,103 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { + var MemoryAllocatorDump = tr.model.MemoryAllocatorDump; + var GlobalMemoryDump = tr.model.GlobalMemoryDump; + var ProcessMemoryDump = tr.model.ProcessMemoryDump; + var ScalarAttribute = tr.model.ScalarAttribute; var VMRegion = tr.model.VMRegion; function createVMRegions() { - return [ - VMRegion.fromDict({ - mappedFile: '/lib/chrome.so', - startAddress: 65536, - sizeInBytes: 536870912, - protectionFlags: VMRegion.PROTECTION_FLAG_READ | - VMRegion.PROTECTION_FLAG_EXECUTE, - byteStats: { - proportionalResident: 8192 - } - }), - VMRegion.fromDict({ - mappedFile: '/usr/lib/x86_64-linux-gnu/libX11.so.6.3.0', - startAddress: 140296983150592, - sizeInBytes: 2097152, - protectionFlags: 0, - byteStats: { - proportionalResident: 0 - } - }), - VMRegion.fromDict({ - startAddress: 10995116277760, - sizeInBytes: 2147483648, - protectionFlags: VMRegion.PROTECTION_FLAG_READ | - VMRegion.PROTECTION_FLAG_WRITE, - byteStats: { - privateDirtyResident: 0, - swapped: 0 - } - }), - VMRegion.fromDict({ - startAddress: 12094627905536, - sizeInBytes: 2147483648, - protectionFlags: VMRegion.PROTECTION_FLAG_READ | - VMRegion.PROTECTION_FLAG_WRITE, - byteStats: { - privateDirtyResident: 0, - swapped: 0 - } - }), - VMRegion.fromDict({ - mappedFile: '/dev/ashmem/dalvik-zygote space', - startAddress: 13194139533312, - sizeInBytes: 100, - protectionFlags: VMRegion.PROTECTION_FLAG_READ | - VMRegion.PROTECTION_FLAG_EXECUTE, - byteStats: { - proportionalResident: 100, - privateDirtyResident: 0, - swapped: 0 - } - }), - VMRegion.fromDict({ - mappedFile: '/dev/ashmem/libc malloc', - startAddress: 14293651161088, - sizeInBytes: 200, - protectionFlags: VMRegion.PROTECTION_FLAG_READ | - VMRegion.PROTECTION_FLAG_EXECUTE, - byteStats: { - proportionalResident: 200, - privateDirtyResident: 0, - swapped: 0 - } - }) - ]; + var model = tr.c.TestUtils.newModel(function(model) { + var gmd = new GlobalMemoryDump(model, 42); + model.globalMemoryDumps.push(gmd); + var process = model.getOrCreateProcess(1); + var pmd = new ProcessMemoryDump(gmd, process, 42); + process.memoryDumps.push(pmd); + gmd.processMemoryDumps[process.pid] = pmd; + + pmd.vmRegions = [ + VMRegion.fromDict({ + mappedFile: '/lib/chrome.so', + startAddress: 65536, + sizeInBytes: 536870912, + protectionFlags: VMRegion.PROTECTION_FLAG_READ | + VMRegion.PROTECTION_FLAG_EXECUTE, + byteStats: { + proportionalResident: 8192 + } + }), + VMRegion.fromDict({ + mappedFile: '/usr/lib/x86_64-linux-gnu/libX11.so.6.3.0', + startAddress: 140296983150592, + sizeInBytes: 2097152, + protectionFlags: 0, + byteStats: { + proportionalResident: 0 + } + }), + VMRegion.fromDict({ + startAddress: 10995116277760, + sizeInBytes: 2147483648, + protectionFlags: VMRegion.PROTECTION_FLAG_READ | + VMRegion.PROTECTION_FLAG_WRITE, + byteStats: { + privateDirtyResident: 0, + swapped: 0 + } + }), + VMRegion.fromDict({ + startAddress: 12094627905536, + sizeInBytes: 2147483648, + protectionFlags: VMRegion.PROTECTION_FLAG_READ | + VMRegion.PROTECTION_FLAG_WRITE, + byteStats: { + privateDirtyResident: 0, + swapped: 0 + } + }), + VMRegion.fromDict({ + mappedFile: '/dev/ashmem/dalvik-zygote space', + startAddress: 13194139533312, + sizeInBytes: 100, + protectionFlags: VMRegion.PROTECTION_FLAG_READ | + VMRegion.PROTECTION_FLAG_EXECUTE, + byteStats: { + proportionalResident: 100, + privateDirtyResident: 0, + swapped: 0 + } + }), + VMRegion.fromDict({ + mappedFile: '/dev/ashmem/libc malloc', + startAddress: 14293651161088, + sizeInBytes: 200, + protectionFlags: VMRegion.PROTECTION_FLAG_READ | + VMRegion.PROTECTION_FLAG_EXECUTE, + byteStats: { + proportionalResident: 200, + privateDirtyResident: 96, + swapped: 0 + } + }) + ]; + + // This is here so that we could test that tracing is discounted from the + // 'Native heap' category. + var tracingDump = new MemoryAllocatorDump(pmd, 'tracing'); + tracingDump.addAttribute('size', new ScalarAttribute('bytes', 500)); + tracingDump.addAttribute('resident_size', + new ScalarAttribute('bytes', 32)); + pmd.memoryAllocatorDumps = [tracingDump]; + }); + + return model.processes[1].memoryDumps[0].mostRecentVmRegions; } function checkRowValue(row, column, expectedValue) { var value = column.value(row); if (typeof(expectedValue) === 'number') - value = value.numBytes; + value = value.value; assert.equal(value, expectedValue); } @@ -105,6 +131,7 @@ tr.b.unittest.testSuite(function() { var viewEl = document.createElement( 'tr-ui-a-memory-dump-vm-regions-details-pane'); viewEl.vmRegions = vmRegions; + viewEl.rebuild(); this.addHTMLOutput(viewEl); var table = tr.b.findDeepElementMatching( @@ -146,7 +173,7 @@ tr.b.unittest.testSuite(function() { assert.lengthOf(rows, 1); var totalRow = rows[0]; - checkRow(totalRow, 'Total', 4833935660, 8492, 0, 0, '', '', 7); + checkRow(totalRow, 'Total', 4833935660, 8460, 64, 0, '', '', 6); var androidRow = totalRow.subRows[0]; checkRow(androidRow, 'Android', 100, 100, 0, 0, '', '', 3); @@ -160,6 +187,13 @@ tr.b.unittest.testSuite(function() { var normalRow = spacesRow.subRows[0]; checkRow(normalRow, 'Normal', '', '', '', '', '', '', 0); + var nativeHeapRow = totalRow.subRows[1]; + checkRow(nativeHeapRow, 'Native heap', 200, 168, 64, 0, '', '', 2); + + var discountedTracingOverheadRow = nativeHeapRow.subRows[1]; + checkRow(discountedTracingOverheadRow, '[discounted tracing overhead]', '', + -32, -32, '', '', '', undefined); + var filesRow = totalRow.subRows[3]; checkRow(filesRow, 'Files', 538968064, 8192, '', '', '', '', 7); @@ -174,7 +208,7 @@ tr.b.unittest.testSuite(function() { checkRow(mmapLibX11Row, '/usr/lib/x86_64-linux-gnu/libX11.so.6.3.0', 2097152, 0, '', '', '00007f996fd80000', '---', undefined); - var otherRow = totalRow.subRows[6]; + var otherRow = totalRow.subRows[5]; checkRow(otherRow, 'Other', 4294967296, '', 0, 0, '', '', 2); var mmapOther2Row = otherRow.subRows[1]; diff --git a/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view_test.html index a015b921..f3db7675 100644 --- a/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view_test.html @@ -14,7 +14,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newAsyncSliceEx = tr.c.test_utils.newAsyncSliceEx; + var newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx; test('instantiate', function() { var model = new tr.Model(); diff --git a/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view_test.html index dec9c223..b0f8eb26 100644 --- a/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view_test.html @@ -26,7 +26,7 @@ tr.b.unittest.testSuite(function() { ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck ]; - return tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + return tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/ui/analysis/multi_event_details_table_test.html b/catapult/tracing/tracing/ui/analysis/multi_event_details_table_test.html index a962d84c..0bf2d13e 100644 --- a/catapult/tracing/tracing/ui/analysis/multi_event_details_table_test.html +++ b/catapult/tracing/tracing/ui/analysis/multi_event_details_table_test.html @@ -18,7 +18,7 @@ tr.b.unittest.testSuite(function() { var Model = tr.Model; var Thread = tr.model.Thread; var EventSet = tr.model.EventSet; - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; test('sortingOfFirstColumn', function() { var model = new Model(); diff --git a/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html index 94b13cbb..e6f34f31 100644 --- a/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html @@ -18,8 +18,8 @@ tr.b.unittest.testSuite(function() { var Model = tr.Model; var Thread = tr.model.Thread; var EventSet = tr.model.EventSet; - var newSliceEx = tr.c.test_utils.newSliceEx; - var newSliceCategory = tr.c.test_utils.newSliceCategory; + var newSliceEx = tr.c.TestUtils.newSliceEx; + var newSliceCategory = tr.c.TestUtils.newSliceCategory; var Slice = tr.model.Slice; test('differentTitles', function() { diff --git a/catapult/tracing/tracing/ui/analysis/multi_event_summary_table_test.html b/catapult/tracing/tracing/ui/analysis/multi_event_summary_table_test.html index 3ef96501..ebef452a 100644 --- a/catapult/tracing/tracing/ui/analysis/multi_event_summary_table_test.html +++ b/catapult/tracing/tracing/ui/analysis/multi_event_summary_table_test.html @@ -17,7 +17,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var Model = tr.Model; var EventSet = tr.model.EventSet; - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; test('basicNoCpu', function() { var model = new Model(); diff --git a/catapult/tracing/tracing/ui/analysis/multi_event_summary_test.html b/catapult/tracing/tracing/ui/analysis/multi_event_summary_test.html index 2cc5904b..5f7782b1 100644 --- a/catapult/tracing/tracing/ui/analysis/multi_event_summary_test.html +++ b/catapult/tracing/tracing/ui/analysis/multi_event_summary_test.html @@ -15,7 +15,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var Model = tr.Model; - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; test('summaryRowNoCpu', function() { var model = new Model(); diff --git a/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view_test.html index 3ac2e700..17894f96 100644 --- a/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view_test.html @@ -15,11 +15,11 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newSampleNamed = tr.c.test_utils.newSampleNamed; + var newSampleNamed = tr.c.TestUtils.newSampleNamed; test('instantiate_withMultipleSamples', function() { var t53; - var m = tr.c.test_utils.newModelWithEvents([], { + var m = tr.c.TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: function(model) { diff --git a/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view_test.html index e3863d36..ce8e070a 100644 --- a/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view_test.html @@ -15,8 +15,8 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newSliceEx = tr.c.test_utils.newSliceEx; - var newFlowEventEx = tr.c.test_utils.newFlowEventEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; + var newFlowEventEx = tr.c.TestUtils.newFlowEventEx; test('instantiate', function() { var model = new tr.Model(); @@ -39,7 +39,7 @@ tr.b.unittest.testSuite(function() { }); test('withFlows', function() { - var m = tr.c.test_utils.newModel(function(m) { + var m = tr.c.TestUtils.newModel(function(m) { m.p1 = m.getOrCreateProcess(1); m.t2 = m.p1.getOrCreateThread(2); diff --git a/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view_test.html index c7d1b826..a0b88c03 100644 --- a/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view_test.html @@ -26,7 +26,7 @@ tr.b.unittest.testSuite(function() { ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck ]; - return tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + return tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/ui/analysis/power_sample_summary_table.html b/catapult/tracing/tracing/ui/analysis/power_sample_summary_table.html index 95c0dba8..99c4ec88 100644 --- a/catapult/tracing/tracing/ui/analysis/power_sample_summary_table.html +++ b/catapult/tracing/tracing/ui/analysis/power_sample_summary_table.html @@ -5,8 +5,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/energy_in_joules.html"> -<link rel="import" href="/tracing/base/units/power_in_watts.html"> +<link rel="import" href="/tracing/base/units/units.html"> <link rel="import" href="/tracing/model/event_set.html"> <link rel="import" href="/tracing/ui/base/table.html"> <link rel="import" href="/tracing/ui/units/time_stamp_span.html"> @@ -25,21 +24,21 @@ found in the LICENSE file. title: 'Min power', width: '100px', value: function(row) { - return tr.b.units.PowerInWatts.format(row.min / 1000.0); + return tr.b.u.Units.powerInWatts.format(row.min / 1000.0); } }, { title: 'Max power', width: '100px', value: function(row) { - return tr.b.units.PowerInWatts.format(row.max / 1000.0); + return tr.b.u.Units.powerInWatts.format(row.max / 1000.0); } }, { title: 'Time-weighted average', width: '100px', value: function(row) { - return tr.b.units.PowerInWatts.format( + return tr.b.u.Units.powerInWatts.format( row.timeWeightedAverage / 1000.0); } }, @@ -47,7 +46,7 @@ found in the LICENSE file. title: 'Energy consumed', width: '100px', value: function(row) { - return tr.b.units.EnergyInJoules.format(row.energyConsumed); + return tr.b.u.Units.energyInJoules.format(row.energyConsumed); } }, { diff --git a/catapult/tracing/tracing/ui/analysis/related_events.html b/catapult/tracing/tracing/ui/analysis/related_events.html index 701c1684..faec4d04 100644 --- a/catapult/tracing/tracing/ui/analysis/related_events.html +++ b/catapult/tracing/tracing/ui/analysis/related_events.html @@ -34,6 +34,7 @@ found in the LICENSE file. Polymer({ ready: function() { this.eventGroups_ = []; + this.cancelFunctions_ = []; this.$.table.tableColumns = [ { @@ -67,6 +68,7 @@ found in the LICENSE file. }, setRelatedEvents: function(eventSet) { + this.cancelAllTasks_(); this.eventGroups_ = []; this.addConnectedFlows_(eventSet); this.addConnectedEvents_(eventSet); @@ -107,8 +109,15 @@ found in the LICENSE file. addToEventGroups.bind(this, 'Internal flow')); }, + cancelAllTasks_: function() { + this.cancelFunctions_.forEach(function(cancelFunction) { + cancelFunction(); + }); + this.cancelFunctions_ = []; + }, + addConnectedEvents_: function(eventSet) { - this.createEventsLinkIfNeeded_( + this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( 'Preceding events', 'Add all events that have led to the selected one(s), connected by ' + 'flow arrows or by call stack.', @@ -118,8 +127,8 @@ found in the LICENSE file. this.addAncestors_(event, events); if (event.startSlice) events.push(event.startSlice); - }.bind(this)); - this.createEventsLinkIfNeeded_( + }.bind(this))); + this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( 'Following events', 'Add all events that have been caused by the selected one(s), ' + 'connected by flow arrows or by call stack.', @@ -129,8 +138,8 @@ found in the LICENSE file. this.addDescendents_(event, events); if (event.endSlice) events.push(event.endSlice); - }.bind(this)); - this.createEventsLinkIfNeeded_( + }.bind(this))); + this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( 'All connected events', 'Add all events connected to the selected one(s) by flow arrows or ' + 'by call stack.', @@ -144,14 +153,17 @@ found in the LICENSE file. events.push(event.startSlice); if (event.endSlice) events.push(event.endSlice); - }.bind(this)); + }.bind(this))); }, createEventsLinkIfNeeded_: function(title, tooltip, events, addFunction) { events = new tr.model.EventSet(events); var lengthBefore = events.length; var task; + var isCanceled = false; function addEventsUntilTimeout(startingIndex) { + if (isCanceled) + return; var startingTime = window.performance.now(); while (startingIndex < events.length) { addFunction(events[startingIndex], events); @@ -175,8 +187,12 @@ found in the LICENSE file. }); this.updateContents_(); }; + function cancelTask() { + isCanceled = true; + } task = new tr.b.Task(addEventsUntilTimeout.bind(this, 0), this); tr.b.Task.RunWhenIdle(task); + return cancelTask; }, addInFlowEvents_: function(event, eventSet) { diff --git a/catapult/tracing/tracing/ui/analysis/related_events_test.html b/catapult/tracing/tracing/ui/analysis/related_events_test.html index ef562895..c416940c 100644 --- a/catapult/tracing/tracing/ui/analysis/related_events_test.html +++ b/catapult/tracing/tracing/ui/analysis/related_events_test.html @@ -17,11 +17,11 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newSliceEx = tr.c.test_utils.newSliceEx; - var newFlowEventEx = tr.c.test_utils.newFlowEventEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; + var newFlowEventEx = tr.c.TestUtils.newFlowEventEx; function createModel() { - var m = tr.c.test_utils.newModel(function(m) { + var m = tr.c.TestUtils.newModel(function(m) { m.p1 = m.getOrCreateProcess(1); m.t2 = m.p1.getOrCreateThread(2); diff --git a/catapult/tracing/tracing/ui/analysis/selection_summary_table_test.html b/catapult/tracing/tracing/ui/analysis/selection_summary_table_test.html index 34484908..fbcc2cb0 100644 --- a/catapult/tracing/tracing/ui/analysis/selection_summary_table_test.html +++ b/catapult/tracing/tracing/ui/analysis/selection_summary_table_test.html @@ -17,7 +17,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var Model = tr.Model; var EventSet = tr.model.EventSet; - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; test('noSelection', function() { var summaryTable = diff --git a/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view_test.html index 6c887a0b..cc83a239 100644 --- a/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view_test.html @@ -14,7 +14,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newAsyncSliceEx = tr.c.test_utils.newAsyncSliceEx; + var newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx; test('instantiate', function() { var model = new tr.Model(); diff --git a/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view_test.html index 62e864fe..8d5a7c43 100644 --- a/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view_test.html @@ -26,7 +26,7 @@ tr.b.unittest.testSuite(function() { ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck ]; - return tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + return tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/ui/analysis/single_event_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/single_event_sub_view_test.html index 3772a704..f827d053 100644 --- a/catapult/tracing/tracing/ui/analysis/single_event_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/single_event_sub_view_test.html @@ -18,10 +18,10 @@ tr.b.unittest.testSuite(function() { var Model = tr.Model; var Thread = tr.model.Thread; var EventSet = tr.model.EventSet; - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; function createSelection(customizeThreadCallback) { - var model = tr.c.test_utils.newModelWithEvents([], { + var model = tr.c.TestUtils.newModelWithEvents([], { customizeModelCallback: function(model) { var t53 = model.getOrCreateProcess(52).getOrCreateThread(53); customizeThreadCallback(t53, model); @@ -43,8 +43,8 @@ tr.b.unittest.testSuite(function() { var options = opt_options || {}; return createSelection(function(t53, model) { if (options.withStartStackFrame || options.withEndStackFrame) { - var fA = tr.c.test_utils.newStackTrace(model, 'cat', ['a1', 'a2']); - var fB = tr.c.test_utils.newStackTrace(model, 'cat', ['b1', 'b2']); + var fA = tr.c.TestUtils.newStackTrace(model, 'cat', ['a1', 'a2']); + var fB = tr.c.TestUtils.newStackTrace(model, 'cat', ['b1', 'b2']); } var slice = newSliceEx({title: 'b', start: 0, duration: 0.002}); diff --git a/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view_test.html index d1318de3..d9203d30 100644 --- a/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view_test.html @@ -16,7 +16,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var Model = tr.Model; var EventSet = tr.model.EventSet; - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; test('analyzeSelectionWithSingleEvent', function() { var model = test_utils.newModel(function(model) { diff --git a/catapult/tracing/tracing/ui/analysis/single_sample_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/single_sample_sub_view_test.html index 599f13ae..91c62709 100644 --- a/catapult/tracing/tracing/ui/analysis/single_sample_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/single_sample_sub_view_test.html @@ -17,11 +17,11 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var Model = tr.Model; var EventSet = tr.model.EventSet; - var newSampleNamed = tr.c.test_utils.newSampleNamed; + var newSampleNamed = tr.c.TestUtils.newSampleNamed; test('instantiate_withSingleSample', function() { var t53; - var model = tr.c.test_utils.newModelWithEvents([], { + var model = tr.c.TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: function(model) { diff --git a/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view_test.html index e27f2c9d..7cce4d0d 100644 --- a/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view_test.html @@ -15,8 +15,8 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newSliceEx = tr.c.test_utils.newSliceEx; - var newFlowEventEx = tr.c.test_utils.newFlowEventEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; + var newFlowEventEx = tr.c.TestUtils.newFlowEventEx; test('instantiate', function() { var model = new tr.Model(); @@ -34,7 +34,7 @@ tr.b.unittest.testSuite(function() { }); test('instantiateWithFlowEvent', function() { - var m = tr.c.test_utils.newModel(function(m) { + var m = tr.c.TestUtils.newModel(function(m) { m.p1 = m.getOrCreateProcess(1); m.t2 = m.p1.getOrCreateThread(2); diff --git a/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view_test.html b/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view_test.html index f3bbf76e..91245e96 100644 --- a/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view_test.html +++ b/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view_test.html @@ -26,7 +26,7 @@ tr.b.unittest.testSuite(function() { ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck ]; - return tr.c.test_utils.newModelWithEvents([lines.join('\n')], { + return tr.c.TestUtils.newModelWithEvents([lines.join('\n')], { shiftWorldToZero: false }); } diff --git a/catapult/tracing/tracing/ui/analysis/stack_frame_test.html b/catapult/tracing/tracing/ui/analysis/stack_frame_test.html index 33b55855..1647dfe2 100644 --- a/catapult/tracing/tracing/ui/analysis/stack_frame_test.html +++ b/catapult/tracing/tracing/ui/analysis/stack_frame_test.html @@ -12,7 +12,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('instantiate', function() { var model = new tr.Model(); - var fA = tr.c.test_utils.newStackTrace(model, 'cat', ['a1', 'a2', 'a3']); + var fA = tr.c.TestUtils.newStackTrace(model, 'cat', ['a1', 'a2', 'a3']); var stackFrameView = document.createElement('tr-ui-a-stack-frame'); stackFrameView.stackFrame = fA; @@ -21,7 +21,7 @@ tr.b.unittest.testSuite(function() { test('clearingStackFrame', function() { var model = new tr.Model(); - var fA = tr.c.test_utils.newStackTrace(model, 'cat', ['a1', 'a2', 'a3']); + var fA = tr.c.TestUtils.newStackTrace(model, 'cat', ['a1', 'a2', 'a3']); var stackFrameView = document.createElement('tr-ui-a-stack-frame'); stackFrameView.stackFrame = fA; diff --git a/catapult/tracing/tracing/ui/analysis/stacked_pane.html b/catapult/tracing/tracing/ui/analysis/stacked_pane.html new file mode 100644 index 00000000..ba5deb30 --- /dev/null +++ b/catapult/tracing/tracing/ui/analysis/stacked_pane.html @@ -0,0 +1,89 @@ +<!DOCTYPE html> +<!-- +Copyright 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/base/base.html"> + +<!-- +@fileoverview Analysis view stacked pane. See the stacked pane view element +(tr-ui-a-stacked-pane-view) documentation for more details. +--> +<polymer-element name="tr-ui-a-stacked-pane"> + <script> + 'use strict'; + + Polymer({ + rebuild: function() { + /** + * Rebuild the pane if necessary. + * + * This method is not intended to be overriden by subclasses. Please + * override scheduleRebuildPane_() instead. + */ + if (!this.paneDirty_) { + // Avoid rebuilding unnecessarily as it breaks things like table + // selection. + return; + } + + this.paneDirty_ = false; + this.rebuildPane_(); + }, + + /** + * Mark the UI state of the pane as dirty and schedule a rebuild. + * + * This method is intended to be called by subclasses. + */ + scheduleRebuildPane_: function() { + if (this.paneDirty_) + return; + this.paneDirty_ = true; + setTimeout(this.rebuild.bind(this), 0); + }, + + /** + * Called when the pane is dirty and a rebuild is triggered. + * + * This method is intended to be overriden by subclasses (instead of + * directly overriding rebuild()). + */ + rebuildPane_: function() { + }, + + /** + * Request changing the child pane of this pane in the associated stacked + * pane view. If the assigned builder is undefined, request removing the + * current child pane. + * + * Note that setting this property before appended() is called will have no + * effect (as there will be no listener attached to the pane). + * + * This method is intended to be called by subclasses. + */ + set childPaneBuilder(childPaneBuilder) { + this.childPaneBuilder_ = childPaneBuilder; + this.dispatchEvent(new tr.b.Event('request-child-pane-change')); + }, + + get childPaneBuilder() { + return this.childPaneBuilder_; + }, + + /** + * Called right after the pane is appended to a pane view. + * + * This method triggers an immediate rebuild by default (if necessary). + * Subclasses are free to change this behavior (e.g. if a pane has lots of + * data to display, it might decide to defer rebuilding in order not to + * cause jank). + */ + appended: function() { + this.rebuild(); + } + }); + </script> +</polymer-element> diff --git a/catapult/tracing/tracing/ui/analysis/stacked_pane_test.html b/catapult/tracing/tracing/ui/analysis/stacked_pane_test.html new file mode 100644 index 00000000..f76feea8 --- /dev/null +++ b/catapult/tracing/tracing/ui/analysis/stacked_pane_test.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<!-- +Copyright 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/ui/analysis/stacked_pane.html"> + +<script> +'use strict'; + +tr.b.unittest.testSuite(function() { + test('rebuild', function() { + var pane = document.createElement('tr-ui-a-stacked-pane'); + var didFireBuildPane; + pane.rebuildPane_ = function() { + didFireBuildPane = true; + }; + + function checkRebuild(expectedDidFireBuildPane) { + didFireBuildPane = false; + pane.rebuild(); + assert.strictEqual(didFireBuildPane, expectedDidFireBuildPane); + } + + // No rebuilds should occur when not scheduled. + checkRebuild(false); + checkRebuild(false); + + // Single rebuild should occur when scheduled once. + pane.scheduleRebuildPane_(); + checkRebuild(true); + checkRebuild(false); + + // Only a single rebuild should occur even when scheduled multiple times. + pane.scheduleRebuildPane_(); + pane.scheduleRebuildPane_(); + checkRebuild(true); + checkRebuild(false); + }); + + test('changeChildPane', function() { + var pane = document.createElement('tr-ui-a-stacked-pane'); + var didFireEvent; + pane.addEventListener('request-child-pane-change', function() { + didFireEvent = true; + }); + + didFireEvent = false; + pane.childPaneBuilder = undefined; + assert.isTrue(didFireEvent); + + didFireEvent = false; + pane.childPaneBuilder = function() { + return undefined; + }; + assert.isTrue(didFireEvent); + + didFireEvent = false; + pane.childPaneBuilder = function() { + return document.createElement('tr-ui-a-stacked-pane'); + }; + assert.isTrue(didFireEvent); + }); +}); +</script> diff --git a/catapult/tracing/tracing/ui/analysis/stacked_pane_view.html b/catapult/tracing/tracing/ui/analysis/stacked_pane_view.html new file mode 100644 index 00000000..a3c52f78 --- /dev/null +++ b/catapult/tracing/tracing/ui/analysis/stacked_pane_view.html @@ -0,0 +1,189 @@ +<!DOCTYPE html> +<!-- +Copyright 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/base/base.html"> + +<!-- +@fileoverview Analysis view container which displays vertically stacked panes. +The panes represent a hierarchy where a child pane contains the details of the +current selection in its parent pane. The container provides simple primitives +for panes to request changing their child pane: + + +=<tr-ui-a-stacked-pane-view>=+ +=<tr-ui-a-stacked-pane-view>=+ + |+.<tr-ui-a-stacked-pane>....+| |+.<tr-ui-a-stacked-pane>....+| + |: Pane 1 +| ===========> |: Pane 1 +| + |+...........................+| Pane 1 |+...........................+| + |+.<tr-ui-a-stacked-pane>....+| requests |+.<tr-ui-a-stacked-pane>....+| + |: Pane 2 (detail of Pane 1) +| child pane |: Pane 4 (detail of Pane 1) +| + |+...........................+| change (e.g. |+...........................+| + |+.<tr-ui-a-stacked-pane>....+| selection +=============================+ + |: Pane 3 (detail of Pane 2) +| changed) + |+...........................+| + +=============================+ + +Note that the actual UI provided by tr-ui-a-stacked-pane-view and +tr-ui-a-stacked-pane is merely a wrapper container with flex box vertical +stacking. No other visual features (such as pane spacing or borders) is +provided by either element. + +The stacked pane element (tr-ui-a-stacked-pane) is defined in a separate file. + +Sample use case: + + Create an empty stacked pane view and add it to the DOM: + + var paneView = document.createElement('tr-ui-a-stacked-pane-view'); + someParentView.appendChild(paneView); + + Define one or more pane subclasses: + + <polymer-element name="some-pane-1" extends="tr-ui-a-stacked-pane"> + ... + </polymer-element> + + Set the top-level pane (by providing a builder function): + + paneView.setPaneBuilder(function() { + var topPane = document.createElement('some-pane-1'); + pane.someProperty = someValue; + return topPane; + }); + + Show a child pane with details upon user interaction (these methods should be + in the definition of the pane subclass Polymer element): + + ready: function() { + this.$.table.addEventListener( + 'selection-changed', this.changeChildPane_.bind(this)); + } + + changeChildPane_: function() { + this.childPaneBuilder = function() { + var selectedRow = this.$.table.selectedTableRow; + var detailsPane = document.createElement('some-pane-2'); + detailsPane.someProperty = selectedRow; + return detailsPane; + }.bind(this); + } +--> +<polymer-element name="tr-ui-a-stacked-pane-view"> + <template> + <style> + :host { + display: flex; + flex-direction: column; + } + + #pane_container > * { + flex: 0 0 auto; + } + </style> + <div id="pane_container"> + </div> + </template> + <script> + 'use strict'; + + Polymer({ + /** + * Add a pane to the stacked pane view. This method performs two operations: + * + * 1. Remove existing descendant panes + * If the optional parent pane is provided, all its current descendant + * panes are removed. Otherwise, all panes are removed from the view. + * + * 2. Build and add new pane + * If a pane builder is provided and returns a pane, the new pane is + * appended to the view (after the provided parent, or at the top). + */ + setPaneBuilder: function(paneBuilder, opt_parentPane) { + var paneContainer = this.$.pane_container; + + // If the parent pane is provided, it must be an HTML element and a child + // of the pane container. + if (opt_parentPane) { + if (!(opt_parentPane instanceof HTMLElement)) + throw new Error('Parent pane must be an HTML element'); + if (opt_parentPane.parentElement !== paneContainer) + throw new Error('Parent pane must be a child of the pane container'); + } + + // Remove all descendants of the parent pane (or all panes if no parent + // pane was specified) in reverse order. + while (paneContainer.lastElementChild !== null && + paneContainer.lastElementChild !== opt_parentPane) { + var removedPane = this.$.pane_container.lastElementChild; + var listener = this.listeners_.get(removedPane); + if (listener === undefined) + throw new Error('No listener associated with pane'); + this.listeners_.delete(removedPane); + removedPane.removeEventListener( + 'request-child-pane-change', listener); + paneContainer.removeChild(removedPane); + } + + if (opt_parentPane && opt_parentPane.parentElement !== paneContainer) + throw new Error('Parent pane was removed from the pane container'); + + // This check is performed here (and not at the beginning of the method) + // because undefined pane builder means that the parent pane requested + // having no child pane (e.g. when selection is cleared). + if (!paneBuilder) + return; + + var pane = paneBuilder(); + if (!pane) + return; + + if (!(pane instanceof HTMLElement)) + throw new Error('Pane must be an HTML element'); + + // Listen for child pane change requests from the newly added pane. + var listener = function(event) { + this.setPaneBuilder(pane.childPaneBuilder, pane); + }.bind(this); + if (!this.listeners_) { + // Instead of initializing the listeners map in a created() callback, + // we do it lazily here so that subclasses could provide their own + // created() callback (Polymer currently doesn't allow calling overriden + // superclass methods in strict mode). + this.listeners_ = new WeakMap(); + } + this.listeners_.set(pane, listener); + pane.addEventListener('request-child-pane-change', listener); + + paneContainer.appendChild(pane); + pane.appended(); + }, + + /** + * Request rebuilding all panes in the view. The panes are rebuilt from the + * top to the bottom (so that parent panes could request changing their + * child panes when they're being rebuilt and the newly constructed child + * panes would be rebuilt as well). + */ + rebuild: function() { + var currentPane = this.$.pane_container.firstElementChild; + while (currentPane) { + currentPane.rebuild(); + currentPane = currentPane.nextElementSibling; + } + }, + + // For testing purposes. + get panesForTesting() { + var panes = []; + var currentChild = this.$.pane_container.firstElementChild; + while (currentChild) { + panes.push(currentChild); + currentChild = currentChild.nextElementSibling; + } + return panes; + } + }); + </script> +</polymer-element> diff --git a/catapult/tracing/tracing/ui/analysis/stacked_pane_view_test.html b/catapult/tracing/tracing/ui/analysis/stacked_pane_view_test.html new file mode 100644 index 00000000..5afcd1bd --- /dev/null +++ b/catapult/tracing/tracing/ui/analysis/stacked_pane_view_test.html @@ -0,0 +1,203 @@ +<!DOCTYPE html> +<!-- +Copyright 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/ui/analysis/stacked_pane.html"> +<link rel="import" href="/tracing/ui/analysis/stacked_pane_view.html"> + +<script> +'use strict'; + +tr.b.unittest.testSuite(function() { + function createPaneView() { + return document.createElement('tr-ui-a-stacked-pane-view'); + } + + function createPane(paneId, opt_rebuildPaneCallback, opt_appendedCallback) { + var paneEl = document.createElement('tr-ui-a-stacked-pane'); + paneEl.paneId = paneId; + + var divEl = document.createElement('div'); + divEl.textContent = 'Pane ' + paneId; + divEl.style.width = '400px'; + divEl.style.background = '#ccc'; + divEl.style.textAlign = 'center'; + paneEl.appendChild(divEl); + + if (opt_rebuildPaneCallback) + paneEl.rebuildPane_ = opt_rebuildPaneCallback; + + if (opt_appendedCallback) + paneEl.appended = opt_appendedCallback; + + return paneEl; + } + + function createPaneBuilder(paneId, opt_rebuildPaneCallback, + opt_appendedCallback) { + return createPane.bind( + undefined, paneId, opt_rebuildPaneCallback, opt_appendedCallback); + } + + function assertPanes(paneView, expectedPaneIds) { + var actualPaneIds = paneView.panesForTesting.map(function(pane) { + return pane.paneId; + }); + assert.deepEqual(actualPaneIds, expectedPaneIds); + } + + test('instantiate_empty', function() { + var viewEl = createPaneView(); + viewEl.rebuild(); + assertPanes(viewEl, []); + // Don't add the pane to HTML output because it has zero height. + }); + + test('instantiate_singlePane', function() { + var viewEl = createPaneView(); + + viewEl.setPaneBuilder(createPaneBuilder(1)); + viewEl.rebuild(); + + assertPanes(viewEl, [1]); + this.addHTMLOutput(viewEl); + }); + + test('instantiate_multiplePanes', function() { + var viewEl = createPaneView(); + + viewEl.setPaneBuilder(createPaneBuilder(1)); + viewEl.setPaneBuilder(createPaneBuilder(2), viewEl.panesForTesting[0]); + viewEl.setPaneBuilder(createPaneBuilder(3), viewEl.panesForTesting[1]); + + assertPanes(viewEl, [1, 2, 3]); + this.addHTMLOutput(viewEl); + }); + + test('changePanes', function() { + var viewEl = createPaneView(); + + viewEl.setPaneBuilder(createPaneBuilder(1)); + assertPanes(viewEl, [1]); + + viewEl.setPaneBuilder(null); + assertPanes(viewEl, []); + + viewEl.setPaneBuilder(createPaneBuilder(2)); + assertPanes(viewEl, [2]); + + viewEl.setPaneBuilder(createPaneBuilder(3), viewEl.panesForTesting[0]); + assertPanes(viewEl, [2, 3]); + + viewEl.setPaneBuilder(createPaneBuilder(4), viewEl.panesForTesting[0]); + assertPanes(viewEl, [2, 4]); + + viewEl.setPaneBuilder(createPaneBuilder(5), viewEl.panesForTesting[1]); + assertPanes(viewEl, [2, 4, 5]); + + viewEl.setPaneBuilder(createPaneBuilder(6), viewEl.panesForTesting[2]); + assertPanes(viewEl, [2, 4, 5, 6]); + + viewEl.setPaneBuilder(createPaneBuilder(7), viewEl.panesForTesting[1]); + assertPanes(viewEl, [2, 4, 7]); + + this.addHTMLOutput(viewEl); + }); + + test('childPanes', function() { + var viewEl = createPaneView(); + + viewEl.setPaneBuilder(createPaneBuilder(1)); + assertPanes(viewEl, [1]); + + // Pane 1 requests a child pane 2. + var pane1 = viewEl.panesForTesting[0]; + pane1.childPaneBuilder = createPaneBuilder(2); + assertPanes(viewEl, [1, 2]); + + // Pane 2 requests removing its child pane (nothing happens). + var pane2 = viewEl.panesForTesting[1]; + pane2.childPaneBuilder = undefined; + assertPanes(viewEl, [1, 2]); + + // Pane 2 requests a child pane 3. + pane2.childPaneBuilder = createPaneBuilder(3); + assertPanes(viewEl, [1, 2, 3]); + + // Pane 2 requests a child pane 4 (its previous child pane 3 is removed). + pane2.childPaneBuilder = createPaneBuilder(4); + assertPanes(viewEl, [1, 2, 4]); + + // Pane 1 requests removing its child pane (panes 2 and 4 are removed). + pane1.childPaneBuilder = undefined; + assertPanes(viewEl, [1]); + + // Check that removed panes cannot affect the pane view. + pane2.childPaneBuilder = createPaneBuilder(5); + assertPanes(viewEl, [1]); + + // Pane 1 requests a child pane 6 (check that everything still works). + pane1.childPaneBuilder = createPaneBuilder(6); + assertPanes(viewEl, [1, 6]); + + // Change the top pane to pane 7. + viewEl.setPaneBuilder(createPaneBuilder(7)); + assertPanes(viewEl, [7]); + + // Check that removed panes cannot affect the pane view. + pane1.childPaneBuilder = createPaneBuilder(5); + assertPanes(viewEl, [7]); + }); + + test('rebuild', function() { + var viewEl = createPaneView(); + + var rebuiltPaneIds = []; + var rebuildPaneCallback = function() { + rebuiltPaneIds.push(this.paneId); + }; + + viewEl.setPaneBuilder(createPaneBuilder(1, rebuildPaneCallback)); + viewEl.setPaneBuilder(createPaneBuilder(2, rebuildPaneCallback), + viewEl.panesForTesting[0]); + viewEl.setPaneBuilder(createPaneBuilder(3, rebuildPaneCallback), + viewEl.panesForTesting[1]); + + // Rebuild isn't triggered. + assert.deepEqual(rebuiltPaneIds, []); + + // Rebuild is triggered, but it isn't necessary (all panes are clean). + viewEl.rebuild(); + assert.deepEqual(rebuiltPaneIds, []); + + // All panes are now marked as dirty, but rebuild isn't triggered (it was + // only scheduled). + viewEl.panesForTesting.forEach(function(pane) { + pane.scheduleRebuildPane_(); + }); + assert.deepEqual(rebuiltPaneIds, []); + + // Finally, rebuild was triggered and the panes are dirty. + viewEl.rebuild(); + assert.deepEqual(rebuiltPaneIds, [1, 2, 3]); + + // Make sure that panes are clean after the previous rebuild. + viewEl.rebuild(); + assert.deepEqual(rebuiltPaneIds, [1, 2, 3]); + }); + + test('appended', function() { + var viewEl = createPaneView(); + var didFireAppended; + + didFireAppended = false; + viewEl.setPaneBuilder(createPaneBuilder(1, undefined, function() { + didFireAppended = true; + })); + assert.isTrue(didFireAppended); + }); +}); +</script> diff --git a/catapult/tracing/tracing/ui/annotations/annotation_view_test.html b/catapult/tracing/tracing/ui/annotations/annotation_view_test.html index 0a434d47..8a975cc3 100644 --- a/catapult/tracing/tracing/ui/annotations/annotation_view_test.html +++ b/catapult/tracing/tracing/ui/annotations/annotation_view_test.html @@ -23,7 +23,7 @@ tr.b.unittest.testSuite(function() { var model = new tr.Model(); var process = model.getOrCreateProcess(1); var thread = process.getOrCreateThread(2); - thread.sliceGroup.pushSlice(tr.c.test_utils.newSliceNamed('a', 80, 50)); + thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceNamed('a', 80, 50)); var timeline = document.createElement('tr-ui-timeline-track-view'); var vp = new tr.ui.TimelineViewport(timeline); diff --git a/catapult/tracing/tracing/ui/base/table.html b/catapult/tracing/tracing/ui/base/table.html index d00e7c0c..a4c71a4e 100644 --- a/catapult/tracing/tracing/ui/base/table.html +++ b/catapult/tracing/tracing/ui/base/table.html @@ -243,7 +243,7 @@ found in the LICENSE file. * @param {Array} columns An array of data objects. */ set tableColumns(columns) { - // Figure out the columsn with expand buttons... + // Figure out the columns with expand buttons... var columnsWithExpandButtons = []; for (var i = 0; i < columns.length; i++) { if (columns[i].showExpandButtons) diff --git a/catapult/tracing/tracing/ui/brushing_state_controller_test.html b/catapult/tracing/tracing/ui/brushing_state_controller_test.html index 7aeefbdc..1f44f596 100644 --- a/catapult/tracing/tracing/ui/brushing_state_controller_test.html +++ b/catapult/tracing/tracing/ui/brushing_state_controller_test.html @@ -15,14 +15,14 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; var EventSet = tr.model.EventSet; var SelectionState = tr.model.SelectionState; var Task = tr.b.Task; function newSimpleFakeTimelineView() { - var m = tr.c.test_utils.newModel(function(m) { + var m = tr.c.TestUtils.newModel(function(m) { m.p1 = m.getOrCreateProcess(1); m.t2 = m.p1.getOrCreateThread(2); @@ -110,7 +110,7 @@ tr.b.unittest.testSuite(function() { bs1.selection = new EventSet([m1.sA]); // Change the model. - var m2 = tr.c.test_utils.newModel(function(m) { + var m2 = tr.c.TestUtils.newModel(function(m) { m.p1 = m.getOrCreateProcess(1); m.t2 = m.p1.getOrCreateThread(2); diff --git a/catapult/tracing/tracing/ui/brushing_state_test.html b/catapult/tracing/tracing/ui/brushing_state_test.html index c68eac21..e88a47a5 100644 --- a/catapult/tracing/tracing/ui/brushing_state_test.html +++ b/catapult/tracing/tracing/ui/brushing_state_test.html @@ -15,13 +15,13 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; var EventSet = tr.model.EventSet; var SelectionState = tr.model.SelectionState; function newSimpleModel() { - return tr.c.test_utils.newModel(function(m) { + return tr.c.TestUtils.newModel(function(m) { m.p1 = m.getOrCreateProcess(1); m.t2 = m.p1.getOrCreateThread(2); diff --git a/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog.html b/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog.html index bf56a8a7..f810dd8b 100644 --- a/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog.html +++ b/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog.html @@ -115,7 +115,6 @@ found in the LICENSE file. .record-selection-dialog .labeled-option-group { -webkit-flex: 0 0 auto; -webkit-flex-direction: column; - -webkit-align-items: left; display: -webkit-flex; } diff --git a/catapult/tracing/tracing/ui/extras/analysis/sampling_summary_test.html b/catapult/tracing/tracing/ui/extras/analysis/sampling_summary_test.html index 9a0619c8..9a7c82ef 100644 --- a/catapult/tracing/tracing/ui/extras/analysis/sampling_summary_test.html +++ b/catapult/tracing/tracing/ui/extras/analysis/sampling_summary_test.html @@ -18,7 +18,7 @@ tr.b.unittest.testSuite(function() { var StackFrame = tr.model.StackFrame; var Sample = tr.model.Sample; - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; function createSelection() { var selection = new tr.model.EventSet(); diff --git a/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html b/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html index 8aae93a8..b06765aa 100644 --- a/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html +++ b/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html @@ -20,7 +20,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('instantiate', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = tr.b.dictionaryValues(m.processes)[0]; var instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0]; diff --git a/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html b/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html index d60fe02b..50c6477c 100644 --- a/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html +++ b/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html @@ -19,7 +19,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('tileCoverageRectCount', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = m.processes[1]; var instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0]; diff --git a/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html b/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html index cf9f36cd..a4bcab78 100644 --- a/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html +++ b/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html @@ -19,7 +19,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('instantiate', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = m.processes[1]; var instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0]; @@ -36,7 +36,7 @@ tr.b.unittest.testSuite(function() { }); test('instantiate_withTileHighlight', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = m.processes[1]; var instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0]; diff --git a/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection_test.html b/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection_test.html index 508cebbc..ee8e91c3 100644 --- a/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection_test.html +++ b/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection_test.html @@ -20,7 +20,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('basic', function() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = m.processes[1]; var rasterTasks = p.threads[1].sliceGroup.slices.filter(function(slice) { return slice.title == 'RasterTask'; diff --git a/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html b/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html index 017bcdde..be771775 100644 --- a/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html +++ b/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html @@ -26,7 +26,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { function createSelection() { - var m = tr.c.test_utils.newModelWithEvents([g_catLTHIEvents]); + var m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]); var p = m.processes[1]; var rasterTasks = p.threads[1].sliceGroup.slices.filter(function(slice) { return slice.title == 'RasterTask' || slice.title == 'AnalyzeTask'; diff --git a/catapult/tracing/tracing/ui/extras/drive/index.html b/catapult/tracing/tracing/ui/extras/drive/index.html index bfd23f82..2c44cea2 100644 --- a/catapult/tracing/tracing/ui/extras/drive/index.html +++ b/catapult/tracing/tracing/ui/extras/drive/index.html @@ -403,7 +403,8 @@ found in the LICENSE file. function createViewFromTraces(filenames, traces) { var m = new tr.Model(); - var p = m.importTracesWithProgressDialog(traces, true); + var i = new tr.importer.Import(m); + var p = i.importTracesWithProgressDialog(traces); p.then( function() { timelineViewEl_.model = m; diff --git a/catapult/tracing/tracing/ui/extras/rail/rail_score_side_panel_test.html b/catapult/tracing/tracing/ui/extras/rail/rail_score_side_panel_test.html index c519d88f..1a59681b 100644 --- a/catapult/tracing/tracing/ui/extras/rail/rail_score_side_panel_test.html +++ b/catapult/tracing/tracing/ui/extras/rail/rail_score_side_panel_test.html @@ -14,7 +14,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var test_utils = tr.c.test_utils; + var test_utils = tr.c.TestUtils; var CompoundEventSelectionState = tr.model.CompoundEventSelectionState; function createModel(opt_customizeModelCallback) { diff --git a/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel_test.html b/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel_test.html index 9b59a8f3..1e888404 100644 --- a/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel_test.html +++ b/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel_test.html @@ -121,7 +121,7 @@ tr.b.unittest.testSuite(function() { var selectionChanged = false; - panel.model = tr.c.test_utils.newModelWithEvents([events]); + panel.model = tr.c.TestUtils.newModelWithEvents([events]); function listener(e) { selectionChanged = true; assert.equal(e.selection.length, 3); diff --git a/catapult/tracing/tracing/ui/extras/side_panel/time_summary_side_panel.html b/catapult/tracing/tracing/ui/extras/side_panel/time_summary_side_panel.html index f1128ad2..1094c6ff 100644 --- a/catapult/tracing/tracing/ui/extras/side_panel/time_summary_side_panel.html +++ b/catapult/tracing/tracing/ui/extras/side_panel/time_summary_side_panel.html @@ -213,7 +213,7 @@ found in the LICENSE file. data.push({ label: resultsForGroup.name, value: value, - valueText: tr.b.units.TimeDuration.format(value), + valueText: tr.b.u.TimeDuration.format(value), resultsForGroup: resultsForGroup }); } @@ -366,7 +366,7 @@ found in the LICENSE file. extraData.push({ label: 'CPU Idle', value: idleTime, - valueText: tr.b.units.TimeDuration.format(idleTime) + valueText: tr.b.u.TimeDuration.format(idleTime) }); extraValue += idleTime; } diff --git a/catapult/tracing/tracing/ui/extras/side_panel/time_summary_side_panel_test.html b/catapult/tracing/tracing/ui/extras/side_panel/time_summary_side_panel_test.html index 5d59ca62..94db77ca 100644 --- a/catapult/tracing/tracing/ui/extras/side_panel/time_summary_side_panel_test.html +++ b/catapult/tracing/tracing/ui/extras/side_panel/time_summary_side_panel_test.html @@ -13,11 +13,11 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newSliceNamed = tr.c.test_utils.newSliceNamed; + var newSliceNamed = tr.c.TestUtils.newSliceNamed; function createModel(opt_options) { var options = opt_options || {}; - var m = tr.c.test_utils.newModelWithEvents([], { + var m = tr.c.TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: function(m) { @@ -140,7 +140,7 @@ tr.b.unittest.testSuite(function() { var ts = document.createElement('tr-ui-e-s-time-summary-side-panel'); var groups = []; - var m = tr.c.test_utils.newModelWithEvents([], { + var m = tr.c.TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: function(m) { diff --git a/catapult/tracing/tracing/ui/extras/systrace_config.html b/catapult/tracing/tracing/ui/extras/systrace_config.html index 6d98f883..1aecd558 100644 --- a/catapult/tracing/tracing/ui/extras/systrace_config.html +++ b/catapult/tracing/tracing/ui/extras/systrace_config.html @@ -13,3 +13,4 @@ found in the LICENSE file. <!-- Features used by Android systrace. --> <link rel="import" href="/tracing/ui/extras/side_panel/alerts_side_panel.html"> +<link rel="import" href="/tracing/ui/extras/highlighter/vsync_highlighter.html"> diff --git a/catapult/tracing/tracing/ui/find_controller_test.html b/catapult/tracing/tracing/ui/find_controller_test.html index cf80a8a0..70ae63ae 100644 --- a/catapult/tracing/tracing/ui/find_controller_test.html +++ b/catapult/tracing/tracing/ui/find_controller_test.html @@ -209,7 +209,7 @@ tr.b.unittest.testSuite(function() { }); test('findControllerWithRealTimeline', function() { - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { var p1 = model.getOrCreateProcess(1); var t1 = p1.getOrCreateThread(1); t1.sliceGroup.pushSlice(new tr.model.ThreadSlice( diff --git a/catapult/tracing/tracing/ui/side_panel/side_panel_container_test.html b/catapult/tracing/tracing/ui/side_panel/side_panel_container_test.html index 0e983a0a..8dc296c3 100644 --- a/catapult/tracing/tracing/ui/side_panel/side_panel_container_test.html +++ b/catapult/tracing/tracing/ui/side_panel/side_panel_container_test.html @@ -31,7 +31,7 @@ tr.b.unittest.testSuite(function() { }; function createModel() { - var m = tr.c.test_utils.newModelWithEvents([], { + var m = tr.c.TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: function(m) { diff --git a/catapult/tracing/tracing/ui/timeline_track_view.html b/catapult/tracing/tracing/ui/timeline_track_view.html index edb96aac..f9636082 100644 --- a/catapult/tracing/tracing/ui/timeline_track_view.html +++ b/catapult/tracing/tracing/ui/timeline_track_view.html @@ -821,7 +821,7 @@ found in the LICENSE file. var hiWX = dt.xViewToWorld( (hiX - canv.offsetLeft) * pixelRatio); - this.$.drag_box.textContent = tr.b.units.TimeDuration.format(hiWX - loWX); + this.$.drag_box.textContent = tr.b.u.TimeDuration.format(hiWX - loWX); var e = new tr.b.Event('selectionChanging'); e.loWX = loWX; diff --git a/catapult/tracing/tracing/ui/timeline_track_view_test.html b/catapult/tracing/tracing/ui/timeline_track_view_test.html index 7a15c9ee..15433f83 100644 --- a/catapult/tracing/tracing/ui/timeline_track_view_test.html +++ b/catapult/tracing/tracing/ui/timeline_track_view_test.html @@ -21,7 +21,7 @@ tr.b.unittest.testSuite(function() { test('instantiate', function() { var num_threads = 500; - var model = tr.c.test_utils.newModelWithEvents([], { + var model = tr.c.TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: function(model) { @@ -57,9 +57,9 @@ tr.b.unittest.testSuite(function() { var t1asg = t1.asyncSliceGroup; t1asg.slices.push( - tr.c.test_utils.newAsyncSliceNamed('a', 0, 1, t1, t1)); + tr.c.TestUtils.newAsyncSliceNamed('a', 0, 1, t1, t1)); t1asg.slices.push( - tr.c.test_utils.newAsyncSliceNamed('b', 1, 2, t1, t1)); + tr.c.TestUtils.newAsyncSliceNamed('b', 1, 2, t1, t1)); var timeline = document.createElement('tr-ui-timeline-track-view'); timeline.model = model; @@ -139,7 +139,7 @@ tr.b.unittest.testSuite(function() { var model = new tr.Model(); var p1 = model.getOrCreateProcess(1); var t1 = p1.getOrCreateThread(2); - t1.sliceGroup.pushSlice(tr.c.test_utils.newSlice(0, 1)); + t1.sliceGroup.pushSlice(tr.c.TestUtils.newSlice(0, 1)); var timeline = document.createElement('tr-ui-timeline-track-view'); timeline.model = model; @@ -156,7 +156,7 @@ tr.b.unittest.testSuite(function() { {name: 'b', args: {}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'}, {name: 'a', args: {}, pid: 52, ts: 634, cat: 'foo', tid: 53, ph: 'E'} ]; - var model = tr.c.test_utils.newModelWithEvents([events]); + var model = tr.c.TestUtils.newModelWithEvents([events]); var trackView = document.createElement('tr-ui-timeline-track-view'); trackView.model = model; this.addHTMLOutput(trackView); @@ -174,7 +174,7 @@ tr.b.unittest.testSuite(function() { {name: 'b', args: {}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'}, {name: 'a', args: {}, pid: 52, ts: 634, cat: 'foo', tid: 53, ph: 'E'} ]; - var model = tr.c.test_utils.newModelWithEvents([events]); + var model = tr.c.TestUtils.newModelWithEvents([events]); var trackView = document.createElement('tr-ui-timeline-track-view'); trackView.model = model; this.addHTMLOutput(trackView); @@ -191,7 +191,7 @@ tr.b.unittest.testSuite(function() { {name: 'b', args: {}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'}, {name: 'a', args: {}, pid: 52, ts: 634, cat: 'foo', tid: 53, ph: 'E'} ]; - var model = tr.c.test_utils.newModelWithEvents([events]); + var model = tr.c.TestUtils.newModelWithEvents([events]); var trackView = document.createElement('tr-ui-timeline-track-view'); trackView.model = model; this.addHTMLOutput(trackView); diff --git a/catapult/tracing/tracing/ui/timeline_view.html b/catapult/tracing/tracing/ui/timeline_view.html index 2b0a4a12..84df3ac2 100644 --- a/catapult/tracing/tracing/ui/timeline_view.html +++ b/catapult/tracing/tracing/ui/timeline_view.html @@ -394,7 +394,7 @@ found in the LICENSE file. this.railScoreSpan_.railScore = railScore; } - this.$.display_unit.preferredDisplayUnit = model.intrinsicTimeUnit; + this.$.display_unit.preferredTimeDisplayMode = model.intrinsicTimeUnit; } // Do things that are selection specific diff --git a/catapult/tracing/tracing/ui/timeline_view_test.html b/catapult/tracing/tracing/ui/timeline_view_test.html index 90eb97ce..c5a3d103 100644 --- a/catapult/tracing/tracing/ui/timeline_view_test.html +++ b/catapult/tracing/tracing/ui/timeline_view_test.html @@ -15,7 +15,7 @@ found in the LICENSE file. 'use strict'; tr.b.unittest.testSuite(function() { - var newSliceNamed = tr.c.test_utils.newSliceNamed; + var newSliceNamed = tr.c.TestUtils.newSliceNamed; var Task = tr.b.Task; function setupTimeline() { diff --git a/catapult/tracing/tracing/ui/timeline_viewport_test.html b/catapult/tracing/tracing/ui/timeline_viewport_test.html index 625fd02c..0e1f4cf1 100644 --- a/catapult/tracing/tracing/ui/timeline_viewport_test.html +++ b/catapult/tracing/tracing/ui/timeline_viewport_test.html @@ -67,7 +67,7 @@ tr.b.unittest.testSuite(function() { test('locationObj', function() { var process; var thread; - var model = tr.c.test_utils.newModelWithEvents([], { + var model = tr.c.TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: function(model) { @@ -75,9 +75,9 @@ tr.b.unittest.testSuite(function() { thread = process.getOrCreateThread(456); thread.asyncSliceGroup.push( - tr.c.test_utils.newAsyncSliceNamed('a', 80, 20, thread, thread)); + tr.c.TestUtils.newAsyncSliceNamed('a', 80, 20, thread, thread)); thread.asyncSliceGroup.push( - tr.c.test_utils.newAsyncSliceNamed('a', 85, 10, thread, thread)); + tr.c.TestUtils.newAsyncSliceNamed('a', 85, 10, thread, thread)); } }); diff --git a/catapult/tracing/tracing/ui/tracks/async_slice_group_track_test.html b/catapult/tracing/tracing/ui/tracks/async_slice_group_track_test.html index d59968ad..355a7ed3 100644 --- a/catapult/tracing/tracing/ui/tracks/async_slice_group_track_test.html +++ b/catapult/tracing/tracing/ui/tracks/async_slice_group_track_test.html @@ -19,8 +19,8 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck var ProcessTrack = tr.ui.tracks.ProcessTrack; var Thread = tr.model.Thread; var ThreadTrack = tr.ui.tracks.ThreadTrack; - var newAsyncSlice = tr.c.test_utils.newAsyncSlice; - var newAsyncSliceNamed = tr.c.test_utils.newAsyncSliceNamed; + var newAsyncSlice = tr.c.TestUtils.newAsyncSlice; + var newAsyncSliceNamed = tr.c.TestUtils.newAsyncSliceNamed; test('filterSubRows', function() { var model = new tr.Model(); diff --git a/catapult/tracing/tracing/ui/tracks/counter_track_perf_test.html b/catapult/tracing/tracing/ui/tracks/counter_track_perf_test.html index af684e80..afa3ad3f 100644 --- a/catapult/tracing/tracing/ui/tracks/counter_track_perf_test.html +++ b/catapult/tracing/tracing/ui/tracks/counter_track_perf_test.html @@ -43,7 +43,7 @@ tr.b.unittest.testSuite(function() { return; var fileUrl = '/test_data/counter_tracks.html'; var events = getSynchronous(fileUrl); - model = tr.c.test_utils.newModelWithEvents([events]); + model = tr.c.TestUtils.newModelWithEvents([events]); } function setUp() { diff --git a/catapult/tracing/tracing/ui/tracks/cpu_track_test.html b/catapult/tracing/tracing/ui/tracks/cpu_track_test.html index 11aa451a..61108d51 100644 --- a/catapult/tracing/tracing/ui/tracks/cpu_track_test.html +++ b/catapult/tracing/tracing/ui/tracks/cpu_track_test.html @@ -48,7 +48,7 @@ tr.b.unittest.testSuite(function() { test('withSamples', function() { var thread; var cpu; - var model = tr.c.test_utils.newModelWithEvents([], { + var model = tr.c.TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: function(model) { diff --git a/catapult/tracing/tracing/ui/tracks/drawing_container_perf_test.html b/catapult/tracing/tracing/ui/tracks/drawing_container_perf_test.html index 07046ff9..cd4862f3 100644 --- a/catapult/tracing/tracing/ui/tracks/drawing_container_perf_test.html +++ b/catapult/tracing/tracing/ui/tracks/drawing_container_perf_test.html @@ -20,7 +20,7 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck generalModel; var fileUrl = '/test_data/thread_time_visualisation.json.gz'; var events = tr.b.getSync(fileUrl); - generalModel = tr.c.test_utils.newModelWithEvents([events]); + generalModel = tr.c.TestUtils.newModelWithEvents([events]); return generalModel; } @@ -102,13 +102,13 @@ tr.b.unittest.testSuite(function() { // @suppress longLineCheck __proto__: DCPerfTestCase.prototype, setUp: function() { - var model = tr.c.test_utils.newModel(function(m) { + var model = tr.c.TestUtils.newModel(function(m) { var proc = m.getOrCreateProcess(1); for (var tid = 1; tid <= 5; tid++) { var thread = proc.getOrCreateThread(tid); for (var i = 0; i < 5000; i++) { var mod = Math.floor(i / 100) % 4; - var slice = tr.c.test_utils.newAsyncSliceEx({ + var slice = tr.c.TestUtils.newAsyncSliceEx({ name: 'Test' + i, colorId: tid + mod, id: tr.b.GUID.allocate(), diff --git a/catapult/tracing/tracing/ui/tracks/frame_track_test.html b/catapult/tracing/tracing/ui/tracks/frame_track_test.html index 3258feed..8db1b14d 100644 --- a/catapult/tracing/tracing/ui/tracks/frame_track_test.html +++ b/catapult/tracing/tracing/ui/tracks/frame_track_test.html @@ -22,11 +22,11 @@ tr.b.unittest.testSuite(function() { var SelectionState = tr.model.SelectionState; var Viewport = tr.ui.TimelineViewport; - var newSliceNamed = tr.c.test_utils.newSliceNamed; + var newSliceNamed = tr.c.TestUtils.newSliceNamed; var createFrames = function() { var frames = undefined; - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { var process = model.getOrCreateProcess(1); var thread = process.getOrCreateThread(1); for (var i = 1; i < 5; i++) { diff --git a/catapult/tracing/tracing/ui/tracks/interaction_track_test.html b/catapult/tracing/tracing/ui/tracks/interaction_track_test.html index 1378a483..470b9474 100644 --- a/catapult/tracing/tracing/ui/tracks/interaction_track_test.html +++ b/catapult/tracing/tracing/ui/tracks/interaction_track_test.html @@ -23,10 +23,10 @@ tr.b.unittest.testSuite(function() { var drawingContainer = new tr.ui.tracks.DrawingContainer(viewport); div.appendChild(drawingContainer); var track = new tr.ui.tracks.InteractionTrack(viewport); - track.model = tr.c.test_utils.newModel(function(model) { + track.model = tr.c.TestUtils.newModel(function(model) { var process = model.getOrCreateProcess(1); var thread = process.getOrCreateThread(1); - thread.sliceGroup.pushSlice(tr.c.test_utils.newSlice(0, 200)); + thread.sliceGroup.pushSlice(tr.c.TestUtils.newSlice(0, 200)); model.interactionRecords.push(new tr.model.InteractionRecord( 'a', 0, 100, 100)); model.interactionRecords.push(new tr.model.InteractionRecord( diff --git a/catapult/tracing/tracing/ui/tracks/memory_dump_track_test_utils.html b/catapult/tracing/tracing/ui/tracks/memory_dump_track_test_utils.html index 08d02432..bb1b9eb5 100644 --- a/catapult/tracing/tracing/ui/tracks/memory_dump_track_test_utils.html +++ b/catapult/tracing/tracing/ui/tracks/memory_dump_track_test_utils.html @@ -71,7 +71,7 @@ tr.exportTo('tr.ui.tracks', function() { var maybeDumpSizes = function(dumpSizes) { return withAllocatorDumps ? dumpSizes : undefined; }; - return tr.c.test_utils.newModel(function(model) { + return tr.c.TestUtils.newModel(function(model) { // Construct a model with three processes. var pa = model.getOrCreateProcess(3); var pb = model.getOrCreateProcess(6); diff --git a/catapult/tracing/tracing/ui/tracks/process_summary_track_test.html b/catapult/tracing/tracing/ui/tracks/process_summary_track_test.html index 0f558d9e..3015e238 100644 --- a/catapult/tracing/tracing/ui/tracks/process_summary_track_test.html +++ b/catapult/tracing/tracing/ui/tracks/process_summary_track_test.html @@ -15,12 +15,12 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { var ProcessSummaryTrack = tr.ui.tracks.ProcessSummaryTrack; - var newSlice = tr.c.test_utils.newSlice; - var newSliceNamed = tr.c.test_utils.newSliceNamed; + var newSlice = tr.c.TestUtils.newSlice; + var newSliceNamed = tr.c.TestUtils.newSliceNamed; test('buildRectSimple', function() { var process; - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { process = model.getOrCreateProcess(1); // XXXX // XXXX @@ -40,7 +40,7 @@ tr.b.unittest.testSuite(function() { test('buildRectComplex', function() { var process; - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { process = model.getOrCreateProcess(1); // XXXX X X XX // XXXX XXX X @@ -70,7 +70,7 @@ tr.b.unittest.testSuite(function() { test('buildRectImportantSlice', function() { var process; - var model = tr.c.test_utils.newModel(function(model) { + var model = tr.c.TestUtils.newModel(function(model) { // [ unimportant ] // [important] var a = newSliceNamed('unimportant', 4, 21); diff --git a/catapult/tracing/tracing/ui/tracks/slice_group_track_test.html b/catapult/tracing/tracing/ui/tracks/slice_group_track_test.html index 66245e02..6e3ff981 100644 --- a/catapult/tracing/tracing/ui/tracks/slice_group_track_test.html +++ b/catapult/tracing/tracing/ui/tracks/slice_group_track_test.html @@ -17,7 +17,7 @@ tr.b.unittest.testSuite(function() { var ThreadTrack = tr.ui.tracks.ThreadTrack; var SliceGroup = tr.model.SliceGroup; var SliceGroupTrack = tr.ui.tracks.SliceGroupTrack; - var newSliceEx = tr.c.test_utils.newSliceEx; + var newSliceEx = tr.c.TestUtils.newSliceEx; test('subRowBuilderBasic', function() { var m = new tr.Model(); diff --git a/catapult/tracing/tracing/ui/tracks/thread_track_test.html b/catapult/tracing/tracing/ui/tracks/thread_track_test.html index fafe4795..cc6ace19 100644 --- a/catapult/tracing/tracing/ui/tracks/thread_track_test.html +++ b/catapult/tracing/tracing/ui/tracks/thread_track_test.html @@ -25,9 +25,9 @@ tr.b.unittest.testSuite(function() { var ThreadSlice = tr.model.ThreadSlice; var ThreadTrack = tr.ui.tracks.ThreadTrack; var Viewport = tr.ui.TimelineViewport; - var newAsyncSlice = tr.c.test_utils.newAsyncSlice; - var newAsyncSliceNamed = tr.c.test_utils.newAsyncSliceNamed; - var newSliceEx = tr.c.test_utils.newSliceEx; + var newAsyncSlice = tr.c.TestUtils.newAsyncSlice; + var newAsyncSliceNamed = tr.c.TestUtils.newAsyncSliceNamed; + var newSliceEx = tr.c.TestUtils.newSliceEx; test('selectionHitTestingWithThreadTrack', function() { var model = new tr.Model(); @@ -88,7 +88,7 @@ tr.b.unittest.testSuite(function() { test('sampleThreadSlices', function() { var thread; var cpu; - var model = tr.c.test_utils.newModelWithEvents([], { + var model = tr.c.TestUtils.newModelWithEvents([], { shiftWorldToZero: false, pruneContainers: false, customizeModelCallback: function(model) { diff --git a/catapult/tracing/tracing/ui/units/generic_table_view.html b/catapult/tracing/tracing/ui/units/generic_table_view.html index 207ffb57..eaea42e8 100644 --- a/catapult/tracing/tracing/ui/units/generic_table_view.html +++ b/catapult/tracing/tracing/ui/units/generic_table_view.html @@ -160,7 +160,7 @@ tr.exportTo('tr.ui.units', function() { this.items_ = undefined; } else if (itemsOrGenericTable instanceof Array) { this.items_ = itemsOrGenericTable; - } else if (itemsOrGenericTable instanceof tr.b.units.GenericTable) { + } else if (itemsOrGenericTable instanceof tr.b.u.GenericTable) { this.items_ = itemsOrGenericTable.items; } this.updateContents_(); @@ -264,6 +264,22 @@ tr.exportTo('tr.ui.units', function() { this.$.table.tableRows = this.items_; this.$.table.footerRows = this.createFooterRowsIfNeeded_(columns); this.$.table.rebuild(); + }, + + get supportsSelection() { + return this.$.supportsSelection; + }, + + set supportsSelection(supportsSelection) { + this.$.table.supportsSelection = supportsSelection; + }, + + get rowHighlightEnabled() { + return this.$.rowHighlightEnabled; + }, + + set rowHighlightEnabled(rowHighlightEnabled) { + this.$.table.rowHighlightEnabled = rowHighlightEnabled; } }); diff --git a/catapult/tracing/tracing/ui/units/generic_table_view_test.html b/catapult/tracing/tracing/ui/units/generic_table_view_test.html index 01c7ed72..ef9117e4 100644 --- a/catapult/tracing/tracing/ui/units/generic_table_view_test.html +++ b/catapult/tracing/tracing/ui/units/generic_table_view_test.html @@ -112,7 +112,7 @@ tr.b.unittest.testSuite(function() { test('usingGenericTable', function() { var table = document.createElement('tr-ui-u-generic-table-view'); - table.items = new tr.b.units.GenericTable([ + table.items = new tr.b.u.GenericTable([ { a: 1 } @@ -122,7 +122,7 @@ tr.b.unittest.testSuite(function() { test('valueIsObject', function() { var table = document.createElement('tr-ui-u-generic-table-view'); - table.items = new tr.b.units.GenericTable([ + table.items = new tr.b.u.GenericTable([ { a: {x: 1, y: 'string'} }, diff --git a/catapult/tracing/tracing/ui/units/histogram_span.html b/catapult/tracing/tracing/ui/units/histogram_span.html new file mode 100644 index 00000000..a8ce72bb --- /dev/null +++ b/catapult/tracing/tracing/ui/units/histogram_span.html @@ -0,0 +1,132 @@ +<!DOCTYPE HTML> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/base/statistics.html"> +<link rel="import" href="/tracing/base/units/units.html"> +<link rel="import" href="/tracing/base/units/histogram.html"> +<link rel="import" href="/tracing/ui/base/table.html"> +<link rel="import" href="/tracing/ui/units/scalar_span.html"> + +<polymer-element name="tr-ui-u-histogram-span"> + <template> + <style> + :host { + display: flex; + flex-direction: column; + } + + #stats { + display: flex; + flex-direction: row; + flex: 0 0 auto; + font-weight: bold; + } + + #nnans { + color: red; + } + #table { + flex: 1 1 auto; + } + </style> + <div id="stats"> + <span id="nsamples"></span> samples, + <span id="hadnans"><span id="nnans"></span> non-numeric samples, + </span> + average=<tr-ui-u-scalar-span id="average"></tr-ui-u-scalar-span> + </div> + <tr-ui-b-table id="table"> + </tr-ui-b-table> + </template> + <script> + 'use strict'; + + Polymer({ + created: function() { + this.histogram_ = undefined; + }, + + get histogram() { + return this.histogram_; + }, + + set histogram(histogram) { + this.histogram_ = histogram; + this.updateContents_(); + }, + + updateContents_: function() { + var table = this.$.table; + if (!this.histogram_) { + this.$.nsamples.textContent = 0; + this.$.average.setValueAndUnit(undefined, undefined); + this.$.table.tableRows = []; + return; + } + + this.$.nsamples.textContent = this.histogram_.numValues; + this.$.average.setValueAndUnit(this.histogram_.average, + this.histogram_.unit); + if (this.histogram_.numNans > 0) { + this.$.hadnans.style.display = ''; + this.$.nnans.textContent = this.histogram_.numNans; + } else { + this.$.hadnans.style.display = 'none'; + } + + var maximumBinValue = tr.b.Statistics.max(this.histogram_.allBins, + function(bin) { + return bin.count; + }); + table.tableColumns = [ + { + title: 'Min', + width: '200px', + value: function(bin) { + if (bin === this.histogram_.underflowBin) + return '-' + String.fromCharCode(0x221e); + var span = document.createElement('tr-ui-u-scalar-span'); + span.setValueAndUnit(bin.range.min, this.histogram_.unit); + return span; + }.bind(this) + }, + { + title: 'Max (exclusive)', + width: '200px', + value: function(bin) { + if (bin === this.histogram_.overflowBin) + return String.fromCharCode(0x221e); + var span = document.createElement('tr-ui-u-scalar-span'); + span.setValueAndUnit(bin.range.max, this.histogram_.unit); + return span; + }.bind(this) + }, + { + title: 'Quantity', + width: '100%', + value: function(bin) { + var span = document.createElement('tr-ui-u-scalar-span'); + span.setValueAndUnit(bin.count, tr.b.u.Units.unitlessNumber); + span.percentage = bin.count / maximumBinValue; + span.rightAlign = true; + return span; + } + } + ]; + var rows = []; + if (this.histogram_.underflowBin.count) + rows.push(this.histogram_.underflowBin); + rows.push.apply(rows, this.histogram.centralBins); + if (this.histogram_.overflowBin.count) + rows.push(this.histogram_.overflowBin); + table.tableRows = rows; + this.rowHighlightEnabled = true; + table.rebuild(); + } + }); + </script> +</polymer-element> diff --git a/catapult/tracing/tracing/ui/units/histogram_span_test.html b/catapult/tracing/tracing/ui/units/histogram_span_test.html new file mode 100644 index 00000000..bbc014e6 --- /dev/null +++ b/catapult/tracing/tracing/ui/units/histogram_span_test.html @@ -0,0 +1,65 @@ +<!DOCTYPE html> +<!-- +Copyright (c) 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<link rel="import" href="/tracing/ui/units/histogram_span.html"> +<script> +'use strict'; + +tr.b.unittest.testSuite(function() { + test('basic', function() { + var h = new tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, 1000), + 10); + h.add(-1, 'a'); + h.add(0, 'b'); + h.add(0, 'b'); + h.add(0, 'b'); + h.add(0, 'b'); + h.add(0, 'b'); + h.add(0, 'b'); + h.add(0, 'c'); + h.add(500, 'c'); + h.add(999, 'd'); + h.add(1000, 'd'); + + var span = document.createElement('tr-ui-u-histogram-span'); + span.histogram = h; + this.addHTMLOutput(span); + }); + + test('undefined', function() { + var span = document.createElement('tr-ui-u-histogram-span'); + span.histogram = undefined; + this.addHTMLOutput(span); + }); + + test('emptyHistogram', function() { + var h = new tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, 1000), + 10); + + var span = document.createElement('tr-ui-u-histogram-span'); + span.histogram = h; + this.addHTMLOutput(span); + }); + + test('nans', function() { + var h = new tr.b.u.Histogram.createLinear( + tr.b.u.Units.timeDurationInMs, + tr.b.Range.fromExplicitRange(0, 1000), + 10); + h.add(undefined, 'b'); + h.add(NaN, 'c'); + + var span = document.createElement('tr-ui-u-histogram-span'); + span.histogram = h; + this.addHTMLOutput(span); + }); + +}); +</script> diff --git a/catapult/tracing/tracing/ui/units/preferred_display_unit.html b/catapult/tracing/tracing/ui/units/preferred_display_unit.html index d46bcb03..9a46d35d 100644 --- a/catapult/tracing/tracing/ui/units/preferred_display_unit.html +++ b/catapult/tracing/tracing/ui/units/preferred_display_unit.html @@ -4,34 +4,34 @@ Copyright (c) 2015 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <polymer-element name="tr-ui-u-preferred-display-unit"> <script> 'use strict'; Polymer({ ready: function() { - this.unit_ = undefined; + this.preferredTimeDisplayMode_ = undefined; }, attached: function() { - tr.b.units.Time.didPreferredUnitChange(); + tr.b.u.Units.didPreferredTimeDisplayUnitChange(); }, detached: function() { - tr.b.units.Time.didPreferredUnitChange(); + tr.b.u.Units.didPreferredTimeDisplayUnitChange(); }, // null means no-preference - get preferredDisplayUnit() { - return this.unit_; + get preferredTimeDisplayMode() { + return this.preferredTimeDisplayMode_; }, - set preferredDisplayUnit(v) { - if (this.unit_ === v) + set preferredTimeDisplayMode(v) { + if (this.preferredTimeDisplayMode_ === v) return; - this.unit_ = v; - tr.b.units.Time.didPreferredUnitChange(); + this.preferredTimeDisplayMode_ = v; + tr.b.u.Units.didPreferredTimeDisplayUnitChange(); } }); diff --git a/catapult/tracing/tracing/ui/units/preferred_display_unit_test.html b/catapult/tracing/tracing/ui/units/preferred_display_unit_test.html index 790b7c9e..163fc5e6 100644 --- a/catapult/tracing/tracing/ui/units/preferred_display_unit_test.html +++ b/catapult/tracing/tracing/ui/units/preferred_display_unit_test.html @@ -5,7 +5,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <link rel="import" href="/tracing/ui/units/preferred_display_unit.html"> <script> @@ -14,7 +14,7 @@ found in the LICENSE file. tr.b.unittest.testSuite(function() { test('instantiate', function() { var unit = document.createElement('tr-ui-u-preferred-display-unit'); - var ms = tr.b.units.Time.supportedUnits.ms; + var ms = tr.b.u.TimeDisplayModes.ms; unit.preferredDisplayUnit = ms; assert.equal(unit.preferredDisplayUnit, ms); }); diff --git a/catapult/tracing/tracing/ui/units/scalar_span.html b/catapult/tracing/tracing/ui/units/scalar_span.html new file mode 100644 index 00000000..0be70ff6 --- /dev/null +++ b/catapult/tracing/tracing/ui/units/scalar_span.html @@ -0,0 +1,183 @@ +<!DOCTYPE html> +<!-- +Copyright 2015 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/ui/base/deep_utils.html"> +<link rel="import" href="/tracing/ui/base/polymer_utils.html"> +<link rel="import" href="/tracing/base/units/units.html"> +<link rel="import" href="/tracing/base/units/scalar.html"> + +<script> +'use strict'; +tr.exportTo('tr.ui.units', function() { + function createScalarSpan(value, opt_config) { + if (value === undefined) + return ''; + var config = opt_config || {}; + var ownerDocument = config.ownerDocument || document; + var span = ownerDocument.createElement('tr-ui-u-scalar-span'); + span.value = value; + return span; + } + + tr.b.u.Units.addEventListener('display-mode-changed', function(e) { + var subclassNames = tr.ui.b.getPolymerElementsThatSubclass( + 'tr-ui-u-scalar-span'); + var isSubclass = {}; + subclassNames.forEach(function(n) { + isSubclass[n.toUpperCase()] = true; + }); + + var m = tr.b.findDeepElementsMatchingPredicate( + document.body, + function(el) { + return isSubclass[el.tagName]; + }); + m.forEach(function(el) { + el.updateContent_(); + }); + }); + + return { + createScalarSpan: createScalarSpan + }; +}); +</script> + +<polymer-element name="tr-ui-u-scalar-span"> + <template> + <style> + :host { + display: block; + position: relative; + } + #content.right-align { + text-align: right; + position: relative; + display: block; + } + #sparkline { + width: 0%; + position: absolute; + bottom: 0; + right: 0; + display: none; + height: 100%; + background-color: hsla(216, 100%, 94.5%, .75); + border-left: 1px solid hsl(216, 100%, 89%); + box-sizing: border-box; + } + #warning { + margin-left: 4px; + font-size: 66%; + } + </style> + <span id="sparkline"></span> + <span id="content"></span> + <span id="warning" style="display:none">⚠</span> + </template> + <script> + 'use strict'; + + Polymer({ + ready: function() { + this.value_ = undefined; + this.unit_ = undefined; + + this.warning_ = undefined; + this.percentage_ = undefined; + }, + + set contentTextDecoration(deco) { + this.$.content.style.textDecoration = deco; + }, + + get value() { + return this.value_; + }, + + set value(value) { + if (value instanceof tr.b.u.Scalar) { + this.value_ = value.value; + this.unit_ = value.unit; + } else { + this.value_ = value; + } + this.updateContent_(); + }, + + get unit() { + return this.unit_; + }, + + set unit(unit) { + this.unit_ = unit; + this.updateContent_(); + }, + + setValueAndUnit: function(value, unit) { + this.value_ = value; + this.unit_ = unit; + this.updateContent_(); + }, + + get percentage() { + return this.percentage_; + }, + + set percentage(percentage) { + this.percentage_ = percentage; + this.updateSparkline_(); + }, + + get rightAlign() { + return this.$.content.classList.contains('right-align'); + }, + + set rightAlign(rightAlign) { + if (rightAlign) + this.$.content.classList.add('right-align'); + else + this.$.content.classList.remove('right-align'); + }, + + updateSparkline_: function() { + if (this.percentage_ === undefined) { + this.$.sparkline.style.display = 'none'; + this.$.sparkline.style.width = '0'; + } else { + this.$.sparkline.style.display = 'block'; + this.$.sparkline.style.width = (this.percentage_ * 100) + '%'; + } + }, + + updateContent_: function() { + if (this.unit_ === undefined) { + this.$.content.textContent = ''; + return; + } + var content = this.unit_.format(this.value); + this.$.content.textContent = content; + }, + + get warning() { + return this.warning_; + }, + + set warning(warning) { + this.warning_ = warning; + var warningEl = this.$.warning; + if (this.warning_) { + warningEl.title = warning; + warningEl.style.display = ''; + } else { + warningEl.title = ''; + warningEl.style.display = 'none'; + } + } + }); + </script> +</polymer-element> diff --git a/catapult/tracing/tracing/ui/units/size_in_bytes_span.html b/catapult/tracing/tracing/ui/units/size_in_bytes_span.html deleted file mode 100644 index 44dd8bd6..00000000 --- a/catapult/tracing/tracing/ui/units/size_in_bytes_span.html +++ /dev/null @@ -1,49 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/base/units/size_in_bytes.html"> - -<polymer-element name="tr-ui-u-size-in-bytes-span"> - <template> - <style> - :host { - display: flex; - flex-direction: row; - align-items: center; - } - </style> - <span id="content"></span> - </template> - <script> - 'use strict'; - - Polymer({ - ready: function() { - this.$.content.textContent = String.fromCharCode(9888); - this.numBytes_ = undefined; - }, - - get numBytes() { - return this.numBytes_; - }, - - set numBytes(numBytesOrSizeInBytes) { - if (numBytesOrSizeInBytes instanceof tr.b.units.SizeInBytes) - this.numBytes_ = numBytesOrSizeInBytes.numBytes; - else - this.numBytes_ = numBytesOrSizeInBytes; - - this.$.content.textContent = - tr.b.units.SizeInBytes.format(this.numBytes_); - }, - - get stringContent() { - return this.$.content.textContent; - } - }); - </script> -</polymer-element> diff --git a/catapult/tracing/tracing/ui/units/size_in_bytes_span_test.html b/catapult/tracing/tracing/ui/units/size_in_bytes_span_test.html deleted file mode 100644 index ae95dd4d..00000000 --- a/catapult/tracing/tracing/ui/units/size_in_bytes_span_test.html +++ /dev/null @@ -1,28 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/ui/units/size_in_bytes_span.html"> - -<script> -'use strict'; - -tr.b.unittest.testSuite(function() { - test('instantiate', function() { - var timeSpan = document.createElement('tr-ui-u-size-in-bytes-span'); - timeSpan.numBytes = 5 * 1024; - assert.equal(timeSpan.numBytes, 5 * 1024); - this.addHTMLOutput(timeSpan); - }); - - test('instantiateWithObject', function() { - var timeSpan = document.createElement('tr-ui-u-size-in-bytes-span'); - timeSpan.numBytes = new tr.b.units.SizeInBytes(5 * 1024); - assert.equal(timeSpan.numBytes, 5 * 1024); - this.addHTMLOutput(timeSpan); - }); -}); -</script> diff --git a/catapult/tracing/tracing/ui/units/time_duration_span.html b/catapult/tracing/tracing/ui/units/time_duration_span.html index e4f38d94..aedaf2b4 100644 --- a/catapult/tracing/tracing/ui/units/time_duration_span.html +++ b/catapult/tracing/tracing/ui/units/time_duration_span.html @@ -5,9 +5,10 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/ui/base/deep_utils.html"> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <link rel="import" href="/tracing/base/units/time_duration.html"> +<link rel="import" href="/tracing/ui/base/deep_utils.html"> +<link rel="import" href="/tracing/ui/units/scalar_span.html"> <script> 'use strict'; @@ -23,6 +24,7 @@ tr.exportTo('tr.ui.units', function() { var config = opt_config || {}; var ownerDocument = config.ownerDocument || document; var span = ownerDocument.createElement('tr-ui-u-time-duration-span'); + span.setValueAndUnit(duration, tr.b.u.Units.timeDurationInMs); if (config.total) span.percentage = duration / config.total; span.duration = duration; @@ -32,126 +34,28 @@ tr.exportTo('tr.ui.units', function() { return span; } - tr.b.units.Time.addEventListener('display-unit-changed', function(e) { - tr.b.findDeepElementsMatching(document.body, - 'tr-ui-u-time-duration-span').forEach(function(el) { - el.updateContent_(); - }); - }); - return { createTimeDurationSpan: createTimeDurationSpan }; }); </script> -<polymer-element name="tr-ui-u-time-duration-span"> - <template> - <style> - :host { - display: block; - position: relative; - } - #content.right-align { - text-align: right; - position: relative; - display: block; - } - #sparkline { - width: 0%; - position: absolute; - bottom: 0; - right: 0; - display: none; - height: 100%; - background-color: hsl(216, 100%, 94.5%); - border-left: 1px solid hsl(216, 100%, 89%); - box-sizing: border-box; - } - #warning { - margin-left: 4px; - font-size: 66%; - } - </style> - <span id="sparkline"></span> - <span id="content"></span> - <span id="warning" style="display:none">⚠</span> - </template> +<polymer-element name="tr-ui-u-time-duration-span" + extends="tr-ui-u-scalar-span"> <script> 'use strict'; Polymer({ - ready: function() { - this.warning_ = undefined; - this.duration_ = undefined; - this.percentage_ = undefined; - }, - - set contentTextDecoration(deco) { - this.$.content.style.textDecoration = deco; - }, - get duration() { - return this.duration_; + return this.value; }, set duration(duration) { - if (duration instanceof tr.b.units.TimeDuration) - this.duration_ = duration.duration; - else - this.duration_ = duration; - this.updateContent_(); - }, - - get percentage() { - return this.percentage_; - }, - - set percentage(percentage) { - this.percentage_ = percentage; - this.updateSparkline_(); - }, - - get rightAlign() { - return this.$.content.classList.contains('right-align'); - }, - - set rightAlign(rightAlign) { - if (rightAlign) - this.$.content.classList.add('right-align'); - else - this.$.content.classList.remove('right-align'); - }, - - updateSparkline_: function() { - if (this.percentage_ === undefined) { - this.$.sparkline.style.display = 'none'; - this.$.sparkline.style.width = '0'; - } else { - this.$.sparkline.style.display = 'block'; - this.$.sparkline.style.width = (this.percentage_ * 100) + '%'; - } - }, - - updateContent_: function() { - var content = tr.b.units.TimeDuration.format(this.duration_); - this.$.content.textContent = content; - }, - - get warning() { - return this.warning_; - }, - - set warning(warning) { - this.warning_ = warning; - var warningEl = this.$.warning; - if (this.warning_) { - warningEl.title = warning; - warningEl.style.display = ''; - } else { - warningEl.title = ''; - warningEl.style.display = 'none'; + if (duration instanceof tr.b.u.TimeDuration) { + this.value = duration; + return; } + this.setValueAndUnit(duration, tr.b.u.Units.timeDurationInMs); } }); </script> diff --git a/catapult/tracing/tracing/ui/units/time_duration_span_test.html b/catapult/tracing/tracing/ui/units/time_duration_span_test.html index a5b09f3a..6363d16f 100644 --- a/catapult/tracing/tracing/ui/units/time_duration_span_test.html +++ b/catapult/tracing/tracing/ui/units/time_duration_span_test.html @@ -4,7 +4,7 @@ Copyright (c) 2015 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <link rel="import" href="/tracing/ui/units/time_duration_span.html"> <script> 'use strict'; @@ -35,7 +35,7 @@ tr.b.unittest.testSuite(function() { test('instantiateWithObject', function() { var timeSpan = document.createElement('tr-ui-u-time-duration-span'); - timeSpan.duration = new tr.b.units.TimeDuration(73); + timeSpan.duration = new tr.b.u.TimeDuration(73); this.addHTMLOutput(timeSpan); assert.equal(timeSpan.duration, 73); }); @@ -73,18 +73,17 @@ tr.b.unittest.testSuite(function() { test('respectCurrentDisplayUnit', function() { try { - var Time = tr.b.units.Time; - Time.currentDisplayUnit = Time.supportedUnits.ns; + tr.b.u.Units.currentTimeDisplayMode = tr.b.u.TimeDisplayModes.ns; var timeSpan = document.createElement('tr-ui-u-time-duration-span'); timeSpan.duration = 73; this.addHTMLOutput(timeSpan); assert.isTrue(timeSpan.$.content.textContent.indexOf('ns') > 0); - Time.currentDisplayUnit = Time.supportedUnits.ms; + tr.b.u.Units.currentTimeDisplayMode = tr.b.u.TimeDisplayModes.ms; assert.isTrue(timeSpan.$.content.textContent.indexOf('ms') > 0); } finally { - Time.reset(); + tr.b.u.Units.reset(); } }); diff --git a/catapult/tracing/tracing/ui/units/time_stamp_span.html b/catapult/tracing/tracing/ui/units/time_stamp_span.html index 6ccf288a..09f99503 100644 --- a/catapult/tracing/tracing/ui/units/time_stamp_span.html +++ b/catapult/tracing/tracing/ui/units/time_stamp_span.html @@ -5,9 +5,11 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/ui/base/deep_utils.html"> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/time_display_mode.html"> <link rel="import" href="/tracing/base/units/time_stamp.html"> +<link rel="import" href="/tracing/base/units/units.html"> +<link rel="import" href="/tracing/ui/base/deep_utils.html"> +<link rel="import" href="/tracing/ui/units/scalar_span.html"> <script> 'use strict'; @@ -22,45 +24,28 @@ tr.exportTo('tr.ui.units', function() { return span; } - tr.b.units.Time.addEventListener('display-unit-changed', function(e) { - tr.b.findDeepElementsMatching(document.body, - 'tr-ui-u-time-stamp-span').forEach(function(el) { - el.updateContent_(); - }); - }); - return { createTimeStampSpan: createTimeStampSpan }; }); </script> -<polymer-element name="tr-ui-u-time-stamp-span"> - <template> - </template> +<polymer-element name="tr-ui-u-time-stamp-span" + extends="tr-ui-u-scalar-span"> <script> 'use strict'; Polymer({ - ready: function() { - this.timestamp_ = undefined; - }, - get timestamp() { - return this.timestamp_; + return this.value; }, set timestamp(timestamp) { - if (timestamp instanceof tr.b.units.TimeStamp) - this.timestamp_ = timestamp.timestamp; - else - this.timestamp_ = timestamp; - this.updateContent_(); - }, - - updateContent_: function() { - var content = tr.b.units.TimeStamp.format(this.timestamp_); - this.shadowRoot.textContent = content; + if (timestamp instanceof tr.b.u.TimeStamp) { + this.value = timestamp; + return; + } + this.setValueAndUnit(timestamp, tr.b.u.Units.timeStampInMs); } }); </script> diff --git a/catapult/tracing/tracing/ui/units/time_stamp_span_test.html b/catapult/tracing/tracing/ui/units/time_stamp_span_test.html index 10b9ff7b..850bee63 100644 --- a/catapult/tracing/tracing/ui/units/time_stamp_span_test.html +++ b/catapult/tracing/tracing/ui/units/time_stamp_span_test.html @@ -4,7 +4,7 @@ Copyright (c) 2015 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<link rel="import" href="/tracing/base/units/time.html"> +<link rel="import" href="/tracing/base/units/units.html"> <link rel="import" href="/tracing/ui/units/time_stamp_span.html"> <script> 'use strict'; @@ -35,25 +35,24 @@ tr.b.unittest.testSuite(function() { test('instantiateWithObject', function() { var timeStamp = document.createElement('tr-ui-u-time-stamp-span'); - timeStamp.timestamp = new tr.b.units.TimeStamp(73); + timeStamp.timestamp = new tr.b.u.TimeStamp(73); this.addHTMLOutput(timeStamp); assert.equal(timeStamp.timestamp, 73); }); test('respectCurrentDisplayUnit', function() { try { - var Time = tr.b.units.Time; - Time.currentDisplayUnit = Time.supportedUnits.ns; + tr.b.u.Units.currentTimeDisplayMode = tr.b.u.TimeDisplayModes.ns; var timeStamp = document.createElement('tr-ui-u-time-stamp-span'); timeStamp.timestamp = 73; this.addHTMLOutput(timeStamp); assert.isTrue(timeStamp.shadowRoot.textContent.indexOf('ns') > 0); - Time.currentDisplayUnit = Time.supportedUnits.ms; + tr.b.u.Units.currentTimeDisplayMode = tr.b.u.TimeDisplayModes.ms; assert.isTrue(timeStamp.shadowRoot.textContent.indexOf('ms') > 0); } finally { - Time.reset(); + tr.b.u.Units.reset(); } }); }); diff --git a/catapult/tracing/tracing_build/__init__.py b/catapult/tracing/tracing_build/__init__.py index 40dc4d65..528e8059 100644 --- a/catapult/tracing/tracing_build/__init__.py +++ b/catapult/tracing/tracing_build/__init__.py @@ -5,14 +5,5 @@ import os import sys - -def _AddTracingProjectPath(): - tracing_path = os.path.normpath( - os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) - if tracing_path not in sys.path: - sys.path.insert(0, tracing_path) - - -_AddTracingProjectPath() import tracing_project tracing_project.UpdateSysPathIfNeeded() diff --git a/systrace.py b/systrace.py index 798ac1ec..10824c7c 100755 --- a/systrace.py +++ b/systrace.py @@ -1,207 +1,22 @@ #!/usr/bin/env python -# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Copyright (c) 2015 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Android system-wide tracing utility. - -This is a tool for capturing a trace that includes data from both userland and -the kernel. It creates an HTML file for visualizing the trace. -""" - +import os import sys -# Make sure we're using a new enough version of Python. -# The flags= parameter of re.sub() is new in Python 2.7. -if sys.version_info[:2] < (2, 7): - print >> sys.stderr, '\nThis script requires Python 2.7 or newer.' +version = sys.version_info[:2] +if version != (2, 7): + sys.stderr.write('Systrace does not support Python %d.%d. ' + 'Please use Python 2.7.\n' % version) sys.exit(1) -# pylint: disable=g-bad-import-order,g-import-not-at-top -import imp -import optparse -import os - -import util - - -# The default agent directory. -DEFAULT_AGENT_DIR = 'agents' - - -def parse_options(argv): - """Parses and checks the command-line options. - - Returns: - A tuple containing the options structure and a list of categories to - be traced. - """ - usage = 'Usage: %prog [options] [category1 [category2 ...]]' - desc = 'Example: %prog -b 32768 -t 15 gfx input view sched freq' - parser = optparse.OptionParser(usage=usage, description=desc) - parser.add_option('-o', dest='output_file', help='write HTML to FILE', - default='trace.html', metavar='FILE') - parser.add_option('-t', '--time', dest='trace_time', type='int', - help='trace for N seconds', metavar='N') - parser.add_option('-b', '--buf-size', dest='trace_buf_size', type='int', - help='use a trace buffer size of N KB', metavar='N') - parser.add_option('-k', '--ktrace', dest='kfuncs', action='store', - help='specify a comma-separated list of kernel functions ' - 'to trace') - parser.add_option('-l', '--list-categories', dest='list_categories', - default=False, action='store_true', - help='list the available categories and exit') - parser.add_option('-a', '--app', dest='app_name', default=None, type='string', - action='store', - help='enable application-level tracing for comma-separated ' - 'list of app cmdlines') - parser.add_option('--no-fix-threads', dest='fix_threads', default=True, - action='store_false', - help='don\'t fix missing or truncated thread names') - parser.add_option('--no-fix-tgids', dest='fix_tgids', default=True, - action='store_false', - help='Do not run extra commands to restore missing thread to\ - thread group id mappings.') - parser.add_option('--no-fix-circular', dest='fix_circular', default=True, - action='store_false', - help='don\'t fix truncated circular traces') - parser.add_option('--no-compress', dest='compress_trace_data', - default=True, action='store_false', - help='Tell the device not to send the trace data in ' - 'compressed form.') - parser.add_option('--link-assets', dest='link_assets', default=False, - action='store_true', - help='(deprecated)') - parser.add_option('--boot', dest='boot', default=False, action='store_true', - help='reboot the device with tracing during boot enabled. ' - 'The report is created by hitting Ctrl+C after the device ' - 'has booted up.') - parser.add_option('--from-file', dest='from_file', action='store', - help='read the trace from a file (compressed) rather than ' - 'running a live trace') - parser.add_option('--asset-dir', dest='asset_dir', default='trace-viewer', - type='string', help='(deprecated)') - parser.add_option('-e', '--serial', dest='device_serial', type='string', - help='adb device serial number') - parser.add_option('--agent-dirs', dest='agent_dirs', type='string', - help='the directories of additional systrace agent modules.' - ' The directories should be comma separated, e.g., ' - '--agent-dirs=dir1,dir2,dir3. Directory |%s| is the default' - ' agent directory and will always be checked.' - % DEFAULT_AGENT_DIR) - - options, categories = parser.parse_args(argv[1:]) - - if options.link_assets or options.asset_dir != 'trace-viewer': - parser.error('--link-assets and --asset-dir are deprecated.') - - if (options.trace_time is not None) and (options.trace_time <= 0): - parser.error('the trace time must be a positive number') - - if (options.trace_buf_size is not None) and (options.trace_buf_size <= 0): - parser.error('the trace buffer size must be a positive number') - - return (options, categories) - - -def write_trace_html(html_filename, script_dir, agents): - """Writes out a trace html file. - - Args: - html_filename: The name of the file to write. - script_dir: The directory containing this script. - agents: The systrace agents. - """ - html_prefix = read_asset(script_dir, 'prefix.html') - html_suffix = read_asset(script_dir, 'suffix.html') - trace_viewer_html = read_asset(script_dir, 'systrace_trace_viewer.html') - - # Open the file in binary mode to prevent python from changing the - # line endings. - html_file = open(html_filename, 'wb') - html_file.write(html_prefix.replace('{{SYSTRACE_TRACE_VIEWER_HTML}}', - trace_viewer_html)) - - html_file.write('<!-- BEGIN TRACE -->\n') - for a in agents: - html_file.write(' <script class="') - html_file.write(a.get_class_name()) - html_file.write('" type="application/text">\n') - html_file.write(a.get_trace_data()) - html_file.write(' </script>\n') - html_file.write('<!-- END TRACE -->\n') - - html_file.write(html_suffix) - html_file.close() - print '\n wrote file://%s\n' % os.path.abspath(html_filename) - - -def create_agents(options, categories): - """Create systrace agents. - - This function will search systrace agent modules in agent directories and - create the corresponding systrace agents. - Args: - options: The command-line options. - categories: The trace categories to capture. - Returns: - The list of systrace agents. - """ - agent_dirs = [os.path.join(os.path.dirname(__file__), DEFAULT_AGENT_DIR)] - if options.agent_dirs: - agent_dirs.extend(options.agent_dirs.split(',')) - - agents = [] - for agent_dir in agent_dirs: - if not agent_dir: - continue - for filename in os.listdir(agent_dir): - (module_name, ext) = os.path.splitext(filename) - if ext != '.py' or module_name == '__init__': - continue - (f, pathname, data) = imp.find_module(module_name, [agent_dir]) - try: - module = imp.load_module(module_name, f, pathname, data) - finally: - if f: - f.close() - if module: - agent = module.try_create_agent(options, categories) - if not agent: - continue - agents.append(agent) - return agents - - -def main(): - options, categories = parse_options(sys.argv) - agents = create_agents(options, categories) - - if not agents: - dirs = DEFAULT_AGENT_DIR - if options.agent_dirs: - dirs += ',' + options.agent_dirs - print >> sys.stderr, ('No systrace agent is available in directories |%s|.' - % dirs) - sys.exit(1) - - for a in agents: - a.start() - - for a in agents: - a.collect_result() - if not a.expect_trace(): - # Nothing more to do. - return - - script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) - write_trace_html(options.output_file, script_dir, agents) - - -def read_asset(src_dir, filename): - return open(os.path.join(src_dir, filename)).read() - +systrace_dir = os.path.abspath( + os.path.join(os.path.dirname(__file__), 'catapult', 'systrace', 'systrace')) +sys.path.insert(0, systrace_dir) +import systrace if __name__ == '__main__': - main() + sys.exit(systrace.main()) diff --git a/systrace_trace_viewer.html b/systrace_trace_viewer.html index eb7a8e7f..fc3e5743 100644 --- a/systrace_trace_viewer.html +++ b/systrace_trace_viewer.html @@ -1,5 +1,5 @@ <template id="overlay-template"> -<style> + <style> overlay-mask { left: 0; padding: 8px; @@ -81,23 +81,24 @@ padding: 4px; } </style> -<overlay-mask> -<overlay-vertical-centering-container> -<overlay-frame> -<title-bar> -<title></title> -<close-button>✕</close-button> -</title-bar> -<overlay-content> -<content></content> -</overlay-content> -<button-bar></button-bar> -</overlay-frame> -</overlay-vertical-centering-container> -</overlay-mask> -</template><polymer-element name="tr-ui-a-tab-view" constructor="TracingAnalysisTabView"> -<template> -<style> + + <overlay-mask> + <overlay-vertical-centering-container> + <overlay-frame> + <title-bar> + <title></title> + <close-button>✕</close-button> + </title-bar> + <overlay-content> + <content></content> + </overlay-content> + <button-bar></button-bar> + </overlay-frame> + </overlay-vertical-centering-container> + </overlay-mask> +</template><polymer-element constructor="TracingAnalysisTabView" name="tr-ui-a-tab-view"> + <template> + <style> :host { display: flex; flex-flow: column nowrap; @@ -166,31 +167,35 @@ font-weight: bold; } </style> -<tab-strip> -<tab-strip-heading id="tshh"> -<span id="tsh"></span> -</tab-strip-heading> -<template repeat="{{tab in tabs_}}"> -<tab-button button-id="{{ tab.id }}" on-click="{{ tabButtonSelectHandler_ }}" selected="{{ selectedTab_.id === tab.id }}"> -<button-label>{{ tab.label ? tab.label : 'No Label'}}</button-label> -</tab-button> -</template> -</tab-strip> -<tabs-content-container id="content-container"> -<content></content> -</tabs-content-container> -</template> -</polymer-element><polymer-element name="tr-ui-a-sub-view"> + <tab-strip> + <tab-strip-heading id="tshh"> + <span id="tsh"></span> + </tab-strip-heading> + <template repeat="{{tab in tabs_}}"> + <tab-button button-id="{{ tab.id }}" on-click="{{ tabButtonSelectHandler_ }}" selected="{{ selectedTab_.id === tab.id }}"> + <button-label>{{ tab.label ? tab.label : 'No Label'}}</button-label> + </tab-button> + </template> + </tab-strip> + + <tabs-content-container id="content-container"> + <content></content> + </tabs-content-container> + </template> + + +</polymer-element><polymer-element name="tr-ui-a-sub-view"> + </polymer-element><style> * /deep/ .labeled-checkbox { display: flex; white-space: nowrap; } -</style><polymer-element name="tr-ui-a-analysis-link" is="a" on-click="{{onClicked_}}" on-mouseenter="{{onMouseEnter_}}" on-mouseleave="{{onMouseLeave_}}"> -<template> -<style> +</style><polymer-element is="a" name="tr-ui-a-analysis-link" on-click="{{onClicked_}}" on-mouseenter="{{onMouseEnter_}}" on-mouseleave="{{onMouseLeave_}}"> + <template> + <style> :host { display: inline; color: -webkit-link; @@ -199,12 +204,12 @@ cursor: pointer; } </style> -<content></content> -</template> - + <content></content> + </template> + </polymer-element><polymer-element name="tr-ui-b-table"> -<template> -<style> + <template> + <style> :host { display: flex; flex-direction: column; @@ -328,20 +333,19 @@ transform: rotate(90deg); } </style> -<table> -<thead id="head"> -</thead> -<tbody id="body"> -</tbody> -<tfoot id="foot"> -</tfoot> -</table> -</template> - -</polymer-element> -<polymer-element name="tr-ui-b-table-header-cell" on-tap="onTap_"> -<template> -<style> + <table> + <thead id="head"> + </thead> + <tbody id="body"> + </tbody> + <tfoot id="foot"> + </tfoot> + </table> + </template> + +</polymer-element><polymer-element name="tr-ui-b-table-header-cell" on-tap="onTap_"> + <template> + <style> :host { -webkit-user-select: none; display: flex; @@ -362,24 +366,14 @@ line-height: 85%; } </style> -<span id="title"></span><side-element id="side"></side-element> -</template> -</polymer-element><polymer-element name="tr-ui-u-size-in-bytes-span"> -<template> -<style> - :host { - display: flex; - flex-direction: row; - align-items: center; - } - </style> -<span id="content"></span> -</template> + <span id="title"></span><side-element id="side"></side-element> + </template> -</polymer-element><polymer-element name="tr-ui-u-time-duration-span"> -<template> -<style> + +</polymer-element><polymer-element name="tr-ui-u-scalar-span"> + <template> + <style> :host { display: block; position: relative; @@ -396,7 +390,7 @@ right: 0; display: none; height: 100%; - background-color: hsl(216, 100%, 94.5%); + background-color: hsla(216, 100%, 94.5%, .75); border-left: 1px solid hsl(216, 100%, 89%); box-sizing: border-box; } @@ -405,52 +399,53 @@ font-size: 66%; } </style> -<span id="sparkline"></span> -<span id="content"></span> -<span id="warning" style="display:none">⚠</span> -</template> - -</polymer-element><polymer-element name="tr-ui-u-time-stamp-span"> -<template> -</template> - -</polymer-element><polymer-element name="tr-ui-a-generic-object-view" is="HTMLUnknownElement"> -<template> -<style> + <span id="sparkline"></span> + <span id="content"></span> + <span id="warning" style="display:none">⚠</span> + </template> + +</polymer-element><polymer-element extends="tr-ui-u-scalar-span" name="tr-ui-u-time-duration-span"> + +</polymer-element><polymer-element extends="tr-ui-u-scalar-span" name="tr-ui-u-time-stamp-span"> + +</polymer-element><polymer-element is="HTMLUnknownElement" name="tr-ui-a-generic-object-view"> + <template> + <style> :host { display: block; font-family: monospace; } </style> -<div id="content"> -</div> -</template> - -</polymer-element> -<polymer-element name="tr-ui-a-generic-object-view-with-label" is="HTMLUnknownElement"> -<template> -<style> + <div id="content"> + </div> + </template> + + +</polymer-element><polymer-element is="HTMLUnknownElement" name="tr-ui-a-generic-object-view-with-label"> + <template> + <style> :host { display: block; } </style> -</template> + </template> + </polymer-element><polymer-element name="tr-ui-a-stack-frame"> -<template> -<style> + <template> + <style> :host { display: flex; flex-direction: row; align-items: center; } </style> -<tr-ui-b-table id="table"></tr-ui-b-table> -</template> - -</polymer-element><polymer-element name="tr-ui-a-single-event-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <tr-ui-b-table id="table"></tr-ui-b-table> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-event-sub-view"> + <template> + <style> :host { display: flex; flex-direction: column; @@ -460,13 +455,13 @@ align-self: stretch; } </style> -<tr-ui-b-table id="table"> -</tr-ui-b-table> -</template> - + <tr-ui-b-table id="table"> + </tr-ui-b-table> + </template> + </polymer-element><polymer-element name="tr-ui-a-related-events"> -<template> -<style> + <template> + <style> :host { display: flex; flex-direction: column; @@ -476,12 +471,13 @@ align-self: stretch; } </style> -<tr-ui-b-table id="table"></tr-ui-b-table> -</template> + <tr-ui-b-table id="table"></tr-ui-b-table> + </template> -</polymer-element><polymer-element name="tr-ui-a-single-thread-slice-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-thread-slice-sub-view"> + <template> + <style> :host { display: flex; flex-direction: row; @@ -492,16 +488,17 @@ } </style> -<tr-ui-a-single-event-sub-view id="content"></tr-ui-a-single-event-sub-view> -<div id="events"> -<tr-ui-a-related-events id="relatedEvents"> -</tr-ui-a-related-events> -</div> -</template> - + <tr-ui-a-single-event-sub-view id="content"></tr-ui-a-single-event-sub-view> + <div id="events"> + <tr-ui-a-related-events id="relatedEvents"> + </tr-ui-a-related-events> + </div> + </template> + + </polymer-element><polymer-element name="tr-ui-a-selection-summary-table"> -<template> -<style> + <template> + <style> :host { display: flex; } @@ -510,13 +507,14 @@ align-self: stretch; } </style> -<tr-ui-b-table id="table"> -</tr-ui-b-table> -</template> - + <tr-ui-b-table id="table"> + </tr-ui-b-table> + + </template> + </polymer-element><polymer-element name="tr-ui-a-multi-event-summary-table"> -<template> -<style> + <template> + <style> :host { display: flex; } @@ -525,13 +523,14 @@ align-self: stretch; } </style> -<tr-ui-b-table id="table"> -</tr-ui-b-table> -</template> - + <tr-ui-b-table id="table"> + </tr-ui-b-table> + + </template> + </polymer-element><polymer-element name="tr-ui-a-multi-event-details-table"> -<template> -<style> + <template> + <style> :host { display: flex; flex-direction: column; @@ -549,15 +548,16 @@ font-size: 12px; } </style> -<tr-ui-b-table id="titletable"> -</tr-ui-b-table> -<tr-ui-b-table id="table"> -</tr-ui-b-table> -</template> - -</polymer-element><polymer-element name="tr-ui-a-multi-event-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <tr-ui-b-table id="titletable"> + </tr-ui-b-table> + <tr-ui-b-table id="table"> + </tr-ui-b-table> + </template> + + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-event-sub-view"> + <template> + <style> :host { display: flex; overflow: auto; @@ -585,12 +585,12 @@ border-bottom: 1px solid #aaa; } </style> -<div id="content"></div> -</template> - -</polymer-element><polymer-element name="tr-ui-a-multi-thread-slice-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <div id="content"></div> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-thread-slice-sub-view"> + <template> + <style> :host { display: flex; } @@ -603,24 +603,26 @@ flex: 0 1 200px; } </style> -<div id="content"></div> -</template> - -</polymer-element><polymer-element name="tr-ui-a-single-async-slice-sub-view" extends="tr-ui-a-single-event-sub-view"> - -</polymer-element><polymer-element name="tr-ui-a-multi-async-slice-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <div id="content"></div> + </template> + + +</polymer-element><polymer-element extends="tr-ui-a-single-event-sub-view" name="tr-ui-a-single-async-slice-sub-view"> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-async-slice-sub-view"> + <template> + <style> :host { display: flex; } </style> -<tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view> -</template> + <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view> + </template> -</polymer-element><polymer-element name="tr-ui-a-single-cpu-slice-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-cpu-slice-sub-view"> + <template> + <style> table { border-collapse: collapse; border-width: 0; @@ -650,43 +652,44 @@ background-color: #e2e2e2; } </style> -<table> -<tr> -<td>Running process:</td><td id="process-name"></td> -</tr> -<tr> -<td>Running thread:</td><td id="thread-name"></td> -</tr> -<tr> -<td>Start:</td> -<td> -<tr-ui-u-time-stamp-span id="start"> -</tr-ui-u-time-stamp-span> -</td> -</tr> -<tr> -<td>Duration:</td> -<td> -<tr-ui-u-time-duration-span id="duration"> -</tr-ui-u-time-duration-span> -</td> -</tr> -<tr> -<td>Active slices:</td><td id="running-thread"></td> -</tr> -<tr> -<td>Args:</td> -<td> -<tr-ui-a-generic-object-view id="args"> -</tr-ui-a-generic-object-view> -</td> -</tr> -</table> -</template> - -</polymer-element><polymer-element name="tr-ui-a-multi-cpu-slice-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <table> + <tbody><tr> + <td>Running process:</td><td id="process-name"></td> + </tr> + <tr> + <td>Running thread:</td><td id="thread-name"></td> + </tr> + <tr> + <td>Start:</td> + <td> + <tr-ui-u-time-stamp-span id="start"> + </tr-ui-u-time-stamp-span> + </td> + </tr> + <tr> + <td>Duration:</td> + <td> + <tr-ui-u-time-duration-span id="duration"> + </tr-ui-u-time-duration-span> + </td> + </tr> + <tr> + <td>Active slices:</td><td id="running-thread"></td> + </tr> + <tr> + <td>Args:</td> + <td> + <tr-ui-a-generic-object-view id="args"> + </tr-ui-a-generic-object-view> + </td> + </tr> + </tbody></table> + </template> + + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-cpu-slice-sub-view"> + <template> + <style> :host { display: flex; } @@ -694,12 +697,13 @@ flex: 1 1 auto; } </style> -<tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view> -</template> + <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view> + </template> -</polymer-element><polymer-element name="tr-ui-a-single-thread-time-slice-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-thread-time-slice-sub-view"> + <template> + <style> table { border-collapse: collapse; border-width: 0; @@ -729,46 +733,50 @@ background-color: #e2e2e2; } </style> -<table> -<tr> -<td>Running process:</td><td id="process-name"></td> -</tr> -<tr> -<td>Running thread:</td><td id="thread-name"></td> -</tr> -<tr> -<td>State:</td> -<td><b><span id="state"></span></b></td> -</tr> -<tr> -<td>Start:</td> -<td> -<tr-ui-u-time-stamp-span id="start"> -</tr-ui-u-time-stamp-span> -</td> -</tr> -<tr> -<td>Duration:</td> -<td> -<tr-ui-u-time-duration-span id="duration"> -</tr-ui-u-time-duration-span> -</td> -</tr> -<tr> -<td>On CPU:</td><td id="on-cpu"></td> -</tr> -<tr> -<td>Running instead:</td><td id="running-instead"></td> -</tr> -<tr> -<td>Args:</td><td id="args"></td> -</tr> -</table> -</template> - -</polymer-element><polymer-element name="tr-ui-a-multi-thread-time-slice-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <table> + <tbody><tr> + <td>Running process:</td><td id="process-name"></td> + </tr> + <tr> + <td>Running thread:</td><td id="thread-name"></td> + </tr> + <tr> + <td>State:</td> + <td><b><span id="state"></span></b></td> + </tr> + <tr> + <td>Start:</td> + <td> + <tr-ui-u-time-stamp-span id="start"> + </tr-ui-u-time-stamp-span> + </td> + </tr> + <tr> + <td>Duration:</td> + <td> + <tr-ui-u-time-duration-span id="duration"> + </tr-ui-u-time-duration-span> + </td> + </tr> + + <tr> + <td>On CPU:</td><td id="on-cpu"></td> + </tr> + + <tr> + <td>Running instead:</td><td id="running-instead"></td> + </tr> + + <tr> + <td>Args:</td><td id="args"></td> + </tr> + </tbody></table> + </template> + + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-thread-time-slice-sub-view"> + <template> + <style> :host { display: flex; } @@ -776,54 +784,58 @@ flex: 1 1 auto; } </style> -<tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view> -</template> + <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view> + </template> -</polymer-element><polymer-element name="tr-ui-a-single-instant-event-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-instant-event-sub-view"> + <template> + <style> :host { display: block; } </style> -<div id="content"></div> -</template> + <div id="content"></div> + </template> -</polymer-element><polymer-element name="tr-ui-a-multi-instant-event-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-instant-event-sub-view"> + <template> + <style> :host { display: block; } </style> -<div id="content"></div> -</template> + <div id="content"></div> + </template> -</polymer-element><polymer-element name="tr-ui-a-counter-sample-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-counter-sample-sub-view"> + <template> + <style> :host { display: flex; flex-direction: column; } </style> -<tr-ui-b-table id="table"></tr-ui-b-table> -</template> -</polymer-element><polymer-element name="tr-ui-a-single-flow-event-sub-view" extends="tr-ui-a-single-event-sub-view"> - -</polymer-element><polymer-element name="tr-ui-a-multi-flow-event-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <tr-ui-b-table id="table"></tr-ui-b-table> + </template> +</polymer-element><polymer-element extends="tr-ui-a-single-event-sub-view" name="tr-ui-a-single-flow-event-sub-view"> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-flow-event-sub-view"> + <template> + <style> :host { display: flex; } </style> -<tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view> -</template> + <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view> + </template> -</polymer-element><polymer-element name="tr-ui-a-single-object-instance-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-object-instance-sub-view"> + <template> + <style> :host { display: block; } @@ -852,12 +864,12 @@ vertical-align: top; } </style> -<div id="content"></div> -</template> - -</polymer-element><polymer-element name="tr-ui-a-single-object-snapshot-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <div id="content"></div> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-object-snapshot-sub-view"> + <template> + <style> #args { white-space: pre; } @@ -882,46 +894,47 @@ vertical-align: top; } </style> -<content></content> -</template> - -</polymer-element><polymer-element name="tr-ui-a-multi-object-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <content></content> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-object-sub-view"> + <template> + <style> :host { display: flex; } </style> -<tr-ui-b-table id="content"></tr-ui-b-table> -</template> - -</polymer-element><polymer-element name="tr-ui-a-single-sample-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <tr-ui-b-table id="content"></tr-ui-b-table> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-sample-sub-view"> + <template> + <style> :host { display: flex; } </style> -<tr-ui-b-table id="content"></tr-ui-b-table> -</template> - -</polymer-element><polymer-element name="tr-ui-a-multi-sample-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <tr-ui-b-table id="content"></tr-ui-b-table> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-sample-sub-view"> + <template> + <style> :host { display: block; } </style> -<div id="content"></div> -</template> - -</polymer-element><polymer-element name="tr-ui-a-single-interaction-record-sub-view" extends="tr-ui-a-sub-view"> - -</polymer-element><polymer-element name="tr-ui-a-multi-interaction-record-sub-view" extends="tr-ui-a-sub-view"> - -</polymer-element><polymer-element name="tr-ui-a-alert-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <div id="content"></div> + </template> + + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-interaction-record-sub-view"> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-interaction-record-sub-view"> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-alert-sub-view"> + <template> + <style> :host { display: flex; flex-direction: column; @@ -931,13 +944,13 @@ align-self: stretch; } </style> -<tr-ui-b-table id="table"> -</tr-ui-b-table> -</template> - -</polymer-element><polymer-element name="tr-ui-a-single-frame-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <tr-ui-b-table id="table"> + </tr-ui-b-table> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-frame-sub-view"> + <template> + <style> :host { display: flex; flex-direction: column; @@ -947,15 +960,15 @@ align-self: stretch; } </style> -<tr-ui-a-alert-sub-view id="asv"> -</tr-ui-a-alert-sub-view> -</template> - -</polymer-element><polymer-element name="tr-ui-a-multi-frame-sub-view" extends="tr-ui-a-sub-view"> - + <tr-ui-a-alert-sub-view id="asv"> + </tr-ui-a-alert-sub-view> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-frame-sub-view"> + </polymer-element><polymer-element name="tr-ui-b-color-legend"> -<template> -<style> + <template> + <style> :host { display: inline-block; } @@ -965,13 +978,15 @@ line-height: 0%; /* Prevent the square from increasing legend height. */ } </style> -<span id="square"></span> -<span id="label"></span> -</template> - -</polymer-element><polymer-element name="tr-ui-a-memory-dump-allocator-details-pane"> -<template> -<style> + <span id="square"></span> + <span id="label"></span> + </template> + +</polymer-element><polymer-element name="tr-ui-a-stacked-pane"> + +</polymer-element><polymer-element extends="tr-ui-a-stacked-pane" name="tr-ui-a-memory-dump-allocator-details-pane"> + <template> + <style> :host { display: flex; flex-direction: column; @@ -1002,13 +1017,13 @@ text-align: center; } </style> -<div id="label">Allocator details</div> -<div id="contents"></div> -</template> - -</polymer-element><polymer-element name="tr-ui-a-memory-dump-vm-regions-details-pane"> -<template> -<style> + <div id="label">Allocator details</div> + <div id="contents"></div> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-stacked-pane" name="tr-ui-a-memory-dump-vm-regions-details-pane"> + <template> + <style> :host { display: flex; flex-direction: column; @@ -1039,15 +1054,15 @@ text-align: center; } </style> -<div id="label">Memory maps</div> -<div id="contents"></div> -</template> - + <div id="label">Memory maps</div> + <div id="contents"></div> + </template> + </polymer-element><polymer-element name="tr-ui-b-view-specific-brushing-state"> - -</polymer-element><polymer-element name="tr-ui-a-memory-dump-overview-pane"> -<template> -<style> + +</polymer-element><polymer-element extends="tr-ui-a-stacked-pane" name="tr-ui-a-memory-dump-overview-pane"> + <template> + <style> :host { display: flex; flex-direction: column; @@ -1070,64 +1085,65 @@ align-self: stretch; } </style> -<tr-ui-b-view-specific-brushing-state id="state" view-id="analysis.memory_dump_overview_pane"> -</tr-ui-b-view-specific-brushing-state> -<div id="label">Overview</div> -<tr-ui-b-table id="table"> -</tr-ui-b-table> -</template> - -</polymer-element><polymer-element name="tr-ui-a-memory-dump-view"> -<template> -<style> + <tr-ui-b-view-specific-brushing-state id="state" view-id="analysis.memory_dump_overview_pane"> + </tr-ui-b-view-specific-brushing-state> + <div id="label">Overview</div> + <tr-ui-b-table id="table"> + </tr-ui-b-table> + </template> + +</polymer-element><polymer-element name="tr-ui-a-stacked-pane-view"> + <template> + <style> :host { display: flex; flex-direction: column; } - #overview_pane, - #details_pane_container { + #pane_container > * { flex: 0 0 auto; } </style> -<tr-ui-a-memory-dump-overview-pane id="overview_pane"> -</tr-ui-a-memory-dump-overview-pane> -<div id="details_pane_container"> -</div> -</template> - -</polymer-element><polymer-element name="tr-ui-a-single-process-memory-dump-sub-view" extends="tr-ui-a-sub-view"> -<template> -<tr-ui-a-memory-dump-view id="memory_dump_view"> -</tr-ui-a-memory-dump-view> -</template> - -</polymer-element><polymer-element name="tr-ui-a-multi-process-memory-dump-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <div id="pane_container"> + </div> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-stacked-pane-view" name="tr-ui-a-memory-dump-view"> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-process-memory-dump-sub-view"> + <template> + <tr-ui-a-memory-dump-view id="memory_dump_view"> + </tr-ui-a-memory-dump-view> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-process-memory-dump-sub-view"> + <template> + <style> :host { display: flex; } </style> -<tr-ui-b-table id="content"></tr-ui-b-table> -</template> - -</polymer-element><polymer-element name="tr-ui-a-single-global-memory-dump-sub-view" extends="tr-ui-a-sub-view"> -<template> -<tr-ui-a-memory-dump-view id="memory_dump_view"> -</tr-ui-a-memory-dump-view> -</template> - -</polymer-element><polymer-element name="tr-ui-a-multi-global-memory-dump-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <tr-ui-b-table id="content"></tr-ui-b-table> + </template> + + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-single-global-memory-dump-sub-view"> + <template> + <tr-ui-a-memory-dump-view id="memory_dump_view"> + </tr-ui-a-memory-dump-view> + </template> + +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-global-memory-dump-sub-view"> + <template> + <style> :host { display: flex; } </style> -<tr-ui-b-table id="content"></tr-ui-b-table> -</template> + <tr-ui-b-table id="content"></tr-ui-b-table> + </template> + </polymer-element><style> * /deep/ .chart-base #title { font-size: 16pt; @@ -1145,37 +1161,37 @@ shape-rendering: crispEdges; stroke: #000; } -</style> -<template id="chart-base-template"> -<svg> -<g xmlns="http://www.w3.org/2000/svg" id="chart-area"> -</g><g class="x axis"></g> -<g class="y axis"></g> -<text id="title"></text> -</svg> +</style><template id="chart-base-template"> + <svg> + <g id="chart-area" xmlns="http://www.w3.org/2000/svg"> + <g class="x axis"></g> + <g class="y axis"></g> + <text id="title"></text> + </g> + </svg> </template><style> * /deep/ .line-chart .line{fill:none;stroke-width:1.5px}* /deep/ .line-chart #brushes>rect{fill:rgb(192,192,192)} </style><polymer-element name="tr-ui-a-frame-power-usage-chart"> -<template> -<div id="content"></div> -</template> + <template> + <div id="content"></div> + </template> </polymer-element><polymer-element name="tr-ui-a-power-sample-summary-table"> -<template> -<tr-ui-b-table id="table"></tr-ui-b-table> -</template> - + <template> + <tr-ui-b-table id="table"></tr-ui-b-table> + </template> + </polymer-element><polymer-element name="tr-ui-a-power-sample-table"> -<template> -<style> + <template> + <style> :host { display: flex; } </style> -<tr-ui-b-table id="table"></tr-ui-b-table> -</template> -</polymer-element><polymer-element name="tr-ui-a-multi-power-sample-sub-view" extends="tr-ui-a-sub-view"> -<template> -<style> + <tr-ui-b-table id="table"></tr-ui-b-table> + </template> +</polymer-element><polymer-element extends="tr-ui-a-sub-view" name="tr-ui-a-multi-power-sample-sub-view"> + <template> + <style> :host { display: flex; flex-direction: row; @@ -1189,18 +1205,18 @@ width: 50%; } </style> -<div id="tables"> -<tr-ui-a-power-sample-summary-table id="summaryTable"> -</tr-ui-a-power-sample-summary-table> -<tr-ui-a-power-sample-table id="samplesTable"> -</tr-ui-a-power-sample-table> -</div> -<tr-ui-a-frame-power-usage-chart id="chart"> -</tr-ui-a-frame-power-usage-chart> -</template> + <div id="tables"> + <tr-ui-a-power-sample-summary-table id="summaryTable"> + </tr-ui-a-power-sample-summary-table> + <tr-ui-a-power-sample-table id="samplesTable"> + </tr-ui-a-power-sample-table> + </div> + <tr-ui-a-frame-power-usage-chart id="chart"> + </tr-ui-a-frame-power-usage-chart> + </template> </polymer-element><polymer-element name="tr-ui-a-analysis-view"> -<template> -<style> + <template> + <style> :host { background-color: white; display: flex; @@ -1217,14 +1233,14 @@ flex: 1 0 auto; } </style> -<content></content> -</template> - + <content></content> + </template> + </polymer-element><style> * /deep/ x-drag-handle{-webkit-user-select:none;box-sizing:border-box;display:block}* /deep/ x-drag-handle.horizontal-drag-handle{background-image:-webkit-gradient(linear,0 0,0 100%,from(#E5E5E5),to(#D1D1D1));border-bottom:1px solid #8e8e8e;border-top:1px solid white;cursor:ns-resize;height:7px;position:relative;z-index:10}* /deep/ x-drag-handle.vertical-drag-handle{background-image:-webkit-gradient(linear,0 0,100% 0,from(#E5E5E5),to(#D1D1D1));border-left:1px solid white;border-right:1px solid #8e8e8e;cursor:ew-resize;position:relative;width:7px;z-index:10} </style><polymer-element name="tr-ui-b-dropdown"> -<template> -<style> + <template> + <style> :host { position: relative; display: flex; @@ -1271,22 +1287,22 @@ cursor: default; } </style> -<tr-ui-b-toolbar-button id="outer" on-keydown="{{ onOuterKeyDown_ }}" on-click="{{ onOuterClick_ }}"> -<div id="icon">⚙</div> -<div id="state">▾</div> -</tr-ui-b-toolbar-button> -<dialog id="dialog" on-click="{{ onDialogClick_ }}" on-cancel="{{ onDialogCancel_ }}"> -<div id="dialog-frame"> -<content></content> -</div> -</dialog> -</template> - + <tr-ui-b-toolbar-button id="outer" on-click="{{ onOuterClick_ }}" on-keydown="{{ onOuterKeyDown_ }}"> + <div id="icon">⚙</div> + <div id="state">▾</div> + </tr-ui-b-toolbar-button> + <dialog id="dialog" on-cancel="{{ onDialogCancel_ }}" on-click="{{ onDialogClick_ }}"> + <div id="dialog-frame"> + <content></content> + </div> + </dialog> + </template> + </polymer-element><polymer-element name="tv-ui-b-hotkey-controller"> - -</polymer-element><polymer-element name="tr-ui-b-toolbar-button" noscript="noscript"> -<template> -<style> + +</polymer-element><polymer-element name="tr-ui-b-toolbar-button" noscript=""> + <template> + <style> :host { display: flex; background-color: #f8f8f8; @@ -1310,13 +1326,13 @@ align-self: center; } </style> -<div id="aligner"> -<content></content> -</div> -</template> + <div id="aligner"> + <content></content> + </div> + </template> </polymer-element><polymer-element name="tr-ui-b-mouse-mode-icon"> -<template> -<style> + <template> + <style> :host { display: block; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAChCAYAAACbBNzvAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABV0RVh0Q3JlYXRpb24gVGltZQA3LzE2LzEzRNEKUwAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAA9aSURBVHic7V1rTFvl//+UrgUmZWMpbLa6cLErwpYxkqLGkjAG88WSbmumGUllvlmAJctMRtybvlHrLXiJUekMIZuYSCL5gS+EuLIXGEGjqCsllCEW6xQECgzWG7S05/+C/zkp9LTn0gsL6ych9JzznOdzPj19Luf5PN/nCN59913ixRdfRFdXFxLx/2GDgCAIYmpqCoWFhUjE/4cNae+99x4AIFH/Hzak7nDqDu+wOyyw2WzEdl9EMpG23ReQbKQE73Q8coJ3bfcFWK1W/Pbbb/D7/UhLi/37DwaDEIvFKC8vR0lJSdjxbRVstVoxPDyMxx9/HAUFBcjMzIRAIOCdXzAYhNvtht1ux/DwMACEid5WwSMjI3jyySdRXFwMsVgMoVAYk2CCIJCZmYns7GyMjo5iZGQkPoKXl5exd+9e3hdGIhgMIj8/H5mZmRCJRIyCyQ5NJBAEgUAgAKFQiIKCAiwsLISl4VxoHA4H+vv74Xa7uZ4aBqFQiOzsbIhEIojFYojFYohEItq/8fFxXLlyBUtLSxHThOaxZ88eCIXC2AWPj48DAH799deYBaelpUEoFLL6++qrrwAAH3zwAav0YrGYthLkJHh6ehpzc3MAgPn5eUxPT8csWiAQMJbboaEhmM1mAIDFYsHQ0BDvPDkJtlgsYdt+v59LFrxw/fr1sG2Xy8UrL06C6+vrw7bFYjEvYi747rvvwrYlEgmvvDjV0g6HI+p2ohBP3qh32OFwoLe3l1VGvb29sNvtvC8kFCMjI9DpdKzS6nQ6mEwm1nnTPg/7/X6MjY1hcnKS/VX+P/bu3YuysjLk5uYypv36669x8uRJZGRkQCQSwev1oqOjAz09PZx5CwsLcenSJRw+fBh+vx+rq6swmUx46aWXNqWjvcMDAwO8xAIbnZKBgQFeNXhzczMvscBGp6S5uRk//vhj1HS0grVaLYqLi3kRy+Vy1NXVRe0RRcKNGzeg0Wh48apUKnR1daG6ujpqOtpKy+VyQa1Wo6SkBLdv38aFCxeoY5988gn1+fLly9TnL774ApWVlXjiiSfgdDqxtrbG+aJ9Ph/0ej3OnDkDvV6PW7duUceOHDlCfR4dHaU+v/DCC7h27RrUajWcTidWV1ejctAKJggCKysryMzMhE6nw+zsLO3Joft1Oh0ePHiApaUlduqi8BYVFaGvr48Vb19fHyfeqM2Sz+dj3QTEs4lKJC+njsfWJoptkxUrtjZRbJssOnASXFtbG3U7UXjrrbeibnMBJ8FZWVkoKysDABQUFCArK4s3MRcoFArqrlZXV0OhUPDOi5Ngn8+Hw4cPQyqV4tlnn4XP5+NNTIIgmH0An8+HV155BUqlEq+++ior3kAgQLuf84jH2toajh8/jvX1da6n0sLj8SAjI4MxHUEQ+PTTT1nlSRAEHjx4QHtsW8e0RCIR7HY79uzZE/GOcEUgEEAgEMDff/8NkUgUdnxbBR85cgRmsxkCgQD5+fkRh2XYIhAI4P79+5iamoLD4cCxY8fC0myr4KeeegoCgQBWqxVzc3NIS0uLedQyGAxi165dKC8vR1FRUVialHu405ESvNPxyAlOuYfJRMo9fFjdw3iBq3vIBDbu4bYK3uoextKtJEH2yWNyD8nyEG8wuYcffvgha3cxru6h3W5Hf39/QoyzaE6fyWRCQ0MDZ+MsLu7h8vIyent7sby8zIk8VkxNTUGn08Fms8UlP04Nn9/vR39/f9w8JLZwu91obGzk5CFFAq+Wfnh4mDKok4mWlha0trbGlAfvrs3k5CQGBgaSYoiHoqenB1evXk2OIb4VDocDJpMp6eXaYrGgsbGRV7mOufPq8XgwMDCQ9HI9NzeHq1evci7XvDseUqkUWq0W6enpCAaDcDqd8Hq9fLNjDaVSiRs3bkAikfDi5XSHxWIxampqAAALCwsYGhrC7Ows5ufnEypWIpHAYDAAACYmJnD9+nXevJwEnzp1CjKZDBUVFQCAsbGxpJTfjz76CFVVVWhqagIAdHR08G6XWQuuqanB7t274fV6UVpaiuzsbAAbTzyJhMFggEKhgNfrRX19PWQyGQDAaDTyyo+V4JqaGshkMsricLlcOH78OICNCWp8p0cwwWAwoKqqahPvG2+8AWDji+7u7uacJyvBMpksrKxkZWVR0yLGxsY4E7NBVVVVGK9CoaCmRXR0dHDOk5VguorB5/OhoqICYrE4YZ2PSLxXrlyBRCLhNcE1pufh1dVVXLx4EWlpaRGnJzCBjXtId87g4GBU3ri5h1uJ5+fnY8mCtXvIhTflHoYg5R4mEyn3MAl45KyWlOCdjkdOcMo9TCZS7mHKPeSGhLmH5LBOrAGXXN1DcliHrgdFgsk95CzYbrfDbDbD7/ejrKwstpmtNO5hJJhMJrS2tsLtdqOpqQlarTZi2mjuIWvBfr8fZrN50/iz2WzG9PQ0nn/+edonEzZgij10uVwwGo2bxp+NRiOGhobw+uuv005hjtk9JENz6AbbyWCuRESp2Ww2NDc30w62WywW6HQ6zoOIrO5wbm4uzp8/j5WVFXR2dm46VldXh3379mF5eTku86dDUVxcjK6uLthstrClqrq6unDo0CHOvKwE+/1+LC4uUqG0oZiYmIhaicQCkvfu3bthxwYGBnhVmpy6NnSD7kxxQvEA3Zo+fIsQJ8F040j379/nRcwFdF4037FwToLphkUXFxd5EXMB3chkUgQ7nc6wfT6fL+Gm+H///Re2z+Vy8TLFGSut/v5+RsPsm2++AbDR84pXLFNDQwPjelxnz54FsBFK+/nnn7PKl/EOa7VaVmHvYrE4au+HK27evMkq7F0ikeDmzZus82UU7HK5qG8yGs6ePct73gUdfD4f2tvbGdO1t7dzaocZBRMEAaFQSBnhdKipqYFQKORlm0TjzcvLo4xwOhgMBuTl5XHiZVVp+f1+yGQy2iDq4uJiyGSyhFRcfr8fVVVVtEHUGo0GVVVVnHlZ19JerxdqtRpSqZTaJ5VKoVarEzrdwev1Qq/XQ6lUUvuUSiX0ej0vXk7N0srKCjQaDbXmjUajwcrKCmfSULD5Oa6srKCtrQ0SiQQSiQRtbW2MvHFzD0MrsXhUUmzdw9BKjKmSiqt7SBBE3Conru4hOa8kWqBnyj3cgl0EQcQ0cMYWW3kIgkiKe7iVV2C1Won09PSYxLCB1+tFZmYmtb22tobt4E1LBimATaQAkiKWjveR85ZSgnc6Uu5hMpFyD1PuITekYg/ZxB52dXXFTMo2n1D38NSpU7zjDEP/yHzisnJpIsBm5dJ45rntgpONuITTJirctqWlJabjdGAUvNUEp0NouxcvtLa2MgZhmUwmzqKjCrbb7aw9HC5pmWAymVivb2kymTgFe0RslrbeNTa1rtlshkgkQn5+PusL2Iqtd42NdWM0GpGVlYWTJ08ypo14h/nGI8Uax8Q3XJbteREFV1ZW8iLmex6Ja9euJfS8iD9puVyOmpoa3L59G8DmVUq3glzNlAzoimVgvrq6GmlpadDr9QA2r1K6FeRqpmRAFxveiIK9Xi8VZ/jLL78whulUVFTELJbkJeMMjUYjI29TUxNrsQBDX5qMM4w0qE2iuLgYpaWlcXMPyThDphWMNRoN6uvrOfGyskvVanXUNGq1Oq5WKclL/qwjQa/Xc+Zl1dNi8nFi9ZeSyZvqS0erjbmAbT6kT7X1lQp8QeYTyasKE8w3aJJvPh6PBwRBYGZmJi68MzMzqdjDUDx67mEsFxwrUrGHSUCqWdrpSAne6dix7uFzzz1HW0s/FO7h/v37UVBQgMceeyxm99DlcsFut2NwcBACgSDsnTHb7h4ePHgQxcXFcTPTMjIyIJFIcOfOHfz+++8Pl2DSPSTftxQv93DXrl0oKirCnTt3wtIwFhq62aputxtms5maCR8pHROEQiEkEgntew/X1tbC3mu4tLSE9vZ2nD9/njZd6Pn79u3jHoo3OTmJsbExnDlzBsDGWLXdbqcNoent7YVCocChQ4dYh+VFij3s7u5GR0cH9YWaTCbcunVr0yMkmfbChQvQarXQarVUWF4wGER6ejp7wdPT0zCbzfB4PJv2R7NT/H4/rFYrJicnUVZWxnowPtTpGxoagtFoDAsIi2anuN1ufPnll+ju7salS5dw4sQJKk+64hH2FTgcDgwPD4eJZQu/3w+bzcZ5JSSLxYL333+fNvqNDdxuN3p6ehjPDxMsl8tjjkw5ceIENfOVLVQqFd58882YeA0GA7WiWiSECfb5fPjpp58AbKyBx/bCpVIp6urqAADff/895wf6tbU1fPbZZwCAjz/+mPHCSSiVSsr3eueddxh5aWtpMrwuJyeH9cuczp07R5UZvktO/fnnnwCAY8eOoa+vj9U5nZ2d1CsH2fhaUZulwcFB1kGNi4uLjK/gYwuDwcCJ9+2332add9RmyW63w+12Q6FQIC8vD5cvX8bCwgI19VcqlcJms8HhcGBycjJuSz6aTCbMzs5Cq9Xi6NGjGB0dxcTEBJxOJyQSCZRKJUZGRjAyMoL//e9/jBFsoaAVLJfLKZvD4XBQ37ZEItlUph0OB238gVwu5ySQhEqlopo+i8VCtbsymWxTmb579y6t46BSqRg5aAXX1tbi22+/DZvY5XQ6aQMuQyGVSlFbW8trgb6WlhY0NDRgYmJi0/6ZmRnGYVylUomWlhbGeGbaMuzxeKDRaKhVDdkgOzsblZWVOHfuHO82fH19HW1tbWhqamL9ul2ZTIbXXnsNnZ2drN7yFfFFjy6XC6WlpVCpVFhaWsK///5LVfnz8/PIy8sDAOzevRu5ubnIycmBx+OJKZ6YIAj4fD7U19ejsbERf/zxB4aHhykrdHx8HE8//TQAYP/+/VAqlVAoFJx4I1ZapGiyrBw4cAD37t2DXC7HgQMHAGx0QXNycrC+vh63VR5Cecnw3J6eHqhUKpSXlwPY6OI+88wzALiHxnN6PPz555/D9h08eJATIR/Qzd9gE/FKh9SYFlvI5XKqPMUCrlFuKpUKp0+fZkwXDAZp93MSLBaLUVJSgqNHjyIjIwNerzfmOR0ul4sx9lAikeD06dN4+eWXIZVKGXnj5h5evHgRXq8XHo+Hd9MTCpFIhHv37iEnJydqp/+HH36A1+uFy+VirKTi6h7Gug7tVpDuIUEQKCwsjOge/vPPP6zyCwQCWF5exl9//YX5+Xla93DbzTSbzQar1Yr19fW4uoclJSUp9xB4BJullOCdjkdO8P8BGCQ0hnF1DxUAAAAASUVORK5CYII=); @@ -1327,11 +1343,11 @@ cursor: auto; } </style> -</template> - + </template> + </polymer-element><polymer-element name="tr-ui-b-mouse-mode-selector"> -<template> -<style> + <template> + <style> :host { -webkit-user-drag: element; @@ -1372,17 +1388,17 @@ } </style> -<div class="drag-handle"></div> -<div class="buttons"> -</div> -</template> + <div class="drag-handle"></div> + <div class="buttons"> + </div> + </template> </polymer-element><style> .track-button{background-color:rgba(255,255,255,0.5);border:1px solid rgba(0,0,0,0.1);color:rgba(0,0,0,0.2);font-size:10px;height:12px;text-align:center;width:12px}.track-button:hover{background-color:rgba(255,255,255,1.0);border:1px solid rgba(0,0,0,0.5);box-shadow:0 0 .05em rgba(0,0,0,0.4);color:rgba(0,0,0,1)}.track-close-button{left:2px;position:absolute;top:2px}.track-collapse-button{left:3px;position:absolute;top:2px} </style><style> .drawing-container{-webkit-box-flex:1;display:inline;overflow:auto;overflow-x:hidden;position:relative}.drawing-container-canvas{-webkit-box-flex:1;display:block;pointer-events:none;position:absolute;top:0} </style><polymer-element name="tr-ui-heading"> -<template> -<style> + <template> + <style> :host { background-color: rgb(243, 245, 247); border-right: 1px solid #8e8e8e; @@ -1412,13 +1428,14 @@ display: none; } </style> -<heading id="heading" on-click="{{onHeadingDivClicked_}}"> -<span id="arrow"></span> -<span id="heading_content"></span> -<tr-ui-a-analysis-link id="link"></tr-ui-a-analysis-link> -</heading> -</template> - + <heading id="heading" on-click="{{onHeadingDivClicked_}}"> + <span id="arrow"></span> + <span id="heading_content"></span> + <tr-ui-a-analysis-link id="link"></tr-ui-a-analysis-link> + </heading> + </template> + + </polymer-element><style> .letter-dot-track { height: 18px; @@ -1449,8 +1466,8 @@ </style><style> .ruler-track{height:12px}.ruler-track.tall-mode{height:30px} </style><polymer-element name="tr-ui-timeline-track-view"> -<template> -<style> + <template> + <style> :host { -webkit-box-orient: vertical; display: -webkit-box; @@ -1476,16 +1493,19 @@ font-size: 8pt; } </style> -<content></content> -<div id="drag_box"></div> -<div id="hint_text"></div> -<tv-ui-b-hotkey-controller id="hotkey_controller"> -</tv-ui-b-hotkey-controller> -</template> + <content></content> + + <div id="drag_box"></div> + <div id="hint_text"></div> + <tv-ui-b-hotkey-controller id="hotkey_controller"> + </tv-ui-b-hotkey-controller> + </template> + + </polymer-element><polymer-element name="tr-ui-find-control"> -<template> -<style> + <template> + <style> :host { -webkit-user-select: none; display: -webkit-flex; @@ -1536,20 +1556,22 @@ } @keyframes spin { 100% { transform: rotate(360deg); } } </style> -<input type="text" id="filter" on-input="{{ filterTextChanged }}" on-keydown="{{ filterKeyDown }}" on-blur="{{ filterBlur }}" on-focus="{{ filterFocus }}" on-mouseup="{{ filterMouseUp }}" /> -<div id="spinner"></div> -<tr-ui-b-toolbar-button on-click="{{ findPrevious }}"> - ← + + <input id="filter" on-blur="{{ filterBlur }}" on-focus="{{ filterFocus }}" on-input="{{ filterTextChanged }}" on-keydown="{{ filterKeyDown }}" on-mouseup="{{ filterMouseUp }}" type="text"/> + <div id="spinner"></div> + <tr-ui-b-toolbar-button on-click="{{ findPrevious }}"> + ← </tr-ui-b-toolbar-button> -<tr-ui-b-toolbar-button on-click="{{ findNext }}"> - → + <tr-ui-b-toolbar-button on-click="{{ findNext }}"> + → </tr-ui-b-toolbar-button> -<div id="hitCount">0 of 0</div> -</template> + <div id="hitCount">0 of 0</div> + </template> + </polymer-element><polymer-element name="tr-ui-scripting-control"> -<template> -<style> + <template> + <style> :host { flex: 1 1 auto; } @@ -1601,16 +1623,19 @@ color: #468; } </style> -<div id="root" class="root hidden" tabindex="0" on-focus="{{ onConsoleFocus }}"> -<div id="history"></div> -<div id="prompt" on-keypress="{{ promptKeyPress }}" on-keydown="{{ promptKeyDown }}" on-blur="{{ onConsoleBlur }}"> -</div></div></template> -</polymer-element><polymer-element name="tr-ui-side-panel"> + <div class="root hidden" id="root" on-focus="{{ onConsoleFocus }}" tabindex="0"> + <div id="history"></div> + <div id="prompt" on-blur="{{ onConsoleBlur }}" on-keydown="{{ promptKeyDown }}" on-keypress="{{ promptKeyPress }}"> + -</polymer-element><polymer-element name="tr-ui-side-panel-container" is="HTMLUnknownElement"> -<template> -<style> + + +</div></div></template></polymer-element><polymer-element name="tr-ui-side-panel"> + +</polymer-element><polymer-element is="HTMLUnknownElement" name="tr-ui-side-panel-container"> + <template> + <style> :host { align-items: stretch; display: -webkit-flex; @@ -1663,14 +1688,16 @@ padding: 14px 2px 14px 1px; } </style> -<active-panel-container id="active_panel_container"> -</active-panel-container> -<tab-strip id="tab_strip"></tab-strip> -</template> + <active-panel-container id="active_panel_container"> + </active-panel-container> + <tab-strip id="tab_strip"></tab-strip> + </template> + + </polymer-element><polymer-element name="tr-ui-timeline-view-help-overlay"> -<template> -<style> + <template> + <style> :host { -webkit-flex: 1 1 auto; -webkit-flex-direction: row; @@ -1729,142 +1756,167 @@ background-position: -1px -101px; } </style> -<div class="column left"> -<h2>Navigation</h2> -<div class="pair"> -<div class="command">w/s</div> -<div class="action">Zoom in/out (+shift: faster)</div> -</div> -<div class="pair"> -<div class="command">a/d</div> -<div class="action">Pan left/right (+shift: faster)</div> -</div> -<div class="pair"> -<div class="command">→/shift-TAB</div> -<div class="action">Select previous event</div> -</div> -<div class="pair"> -<div class="command">←/TAB</div> -<div class="action">Select next event</div> -</div> -<h2>Mouse Controls</h2> -<div class="pair"> -<div class="command">click</div> -<div class="action">Select event</div> -</div> -<div class="pair"> -<div class="command">alt-mousewheel</div> -<div class="action">Zoom in/out</div> -</div> -<h3> -<tr-ui-b-mouse-mode-icon modename="SELECTION"></tr-ui-b-mouse-mode-icon> + <div class="column left"> + <h2>Navigation</h2> + <div class="pair"> + <div class="command">w/s</div> + <div class="action">Zoom in/out (+shift: faster)</div> + </div> + + <div class="pair"> + <div class="command">a/d</div> + <div class="action">Pan left/right (+shift: faster)</div> + </div> + + <div class="pair"> + <div class="command">→/shift-TAB</div> + <div class="action">Select previous event</div> + </div> + + <div class="pair"> + <div class="command">←/TAB</div> + <div class="action">Select next event</div> + </div> + + <h2>Mouse Controls</h2> + <div class="pair"> + <div class="command">click</div> + <div class="action">Select event</div> + </div> + <div class="pair"> + <div class="command">alt-mousewheel</div> + <div class="action">Zoom in/out</div> + </div> + + <h3> + <tr-ui-b-mouse-mode-icon modename="SELECTION"></tr-ui-b-mouse-mode-icon> Select mode </h3> -<div class="pair"> -<div class="command">drag</div> -<div class="action">Box select</div> -</div> -<div class="pair"> -<div class="command">double click</div> -<div class="action">Select all events with same title</div> -</div> -<h3> -<tr-ui-b-mouse-mode-icon modename="PANSCAN"></tr-ui-b-mouse-mode-icon> + <div class="pair"> + <div class="command">drag</div> + <div class="action">Box select</div> + </div> + + <div class="pair"> + <div class="command">double click</div> + <div class="action">Select all events with same title</div> + </div> + + <h3> + <tr-ui-b-mouse-mode-icon modename="PANSCAN"></tr-ui-b-mouse-mode-icon> Pan mode </h3> -<div class="pair"> -<div class="command">drag</div> -<div class="action">Pan the view</div> -</div> -<h3> -<tr-ui-b-mouse-mode-icon modename="ZOOM"></tr-ui-b-mouse-mode-icon> + <div class="pair"> + <div class="command">drag</div> + <div class="action">Pan the view</div> + </div> + + <h3> + <tr-ui-b-mouse-mode-icon modename="ZOOM"></tr-ui-b-mouse-mode-icon> Zoom mode </h3> -<div class="pair"> -<div class="command">drag</div> -<div class="action">Zoom in/out by dragging up/down</div> -</div> -<h3> -<tr-ui-b-mouse-mode-icon modename="TIMING"></tr-ui-b-mouse-mode-icon> + <div class="pair"> + <div class="command">drag</div> + <div class="action">Zoom in/out by dragging up/down</div> + </div> + + <h3> + <tr-ui-b-mouse-mode-icon modename="TIMING"></tr-ui-b-mouse-mode-icon> Timing mode </h3> -<div class="pair"> -<div class="command">drag</div> -<div class="action">Create or move markers</div> -</div> -<div class="pair"> -<div class="command">double click</div> -<div class="action">Set marker range to slice</div> -</div> -</div> -<div class="column right"> -<h2>General</h2> -<div class="pair"> -<div class="command">1-4</div> -<div class="action">Switch mouse mode</div> -</div> -<div class="pair"> -<div class="command">shift</div> -<div class="action">Hold for temporary select</div> -</div> -<div class="pair"> -<div class="command">space</div> -<div class="action">Hold for temporary pan</div> -</div> -<div class="pair"> -<div class="command"><span class="mod"></span></div> -<div class="action">Hold for temporary zoom</div> -</div> -<div class="pair"> -<div class="command">/</div> -<div class="action">Search</div> -</div> -<div class="pair"> -<div class="command">enter</div> -<div class="action">Step through search results</div> -</div> -<div class="pair"> -<div class="command">f</div> -<div class="action">Zoom into selection</div> -</div> -<div class="pair"> -<div class="command">z/0</div> -<div class="action">Reset zoom and pan</div> -</div> -<div class="pair"> -<div class="command">g/G</div> -<div class="action">Toggle 60hz grid</div> -</div> -<div class="pair"> -<div class="command">v</div> -<div class="action">Highlight VSync</div> -</div> -<div class="pair"> -<div class="command">h</div> -<div class="action">Toggle low/high details</div> -</div> -<div class="pair"> -<div class="command">m</div> -<div class="action">Mark current selection</div> -</div> -<div class="pair"> -<div class="command">`</div> -<div class="action">Show or hide the scripting console</div> -</div> -<div class="pair"> -<div class="command">?</div> -<div class="action">Show help</div> -</div> -</div> -</template> - + <div class="pair"> + <div class="command">drag</div> + <div class="action">Create or move markers</div> + </div> + + <div class="pair"> + <div class="command">double click</div> + <div class="action">Set marker range to slice</div> + </div> + </div> + + <div class="column right"> + <h2>General</h2> + <div class="pair"> + <div class="command">1-4</div> + <div class="action">Switch mouse mode</div> + </div> + + <div class="pair"> + <div class="command">shift</div> + <div class="action">Hold for temporary select</div> + </div> + + <div class="pair"> + <div class="command">space</div> + <div class="action">Hold for temporary pan</div> + </div> + + <div class="pair"> + <div class="command"><span class="mod"></span></div> + <div class="action">Hold for temporary zoom</div> + </div> + + <div class="pair"> + <div class="command">/</div> + <div class="action">Search</div> + </div> + + <div class="pair"> + <div class="command">enter</div> + <div class="action">Step through search results</div> + </div> + + <div class="pair"> + <div class="command">f</div> + <div class="action">Zoom into selection</div> + </div> + + <div class="pair"> + <div class="command">z/0</div> + <div class="action">Reset zoom and pan</div> + </div> + + <div class="pair"> + <div class="command">g/G</div> + <div class="action">Toggle 60hz grid</div> + </div> + + <div class="pair"> + <div class="command">v</div> + <div class="action">Highlight VSync</div> + </div> + + <div class="pair"> + <div class="command">h</div> + <div class="action">Toggle low/high details</div> + </div> + + <div class="pair"> + <div class="command">m</div> + <div class="action">Mark current selection</div> + </div> + + <div class="pair"> + <div class="command">`</div> + <div class="action">Show or hide the scripting console</div> + </div> + + <div class="pair"> + <div class="command">?</div> + <div class="action">Show help</div> + </div> + </div> + </template> + + </polymer-element><polymer-element name="tr-ui-u-array-of-numbers-span"> -<template> -</template> - + <template> + </template> + </polymer-element><polymer-element name="tr-ui-u-generic-table-view"> -<template> -<style> + <template> + <style> :host { display: flex; } @@ -1873,25 +1925,26 @@ align-self: stretch; } </style> -<tr-ui-b-table id="table"></tr-ui-b-table> -</template> + <tr-ui-b-table id="table"></tr-ui-b-table> + </template> </polymer-element><polymer-element name="tr-ui-timeline-view-metadata-overlay"> -<template> -<style> + <template> + <style> :host { width: 700px; overflow: auto; } </style> -<tr-ui-u-generic-table-view id="gtv"></tr-ui-u-generic-table-view> -</template> + <tr-ui-u-generic-table-view id="gtv"></tr-ui-u-generic-table-view> + </template> + </polymer-element><polymer-element name="tr-ui-u-preferred-display-unit"> - + </polymer-element><polymer-element name="tr-ui-timeline-view"> -<template> -<style> + <template> + <style> :host { flex-direction: column; cursor: default; @@ -1956,41 +2009,45 @@ x-drag-handle { flex: 0 0 auto; } tr-ui-a-analysis-view { flex: 0 0 auto; } </style> -<tv-ui-b-hotkey-controller id="hkc"></tv-ui-b-hotkey-controller> -<div id="control"> -<div id="bar"> -<div id="left_controls"></div> -<div id="title">^_^</div> -<div id="right_controls"> -<tr-ui-b-toolbar-button id="view_metadata_button"> + + <tv-ui-b-hotkey-controller id="hkc"></tv-ui-b-hotkey-controller> + <div id="control"> + <div id="bar"> + <div id="left_controls"></div> + <div id="title">^_^</div> + <div id="right_controls"> + <tr-ui-b-toolbar-button id="view_metadata_button"> M </tr-ui-b-toolbar-button> -<tr-ui-b-dropdown id="view_options_dropdown"></tr-ui-b-dropdown> -<tr-ui-find-control id="view_find_control"></tr-ui-find-control> -<tr-ui-b-toolbar-button id="view_console_button"> - » + <tr-ui-b-dropdown id="view_options_dropdown"></tr-ui-b-dropdown> + <tr-ui-find-control id="view_find_control"></tr-ui-find-control> + <tr-ui-b-toolbar-button id="view_console_button"> + » </tr-ui-b-toolbar-button> -<tr-ui-b-toolbar-button id="view_help_button"> + <tr-ui-b-toolbar-button id="view_help_button"> ? </tr-ui-b-toolbar-button> -</div> -</div> -<div id="collapsing_controls"></div> -</div> -<middle-container> -<content></content> -<tr-ui-side-panel-container id="side_panel_container"> -</tr-ui-side-panel-container> -</middle-container> -<x-drag-handle id="drag_handle"></x-drag-handle> -<tr-ui-a-analysis-view id="analysis"></tr-ui-a-analysis-view> -<tr-ui-u-preferred-display-unit id="display_unit"> -</tr-ui-u-preferred-display-unit> -</template> - -</polymer-element><polymer-element name="tr-ui-e-s-alerts-side-panel" extends="tr-ui-side-panel"> -<template> -<style> + </div> + </div> + <div id="collapsing_controls"></div> + </div> + <middle-container> + <content></content> + + <tr-ui-side-panel-container id="side_panel_container"> + </tr-ui-side-panel-container> + </middle-container> + <x-drag-handle id="drag_handle"></x-drag-handle> + <tr-ui-a-analysis-view id="analysis"></tr-ui-a-analysis-view> + + <tr-ui-u-preferred-display-unit id="display_unit"> + </tr-ui-u-preferred-display-unit> + </template> + + +</polymer-element><polymer-element extends="tr-ui-side-panel" name="tr-ui-e-s-alerts-side-panel"> + <template> + <style> :host { display: block; width: 250px; @@ -2000,12 +2057,14 @@ display: flex; } </style> -<div id="content"> -<toolbar id="toolbar"></toolbar> -<result-area id="result_area"></result-area> -</div> -</template> + <div id="content"> + <toolbar id="toolbar"></toolbar> + <result-area id="result_area"></result-area> + </div> + </template> + + </polymer-element><script> // Copyright (c) 2014 The Chromium Authors. All rights reserved. @@ -2102,6 +2161,10 @@ function comparePossiblyUndefinedValues(x,y,cmp,opt_this){if(x!==undefined&&y!== return cmp.call(opt_this,x,y);if(x!==undefined) return-1;if(y!==undefined) return 1;return 0;} +function compareNumericWithNaNs(x,y){if(!isNaN(x)&&!isNaN(y)) +return x-y;if(isNaN(x)) +return 1;if(isNaN(y)) +return-1;return 0;} function concatenateArrays(){var values=[];for(var i=0;i<arguments.length;i++){if(!(arguments[i]instanceof Array)) throw new Error('Arguments '+i+'is not an array');values.push.apply(values,arguments[i]);} return values;} @@ -2135,7 +2198,7 @@ return undefined;return ary[i];} function findFirstKeyInDictMatching(dict,opt_func,opt_this){var func=opt_func||identity;for(var key in dict){if(func.call(opt_this,key,dict[key])) return key;} return undefined;} -return{asArray:asArray,concatenateArrays:concatenateArrays,concatenateObjects:concatenateObjects,compareArrays:compareArrays,comparePossiblyUndefinedValues:comparePossiblyUndefinedValues,dictionaryLength:dictionaryLength,dictionaryKeys:dictionaryKeys,dictionaryValues:dictionaryValues,group:group,iterItems:iterItems,mapItems:mapItems,filterItems:filterItems,iterObjectFieldsRecursively:iterObjectFieldsRecursively,identity:identity,findFirstIndexInArray:findFirstIndexInArray,findFirstInArray:findFirstInArray,findFirstKeyInDictMatching:findFirstKeyInDictMatching};});'use strict';tr.exportTo('tr.b',function(){function Range(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;};Range.prototype={__proto__:Object.prototype,reset:function(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;},get isEmpty(){return this.isEmpty_;},addRange:function(range){if(range.isEmpty) +return{asArray:asArray,concatenateArrays:concatenateArrays,concatenateObjects:concatenateObjects,compareArrays:compareArrays,comparePossiblyUndefinedValues:comparePossiblyUndefinedValues,compareNumericWithNaNs:compareNumericWithNaNs,dictionaryLength:dictionaryLength,dictionaryKeys:dictionaryKeys,dictionaryValues:dictionaryValues,group:group,iterItems:iterItems,mapItems:mapItems,filterItems:filterItems,iterObjectFieldsRecursively:iterObjectFieldsRecursively,identity:identity,findFirstIndexInArray:findFirstIndexInArray,findFirstInArray:findFirstInArray,findFirstKeyInDictMatching:findFirstKeyInDictMatching};});'use strict';tr.exportTo('tr.b',function(){function Range(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;};Range.prototype={__proto__:Object.prototype,reset:function(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;},get isEmpty(){return this.isEmpty_;},addRange:function(range){if(range.isEmpty) return;this.addValue(range.min);this.addValue(range.max);},addValue:function(value){if(this.isEmpty_){this.max_=value;this.min_=value;this.isEmpty_=false;return;} this.max_=Math.max(this.max_,value);this.min_=Math.min(this.min_,value);},set min(min){this.isEmpty_=false;this.min_=min;},get min(){if(this.isEmpty_) return undefined;return this.min_;},get max(){if(this.isEmpty_) @@ -2233,11 +2296,14 @@ function findDeepElementMatching(element,selector){return findDeepElementMatchin function findDeepElementsMatching(element,selector){return findDeepElementsMatchingPredicate(element,function(element){return element.matches(selector);});} function findDeepElementWithTextContent(element,re){return findDeepElementMatchingPredicate(element,function(element){if(element.children.length!==0) return false;return re.test(element.textContent);});} -return{iterateElementDeeply:iterateElementDeeply,findDeepElementMatching:findDeepElementMatching,findDeepElementsMatching:findDeepElementsMatching,findDeepElementMatchingPredicate:findDeepElementMatchingPredicate,findDeepElementsMatchingPredicate:findDeepElementsMatchingPredicate,findDeepElementWithTextContent:findDeepElementWithTextContent};});'use strict';tr.exportTo('tr.b.units',function(){var ms={scale:1e-3,suffix:'ms',roundedLess:function(a,b){return Math.round(a*1000)<Math.round(b*1000);},format:function(ts){return new Number(ts).toLocaleString(undefined,{minimumFractionDigits:3})+' ms';}};var ns={scale:1e-9,suffix:'ns',roundedLess:function(a,b){return Math.round(a*1000000)<Math.round(b*1000000);},format:function(ts){return new Number(ts*1000000).toLocaleString(undefined,{maximumFractionDigits:0})+' ns';}};function max(a,b){if(a===undefined) +return{iterateElementDeeply:iterateElementDeeply,findDeepElementMatching:findDeepElementMatching,findDeepElementsMatching:findDeepElementsMatching,findDeepElementMatchingPredicate:findDeepElementMatchingPredicate,findDeepElementsMatchingPredicate:findDeepElementsMatchingPredicate,findDeepElementWithTextContent:findDeepElementWithTextContent};});'use strict';tr.exportTo('tr.b.u',function(){var msDisplayMode={scale:1e-3,suffix:'ms',roundedLess:function(a,b){return Math.round(a*1000)<Math.round(b*1000);},format:function(ts){return new Number(ts).toLocaleString(undefined,{minimumFractionDigits:3})+' ms';}};var nsDisplayMode={scale:1e-9,suffix:'ns',roundedLess:function(a,b){return Math.round(a*1000000)<Math.round(b*1000000);},format:function(ts){return new Number(ts*1000000).toLocaleString(undefined,{maximumFractionDigits:0})+' ns';}};var TimeDisplayModes={ns:nsDisplayMode,ms:msDisplayMode};return{TimeDisplayModes:TimeDisplayModes};});'use strict';tr.exportTo('tr.b.u',function(){var TimeDisplayModes=tr.b.u.TimeDisplayModes;function max(a,b){if(a===undefined) return b;if(b===undefined) return a;return a.scale>b.scale?a:b;} -var Time={supportedUnits:{ms:ms,ns:ns},reset:function(){this.currentDisplayUnit=ms;},currentDisplayUnit_:ms,get currentDisplayUnit(){return this.currentDisplayUnit_;},set currentDisplayUnit(value){if(this.currentDisplayUnit_==value) -return;this.currentDisplayUnit_=value;this.dispatchEvent(new tr.b.Event('display-unit-changed'));},didPreferredUnitChange:function(){var largest=undefined;var els=tr.b.findDeepElementsMatching(document.body,'tr-ui-u-preferred-display-unit');els.forEach(function(el){largest=max(largest,el.preferredDisplayUnit);});this.currentDisplayUnit=largest===undefined?ms:largest;},timestampFromUs:function(us){return us/1000;},maybeTimestampFromUs:function(us){return us===undefined?undefined:us/1000;}};tr.b.EventTarget.decorate(Time);return{Time:Time};});'use strict';tr.exportTo('tr.b',function(){function RegisteredTypeInfo(constructor,metadata){this.constructor=constructor;this.metadata=metadata;};var BASIC_REGISTRY_MODE='BASIC_REGISTRY_MODE';var TYPE_BASED_REGISTRY_MODE='TYPE_BASED_REGISTRY_MODE';var ALL_MODES={BASIC_REGISTRY_MODE:true,TYPE_BASED_REGISTRY_MODE:true};function ExtensionRegistryOptions(mode){if(mode===undefined) +var Units={reset:function(){this.currentTimeDisplayMode=TimeDisplayModes.ms;},timestampFromUs:function(us){return us/1000;},maybeTimestampFromUs:function(us){return us===undefined?undefined:us/1000;},get currentTimeDisplayMode(){return this.currentTimeDisplayMode_;},set currentTimeDisplayMode(value){if(this.currentTimeDisplayMode_==value) +return;this.currentTimeDisplayMode_=value;this.dispatchEvent(new tr.b.Event('display-mode-changed'));},didPreferredTimeDisplayUnitChange:function(){var largest=undefined;var els=tr.b.findDeepElementsMatching(document.body,'tr-ui-u-preferred-display-unit');els.forEach(function(el){largest=max(largest,el.preferredTimeDisplayMode);});this.currentDisplayUnit=largest===undefined?TimeDisplayModes.ms:largest;},unitsByJSONName:{},fromJSON:function(object){var u=this.unitsByJSONName[object];if(u){return u;} +throw new Error('Unrecognized unit');}};tr.b.EventTarget.decorate(Units);Units.reset();Units.timeDurationInMs={asJSON:function(){return'ms';},format:function(value){return Units.currentTimeDisplayMode_.format(value);}};Units.unitsByJSONName['ms']=Units.timeDurationInMs;Units.timeStampInMs={asJSON:function(){return'tsMs';},format:function(value){return Units.currentTimeDisplayMode_.format(value);}};Units.unitsByJSONName['tsMs']=Units.timeStampInMs;Units.normalizedPercentage={asJSON:function(){return'n%';},format:function(value){var tmp=new Number(Math.round(value*100));return tmp.toLocaleString(undefined,{minimumFractionDigits:3})+'%';}};Units.unitsByJSONName['n%']=Units.normalizedPercentage;var SIZE_UNIT_PREFIXES=['','Ki','Mi','Gi','Ti'];Units.sizeInBytes={asJSON:function(){return'sizeInBytes';},format:function(value){var signPrefix='';if(value<0){signPrefix='-';value=-value;} +var i=0;while(value>=1024&&i<SIZE_UNIT_PREFIXES.length-1){value/=1024;i++;} +return signPrefix+value.toFixed(1)+' '+SIZE_UNIT_PREFIXES[i]+'B';}};Units.unitsByJSONName['sizeInBytes']=Units.sizeInBytes;Units.energyInJoules={asJSON:function(){return'J';},format:function(value){return value.toLocaleString(undefined,{minimumFractionDigits:3})+' J';}};Units.unitsByJSONName['J']=Units.energyInJoules;Units.powerInWatts={asJSON:function(){return'W';},format:function(value){return(value*1000.0).toLocaleString(undefined,{minimumFractionDigits:3})+' mW';}};Units.unitsByJSONName['W']=Units.powerInWatts;Units.unitlessNumber={asJSON:function(){return'unitless';},format:function(value){return value.toLocaleString(undefined,{minimumFractionDigits:3,maximumFractionDigits:3});}};Units.unitsByJSONName['unitless']=Units.unitlessNumber;return{Units:Units};});'use strict';tr.exportTo('tr.b',function(){function RegisteredTypeInfo(constructor,metadata){this.constructor=constructor;this.metadata=metadata;};var BASIC_REGISTRY_MODE='BASIC_REGISTRY_MODE';var TYPE_BASED_REGISTRY_MODE='TYPE_BASED_REGISTRY_MODE';var ALL_MODES={BASIC_REGISTRY_MODE:true,TYPE_BASED_REGISTRY_MODE:true};function ExtensionRegistryOptions(mode){if(mode===undefined) throw new Error('Mode is required');if(!ALL_MODES[mode]) throw new Error('Not a mode.');this.mode_=mode;this.defaultMetadata_={};this.defaultConstructor_=undefined;this.mandatoryBaseClass_=undefined;this.defaultTypeInfo_=undefined;this.frozen_=false;} ExtensionRegistryOptions.prototype={freeze:function(){if(this.frozen_) @@ -2291,7 +2357,7 @@ continue;if(this.regex_.test(key)) return true;if(this.regex_.test(obj[key])) return true;} return false;},matchSlice:function(slice){if(this.titleOrCategoryFilter_.matchSlice(slice)) -return true;return this.matchObject_(slice.args);}};return{Filter:Filter,TitleOrCategoryFilter:TitleOrCategoryFilter,ExactTitleFilter:ExactTitleFilter,FullTextFilter:FullTextFilter};});'use strict';tr.exportTo('tr.b.units',function(){function TimeStamp(timestamp){this.timestamp=timestamp;};TimeStamp.prototype={toString:function(){return TimeStamp.format(this.timestamp);}};TimeStamp.format=function(timestamp){return tr.b.units.Time.currentDisplayUnit.format(timestamp);};return{TimeStamp:TimeStamp};});'use strict';tr.exportTo('tr.ui.b',function(){function boundChannel(v){return Math.min(255,Math.max(0,Math.floor(v)));} +return true;return this.matchObject_(slice.args);}};return{Filter:Filter,TitleOrCategoryFilter:TitleOrCategoryFilter,ExactTitleFilter:ExactTitleFilter,FullTextFilter:FullTextFilter};});'use strict';tr.exportTo('tr.b.u',function(){function Scalar(value,unit){this.value=value;this.unit=unit;};Scalar.prototype={toString:function(){return this.unit.format(this.value);}};return{Scalar:Scalar};});'use strict';tr.exportTo('tr.b.u',function(){function TimeStamp(timestamp){tr.b.u.Scalar.call(this,timestamp,tr.b.u.Units.timeStampInMs);};TimeStamp.prototype={__proto__:tr.b.u.Scalar.prototype,get timestamp(){return this.value;}};TimeStamp.format=function(timestamp){return tr.b.u.Units.timeStampInMs.format(timestamp);};return{TimeStamp:TimeStamp};});'use strict';tr.exportTo('tr.ui.b',function(){function boundChannel(v){return Math.min(255,Math.max(0,Math.floor(v)));} function brightenColor(c){var k;if(c.r>=240&&c.g>=240&&c.b>=240) k=0.80;else k=1.45;return{r:boundChannel(c.r*k),g:boundChannel(c.g*k),b:boundChannel(c.b*k)};} @@ -2357,10 +2423,10 @@ SelectableItem.prototype={get modelItem(){return this.modelItem_;},get selected( return;selection.push(modelItem);},addToTrackMap:function(eventToTrackMap,track){var modelItem=this.modelItem_;if(!modelItem) return;eventToTrackMap.addEvent(modelItem,track);}};return{SelectableItem:SelectableItem};});'use strict';tr.exportTo('tr.model',function(){var SelectableItem=tr.model.SelectableItem;var SelectionState=tr.model.SelectionState;function Event(){SelectableItem.call(this,this);this.guid_=tr.b.GUID.allocate();this.selectionState=SelectionState.NONE;this.associatedAlerts=new tr.model.EventSet();this.info=undefined;} Event.prototype={__proto__:SelectableItem.prototype,get guid(){return this.guid_;},addBoundsToRange:function(range){throw new Error('Not implemented');}};return{Event:Event};});'use strict';tr.exportTo('tr.model',function(){function TimedEvent(start){tr.model.Event.call(this);this.start=start;this.duration=0;this.cpuStart=undefined;this.cpuDuration=undefined;} -TimedEvent.prototype={__proto__:tr.model.Event.prototype,get end(){return this.start+this.duration;},addBoundsToRange:function(range){range.addValue(this.start);range.addValue(this.end);},bounds:function(that,precisionUnit){if(precisionUnit===undefined){precisionUnit=tr.b.units.Time.supportedUnits.ms;} +TimedEvent.prototype={__proto__:tr.model.Event.prototype,get end(){return this.start+this.duration;},addBoundsToRange:function(range){range.addValue(this.start);range.addValue(this.end);},bounds:function(that,precisionUnit){if(precisionUnit===undefined){precisionUnit=tr.b.u.TimeDisplayModes.ms;} var startsBefore=precisionUnit.roundedLess(that.start,this.start);var endsAfter=precisionUnit.roundedLess(this.end,that.end);return!startsBefore&&!endsAfter;}};return{TimedEvent:TimedEvent};});'use strict';tr.exportTo('tr.model',function(){function Alert(info,start,opt_associatedEvents,opt_args){tr.model.TimedEvent.call(this,start);this.info=info;this.args=opt_args||{};this.associatedEvents=new tr.model.EventSet(opt_associatedEvents);this.associatedEvents.forEach(function(event){event.associatedAlerts.push(this);},this);} Alert.prototype={__proto__:tr.model.TimedEvent.prototype,get title(){return this.info.title;},get colorId(){return this.info.colorId;},get userFriendlyName(){return'Alert '+this.title+' at '+ -tr.b.units.TimeStamp.format(this.start);}};tr.model.EventRegistry.register(Alert,{name:'alert',pluralName:'alerts',singleViewElementName:'tr-ui-a-alert-sub-view',multiViewElementName:'tr-ui-a-alert-sub-view'});return{Alert:Alert};});'use strict';tr.exportTo('tr.model',function(){function EventContainer(){this.guid_=tr.b.GUID.allocate();this.important=true;this.bounds_=new tr.b.Range();} +tr.b.u.TimeStamp.format(this.start);}};tr.model.EventRegistry.register(Alert,{name:'alert',pluralName:'alerts',singleViewElementName:'tr-ui-a-alert-sub-view',multiViewElementName:'tr-ui-a-alert-sub-view'});return{Alert:Alert};});'use strict';tr.exportTo('tr.model',function(){function EventContainer(){this.guid_=tr.b.GUID.allocate();this.important=true;this.bounds_=new tr.b.Range();} EventContainer.prototype={get guid(){return this.guid_;},get stableId(){throw new Error('Not implemented');},get bounds(){return this.bounds_;},updateBounds:function(){throw new Error('Not implemented');},shiftTimestampsForward:function(amount){throw new Error('Not implemented');},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){throw new Error('Not implemented');},iterateAllChildEventContainers:function(callback,opt_this){throw new Error('Not implemented');},iterateAllEvents:function(callback,opt_this){this.iterateAllEventContainers(function(ec){ec.iterateAllEventsInThisContainer(function(eventType){return true;},callback,opt_this);});},iterateAllEventContainers:function(callback,opt_this){function visit(ec){callback.call(opt_this,ec);ec.iterateAllChildEventContainers(visit);} visit(this);}};return{EventContainer:EventContainer};});'use strict';tr.exportTo('tr.model',function(){var Event=tr.model.Event;var EventRegistry=tr.model.EventRegistry;function PowerSample(series,start,power){Event.call(this);this.series_=series;this.start_=start;this.power_=power;} PowerSample.prototype={__proto__:Event.prototype,get series(){return this.series_;},get start(){return this.start_;},set start(value){this.start_=value;},get power(){return this.power_;},set power(value){this.power_=value;},addBoundsToRange:function(range){range.addValue(this.start);}};EventRegistry.register(PowerSample,{name:'powerSample',pluralName:'powerSamples',singleViewElementName:'tr-ui-a-single-event-sub-view',multiViewElementName:'tr-ui-a-multi-power-sample-sub-view'});return{PowerSample:PowerSample};});'use strict';tr.exportTo('tr.model',function(){var PowerSample=tr.model.PowerSample;function PowerSeries(device){tr.model.EventContainer.call(this);this.device_=device;this.samples_=[];} @@ -2374,7 +2440,7 @@ this.vSyncTimestamps_[i]+=amount;},addCategoriesToDict:function(categoriesDict){ callback.call(opt_this,this.powerSeries_);}};return{Device:Device};});'use strict';tr.exportTo('tr.model',function(){function FlowEvent(category,id,title,colorId,start,args,opt_duration){tr.model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.start=start;this.args=args;this.id=id;this.startSlice=undefined;this.endSlice=undefined;this.startStackFrame=undefined;this.endStackFrame=undefined;if(opt_duration!==undefined) this.duration=opt_duration;} FlowEvent.prototype={__proto__:tr.model.TimedEvent.prototype,get userFriendlyName(){return'Flow event named '+this.title+' at '+ -tr.b.units.TimeStamp.format(this.timestamp);}};tr.model.EventRegistry.register(FlowEvent,{name:'flowEvent',pluralName:'flowEvents',singleViewElementName:'tr-ui-a-single-flow-event-sub-view',multiViewElementName:'tr-ui-a-multi-flow-event-sub-view'});return{FlowEvent:FlowEvent};});'use strict';tr.exportTo('tr.b',function(){function identity(d){return d;} +tr.b.u.TimeStamp.format(this.timestamp);}};tr.model.EventRegistry.register(FlowEvent,{name:'flowEvent',pluralName:'flowEvents',singleViewElementName:'tr-ui-a-single-flow-event-sub-view',multiViewElementName:'tr-ui-a-multi-flow-event-sub-view'});return{FlowEvent:FlowEvent};});'use strict';tr.exportTo('tr.b',function(){function identity(d){return d;} function Statistics(){} Statistics.divideIfPossibleOrZero=function(numerator,denominator){if(denominator===0) return 0;return numerator/denominator;} @@ -2405,9 +2471,7 @@ var s=Statistics.normalizeSamples(timestamps);var samples=s.normalized_samples;v return discrepancy;};Statistics.durationsDiscrepancy=function(durations,opt_absolute,opt_location_count){if(durations.length===0) return 0.0 var timestamps=durations.reduce(function(prev,curr,index,array){prev.push(prev[prev.length-1]+curr);return prev;},[0]);return Statistics.timestampsDiscrepancy(timestamps,opt_absolute,opt_location_count);} -return{Statistics:Statistics};});'use strict';tr.exportTo('tr.model',function(){var Statistics=tr.b.Statistics;var FRAME_PERF_CLASS={GOOD:'good',BAD:'bad',TERRIBLE:'terrible',NEUTRAL:'generic_work'};function Frame(associatedEvents,threadTimeRanges,opt_args){tr.model.Event.call(this);this.threadTimeRanges=threadTimeRanges;this.associatedEvents=new tr.model.EventSet(associatedEvents);this.args=opt_args||{};this.title='Frame';this.start=Statistics.min(threadTimeRanges,function(x){return x.start;});this.end=Statistics.max(threadTimeRanges,function(x){return x.end;});this.totalDuration=Statistics.sum(threadTimeRanges,function(x){return x.end-x.start;});this.perfClass=FRAME_PERF_CLASS.NEUTRAL;};Frame.prototype={__proto__:tr.model.Event.prototype,set perfClass(perfClass){this.colorId=tr.ui.b.getColorIdForReservedName(perfClass);this.perfClass_=perfClass;},get perfClass(){return this.perfClass_;},shiftTimestampsForward:function(amount){this.start+=amount;this.end+=amount;for(var i=0;i<this.threadTimeRanges.length;i++){this.threadTimeRanges[i].start+=amount;this.threadTimeRanges[i].end+=amount;}},addBoundsToRange:function(range){range.addValue(this.start);range.addValue(this.end);}};tr.model.EventRegistry.register(Frame,{name:'frame',pluralName:'frames',singleViewElementName:'tr-ui-a-single-frame-sub-view',multiViewElementName:'tr-ui-a-multi-frame-sub-view'});return{Frame:Frame,FRAME_PERF_CLASS:FRAME_PERF_CLASS};});'use strict';tr.exportTo('tr.b.units',function(){var UNIT_PREFIXES=['','Ki','Mi','Gi','Ti'];function SizeInBytes(numBytes){this.numBytes=numBytes;};SizeInBytes.prototype={toString:function(){return SizeInBytes.format(this.numBytes);}};SizeInBytes.format=function(numBytes){var signPrefix='';if(numBytes<0){signPrefix='-';numBytes=-numBytes;} -var i=0;while(numBytes>=1024&&i<UNIT_PREFIXES.length-1){numBytes/=1024;i++;} -return signPrefix+numBytes.toFixed(1)+' '+UNIT_PREFIXES[i]+'B';};return{SizeInBytes:SizeInBytes};});'use strict';tr.exportTo('tr.model',function(){function Attribute(units){this.units=units;this.infos=[];} +return{Statistics:Statistics};});'use strict';tr.exportTo('tr.model',function(){var Statistics=tr.b.Statistics;var FRAME_PERF_CLASS={GOOD:'good',BAD:'bad',TERRIBLE:'terrible',NEUTRAL:'generic_work'};function Frame(associatedEvents,threadTimeRanges,opt_args){tr.model.Event.call(this);this.threadTimeRanges=threadTimeRanges;this.associatedEvents=new tr.model.EventSet(associatedEvents);this.args=opt_args||{};this.title='Frame';this.start=Statistics.min(threadTimeRanges,function(x){return x.start;});this.end=Statistics.max(threadTimeRanges,function(x){return x.end;});this.totalDuration=Statistics.sum(threadTimeRanges,function(x){return x.end-x.start;});this.perfClass=FRAME_PERF_CLASS.NEUTRAL;};Frame.prototype={__proto__:tr.model.Event.prototype,set perfClass(perfClass){this.colorId=tr.ui.b.getColorIdForReservedName(perfClass);this.perfClass_=perfClass;},get perfClass(){return this.perfClass_;},shiftTimestampsForward:function(amount){this.start+=amount;this.end+=amount;for(var i=0;i<this.threadTimeRanges.length;i++){this.threadTimeRanges[i].start+=amount;this.threadTimeRanges[i].end+=amount;}},addBoundsToRange:function(range){range.addValue(this.start);range.addValue(this.end);}};tr.model.EventRegistry.register(Frame,{name:'frame',pluralName:'frames',singleViewElementName:'tr-ui-a-single-frame-sub-view',multiViewElementName:'tr-ui-a-multi-frame-sub-view'});return{Frame:Frame,FRAME_PERF_CLASS:FRAME_PERF_CLASS};});'use strict';tr.exportTo('tr.model',function(){function Attribute(units){this.units=units;this.infos=[];} Attribute.fromDictIfPossible=function(dict,opt_model){var typeInfo=Attribute.findTypeInfoMatching(function(typeInfo){return typeInfo.metadata.type===dict.type;});if(typeInfo===undefined){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Unknown attribute type \''+dict.type+'\'.'});} return UnknownAttribute.fromDict(dict,opt_model);} return typeInfo.constructor.fromDict(dict,opt_model);};Attribute.findCommonTraits=function(attributes,opt_model){var commonTraits;for(var i=0;i<attributes.length;i++){var attribute=attributes[i];if(attribute===undefined) @@ -2443,13 +2507,13 @@ return 0;return attr.value;} function hasSize(dump){return dump.attributes[SIZE_ATTRIBUTE_NAME]!==undefined;} function optional(value,defaultValue){if(value===undefined) return defaultValue;return value;} -function ownershipToUserFriendlyString(dump,importance){return dump.quantifiedName+' (sharing importance '+ +function ownershipToUserFriendlyString(dump,importance){return dump.quantifiedName+' (importance: '+ optional(importance,0)+')';} -GlobalMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get userFriendlyName(){return'Global memory dump at '+tr.b.units.TimeStamp.format(this.start);},get containerName(){return'global space';},calculateGraphAttributes:function(){this.calculateSizes();this.calculateEffectiveSizes();this.aggregateAttributes();this.discountTracingOverhead();},calculateSizes:function(){this.traverseAllocatorDumpsInDepthFirstPostOrder(this.calculateMemoryAllocatorDumpSize_.bind(this));},calculateMemoryAllocatorDumpSize_:function(dump){var shouldDefineSize=false;function getDependencySize(dependencyDump){var attr=dependencyDump.attributes[SIZE_ATTRIBUTE_NAME];if(attr===undefined) +GlobalMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get userFriendlyName(){return'Global memory dump at '+tr.b.u.TimeStamp.format(this.start);},get containerName(){return'global space';},calculateGraphAttributes:function(){this.calculateSizes();this.calculateEffectiveSizes();this.aggregateAttributes();this.discountTracingOverhead();},calculateSizes:function(){this.traverseAllocatorDumpsInDepthFirstPostOrder(this.calculateMemoryAllocatorDumpSize_.bind(this));},calculateMemoryAllocatorDumpSize_:function(dump){var shouldDefineSize=false;function getDependencySize(dependencyDump){var attr=dependencyDump.attributes[SIZE_ATTRIBUTE_NAME];if(attr===undefined) return 0;shouldDefineSize=true;return attr.value;} var sizeAttribute=dump.getValidSizeAttributeOrUndefined(SIZE_ATTRIBUTE_NAME,this.model);var size=0;var infos=[];var checkDependentSizeIsConsistent=function(){};if(sizeAttribute!==undefined){size=sizeAttribute.value;shouldDefineSize=true;checkDependentSizeIsConsistent=function(dependentSize,dependentName){if(size>=dependentSize) -return;var messageSuffix=' ('+tr.b.units.SizeInBytes.format(size)+') is less than '+dependentName+' ('+ -tr.b.units.SizeInBytes.format(dependentSize)+').';this.model.importWarning({type:'memory_dump_parse_error',message:'Size provided by memory allocator dump \''+ +return;var messageSuffix=' ('+tr.b.u.Units.sizeInBytes.format(size)+') is less than '+dependentName+' ('+ +tr.b.u.Units.sizeInBytes.format(dependentSize)+').';this.model.importWarning({type:'memory_dump_parse_error',message:'Size provided by memory allocator dump \''+ dump.fullName+'\''+messageSuffix});infos.push(new tr.model.AttributeInfo(tr.model.AttributeInfoType.WARNING,'Size provided by this memory allocator dump'+messageSuffix));}.bind(this);} var aggregatedChildrenSize=0;var allOverlaps={};dump.children.forEach(function(childDump){function aggregateDescendantDump(descendantDump){var ownedDumpLink=descendantDump.owns;if(ownedDumpLink!==undefined&&ownedDumpLink.target.isDescendantOf(dump)){var ownedDescendantDump=ownedDumpLink.target;var ownedChildDump=ownedDescendantDump;while(ownedChildDump.parent!==dump) ownedChildDump=ownedChildDump.parent;if(childDump!==ownedChildDump){var overlap=getDependencySize(descendantDump);if(overlap>0){var ownedChildOverlaps=allOverlaps[ownedChildDump.name];if(ownedChildOverlaps===undefined) @@ -2458,9 +2522,8 @@ return;} if(descendantDump.children.length===0){aggregatedChildrenSize+=getDependencySize(descendantDump);return;} descendantDump.children.forEach(aggregateDescendantDump);} aggregateDescendantDump(childDump);});dump.children.forEach(function(childDump){var childOverlaps=allOverlaps[childDump.name];if(childOverlaps===undefined) -return;var message=tr.b.dictionaryValues(tr.b.mapItems(childOverlaps,function(ownerChildName,overlap){return'This memory allocator dump overlaps with its sibling \''+ -ownerChildName+'\' ('+ -tr.b.units.SizeInBytes.format(overlap)+').';})).join(' ');childDump.attributes[SIZE_ATTRIBUTE_NAME].infos.push(new tr.model.AttributeInfo(tr.model.AttributeInfoType.INFORMATION,message));});checkDependentSizeIsConsistent(aggregatedChildrenSize,'the aggregated size of its children');var largestOwnerSize=0;dump.ownedBy.forEach(function(ownershipLink){var owner=ownershipLink.source;var ownerSize=getDependencySize(owner);largestOwnerSize=Math.max(largestOwnerSize,ownerSize);});checkDependentSizeIsConsistent(largestOwnerSize,'the size of its largest owner');if(!shouldDefineSize){dump.attributes[SIZE_ATTRIBUTE_NAME]=undefined;return;} +return;var message=tr.b.dictionaryValues(tr.b.mapItems(childOverlaps,function(ownerChildName,overlap){return'overlaps with its sibling \''+ownerChildName+'\' ('+ +tr.b.u.Units.sizeInBytes.format(overlap)+')';})).join(' ');childDump.attributes[SIZE_ATTRIBUTE_NAME].infos.push(new tr.model.AttributeInfo(tr.model.AttributeInfoType.INFORMATION,message));});checkDependentSizeIsConsistent(aggregatedChildrenSize,'the aggregated size of its children');var largestOwnerSize=0;dump.ownedBy.forEach(function(ownershipLink){var owner=ownershipLink.source;var ownerSize=getDependencySize(owner);largestOwnerSize=Math.max(largestOwnerSize,ownerSize);});checkDependentSizeIsConsistent(largestOwnerSize,'the size of its largest owner');if(!shouldDefineSize){dump.attributes[SIZE_ATTRIBUTE_NAME]=undefined;return;} size=Math.max(size,aggregatedChildrenSize,largestOwnerSize);var sizeAttribute=new tr.model.ScalarAttribute('bytes',size);sizeAttribute.infos=infos;dump.attributes[SIZE_ATTRIBUTE_NAME]=sizeAttribute;if(aggregatedChildrenSize<size&&dump.children!==undefined&&dump.children.length>0){var virtualChild=new tr.model.MemoryAllocatorDump(dump.containerMemoryDump,dump.fullName+'/<unspecified>');virtualChild.parent=dump;dump.children.unshift(virtualChild);virtualChild.attributes[SIZE_ATTRIBUTE_NAME]=new tr.model.ScalarAttribute('bytes',size-aggregatedChildrenSize);}},calculateEffectiveSizes:function(){this.traverseAllocatorDumpsInDepthFirstPostOrder(this.calculateDumpSubSizes_.bind(this));this.traverseAllocatorDumpsInDepthFirstPostOrder(this.calculateDumpOwnershipCoefficient_.bind(this));this.traverseAllocatorDumpsInDepthFirstPreOrder(this.calculateDumpCumulativeOwnershipCoefficient_.bind(this));this.traverseAllocatorDumpsInDepthFirstPostOrder(this.calculateDumpEffectiveSize_.bind(this));},calculateDumpSubSizes_:function(dump){if(!hasSize(dump)) return;if(dump.children===undefined||dump.children.length===0){var size=getSize(dump);dump.notOwningSubSize_=size;dump.notOwnedSubSize_=size;return;} var notOwningSubSize=0;dump.children.forEach(function(childDump){if(childDump.owns!==undefined) @@ -2480,10 +2543,11 @@ cumulativeOwnedCoefficient*=dump.parent.cumulativeOwnedCoefficient_;dump.cumulat dump.cumulativeOwningCoefficient_=cumulativeOwningCoefficient;},calculateDumpEffectiveSize_:function(dump){if(!hasSize(dump)){dump.attributes[EFFECTIVE_SIZE_ATTRIBUTE_NAME]=undefined;return;} var effectiveSize;if(dump.children===undefined||dump.children.length===0){effectiveSize=getSize(dump)*dump.cumulativeOwningCoefficient_*dump.cumulativeOwnedCoefficient_;}else{effectiveSize=0;dump.children.forEach(function(childDump){if(!hasSize(childDump)) return;effectiveSize+=childDump.attributes[EFFECTIVE_SIZE_ATTRIBUTE_NAME].value;});} -var attribute=new tr.model.ScalarAttribute('bytes',effectiveSize);dump.attributes[EFFECTIVE_SIZE_ATTRIBUTE_NAME]=attribute;if(dump.ownedBy.length>0){var message='This memory allocator dump is shared by '+ -dump.ownedBy.map(function(ownershipLink){return ownershipToUserFriendlyString(ownershipLink.source,ownershipLink.importance);}).join(', ')+'.';attribute.infos.push(new tr.model.AttributeInfo(tr.model.AttributeInfoType.MEMORY_OWNED,message));} -if(dump.owns!==undefined){var message='This memory allocator dump shares '+ -ownershipToUserFriendlyString(dump.owns.target,dump.owns.importance)+'.';attribute.infos.push(new tr.model.AttributeInfo(tr.model.AttributeInfoType.MEMORY_OWNER,message));}},aggregateAttributes:function(){this.iterateRootAllocatorDumps(function(dump){dump.aggregateAttributes(this.model);});},discountTracingOverhead:function(){tr.b.iterItems(this.processMemoryDumps,function(pid,dump){dump.discountTracingOverhead(this.model);},this);},iterateContainerDumps:function(fn){fn.call(this,this);tr.b.iterItems(this.processMemoryDumps,function(pid,processDump){fn.call(this,processDump);},this);},iterateRootAllocatorDumps:function(fn){this.iterateContainerDumps(function(containerDump){var memoryAllocatorDumps=containerDump.memoryAllocatorDumps;if(memoryAllocatorDumps===undefined) +var attribute=new tr.model.ScalarAttribute('bytes',effectiveSize);dump.attributes[EFFECTIVE_SIZE_ATTRIBUTE_NAME]=attribute;if(dump.ownedBy.length>0){var message='shared by:'+ +dump.ownedBy.map(function(ownershipLink){return'\n - '+ownershipToUserFriendlyString(ownershipLink.source,ownershipLink.importance);}).join();attribute.infos.push(new tr.model.AttributeInfo(tr.model.AttributeInfoType.MEMORY_OWNED,message));} +if(dump.owns!==undefined){var target=dump.owns.target;var message='shares '+ +ownershipToUserFriendlyString(target,dump.owns.importance)+' with';var otherOwnershipLinks=target.ownedBy.filter(function(ownershipLink){return ownershipLink.source!==dump;});if(otherOwnershipLinks.length>0){message+=':';message+=otherOwnershipLinks.map(function(ownershipLink){return'\n - '+ownershipToUserFriendlyString(ownershipLink.source,ownershipLink.importance);}).join();}else{message+=' no other dumps';} +attribute.infos.push(new tr.model.AttributeInfo(tr.model.AttributeInfoType.MEMORY_OWNER,message));}},aggregateAttributes:function(){this.iterateRootAllocatorDumps(function(dump){dump.aggregateAttributes(this.model);});},discountTracingOverhead:function(){tr.b.iterItems(this.processMemoryDumps,function(pid,dump){dump.discountTracingOverhead(this.model);},this);},iterateContainerDumps:function(fn){fn.call(this,this);tr.b.iterItems(this.processMemoryDumps,function(pid,processDump){fn.call(this,processDump);},this);},iterateRootAllocatorDumps:function(fn){this.iterateContainerDumps(function(containerDump){var memoryAllocatorDumps=containerDump.memoryAllocatorDumps;if(memoryAllocatorDumps===undefined) return;memoryAllocatorDumps.forEach(fn,this);});},traverseAllocatorDumpsInDepthFirstPostOrder:function(fn){var visitedDumps=new WeakSet();var openDumps=new WeakSet();function visit(dump){if(visitedDumps.has(dump)) return;if(openDumps.has(dump)) throw new Error(dump.userFriendlyName+' contains a cycle');openDumps.add(dump);dump.ownedBy.forEach(function(ownershipLink){visit.call(this,ownershipLink.source);},this);dump.children.forEach(visit,this);fn.call(this,dump);visitedDumps.add(dump);openDumps.delete(dump);} @@ -2492,10 +2556,10 @@ return;if(dump.owns!==undefined&&!visitedDumps.has(dump.owns.target)) return;if(dump.parent!==undefined&&!visitedDumps.has(dump.parent)) return;fn.call(this,dump);visitedDumps.add(dump);dump.ownedBy.forEach(function(ownershipLink){visit.call(this,ownershipLink.source);},this);dump.children.forEach(visit,this);} this.iterateRootAllocatorDumps(visit);}};tr.model.EventRegistry.register(GlobalMemoryDump,{name:'globalMemoryDump',pluralName:'globalMemoryDumps',singleViewElementName:'tr-ui-a-single-global-memory-dump-sub-view',multiViewElementName:'tr-ui-a-multi-global-memory-dump-sub-view'});return{GlobalMemoryDump:GlobalMemoryDump};});'use strict';tr.exportTo('tr.model',function(){var InstantEventType={GLOBAL:1,PROCESS:2};function InstantEvent(category,title,colorId,start,args){tr.model.TimedEvent.call(this);this.category=category||'';this.title=title;this.colorId=colorId;this.start=start;this.args=args;this.type=undefined;};InstantEvent.prototype={__proto__:tr.model.TimedEvent.prototype};function GlobalInstantEvent(category,title,colorId,start,args){InstantEvent.apply(this,arguments);this.type=InstantEventType.GLOBAL;};GlobalInstantEvent.prototype={__proto__:InstantEvent.prototype,get userFriendlyName(){return'Global instant event '+this.title+' @ '+ -tr.b.units.TimeStamp.format(start);}};function ProcessInstantEvent(category,title,colorId,start,args){InstantEvent.apply(this,arguments);this.type=InstantEventType.PROCESS;};ProcessInstantEvent.prototype={__proto__:InstantEvent.prototype,get userFriendlyName(){return'Process-level instant event '+this.title+' @ '+ -tr.b.units.TimeStamp.format(start);}};tr.model.EventRegistry.register(InstantEvent,{name:'instantEvent',pluralName:'instantEvents',singleViewElementName:'tr-ui-a-single-instant-event-sub-view',multiViewElementName:'tr-ui-a-multi-instant-event-sub-view'});return{GlobalInstantEvent:GlobalInstantEvent,ProcessInstantEvent:ProcessInstantEvent,InstantEventType:InstantEventType,InstantEvent:InstantEvent};});'use strict';tr.exportTo('tr.model',function(){var CompoundEventSelectionState={NOT_SELECTED:0,EVENT_SELECTED:0x1,SOME_ASSOCIATED_EVENTS_SELECTED:0x2,ALL_ASSOCIATED_EVENTS_SELECTED:0x4,EVENT_AND_SOME_ASSOCIATED_SELECTED:0x1|0x2,EVENT_AND_ALL_ASSOCIATED_SELECTED:0x1|0x4};return{CompoundEventSelectionState:CompoundEventSelectionState};});'use strict';tr.exportTo('tr.model',function(){var CompoundEventSelectionState=tr.model.CompoundEventSelectionState;function InteractionRecord(title,colorId,start,duration){tr.model.TimedEvent.call(this,start);this.title=title;this.colorId=colorId;this.duration=duration;this.args={};this.associatedEvents=new tr.model.EventSet();this.sourceEvents=new tr.model.EventSet();} +tr.b.u.TimeStamp.format(start);}};function ProcessInstantEvent(category,title,colorId,start,args){InstantEvent.apply(this,arguments);this.type=InstantEventType.PROCESS;};ProcessInstantEvent.prototype={__proto__:InstantEvent.prototype,get userFriendlyName(){return'Process-level instant event '+this.title+' @ '+ +tr.b.u.TimeStamp.format(start);}};tr.model.EventRegistry.register(InstantEvent,{name:'instantEvent',pluralName:'instantEvents',singleViewElementName:'tr-ui-a-single-instant-event-sub-view',multiViewElementName:'tr-ui-a-multi-instant-event-sub-view'});return{GlobalInstantEvent:GlobalInstantEvent,ProcessInstantEvent:ProcessInstantEvent,InstantEventType:InstantEventType,InstantEvent:InstantEvent};});'use strict';tr.exportTo('tr.model',function(){var CompoundEventSelectionState={NOT_SELECTED:0,EVENT_SELECTED:0x1,SOME_ASSOCIATED_EVENTS_SELECTED:0x2,ALL_ASSOCIATED_EVENTS_SELECTED:0x4,EVENT_AND_SOME_ASSOCIATED_SELECTED:0x1|0x2,EVENT_AND_ALL_ASSOCIATED_SELECTED:0x1|0x4};return{CompoundEventSelectionState:CompoundEventSelectionState};});'use strict';tr.exportTo('tr.model',function(){var CompoundEventSelectionState=tr.model.CompoundEventSelectionState;function InteractionRecord(title,colorId,start,duration){tr.model.TimedEvent.call(this,start);this.title=title;this.colorId=colorId;this.duration=duration;this.args={};this.associatedEvents=new tr.model.EventSet();this.sourceEvents=new tr.model.EventSet();} InteractionRecord.prototype={__proto__:tr.model.TimedEvent.prototype,get subSlices(){return[];},get userFriendlyName(){return this.title+' interaction at '+ -tr.b.units.TimeStamp.format(this.start);},computeCompoundEvenSelectionState:function(selection){var cess=CompoundEventSelectionState.NOT_SELECTED;if(selection.contains(this)) +tr.b.u.TimeStamp.format(this.start);},computeCompoundEvenSelectionState:function(selection){var cess=CompoundEventSelectionState.NOT_SELECTED;if(selection.contains(this)) cess|=CompoundEventSelectionState.EVENT_SELECTED;if(this.associatedEvents.intersectionIsEmpty(selection)) return cess;var allContained=this.associatedEvents.every(function(event){return selection.contains(event);});if(allContained) cess|=CompoundEventSelectionState.ALL_ASSOCIATED_EVENTS_SELECTED;else @@ -2528,7 +2592,7 @@ return{findLowIndexInSortedArray:findLowIndexInSortedArray,findIndexInSortedInte CounterSample.groupByTimestamp=function(samples){var samplesByTimestamp=tr.b.group(samples,function(sample){return sample.timestamp;});var timestamps=tr.b.dictionaryKeys(samplesByTimestamp);timestamps.sort();var groups=[];for(var i=0;i<timestamps.length;i++){var ts=timestamps[i];var group=samplesByTimestamp[ts];group.sort(function(x,y){return x.series.seriesIndex-y.series.seriesIndex;});groups.push(group);} return groups;} CounterSample.prototype={__proto__:tr.model.Event.prototype,get series(){return this.series_;},get timestamp(){return this.timestamp_;},get value(){return this.value_;},set timestamp(timestamp){this.timestamp_=timestamp;},addBoundsToRange:function(range){range.addValue(this.timestamp);},getSampleIndex:function(){return tr.b.findLowIndexInSortedArray(this.series.timestamps,function(x){return x;},this.timestamp_);},get userFriendlyName(){return'Counter sample from '+this.series_.title+' at '+ -tr.b.units.TimeStamp.format(this.timestamp);}};tr.model.EventRegistry.register(CounterSample,{name:'counterSample',pluralName:'counterSamples',singleViewElementName:'tr-ui-a-counter-sample-sub-view',multiViewElementName:'tr-ui-a-counter-sample-sub-view'});return{CounterSample:CounterSample};});'use strict';tr.exportTo('tr.model',function(){var CounterSample=tr.model.CounterSample;function CounterSeries(name,color){tr.model.EventContainer.call(this);this.name_=name;this.color_=color;this.timestamps_=[];this.samples_=[];this.counter=undefined;this.seriesIndex=undefined;} +tr.b.u.TimeStamp.format(this.timestamp);}};tr.model.EventRegistry.register(CounterSample,{name:'counterSample',pluralName:'counterSamples',singleViewElementName:'tr-ui-a-counter-sample-sub-view',multiViewElementName:'tr-ui-a-counter-sample-sub-view'});return{CounterSample:CounterSample};});'use strict';tr.exportTo('tr.model',function(){var CounterSample=tr.model.CounterSample;function CounterSeries(name,color){tr.model.EventContainer.call(this);this.name_=name;this.color_=color;this.timestamps_=[];this.samples_=[];this.counter=undefined;this.seriesIndex=undefined;} CounterSeries.prototype={__proto__:tr.model.EventContainer.prototype,get length(){return this.timestamps_.length;},get name(){return this.name_;},get color(){return this.color_;},get samples(){return this.samples_;},get timestamps(){return this.timestamps_;},getSample:function(idx){return this.samples_[idx];},getTimestamp:function(idx){return this.timestamps_[idx];},addCounterSample:function(ts,val){var sample=new CounterSample(this,ts,val);this.addSample(sample);return sample;},addSample:function(sample){this.timestamps_.push(sample.timestamp);this.samples_.push(sample);},getStatistics:function(sampleIndices){var sum=0;var min=Number.MAX_VALUE;var max=-Number.MAX_VALUE;for(var i=0;i<sampleIndices.length;++i){var sample=this.getSample(sampleIndices[i]).value;sum+=sample;min=Math.min(sample,min);max=Math.max(sample,max);} return{min:min,max:max,avg:(sum/sampleIndices.length),start:this.getSample(sampleIndices[0]).value,end:this.getSample(sampleIndices.length-1).value};},shiftTimestampsForward:function(amount){for(var i=0;i<this.timestamps_.length;++i){this.timestamps_[i]+=amount;this.samples_[i].timestamp=this.timestamps_[i];}},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(eventTypePredicate.call(opt_this,tr.model.CounterSample)){this.samples_.forEach(callback,opt_this);}},iterateAllChildEventContainers:function(callback,opt_this){}};return{CounterSeries:CounterSeries};});'use strict';tr.exportTo('tr.model',function(){function Counter(parent,id,category,name){tr.model.EventContainer.call(this);this.parent_=parent;this.id_=id;this.category_=category||'';this.name_=name;this.series_=[];this.totals=[];} Counter.prototype={__proto__:tr.model.EventContainer.prototype,get parent(){return this.parent_;},get id(){return this.id_;},get category(){return this.category_;},get name(){return this.name_;},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){},iterateAllChildEventContainers:function(callback,opt_this){for(var i=0;i<this.series_.length;i++) @@ -2544,7 +2608,7 @@ this.cpuStart=opt_cpuStart;if(opt_cpuDuration!==undefined) this.cpuDuration=opt_cpuDuration;if(opt_argsStripped!==undefined) this.argsStripped=true;} Slice.prototype={__proto__:tr.model.TimedEvent.prototype,get analysisTypeName(){return this.title;},get userFriendlyName(){return'Slice '+this.title+' at '+ -tr.b.units.TimeStamp.format(this.start);},findDescendentSlice:function(targetTitle){if(!this.subSlices) +tr.b.u.TimeStamp.format(this.start);},findDescendentSlice:function(targetTitle){if(!this.subSlices) return undefined;for(var i=0;i<this.subSlices.length;i++){if(this.subSlices[i].title==targetTitle) return this.subSlices[i];var slice=this.subSlices[i].findDescendentSlice(targetTitle);if(slice)return slice;} return undefined;},get mostTopLevelSlice(){var curSlice=this;while(curSlice.parentSlice) @@ -2592,7 +2656,7 @@ return stats;}};Cpu.compare=function(x,y){return x.cpuNumber-y.cpuNumber;};retur ObjectSnapshot.prototype={__proto__:tr.model.Event.prototype,preInitialize:function(){},initialize:function(){},addBoundsToRange:function(range){range.addValue(this.ts);},get userFriendlyName(){return'Snapshot of '+ this.objectInstance.typeName+' '+ this.objectInstance.id+' @ '+ -tr.b.units.TimeStamp.format(this.ts);}};tr.model.EventRegistry.register(ObjectSnapshot,{name:'objectSnapshot',pluralName:'objectSnapshots',singleViewElementName:'tr-ui-a-single-object-snapshot-sub-view',multiViewElementName:'tr-ui-a-multi-object-sub-view'});var options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectSnapshot;options.defaultConstructor=ObjectSnapshot;tr.b.decorateExtensionRegistry(ObjectSnapshot,options);return{ObjectSnapshot:ObjectSnapshot};});'use strict';tr.exportTo('tr.model',function(){var ObjectSnapshot=tr.model.ObjectSnapshot;function ObjectInstance(parent,id,category,name,creationTs,opt_baseTypeName){tr.model.Event.call(this);this.parent=parent;this.id=id;this.category=category;this.baseTypeName=opt_baseTypeName?opt_baseTypeName:name;this.name=name;this.creationTs=creationTs;this.creationTsWasExplicit=false;this.deletionTs=Number.MAX_VALUE;this.deletionTsWasExplicit=false;this.colorId=0;this.bounds=new tr.b.Range();this.snapshots=[];this.hasImplicitSnapshots=false;} +tr.b.u.TimeStamp.format(this.ts);}};tr.model.EventRegistry.register(ObjectSnapshot,{name:'objectSnapshot',pluralName:'objectSnapshots',singleViewElementName:'tr-ui-a-single-object-snapshot-sub-view',multiViewElementName:'tr-ui-a-multi-object-sub-view'});var options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectSnapshot;options.defaultConstructor=ObjectSnapshot;tr.b.decorateExtensionRegistry(ObjectSnapshot,options);return{ObjectSnapshot:ObjectSnapshot};});'use strict';tr.exportTo('tr.model',function(){var ObjectSnapshot=tr.model.ObjectSnapshot;function ObjectInstance(parent,id,category,name,creationTs,opt_baseTypeName){tr.model.Event.call(this);this.parent=parent;this.id=id;this.category=category;this.baseTypeName=opt_baseTypeName?opt_baseTypeName:name;this.name=name;this.creationTs=creationTs;this.creationTsWasExplicit=false;this.deletionTs=Number.MAX_VALUE;this.deletionTsWasExplicit=false;this.colorId=0;this.bounds=new tr.b.Range();this.snapshots=[];this.hasImplicitSnapshots=false;} ObjectInstance.prototype={__proto__:tr.model.Event.prototype,get typeName(){return this.name;},addBoundsToRange:function(range){range.addRange(this.bounds);},addSnapshot:function(ts,args,opt_name,opt_baseTypeName){if(ts<this.creationTs) throw new Error('Snapshots must be >= instance.creationTs');if(ts>=this.deletionTs) throw new Error('Snapshots cannot be added after '+'an objects deletion timestamp.');var lastSnapshot;if(this.snapshots.length>0){lastSnapshot=this.snapshots[this.snapshots.length-1];if(lastSnapshot.ts==ts) @@ -2662,7 +2726,7 @@ return undefined;return instance.getSnapshotAt(ts);},iterObjectInstances:functio this.cpuStart=opt_cpuStart;if(opt_cpuDuration!==undefined) this.cpuDuration=opt_cpuDuration;if(opt_argsStripped!==undefined) this.argsStripped=opt_argsStripped;};AsyncSlice.prototype={__proto__:tr.model.TimedEvent.prototype,get analysisTypeName(){return this.title;},get viewSubGroupTitle(){return this.title;},get userFriendlyName(){return'Async slice '+this.title+' at '+ -tr.b.units.TimeStamp.format(this.start);},findDescendentSlice:function(targetTitle){if(!this.subSlices) +tr.b.u.TimeStamp.format(this.start);},findDescendentSlice:function(targetTitle){if(!this.subSlices) return undefined;for(var i=0;i<this.subSlices.length;i++){if(this.subSlices[i].title==targetTitle) return this.subSlices[i];var slice=this.subSlices[i].findDescendentSlice(targetTitle);if(slice)return slice;} return undefined;},iterateAllDescendents:function(callback,opt_this){this.subSlices.forEach(callback,opt_this);this.subSlices.forEach(function(subSlice){subSlice.iterateAllDescendents(callback,opt_this);},opt_this);},compareTo:function(that){return this.title.localeCompare(that.title);}};tr.model.EventRegistry.register(AsyncSlice,{name:'asyncSlice',pluralName:'asyncSlices',singleViewElementName:'tr-ui-a-single-async-slice-sub-view',multiViewElementName:'tr-ui-a-multi-async-slice-sub-view'});var options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=AsyncSlice;options.defaultConstructor=AsyncSlice;tr.b.decorateExtensionRegistry(AsyncSlice,options);return{AsyncSlice:AsyncSlice};});'use strict';tr.exportTo('tr.model',function(){function AsyncSliceGroup(parentContainer,opt_name){tr.model.EventContainer.call(this);this.parentContainer_=parentContainer;this.slices=[];this.name_=opt_name;this.viewSubGroups_=undefined;} @@ -2793,15 +2857,20 @@ this.flowEventsById_[fe.id].push(fe);}},this);} ModelIndices.prototype={addEventWithId:function(id,event){if(!this.flowEventsById_.hasOwnProperty(id)){this.flowEventsById_[id]=new Array();} this.flowEventsById_[id].push(event);},getFlowEventsWithId:function(id){if(!this.flowEventsById_.hasOwnProperty(id)) return[];return this.flowEventsById_[id];}};return{ModelIndices:ModelIndices};});'use strict';tr.exportTo('tr.model',function(){var DISCOUNTED_ALLOCATOR_NAMES=['winheap','malloc'];function ProcessMemoryDump(globalMemoryDump,process,start){tr.model.ContainerMemoryDump.call(this,start);this.process=process;this.globalMemoryDump=globalMemoryDump;this.totalResidentBytes=undefined;this.vmRegions_=undefined;this.tracingMemoryDiscounted_=false;};ProcessMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get userFriendlyName(){return'Process memory dump at '+ -tr.b.units.TimeStamp.format(this.start);},get containerName(){return this.process.userFriendlyName;},get vmRegions(){throw new Error('VM regions must be accessed through the mostRecentVmRegions field');},set vmRegions(vmRegions){this.vmRegions_=vmRegions;},get hasOwnVmRegions(){return this.vmRegions_!==undefined;},getMostRecentTotalVmRegionStat:function(statName){if(this.mostRecentVmRegions===undefined) +tr.b.u.TimeStamp.format(this.start);},get containerName(){return this.process.userFriendlyName;},get vmRegions(){throw new Error('VM regions must be accessed through the mostRecentVmRegions field');},set vmRegions(vmRegions){this.vmRegions_=vmRegions;},get hasOwnVmRegions(){return this.vmRegions_!==undefined;},getMostRecentTotalVmRegionStat:function(statName){if(this.mostRecentVmRegions===undefined) return undefined;var total=0;this.mostRecentVmRegions.forEach(function(vmRegion){var statValue=vmRegion.byteStats[statName];if(statValue===undefined) return;total+=statValue;});return total;},discountTracingOverhead:function(opt_model){if(this.tracingMemoryDiscounted_) return;this.tracingMemoryDiscounted_=true;var tracingDump=this.getMemoryAllocatorDumpByFullName('tracing');if(tracingDump===undefined) -return;var tracingResidentSizeAttr=tracingDump.getValidSizeAttributeOrUndefined('resident_size',opt_model);if(tracingResidentSizeAttr!==undefined){var tracingResidentSize=tracingResidentSizeAttr.value;if(this.totalResidentBytes!==undefined) -this.totalResidentBytes-=tracingResidentSize;if(this.vmRegions_!==undefined){this.vmRegions_.push(VMRegion.fromDict({mappedFile:'[discounted tracing overhead]',byteStats:{privateDirtyResident:-tracingResidentSize,proportionalResident:-tracingResidentSize}}));}} -var tracingSizeAttr=tracingDump.getValidSizeAttributeOrUndefined('size',opt_model);if(tracingSizeAttr!==undefined){var tracingSize=tracingSizeAttr.value;var hasDiscountedFromAllocatorDumps=DISCOUNTED_ALLOCATOR_NAMES.some(function(allocatorName){var dump=this.getMemoryAllocatorDumpByFullName(allocatorName);if(dump===undefined) -return false;var overheadSizeAttribute=new tr.model.ScalarAttribute('bytes',-tracingSize);var overheadDump=new tr.model.MemoryAllocatorDump(this,allocatorName+'/discounted_tracing_overhead');overheadDump.parent=dump;overheadDump.addAttribute('size',overheadSizeAttribute);dump.children.push(overheadDump);var dumpSizeAttr=dump.getValidSizeAttributeOrUndefined('size',opt_model);if(dumpSizeAttr!==undefined) -dumpSizeAttr.value-=tracingSize;return true;},this);if(hasDiscountedFromAllocatorDumps) +return;function getDiscountedSize(sizeAttrName){var sizeAttr=tracingDump.getValidSizeAttributeOrUndefined(sizeAttrName,opt_model);if(sizeAttr===undefined) +return 0;return sizeAttr.value;} +var discountedSize=getDiscountedSize('size');var discountedEffectiveSize=getDiscountedSize('effective_size');var discountedResidentSize=getDiscountedSize('resident_size');if(discountedResidentSize>0){if(this.totalResidentBytes!==undefined) +this.totalResidentBytes-=discountedResidentSize;if(this.vmRegions_!==undefined){this.vmRegions_.push(VMRegion.fromDict({mappedFile:'[discounted tracing overhead]',byteStats:{privateDirtyResident:-discountedResidentSize,proportionalResident:-discountedResidentSize}}));}} +if(discountedSize>0||discountedEffectiveSize>0){function discountSizeAndEffectiveSize(dump){var dumpSizeAttr=dump.getValidSizeAttributeOrUndefined('size',opt_model);if(dumpSizeAttr!==undefined) +dumpSizeAttr.value-=discountedSize;var dumpEffectiveSizeAttr=dump.getValidSizeAttributeOrUndefined('effective_size',opt_model);if(dumpEffectiveSizeAttr!==undefined) +dumpEffectiveSizeAttr.value-=discountedEffectiveSize;} +var hasDiscountedFromAllocatorDumps=DISCOUNTED_ALLOCATOR_NAMES.some(function(allocatorName){var allocatorDump=this.getMemoryAllocatorDumpByFullName(allocatorName);if(allocatorDump===undefined) +return false;discountSizeAndEffectiveSize(allocatorDump);var allocatedObjectsDumpName=allocatorName+'/allocated_objects';var allocatedObjectsDump=this.getMemoryAllocatorDumpByFullName(allocatedObjectsDumpName);if(allocatedObjectsDump===undefined) +return true;discountSizeAndEffectiveSize(allocatedObjectsDump);var discountDumpName=allocatedObjectsDumpName+'/discounted_tracing_overhead';var discountDump=new tr.model.MemoryAllocatorDump(this,discountDumpName);discountDump.parent=allocatedObjectsDump;discountDump.addAttribute('size',new tr.model.ScalarAttribute('bytes',-discountedSize));discountDump.addAttribute('effective_size',new tr.model.ScalarAttribute('bytes',-discountedEffectiveSize));allocatedObjectsDump.children.push(discountDump);return true;},this);if(hasDiscountedFromAllocatorDumps) this.memoryAllocatorDumps=this.memoryAllocatorDumps;}}};ProcessMemoryDump.hookUpMostRecentVmRegionsLinks=function(processDumps){var mostRecentVmRegions=undefined;processDumps.forEach(function(processDump){if(processDump.vmRegions_!==undefined) mostRecentVmRegions=processDump.vmRegions_;processDump.mostRecentVmRegions=mostRecentVmRegions;});};function VMRegion(startAddress,sizeInBytes,protectionFlags,mappedFile,byteStats){this.startAddress=startAddress;this.sizeInBytes=sizeInBytes;this.protectionFlags=protectionFlags;this.mappedFile=mappedFile;this.byteStats=byteStats;};VMRegion.PROTECTION_FLAG_READ=4;VMRegion.PROTECTION_FLAG_WRITE=2;VMRegion.PROTECTION_FLAG_EXECUTE=1;VMRegion.prototype={get protectionFlagsToString(){if(this.protectionFlags===undefined) return undefined;return((this.protectionFlags&VMRegion.PROTECTION_FLAG_READ?'r':'-')+ @@ -2830,7 +2899,7 @@ this.frames[i].shiftTimestampsForward(amount);for(var i=0;i<this.memoryDumps.len this.memoryDumps[i].shiftTimestampsForward(amount);tr.model.ProcessBase.prototype.shiftTimestampsForward.apply(this,arguments);},updateBounds:function(){tr.model.ProcessBase.prototype.updateBounds.apply(this);for(var i=0;i<this.frames.length;i++) this.frames[i].addBoundsToRange(this.bounds);for(var i=0;i<this.memoryDumps.length;i++) this.memoryDumps[i].addBoundsToRange(this.bounds);},sortMemoryDumps:function(){this.memoryDumps.sort(function(x,y){return x.start-y.start;});tr.model.ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(this.memoryDumps);}};return{Process:Process};});'use strict';tr.exportTo('tr.model',function(){function Sample(cpu,thread,title,start,leafStackFrame,opt_weight,opt_args){tr.model.TimedEvent.call(this,start);this.title=title;this.cpu=cpu;this.thread=thread;this.leafStackFrame=leafStackFrame;this.weight=opt_weight;this.args=opt_args||{};} -Sample.prototype={__proto__:tr.model.TimedEvent.prototype,get colorId(){return this.leafStackFrame.colorId;},get stackTrace(){return this.leafStackFrame.stackTrace;},getUserFriendlyStackTrace:function(){return this.leafStackFrame.getUserFriendlyStackTrace();},get userFriendlyName(){return'Sample at '+tr.b.units.TimeStamp.format(this.start);}};tr.model.EventRegistry.register(Sample,{name:'sample',pluralName:'samples',singleViewElementName:'tr-ui-a-single-sample-sub-view',multiViewElementName:'tr-ui-a-multi-sample-sub-view'});return{Sample:Sample};});'use strict';tr.exportTo('tr.model',function(){function StackFrame(parentFrame,id,category,title,colorId,opt_sourceInfo){if(id===undefined) +Sample.prototype={__proto__:tr.model.TimedEvent.prototype,get colorId(){return this.leafStackFrame.colorId;},get stackTrace(){return this.leafStackFrame.stackTrace;},getUserFriendlyStackTrace:function(){return this.leafStackFrame.getUserFriendlyStackTrace();},get userFriendlyName(){return'Sample at '+tr.b.u.TimeStamp.format(this.start);}};tr.model.EventRegistry.register(Sample,{name:'sample',pluralName:'samples',singleViewElementName:'tr-ui-a-single-sample-sub-view',multiViewElementName:'tr-ui-a-multi-sample-sub-view'});return{Sample:Sample};});'use strict';tr.exportTo('tr.model',function(){function StackFrame(parentFrame,id,category,title,colorId,opt_sourceInfo){if(id===undefined) throw new Error('id must be given');this.parentFrame_=parentFrame;this.id=id;this.category=category||'';this.title_=title;this.colorId=colorId;this.children=[];this.sourceInfo_=opt_sourceInfo;if(this.parentFrame_) this.parentFrame_.addChild(this);} StackFrame.prototype={get parentFrame(){return this.parentFrame_;},get title(){if(this.sourceInfo_){var src=this.sourceInfo_.toString();return this.title_+(src===''?'':' '+src);} @@ -2906,7 +2975,7 @@ this.interactionRecords.forEach(callback,opt_this);if(eventTypePredicate.call(op this.samples.forEach(callback,opt_this);},iterateAllChildEventContainers:function(callback,opt_this){callback.call(opt_this,this.device);callback.call(opt_this,this.kernel);for(var pid in this.processes) callback.call(opt_this,this.processes[pid]);},iterateAllPersistableObjects:function(callback){this.kernel.iterateAllPersistableObjects(callback);for(var pid in this.processes) this.processes[pid].iterateAllPersistableObjects(callback);},updateBounds:function(){this.bounds.reset();var bounds=this.bounds;this.iterateAllChildEventContainers(function(ec){ec.updateBounds();bounds.addRange(ec.bounds);});this.iterateAllEventsInThisContainer(function(eventConstructor){return true;},function(event){event.addBoundsToRange(bounds);});},shiftWorldToZero:function(){var shiftAmount=-this.bounds.min;this.timestampShiftToZeroAmount_=shiftAmount;this.iterateAllChildEventContainers(function(ec){ec.shiftTimestampsForward(shiftAmount);});this.iterateAllEventsInThisContainer(function(eventConstructor){return true;},function(event){event.start+=shiftAmount;});this.updateBounds();},convertTimestampToModelTime:function(sourceClockDomainName,ts){if(sourceClockDomainName!=='traceEventClock') -throw new Error('Only traceEventClock is supported.');return tr.b.units.Time.timestampFromUs(ts)+ +throw new Error('Only traceEventClock is supported.');return tr.b.u.Units.timestampFromUs(ts)+ this.timestampShiftToZeroAmount_;},get numProcesses(){var n=0;for(var p in this.processes) n++;return n;},getProcess:function(pid){return this.processes[pid];},getOrCreateProcess:function(pid){if(!this.processes[pid]) this.processes[pid]=new Process(this,pid);return this.processes[pid];},pushInstantEvent:function(instantEvent){this.instantEvents.push(instantEvent);},addStackFrame:function(stackFrame){if(this.stackFrames[stackFrame.id]) @@ -2920,7 +2989,7 @@ processes.push(this.processes[pid]);return processes;},getAllCounters:function() return counters;},getAnnotationByGUID:function(guid){return this.annotationsByGuid_[guid];},addAnnotation:function(annotation){if(!annotation.guid) throw new Error('Annotation with undefined guid given');this.annotationsByGuid_[annotation.guid]=annotation;tr.b.dispatchSimpleEvent(this,'annotationChange');},removeAnnotation:function(annotation){this.annotationsByGuid_[annotation.guid].onRemove();delete this.annotationsByGuid_[annotation.guid];tr.b.dispatchSimpleEvent(this,'annotationChange');},getAllAnnotations:function(){return tr.b.dictionaryValues(this.annotationsByGuid_);},findAllThreadsNamed:function(name){var namedThreads=[];namedThreads.push.apply(namedThreads,this.kernel.findAllThreadsNamed(name));for(var pid in this.processes){namedThreads.push.apply(namedThreads,this.processes[pid].findAllThreadsNamed(name));} return namedThreads;},set importOptions(options){this.importOptions_=options;},get intrinsicTimeUnit(){if(this.intrinsicTimeUnit_===undefined) -return tr.b.units.Time.supportedUnits.ms;return this.intrinsicTimeUnit_;},set intrinsicTimeUnit(value){if(this.intrinsicTimeUnit_===value) +return tr.b.u.TimeDisplayModes.ms;return this.intrinsicTimeUnit_;},set intrinsicTimeUnit(value){if(this.intrinsicTimeUnit_===value) return;if(this.intrinsicTimeUnit_!==undefined) throw new Error('Intrinsic time unit already set');this.intrinsicTimeUnit_=value;},importWarning:function(data){this.importWarnings_.push(data);if(this.reportedImportWarnings_[data.type]===true) return;if(this.importOptions_.showImportWarnings) @@ -3260,7 +3329,7 @@ ts+=timeShift;if(!handler(eventName,cpuNumber,pid,ts,eventBase)){this.model_.imp extractResult=LinuxPerfImporter._extractEventsFromSystraceMultiHTML(this.events_,true);var lines=extractResult.ok?extractResult.lines:this.events_.split('\n');var lineParser=null;for(var lineNumber=0;lineNumber<lines.length;++lineNumber){var line=lines[lineNumber].trim();if(line.length==0||/^#/.test(line)) continue;if(lineParser==null){lineParser=autoDetectLineParser(line);if(lineParser==null){this.model_.importWarning({type:'parse_error',message:'Cannot parse line: '+line});continue;}} var eventBase=lineParser(line);if(!eventBase){this.model_.importWarning({type:'parse_error',message:'Unrecognized line: '+line});continue;} -this.lines_.push([line,eventBase,parseInt(eventBase.cpuNumber),parseInt(eventBase.pid),parseFloat(eventBase.timestamp)*1000]);}},forEachLine:function(handler){for(var i=0;i<this.lines_.length;++i){var line=this.lines_[i];handler.apply(this,line);}}};tr.importer.Importer.register(LinuxPerfImporter);return{LinuxPerfImporter:LinuxPerfImporter,_LinuxPerfImporterTestExports:TestExports};});'use strict';tr.exportTo('tr.b.units',function(){function TimeDuration(duration){this.duration=duration;};TimeDuration.prototype={toString:function(){return TimeDuration.format(this.duration);}};TimeDuration.format=function(duration){return tr.b.units.Time.currentDisplayUnit.format(duration);};return{TimeDuration:TimeDuration};});'use strict';tr.exportTo('tr.b',function(){function convertEventsToRanges(events){return events.map(function(event){return tr.b.Range.fromExplicitRange(event.start,event.end);});} +this.lines_.push([line,eventBase,parseInt(eventBase.cpuNumber),parseInt(eventBase.pid),parseFloat(eventBase.timestamp)*1000]);}},forEachLine:function(handler){for(var i=0;i<this.lines_.length;++i){var line=this.lines_[i];handler.apply(this,line);}}};tr.importer.Importer.register(LinuxPerfImporter);return{LinuxPerfImporter:LinuxPerfImporter,_LinuxPerfImporterTestExports:TestExports};});'use strict';tr.exportTo('tr.b.u',function(){function TimeDuration(duration){tr.b.u.Scalar.call(this,duration,tr.b.u.Units.timeDurationInMs);};TimeDuration.prototype={__proto__:tr.b.u.Scalar.prototype,get duration(){return this.value;}};TimeDuration.format=function(duration){return tr.b.u.Units.timeDurationInMs.format(duration);};return{TimeDuration:TimeDuration};});'use strict';tr.exportTo('tr.b',function(){function convertEventsToRanges(events){return events.map(function(event){return tr.b.Range.fromExplicitRange(event.start,event.end);});} function mergeRanges(inRanges,mergeThreshold,mergeFunction){var remainingEvents=inRanges.slice();remainingEvents.sort(function(x,y){return x.min-y.min;});if(remainingEvents.length<=1){var merged=[];if(remainingEvents.length==1){merged.push(mergeFunction(remainingEvents));} return merged;} var mergedEvents=[];var currentMergeBuffer=[];var rightEdge;function beginMerging(){currentMergeBuffer.push(remainingEvents[0]);remainingEvents.splice(0,1);rightEdge=currentMergeBuffer[0].max;} @@ -3326,7 +3395,7 @@ callback(slice);});} function AndroidModelHelper(model){this.model=model;this.apps=[];this.surfaceFlinger=undefined;var processes=model.getAllProcesses();for(var i=0;i<processes.length&&!this.surfaceFlinger;i++){this.surfaceFlinger=AndroidSurfaceFlinger.createForProcessIfPossible(processes[i]);} model.getAllProcesses().forEach(function(process){var app=AndroidApp.createForProcessIfPossible(process,this.surfaceFlinger);if(app) this.apps.push(app);},this);};AndroidModelHelper.prototype={iterateImportantSlices:function(callback){if(this.surfaceFlinger){iterateImportantThreadSlices(this.surfaceFlinger.thread,IMPORTANT_SURFACE_FLINGER_SLICES,callback);} -this.apps.forEach(function(app){iterateImportantThreadSlices(app.uiThread,IMPORTANT_UI_THREAD_SLICES,callback);iterateImportantThreadSlices(app.renderThread,IMPORTANT_RENDER_THREAD_SLICES,callback);});}};return{AndroidModelHelper:AndroidModelHelper};});'use strict';tr.exportTo('tr.e.audits',function(){var SCHEDULING_STATE=tr.model.SCHEDULING_STATE;var Auditor=tr.c.Auditor;var AndroidModelHelper=tr.e.audits.AndroidModelHelper;var Statistics=tr.b.Statistics;var FRAME_PERF_CLASS=tr.model.FRAME_PERF_CLASS;var InteractionRecord=tr.model.InteractionRecord;var Alert=tr.model.Alert;var EventInfo=tr.model.EventInfo;var TimeDuration=tr.b.units.TimeDuration;var EXPECTED_FRAME_TIME_MS=16.67;function getStart(e){return e.start;} +this.apps.forEach(function(app){iterateImportantThreadSlices(app.uiThread,IMPORTANT_UI_THREAD_SLICES,callback);iterateImportantThreadSlices(app.renderThread,IMPORTANT_RENDER_THREAD_SLICES,callback);});}};return{AndroidModelHelper:AndroidModelHelper};});'use strict';tr.exportTo('tr.e.audits',function(){var SCHEDULING_STATE=tr.model.SCHEDULING_STATE;var Auditor=tr.c.Auditor;var AndroidModelHelper=tr.e.audits.AndroidModelHelper;var Statistics=tr.b.Statistics;var FRAME_PERF_CLASS=tr.model.FRAME_PERF_CLASS;var InteractionRecord=tr.model.InteractionRecord;var Alert=tr.model.Alert;var EventInfo=tr.model.EventInfo;var TimeDuration=tr.b.u.TimeDuration;var EXPECTED_FRAME_TIME_MS=16.67;function getStart(e){return e.start;} function getDuration(e){return e.duration;} function getCpuDuration(e){return(e.cpuDuration!==undefined)?e.cpuDuration:e.duration;} function frameIsActivityStart(frame){for(var i=0;i<frame.associatedEvents.length;i++){if(frame.associatedEvents[i].title=='activityStart') @@ -3386,7 +3455,17 @@ if(slice.title in this.titleInfoLookup){if(checkExpectedParentNames(this.titlePa slice.info=this.titleInfoLookup[slice.title];} if(slice.subSlices.length>0){if(!(slice.title in parentNames)) parentNames[slice.title]=0;parentNames[slice.title]++;slice.subSlices.forEach(function(subSlice){this.applyEventInfosRecursive_(parentNames,subSlice);},this);parentNames[slice.title]--;if(parentNames[slice.title]==0) -delete parentNames[slice.title];}},applyEventInfos:function(sliceGroup){sliceGroup.topLevelSlices.forEach(function(slice){this.applyEventInfosRecursive_({},slice);},this);}};return{AndroidAuditor:AndroidAuditor};});'use strict';tr.exportTo('tr.b',function(){function Settings(){return Settings;};if(tr.b.unittest&&tr.b.unittest.TestRunner){tr.b.unittest.TestRunner.addEventListener('tr-unittest-will-run',function(){if(tr.isHeadless) +delete parentNames[slice.title];}},applyEventInfos:function(sliceGroup){sliceGroup.topLevelSlices.forEach(function(slice){this.applyEventInfosRecursive_({},slice);},this);}};return{AndroidAuditor:AndroidAuditor};});'use strict';tr.exportTo('tr.e.audits',function(){var VSYNC_COUNTER_PRECISIONS={'android.VSYNC-app':15,'android.VSYNC':15};var VSYNC_SLICE_PRECISIONS={'RenderWidgetHostViewAndroid::OnVSync':5,'VSYNC':10,'vblank':10,'DisplayLinkMac::GetVSyncParameters':5};var BEGIN_FRAME_SLICE_PRECISION={'Scheduler::BeginFrame':10};function VSyncAuditor(model){tr.c.Auditor.call(this,model);};VSyncAuditor.prototype={__proto__:tr.c.Auditor.prototype,runAnnotate:function(){this.model.device.vSyncTimestamps=this.findVSyncTimestamps(this.model);},findVSyncTimestamps:function(model){var times=[];var maxPrecision=Number.NEGATIVE_INFINITY;var maxTitle=undefined;function useInstead(title,precisions){var precision=precisions[title];if(precision===undefined) +return false;if(title===maxTitle) +return true;if(precision<=maxPrecision){if(precision===maxPrecision){console.warn('Encountered two different VSync events ('+ +maxTitle+', '+title+') with the same precision, '+'ignoring the newer one ('+title+')');} +return false;} +maxPrecision=precision;maxTitle=title;times=[];return true;} +for(var pid in model.processes){var process=model.processes[pid];for(var cid in process.counters){if(useInstead(cid,VSYNC_COUNTER_PRECISIONS)){var counter=process.counters[cid];for(var i=0;i<counter.series.length;i++){var series=counter.series[i];Array.prototype.push.apply(times,series.timestamps);}}} +for(var tid in process.threads){var thread=process.threads[tid];for(var i=0;i<thread.sliceGroup.slices.length;i++){var slice=thread.sliceGroup.slices[i];if(useInstead(slice.title,VSYNC_SLICE_PRECISIONS)) +times.push(slice.start);else if(useInstead(slice.title,BEGIN_FRAME_SLICE_PRECISION)) +times.push(slice.args.frame_time_us/1000.0);}}} +times.sort(function(x,y){return x-y;});return times;}};tr.c.Auditor.register(VSyncAuditor);return{VSyncAuditor:VSyncAuditor};});'use strict';tr.exportTo('tr.b',function(){function Settings(){return Settings;};if(tr.b.unittest&&tr.b.unittest.TestRunner){tr.b.unittest.TestRunner.addEventListener('tr-unittest-will-run',function(){if(tr.isHeadless) Settings.setAlternativeStorageInstance(new HeadlessStorage());else Settings.setAlternativeStorageInstance(global.sessionStorage);});} function SessionSettings(){return SessionSettings;} @@ -3781,21 +3860,33 @@ var parentRowInfo=rowInfo.parentRowInfo;if(parentRowInfo){this.selectedTableRow= return;}} throw new Error('Unrecognized command');},focusSelected_:function(){if(!this.selectedTableRowInfo_) return;var node=this.getSelectableNodeGivenTableRowNode_(this.selectedTableRowInfo_.htmlNode);node.focus();}});})();'use strict';Polymer('tr-ui-b-table-header-cell',{created:function(){this.tapCallback_=undefined;this.cellTitle_='';},set cellTitle(value){this.cellTitle_=value;var titleNode=tr.ui.b.asHTMLOrTextNode(this.cellTitle_,this.ownerDocument);this.$.title.innerText='';this.$.title.appendChild(titleNode);},get cellTitle(){return this.cellTitle_;},clearSideContent:function(){this.$.side.textContent='';},set sideContent(content){this.$.side.textContent=content;},get sideContent(){return this.$.side.textContent;},set tapCallback(callback){this.style.cursor='pointer';this.tapCallback_=callback;},get tapCallback(){return this.tapCallback_;},onTap_:function(){if(this.tapCallback_) -this.tapCallback_();}});'use strict';Polymer('tr-ui-u-size-in-bytes-span',{ready:function(){this.$.content.textContent=String.fromCharCode(9888);this.numBytes_=undefined;},get numBytes(){return this.numBytes_;},set numBytes(numBytesOrSizeInBytes){if(numBytesOrSizeInBytes instanceof tr.b.units.SizeInBytes) -this.numBytes_=numBytesOrSizeInBytes.numBytes;else -this.numBytes_=numBytesOrSizeInBytes;this.$.content.textContent=tr.b.units.SizeInBytes.format(this.numBytes_);},get stringContent(){return this.$.content.textContent;}});'use strict';tr.exportTo('tr.ui.units',function(){function createTimeDurationSpan(duration,opt_config){if(duration===undefined) -return'';var config=opt_config||{};var ownerDocument=config.ownerDocument||document;var span=ownerDocument.createElement('tr-ui-u-time-duration-span');if(config.total) +this.tapCallback_();}});'use strict';tr.exportTo('tr.ui.b',function(){Object.observe(Polymer.elements,clearPolymerElementCaches);var elementsByName=undefined;var elementsThatExtend=undefined;var elementSubclasses=undefined;function clearPolymerElementCaches(){elementsByName={};elementsThatExtend=undefined;elementSubclasses={};} +function buildElementMapsIfNeeded(){if(elementsThatExtend!==undefined&&elementsByName!==undefined) +return;elementsByName={};elementsThatExtend={};Polymer.elements.forEach(function(element){if(elementsByName[element.name]) +throw new Error('Something is strange: dupe polymer element names');elementsByName[element.name]=element;if(element.extends){if(elementsThatExtend[element.extends]===undefined) +elementsThatExtend[element.extends]=[];elementsThatExtend[element.extends].push(element.name);}});} +function getPolymerElementNamed(tagName){buildElementMapsIfNeeded();return elementsByName[tagName];} +function getPolymerElementsThatSubclass(tagName){if(Polymer.waitingFor().length){throw new Error('There are unresolved polymer elements. '+'Wait until Polymer.whenReady');} +buildElementMapsIfNeeded();var element=getPolymerElementNamed(tagName);if(!element) +throw new Error(tagName+' is not a polymer element');if(elementSubclasses===undefined) +elementSubclasses={};if(elementSubclasses[tagName]===undefined){var immediateSubElements=elementsThatExtend[element.name];var allSubElements=[];if(immediateSubElements!==undefined&&immediateSubElements.length){immediateSubElements.forEach(function(subElement){allSubElements.push(subElement);allSubElements.push.apply(allSubElements,getPolymerElementsThatSubclass(subElement));});} +elementSubclasses[tagName]=allSubElements;} +return elementSubclasses[tagName];} +return{getPolymerElementNamed:getPolymerElementNamed,getPolymerElementsThatSubclass:getPolymerElementsThatSubclass};});'use strict';tr.exportTo('tr.ui.units',function(){function createScalarSpan(value,opt_config){if(value===undefined) +return'';var config=opt_config||{};var ownerDocument=config.ownerDocument||document;var span=ownerDocument.createElement('tr-ui-u-scalar-span');span.value=value;return span;} +tr.b.u.Units.addEventListener('display-mode-changed',function(e){var subclassNames=tr.ui.b.getPolymerElementsThatSubclass('tr-ui-u-scalar-span');var isSubclass={};subclassNames.forEach(function(n){isSubclass[n.toUpperCase()]=true;});var m=tr.b.findDeepElementsMatchingPredicate(document.body,function(el){return isSubclass[el.tagName];});m.forEach(function(el){el.updateContent_();});});return{createScalarSpan:createScalarSpan};});'use strict';Polymer('tr-ui-u-scalar-span',{ready:function(){this.value_=undefined;this.unit_=undefined;this.warning_=undefined;this.percentage_=undefined;},set contentTextDecoration(deco){this.$.content.style.textDecoration=deco;},get value(){return this.value_;},set value(value){if(value instanceof tr.b.u.Scalar){this.value_=value.value;this.unit_=value.unit;}else{this.value_=value;} +this.updateContent_();},get unit(){return this.unit_;},set unit(unit){this.unit_=unit;this.updateContent_();},setValueAndUnit:function(value,unit){this.value_=value;this.unit_=unit;this.updateContent_();},get percentage(){return this.percentage_;},set percentage(percentage){this.percentage_=percentage;this.updateSparkline_();},get rightAlign(){return this.$.content.classList.contains('right-align');},set rightAlign(rightAlign){if(rightAlign) +this.$.content.classList.add('right-align');else +this.$.content.classList.remove('right-align');},updateSparkline_:function(){if(this.percentage_===undefined){this.$.sparkline.style.display='none';this.$.sparkline.style.width='0';}else{this.$.sparkline.style.display='block';this.$.sparkline.style.width=(this.percentage_*100)+'%';}},updateContent_:function(){if(this.unit_===undefined){this.$.content.textContent='';return;} +var content=this.unit_.format(this.value);this.$.content.textContent=content;},get warning(){return this.warning_;},set warning(warning){this.warning_=warning;var warningEl=this.$.warning;if(this.warning_){warningEl.title=warning;warningEl.style.display='';}else{warningEl.title='';warningEl.style.display='none';}}});'use strict';tr.exportTo('tr.ui.units',function(){function createTimeDurationSpan(duration,opt_config){if(duration===undefined) +return'';var config=opt_config||{};var ownerDocument=config.ownerDocument||document;var span=ownerDocument.createElement('tr-ui-u-time-duration-span');span.setValueAndUnit(duration,tr.b.u.Units.timeDurationInMs);if(config.total) span.percentage=duration/config.total;span.duration=duration;if(config.rightAlign) span.rightAlign=true;return span;} -tr.b.units.Time.addEventListener('display-unit-changed',function(e){tr.b.findDeepElementsMatching(document.body,'tr-ui-u-time-duration-span').forEach(function(el){el.updateContent_();});});return{createTimeDurationSpan:createTimeDurationSpan};});'use strict';Polymer('tr-ui-u-time-duration-span',{ready:function(){this.warning_=undefined;this.duration_=undefined;this.percentage_=undefined;},set contentTextDecoration(deco){this.$.content.style.textDecoration=deco;},get duration(){return this.duration_;},set duration(duration){if(duration instanceof tr.b.units.TimeDuration) -this.duration_=duration.duration;else -this.duration_=duration;this.updateContent_();},get percentage(){return this.percentage_;},set percentage(percentage){this.percentage_=percentage;this.updateSparkline_();},get rightAlign(){return this.$.content.classList.contains('right-align');},set rightAlign(rightAlign){if(rightAlign) -this.$.content.classList.add('right-align');else -this.$.content.classList.remove('right-align');},updateSparkline_:function(){if(this.percentage_===undefined){this.$.sparkline.style.display='none';this.$.sparkline.style.width='0';}else{this.$.sparkline.style.display='block';this.$.sparkline.style.width=(this.percentage_*100)+'%';}},updateContent_:function(){var content=tr.b.units.TimeDuration.format(this.duration_);this.$.content.textContent=content;},get warning(){return this.warning_;},set warning(warning){this.warning_=warning;var warningEl=this.$.warning;if(this.warning_){warningEl.title=warning;warningEl.style.display='';}else{warningEl.title='';warningEl.style.display='none';}}});'use strict';tr.exportTo('tr.ui.units',function(){function createTimeStampSpan(timestamp,opt_config){if(timestamp===undefined) +return{createTimeDurationSpan:createTimeDurationSpan};});'use strict';Polymer('tr-ui-u-time-duration-span',{get duration(){return this.value;},set duration(duration){if(duration instanceof tr.b.u.TimeDuration){this.value=duration;return;} +this.setValueAndUnit(duration,tr.b.u.Units.timeDurationInMs);}});'use strict';tr.exportTo('tr.ui.units',function(){function createTimeStampSpan(timestamp,opt_config){if(timestamp===undefined) return'';var config=opt_config||{};var ownerDocument=config.ownerDocument||document;var span=ownerDocument.createElement('tr-ui-u-time-stamp-span');span.timestamp=timestamp;return span;} -tr.b.units.Time.addEventListener('display-unit-changed',function(e){tr.b.findDeepElementsMatching(document.body,'tr-ui-u-time-stamp-span').forEach(function(el){el.updateContent_();});});return{createTimeStampSpan:createTimeStampSpan};});'use strict';Polymer('tr-ui-u-time-stamp-span',{ready:function(){this.timestamp_=undefined;},get timestamp(){return this.timestamp_;},set timestamp(timestamp){if(timestamp instanceof tr.b.units.TimeStamp) -this.timestamp_=timestamp.timestamp;else -this.timestamp_=timestamp;this.updateContent_();},updateContent_:function(){var content=tr.b.units.TimeStamp.format(this.timestamp_);this.shadowRoot.textContent=content;}});'use strict';function isTable(object){if(!(object instanceof Array)||(object.length<2))return false;for(var colName in object[0]){if(typeof colName!=='string')return false;} +return{createTimeStampSpan:createTimeStampSpan};});'use strict';Polymer('tr-ui-u-time-stamp-span',{get timestamp(){return this.value;},set timestamp(timestamp){if(timestamp instanceof tr.b.u.TimeStamp){this.value=timestamp;return;} +this.setValueAndUnit(timestamp,tr.b.u.Units.timeStampInMs);}});'use strict';function isTable(object){if(!(object instanceof Array)||(object.length<2))return false;for(var colName in object[0]){if(typeof colName!=='string')return false;} for(var i=0;i<object.length;++i){if(!(object[i]instanceof Object))return false;for(var colName in object[i]){if(i&&(object[0][colName]===undefined))return false;var cellType=typeof object[i][colName];if(cellType!=='string'&&cellType!='number')return false;} if(i){for(var colName in object[0]){if(object[i][colName]===undefined)return false;}}} return true;} @@ -3809,9 +3900,7 @@ else{}}else{return this.appendSimpleText_(label,indent,object,suffix);}} if(object instanceof tr.model.ObjectSnapshot){var link=document.createElement('tr-ui-a-analysis-link');link.selection=new tr.model.EventSet(object);this.appendElementWithLabel_(label,indent,link,suffix);return;} if(object instanceof tr.model.ObjectInstance){var link=document.createElement('tr-ui-a-analysis-link');link.selection=new tr.model.EventSet(object);this.appendElementWithLabel_(label,indent,link,suffix);return;} if(object instanceof tr.b.Rect){this.appendSimpleText_(label,indent,object.toString(),suffix);return;} -if(object instanceof tr.b.units.SizeInBytes){var el=this.ownerDocument.createElement('tr-ui-u-size-in-bytes-span');el.numBytes=object.numBytes;this.appendElementWithLabel_(label,indent,el,suffix);return;} -if(object instanceof tr.b.units.TimeDuration){var el=this.ownerDocument.createElement('tr-ui-u-time-duration-span');el.duration=object.duration;this.appendElementWithLabel_(label,indent,el,suffix);return;} -if(object instanceof tr.b.units.TimeStamp){var el=this.ownerDocument.createElement('tr-ui-u-time-stamp-span');el.timestamp=object.timestamp;this.appendElementWithLabel_(label,indent,el,suffix);return;} +if(object instanceof tr.b.u.Scalar){var el=this.ownerDocument.createElement('tr-ui-u-scalar-span');el.value=object;this.appendElementWithLabel_(label,indent,el,suffix);return;} if(object instanceof Array){this.appendElementsForArray_(label,object,indent,depth,maxDepth,suffix);return;} this.appendElementsForObject_(label,object,indent,depth,maxDepth,suffix);},appendElementsForArray_:function(label,object,indent,depth,maxDepth,suffix){if(object.length==0){this.appendSimpleText_(label,indent,'[]',suffix);return;} if(isTable(object)){var table=document.createElement('tr-ui-b-table');var columns=[];tr.b.iterItems(object[0],function(colName){columns.push({title:colName,value:function(row){return row[colName];}});});table.tableColumns=columns;table.tableRows=object;this.appendElementWithLabel_(label,indent,table,suffix);table.rebuild();return;} @@ -3851,18 +3940,20 @@ return selection;},get outFlowEvents(){var selection=new tr.model.EventSet();for selection.push(fs.event);} return selection;},get internalFlowEvents(){var selection=new tr.model.EventSet();for(var guid in this.eventsByGUID_){var fs=this.eventsByGUID_[guid];if(fs.state===FLOW_IN_OUT) selection.push(fs.event);} -return selection;}};return{FlowClassifier:FlowClassifier};});'use strict';Polymer('tr-ui-a-related-events',{ready:function(){this.eventGroups_=[];this.$.table.tableColumns=[{title:'Event(s)',value:function(row){var typeEl=document.createElement('span');typeEl.innerText=row.type;if(row.tooltip) +return selection;}};return{FlowClassifier:FlowClassifier};});'use strict';Polymer('tr-ui-a-related-events',{ready:function(){this.eventGroups_=[];this.cancelFunctions_=[];this.$.table.tableColumns=[{title:'Event(s)',value:function(row){var typeEl=document.createElement('span');typeEl.innerText=row.type;if(row.tooltip) typeEl.title=row.tooltip;return typeEl;},width:'150px'},{title:'Link',width:'100%',value:function(row){var linkEl=document.createElement('tr-ui-a-analysis-link');if(row.name) linkEl.setSelectionAndContent(row.selection,row.name);else -linkEl.selection=row.selection;return linkEl;}}];},hasRelatedEvents:function(){return(this.eventGroups_&&this.eventGroups_.length>0);},setRelatedEvents:function(eventSet){this.eventGroups_=[];this.addConnectedFlows_(eventSet);this.addConnectedEvents_(eventSet);this.addOverlappingSamples_(eventSet);this.updateContents_();},addConnectedFlows_:function(eventSet){var classifier=new tr.ui.analysis.FlowClassifier();eventSet.forEach(function(slice){if(slice.inFlowEvents){slice.inFlowEvents.forEach(function(flow){classifier.addInFlow(flow);});} +linkEl.selection=row.selection;return linkEl;}}];},hasRelatedEvents:function(){return(this.eventGroups_&&this.eventGroups_.length>0);},setRelatedEvents:function(eventSet){this.cancelAllTasks_();this.eventGroups_=[];this.addConnectedFlows_(eventSet);this.addConnectedEvents_(eventSet);this.addOverlappingSamples_(eventSet);this.updateContents_();},addConnectedFlows_:function(eventSet){var classifier=new tr.ui.analysis.FlowClassifier();eventSet.forEach(function(slice){if(slice.inFlowEvents){slice.inFlowEvents.forEach(function(flow){classifier.addInFlow(flow);});} if(slice.outFlowEvents){slice.outFlowEvents.forEach(function(flow){classifier.addOutFlow(flow);});}});if(!classifier.hasEvents()) -return;var addToEventGroups=function(type,flowEvent){this.eventGroups_.push({type:type,selection:new tr.model.EventSet(flowEvent),name:flowEvent.title});};classifier.inFlowEvents.forEach(addToEventGroups.bind(this,'Incoming flow'));classifier.outFlowEvents.forEach(addToEventGroups.bind(this,'Outgoing flow'));classifier.internalFlowEvents.forEach(addToEventGroups.bind(this,'Internal flow'));},addConnectedEvents_:function(eventSet){this.createEventsLinkIfNeeded_('Preceding events','Add all events that have led to the selected one(s), connected by '+'flow arrows or by call stack.',eventSet,function(event,events){this.addInFlowEvents_(event,events);this.addAncestors_(event,events);if(event.startSlice) -events.push(event.startSlice);}.bind(this));this.createEventsLinkIfNeeded_('Following events','Add all events that have been caused by the selected one(s), '+'connected by flow arrows or by call stack.',eventSet,function(event,events){this.addOutFlowEvents_(event,events);this.addDescendents_(event,events);if(event.endSlice) -events.push(event.endSlice);}.bind(this));this.createEventsLinkIfNeeded_('All connected events','Add all events connected to the selected one(s) by flow arrows or '+'by call stack.',eventSet,function(event,events){this.addInFlowEvents_(event,events);this.addOutFlowEvents_(event,events);this.addAncestors_(event,events);this.addDescendents_(event,events);if(event.startSlice) +return;var addToEventGroups=function(type,flowEvent){this.eventGroups_.push({type:type,selection:new tr.model.EventSet(flowEvent),name:flowEvent.title});};classifier.inFlowEvents.forEach(addToEventGroups.bind(this,'Incoming flow'));classifier.outFlowEvents.forEach(addToEventGroups.bind(this,'Outgoing flow'));classifier.internalFlowEvents.forEach(addToEventGroups.bind(this,'Internal flow'));},cancelAllTasks_:function(){this.cancelFunctions_.forEach(function(cancelFunction){cancelFunction();});this.cancelFunctions_=[];},addConnectedEvents_:function(eventSet){this.cancelFunctions_.push(this.createEventsLinkIfNeeded_('Preceding events','Add all events that have led to the selected one(s), connected by '+'flow arrows or by call stack.',eventSet,function(event,events){this.addInFlowEvents_(event,events);this.addAncestors_(event,events);if(event.startSlice) +events.push(event.startSlice);}.bind(this)));this.cancelFunctions_.push(this.createEventsLinkIfNeeded_('Following events','Add all events that have been caused by the selected one(s), '+'connected by flow arrows or by call stack.',eventSet,function(event,events){this.addOutFlowEvents_(event,events);this.addDescendents_(event,events);if(event.endSlice) +events.push(event.endSlice);}.bind(this)));this.cancelFunctions_.push(this.createEventsLinkIfNeeded_('All connected events','Add all events connected to the selected one(s) by flow arrows or '+'by call stack.',eventSet,function(event,events){this.addInFlowEvents_(event,events);this.addOutFlowEvents_(event,events);this.addAncestors_(event,events);this.addDescendents_(event,events);if(event.startSlice) events.push(event.startSlice);if(event.endSlice) -events.push(event.endSlice);}.bind(this));},createEventsLinkIfNeeded_:function(title,tooltip,events,addFunction){events=new tr.model.EventSet(events);var lengthBefore=events.length;var task;function addEventsUntilTimeout(startingIndex){var startingTime=window.performance.now();while(startingIndex<events.length){addFunction(events[startingIndex],events);startingIndex++;if(window.performance.now()-startingTime>8){var newTask=new tr.b.Task(addEventsUntilTimeout.bind(this,startingIndex),this);task.after(newTask);task=newTask;return;}} +events.push(event.endSlice);}.bind(this)));},createEventsLinkIfNeeded_:function(title,tooltip,events,addFunction){events=new tr.model.EventSet(events);var lengthBefore=events.length;var task;var isCanceled=false;function addEventsUntilTimeout(startingIndex){if(isCanceled) +return;var startingTime=window.performance.now();while(startingIndex<events.length){addFunction(events[startingIndex],events);startingIndex++;if(window.performance.now()-startingTime>8){var newTask=new tr.b.Task(addEventsUntilTimeout.bind(this,startingIndex),this);task.after(newTask);task=newTask;return;}} if(lengthBefore===events.length) -return;this.eventGroups_.push({type:title,tooltip:tooltip,selection:events});this.updateContents_();};task=new tr.b.Task(addEventsUntilTimeout.bind(this,0),this);tr.b.Task.RunWhenIdle(task);},addInFlowEvents_:function(event,eventSet){if(!event.inFlowEvents) +return;this.eventGroups_.push({type:title,tooltip:tooltip,selection:events});this.updateContents_();};function cancelTask(){isCanceled=true;} +task=new tr.b.Task(addEventsUntilTimeout.bind(this,0),this);tr.b.Task.RunWhenIdle(task);return cancelTask;},addInFlowEvents_:function(event,eventSet){if(!event.inFlowEvents) return;event.inFlowEvents.forEach(function(e){eventSet.push(e);});},addOutFlowEvents_:function(event,eventSet){if(!event.outFlowEvents) return;event.outFlowEvents.forEach(function(e){eventSet.push(e);});},addAncestors_:function(event,eventSet){if(!event.iterateAllAncestors) return;event.iterateAllAncestors(function(e){eventSet.push(e);});},addDescendents_:function(event,eventSet){if(!event.iterateAllDescendents) @@ -3992,8 +4083,8 @@ return;var existingTraits=columnTraits[attrName];if(existingTraits===undefined){ if(existingTraits.constructor!==attrValue.constructor||existingTraits.units!==attrValue.units){existingTraits.constructor=tr.model.UnknownAttribute;existingTraits.units=undefined;}});if(row.subRows!==undefined) row.subRows.forEach(gatherTraits);};rows.forEach(gatherTraits);var titleBuilder=opt_titleBuilder||tr.b.identity;var columns=[];tr.b.iterItems(columnTraits,function(columnName,columnTraits){var cellGetter=fieldGetter(cellKey,columnName);var title=titleBuilder(columnName);columns.push(MemoryColumn.fromAttributeTraits(columnName,title,columnTraits,cellGetter));});return columns;};MemoryColumn.fromAttributeTraits=function(name,title,traits,cellGetter){var constructor;if(traits.constructor===tr.model.ScalarAttribute) constructor=ScalarMemoryColumn;else -constructor=MemoryColumn;return new constructor(name,title,traits.units,cellGetter);};MemoryColumn.spaceEqually=function(columns){var columnWidth=(100/columns.length).toFixed(3)+'%';columns.forEach(function(column){column.width=columnWidth;});};MemoryColumn.sortByImportance=function(columns,importanceRules){var positions=columns.map(function(column,srcIndex){return{importance:column.getImportance(importanceRules),srcIndex:srcIndex,column:column};});positions.sort(function(a,b){if(a.importance===b.importance) -return a.srcIndex-b.srcIndex;return b.importance-a.importance;});positions.forEach(function(position,dstIndex){columns[dstIndex]=position.column;});};MemoryColumn.iconFromAttributeInfoType=function(type){switch(type){case tr.model.AttributeInfoType.WARNING:return{symbol:String.fromCharCode(9888),color:'red'};case tr.model.AttributeInfoType.LINK:return{symbol:String.fromCharCode(9903)};case tr.model.AttributeInfoType.MEMORY_OWNER:return{symbol:String.fromCharCode(8702),color:'green'};case tr.model.AttributeInfoType.MEMORY_OWNED:return{symbol:String.fromCharCode(8701),color:'green'};default:return{symbol:String.fromCharCode(9432),color:'blue'};} +constructor=MemoryColumn;return new constructor(name,title,traits.units,cellGetter);};MemoryColumn.spaceEqually=function(columns){var columnWidth=(100/columns.length).toFixed(3)+'%';columns.forEach(function(column){column.width=columnWidth;});};MemoryColumn.sortByImportance=function(columns,importanceRules){var positions=columns.map(function(column,srcIndex){return{importance:column.getImportance(importanceRules),column:column};});positions.sort(function(a,b){if(a.importance===b.importance) +return a.column.name.localeCompare(b.column.name);return b.importance-a.importance;});positions.forEach(function(position,dstIndex){columns[dstIndex]=position.column;});};MemoryColumn.iconFromAttributeInfoType=function(type){switch(type){case tr.model.AttributeInfoType.WARNING:return{symbol:String.fromCharCode(9888),color:'red'};case tr.model.AttributeInfoType.LINK:return{symbol:String.fromCharCode(9903)};case tr.model.AttributeInfoType.MEMORY_OWNER:return{symbol:String.fromCharCode(8702),color:'green'};case tr.model.AttributeInfoType.MEMORY_OWNED:return{symbol:String.fromCharCode(8701),color:'green'};default:return{symbol:String.fromCharCode(9432),color:'blue'};} throw new Error('Unreachable');};MemoryColumn.prototype={attr:function(row){var cell=this.cell(row);if(cell===undefined) return undefined;return cell.attr;},value:function(row){var attr=this.attr(row);if(attr===undefined) return'';return this.formatDefinedAttribute(attr);},formatDefinedAttribute:function(attr){var formattedValue=this.formatDefinedAttributeValue(attr);var color;if(typeof this.color==='function') @@ -4011,7 +4102,7 @@ var minImportance=importanceRules[0].importance;for(var i=1;i<importanceRules.le return minImportance-1;},matchesNameCondition:function(condition){if(condition===undefined) return true;if(typeof(condition)==='string') return this.name===condition;return condition.test(this.name);}};function ScalarMemoryColumn(name,title,units,cellGetter){MemoryColumn.call(this,name,title,units,cellGetter);} -ScalarMemoryColumn.prototype={__proto__:MemoryColumn.prototype,formatDefinedAttributeValue:function(attr){if(this.units==='bytes'){var sizeEl=document.createElement('tr-ui-u-size-in-bytes-span');sizeEl.numBytes=attr.value;return sizeEl;} +ScalarMemoryColumn.prototype={__proto__:MemoryColumn.prototype,formatDefinedAttributeValue:function(attr){if(this.units==='bytes'){var sizeEl=document.createElement('tr-ui-u-scalar-span');sizeEl.setValueAndUnit(attr.value,tr.b.u.Units.sizeInBytes);return sizeEl;} return MemoryColumn.prototype.formatDefinedAttributeValue.call(this,attr);},compareDefinedAttributes:function(attrA,attrB){return attrA.value-attrB.value;}};function MemoryCell(attr){this.attr=attr;} MemoryCell.extractAttribute=function(cell){if(cell===undefined) return undefined;return cell.attr;};function fieldGetter(){var fields=tr.b.asArray(arguments);return function(row){var value=row;for(var i=0;i<fields.length;i++) @@ -4026,10 +4117,12 @@ function aggregateTableRowCells(row,subRows,cellKey){var rowCells=row[cellKey];i row[cellKey]=rowCells={};var subRowCellNames={};subRows.forEach(function(subRow){var subRowCells=subRow[cellKey];if(subRowCells===undefined) return;tr.b.iterItems(subRowCells,function(columnName){subRowCellNames[columnName]=true;});});tr.b.iterItems(subRowCellNames,function(cellName){var subRowAttributes=subRows.map(function(subRow){var subRowCells=subRow[cellKey];if(subRowCells===undefined) return undefined;return MemoryCell.extractAttribute(subRowCells[cellName]);},this);var existingRowCell=rowCells[cellName];var existingRowAttribute=MemoryCell.extractAttribute(existingRowCell);var aggregatedAttribute=tr.model.Attribute.aggregate(subRowAttributes,existingRowAttribute);if(existingRowCell!==undefined){existingRowCell.attr=aggregatedAttribute;}else{rowCells[cellName]=new MemoryCell(aggregatedAttribute);}});} -return{MemoryColumn:MemoryColumn,ScalarMemoryColumn:ScalarMemoryColumn,MemoryCell:MemoryCell,fieldGetter:fieldGetter,expandTableRowsRecursively:expandTableRowsRecursively,aggregateTableRowCellsRecursively:aggregateTableRowCellsRecursively,aggregateTableRowCells:aggregateTableRowCells};});'use strict';(function(){var IMPORTANCE_RULES=[{condition:'size',importance:10},{condition:'page_size',importance:0},{condition:/size/,importance:5},{importance:0}];Polymer('tr-ui-a-memory-dump-allocator-details-pane',{created:function(){this.memoryAllocatorDump_=undefined;},ready:function(){this.updateContents_();},set memoryAllocatorDump(memoryAllocatorDump){this.memoryAllocatorDump_=memoryAllocatorDump;this.updateContents_();},get memoryAllocatorDump(){return this.memoryAllocatorDump_;},updateContents_:function(){this.$.contents.textContent='';if(this.memoryAllocatorDump_===undefined){var infoText=this.ownerDocument.createElement('div');this.$.contents.appendChild(infoText);infoText.classList.add('info-text');infoText.innerText='No memory allocator dump selected';return;} +return{MemoryColumn:MemoryColumn,ScalarMemoryColumn:ScalarMemoryColumn,MemoryCell:MemoryCell,fieldGetter:fieldGetter,expandTableRowsRecursively:expandTableRowsRecursively,aggregateTableRowCellsRecursively:aggregateTableRowCellsRecursively,aggregateTableRowCells:aggregateTableRowCells};});'use strict';Polymer('tr-ui-a-stacked-pane',{rebuild:function(){if(!this.paneDirty_){return;} +this.paneDirty_=false;this.rebuildPane_();},scheduleRebuildPane_:function(){if(this.paneDirty_) +return;this.paneDirty_=true;setTimeout(this.rebuild.bind(this),0);},rebuildPane_:function(){},set childPaneBuilder(childPaneBuilder){this.childPaneBuilder_=childPaneBuilder;this.dispatchEvent(new tr.b.Event('request-child-pane-change'));},get childPaneBuilder(){return this.childPaneBuilder_;},appended:function(){this.rebuild();}});'use strict';(function(){var IMPORTANCE_RULES=[{condition:'size',importance:10},{condition:'page_size',importance:0},{condition:/size/,importance:5},{importance:0}];Polymer('tr-ui-a-memory-dump-allocator-details-pane',{created:function(){this.memoryAllocatorDump_=undefined;},set memoryAllocatorDump(memoryAllocatorDump){this.memoryAllocatorDump_=memoryAllocatorDump;this.scheduleRebuildPane_();},get memoryAllocatorDump(){return this.memoryAllocatorDump_;},rebuildPane_:function(){this.$.contents.textContent='';if(this.memoryAllocatorDump_===undefined){var infoText=this.ownerDocument.createElement('div');this.$.contents.appendChild(infoText);infoText.classList.add('info-text');infoText.innerText='No memory allocator dump selected';return;} var rows=this.createRows_();var columns=this.createColumns_(rows);var table=this.ownerDocument.createElement('tr-ui-b-table');this.$.contents.appendChild(table);table.supportsSelection=true;table.tableRows=rows;table.tableColumns=columns;table.rebuild();tr.ui.analysis.expandTableRowsRecursively(table);},createRows_:function(){var createAllocatorRow=function(allocatorDump){var cells=tr.b.mapItems(allocatorDump.attributes,function(attrName,attrValue){return new tr.ui.analysis.MemoryCell(attrValue);});var title=allocatorDump.name;if(title.startsWith('__')&&allocatorDump.ownedBy.length===1){var owner=allocatorDump.ownedBy[0].source;if(owner.containerMemoryDump===allocatorDump.containerMemoryDump){title=tr.ui.b.createSpan({textContent:'suballocation by '+owner.fullName,tooltip:'Suballocation name: '+allocatorDump.fullName,italic:true});}} var row={title:title,cells:cells};if(allocatorDump.children.length>0) -row.subRows=allocatorDump.children.map(createAllocatorRow);return row;};var rows=[createAllocatorRow(this.memoryAllocatorDump_)];return rows;},createColumns_:function(rows){var titleColumn={title:'Allocator',value:function(row){return row.title;},width:'200px',cmp:function(rowA,rowB){return rowA.title.localeCompare(rowB.title);}};var attributeColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,'cells');tr.ui.analysis.MemoryColumn.spaceEqually(attributeColumns);tr.ui.analysis.MemoryColumn.sortByImportance(attributeColumns,IMPORTANCE_RULES);var columns=[titleColumn].concat(attributeColumns);return columns;}});})();'use strict';(function(){var CLASSIFICATION_RULES={name:'Total',children:[{name:'Android',file:/^\/dev\/ashmem(?!\/libc malloc)/,children:[{name:'Java runtime',file:/^\/dev\/ashmem\/dalvik-/,children:[{name:'Spaces',file:/\/dalvik-(alloc|main|large object|non moving|zygote) space/,children:[{name:'Normal',file:/\/dalvik-(alloc|main)/},{name:'Large',file:/\/dalvik-large object/},{name:'Zygote',file:/\/dalvik-zygote/},{name:'Non-moving',file:/\/dalvik-non moving/}]},{name:'Linear Alloc',file:/\/dalvik-LinearAlloc/},{name:'Indirect Reference Table',file:/\/dalvik-indirect.ref/},{name:'Cache',file:/\/dalvik-jit-code-cache/},{name:'Accounting'}]},{name:'Cursor',file:/\/CursorWindow/},{name:'Ashmem'}]},{name:'Native heap',file:/^((\[heap\])|(\[anon:)|(\/dev\/ashmem\/libc malloc)|$)/},{name:'Stack',file:/^\[stack/},{name:'Files',file:/\.((((jar)|(apk)|(ttf)|(odex)|(oat)|(arg))$)|(dex)|(so))/,children:[{name:'so',file:/\.so/},{name:'jar',file:/\.jar$/},{name:'apk',file:/\.apk$/},{name:'ttf',file:/\.ttf$/},{name:'dex',file:/\.((dex)|(odex$))/},{name:'oat',file:/\.oat$/},{name:'art',file:/\.art$/}]},{name:'Devices',file:/(^\/dev\/)|(anon_inode:dmabuf)/,children:[{name:'GPU',file:/\/((nv)|(mali)|(kgsl))/},{name:'DMA',file:/anon_inode:dmabuf/}]},{name:'Discounted tracing overhead',file:/\[discounted tracing overhead\]/}]};function createEmptyRow(rule){var row={title:rule.name,rule:rule,cells:{},subRows:[]};if(rule.children!==undefined) +row.subRows=allocatorDump.children.map(createAllocatorRow);return row;};var rows=[createAllocatorRow(this.memoryAllocatorDump_)];return rows;},createColumns_:function(rows){var titleColumn={title:'Allocator',value:function(row){return row.title;},width:'200px',cmp:function(rowA,rowB){return rowA.title.localeCompare(rowB.title);}};var attributeColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,'cells');tr.ui.analysis.MemoryColumn.spaceEqually(attributeColumns);tr.ui.analysis.MemoryColumn.sortByImportance(attributeColumns,IMPORTANCE_RULES);var columns=[titleColumn].concat(attributeColumns);return columns;}});})();'use strict';(function(){var CLASSIFICATION_RULES={name:'Total',children:[{name:'Android',file:/^\/dev\/ashmem(?!\/libc malloc)/,children:[{name:'Java runtime',file:/^\/dev\/ashmem\/dalvik-/,children:[{name:'Spaces',file:/\/dalvik-(alloc|main|large object|non moving|zygote) space/,children:[{name:'Normal',file:/\/dalvik-(alloc|main)/},{name:'Large',file:/\/dalvik-large object/},{name:'Zygote',file:/\/dalvik-zygote/},{name:'Non-moving',file:/\/dalvik-non moving/}]},{name:'Linear Alloc',file:/\/dalvik-LinearAlloc/},{name:'Indirect Reference Table',file:/\/dalvik-indirect.ref/},{name:'Cache',file:/\/dalvik-jit-code-cache/},{name:'Accounting'}]},{name:'Cursor',file:/\/CursorWindow/},{name:'Ashmem'}]},{name:'Native heap',file:/^((\[heap\])|(\[anon:)|(\/dev\/ashmem\/libc malloc)|(\[discounted tracing overhead\])|$)/},{name:'Stack',file:/^\[stack/},{name:'Files',file:/\.((((jar)|(apk)|(ttf)|(odex)|(oat)|(arg))$)|(dex)|(so))/,children:[{name:'so',file:/\.so/},{name:'jar',file:/\.jar$/},{name:'apk',file:/\.apk$/},{name:'ttf',file:/\.ttf$/},{name:'dex',file:/\.((dex)|(odex$))/},{name:'oat',file:/\.oat$/},{name:'art',file:/\.art$/}]},{name:'Devices',file:/(^\/dev\/)|(anon_inode:dmabuf)/,children:[{name:'GPU',file:/\/((nv)|(mali)|(kgsl))/},{name:'DMA',file:/anon_inode:dmabuf/}]}]};function createEmptyRow(rule){var row={title:rule.name,rule:rule,cells:{},subRows:[]};if(rule.children!==undefined) row.subRows=rule.children.map(createEmptyRow);return row;} function hexString(address,is64BitAddress){var hexPadding=is64BitAddress?'0000000000000000':'00000000';if(address===undefined) return undefined;return(hexPadding+address.toString(16)).substr(-hexPadding.length);} @@ -4041,15 +4134,16 @@ function vmRegionMatchesChildRule(childRule){var fileRegExp=childRule.file;if(fi return true;return fileRegExp.test(vmRegion.mappedFile);} var matchedChildRuleIndex=tr.b.findFirstIndexInArray(rule.children,vmRegionMatchesChildRule);if(matchedChildRuleIndex===-1){matchedChildRuleIndex=rule.children.length;if(matchedChildRuleIndex>=row.subRows.length){row.subRows.push({title:'Other',cells:{},subRows:[]});}} classifyVMRegion(row.subRows[matchedChildRuleIndex],vmRegion,is64BitAddress);} -Polymer('tr-ui-a-memory-dump-vm-regions-details-pane',{created:function(){this.vmRegions_=undefined;},ready:function(){this.updateContents_();},set vmRegions(vmRegions){this.vmRegions_=vmRegions;this.updateContents_();},get vmRegions(){return this.vmRegions_;},updateContents_:function(){this.$.contents.textContent='';if(this.vmRegions_===undefined){var infoText=this.ownerDocument.createElement('div');this.$.contents.appendChild(infoText);infoText.classList.add('info-text');infoText.innerText='No memory maps selected';return;} +Polymer('tr-ui-a-memory-dump-vm-regions-details-pane',{created:function(){this.vmRegions_=undefined;},set vmRegions(vmRegions){this.vmRegions_=vmRegions;this.scheduleRebuildPane_();},get vmRegions(){return this.vmRegions_;},rebuildPane_:function(){this.$.contents.textContent='';if(this.vmRegions_===undefined){var infoText=this.ownerDocument.createElement('div');this.$.contents.appendChild(infoText);infoText.classList.add('info-text');infoText.innerText='No memory maps selected';return;} var rows=this.createRows_();var columns=this.createColumns_(rows);var table=this.ownerDocument.createElement('tr-ui-b-table');this.$.contents.appendChild(table);table.supportsSelection=true;table.tableRows=rows;table.tableColumns=columns;table.rebuild();tr.ui.analysis.expandTableRowsRecursively(table);},createRows_:function(){var is64BitAddress=this.vmRegions_.some(function(vmRegion){if(vmRegion.startAddress===undefined) return;return vmRegion.startAddress>=4294967296;});var rootRow=createEmptyRow(CLASSIFICATION_RULES);this.vmRegions_.map(function(vmRegion){classifyVMRegion(rootRow,vmRegion,is64BitAddress);});tr.ui.analysis.aggregateTableRowCellsRecursively(rootRow,'cells');return[rootRow];},createColumns_:function(rows){var titleColumn={title:'Mapped file',value:function(row){return row.title;},width:'200px',cmp:function(rowA,rowB){return rowA.title.localeCompare(rowB.title);}};var attributeColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,'cells');tr.ui.analysis.MemoryColumn.spaceEqually(attributeColumns);var columns=[titleColumn].concat(attributeColumns);return columns;}});})();'use strict';Polymer('tr-ui-b-view-specific-brushing-state',{get viewId(){return this.getAttribute('view-id');},set viewId(viewId){this.setAttribute('view-id',viewId);},get:function(){var viewId=this.viewId;if(!viewId) throw new Error('Element must have a view-id attribute!');var brushingStateController=tr.c.BrushingStateController.getControllerForElement(this);if(!brushingStateController) return undefined;return brushingStateController.getViewSpecificBrushingState(viewId);},set:function(state){var viewId=this.viewId;if(!viewId) throw new Error('Element must have a view-id attribute!');var brushingStateController=tr.c.BrushingStateController.getControllerForElement(this);if(!brushingStateController) -return;brushingStateController.changeViewSpecificBrushingState(viewId,state);}});'use strict';(function(){var IMPORTANCE_RULES=[{condition:'tracing',importance:0},{importance:1}];var LINK_SYMBOL=String.fromCharCode(9903);Polymer('tr-ui-a-memory-dump-overview-pane',{created:function(){this.processMemoryDumps_=undefined;},ready:function(){this.$.table.supportsSelection=true;this.$.table.cellSelectionMode=true;this.$.table.rowHighlightEnabled=true;this.$.table.addEventListener('selection-changed',function(tableEvent){tableEvent.stopPropagation();var paneEvent=new tr.b.Event('selected-memory-cell-changed');this.dispatchEvent(paneEvent);this.storeSelection_();}.bind(this));},set processMemoryDumps(processMemoryDumps){this.processMemoryDumps_=processMemoryDumps;this.updateContents_();},get processMemoryDumps(){return this.processMemoryDumps_;},get selectedMemoryCell(){var selectedTableRow=this.$.table.selectedTableRow;if(!selectedTableRow) +return;brushingStateController.changeViewSpecificBrushingState(viewId,state);}});'use strict';(function(){var IMPORTANCE_RULES=[{condition:'tracing',importance:0},{importance:1}];var LINK_SYMBOL=String.fromCharCode(9903);Polymer('tr-ui-a-memory-dump-overview-pane',{created:function(){this.processMemoryDumps_=undefined;},ready:function(){this.$.table.supportsSelection=true;this.$.table.cellSelectionMode=true;this.$.table.rowHighlightEnabled=true;this.$.table.addEventListener('selection-changed',function(tableEvent){tableEvent.stopPropagation();this.changeChildPane_();}.bind(this));},set processMemoryDumps(processMemoryDumps){this.processMemoryDumps_=processMemoryDumps;this.scheduleRebuildPane_();},get processMemoryDumps(){return this.processMemoryDumps_;},get selectedMemoryCell(){var selectedTableRow=this.$.table.selectedTableRow;if(!selectedTableRow) return undefined;var selectedColumnIndex=this.$.table.selectedColumnIndex;if(selectedColumnIndex===undefined) -return undefined;var selectedColumn=this.$.table.tableColumns[selectedColumnIndex];var selectedMemoryCell=selectedColumn.cell(selectedTableRow);return selectedMemoryCell;},updateContents_:function(){var processMemoryDumps=this.processMemoryDumps_||[];var rows=processMemoryDumps.map(function(processMemoryDump){function buildVMRegionsPane(){var pane=document.createElement('tr-ui-a-memory-dump-vm-regions-details-pane');pane.vmRegions=processMemoryDump.mostRecentVmRegions;return pane;} +return undefined;var selectedColumn=this.$.table.tableColumns[selectedColumnIndex];var selectedMemoryCell=selectedColumn.cell(selectedTableRow);return selectedMemoryCell;},changeChildPane_:function(){this.storeSelection_();var builder=undefined;if(this.selectedMemoryCell!==undefined) +builder=this.selectedMemoryCell.buildDetailsPane;this.childPaneBuilder=builder;},rebuildPane_:function(){var processMemoryDumps=this.processMemoryDumps_||[];var rows=processMemoryDumps.map(function(processMemoryDump){function buildVMRegionsPane(){var pane=document.createElement('tr-ui-a-memory-dump-vm-regions-details-pane');pane.vmRegions=processMemoryDump.mostRecentVmRegions;return pane;} var usedMemorySizes={};var totalResident=processMemoryDump.totalResidentBytes;if(totalResident!==undefined){var cell=new tr.ui.analysis.MemoryCell(new tr.model.ScalarAttribute('bytes',totalResident));cell.buildDetailsPane=buildVMRegionsPane;usedMemorySizes['Total resident']=cell;} function addByteStatCell(byteStatName,columnTitle){var byteStat=processMemoryDump.getMostRecentTotalVmRegionStat(byteStatName);if(byteStat!==undefined){var attr=new tr.model.ScalarAttribute('bytes',byteStat);if(!processMemoryDump.hasOwnVmRegions){attr.infos.push(new tr.model.AttributeInfo(tr.model.AttributeInfoType.LINK,'Older value (process did not dump memory maps).'));attr.isOlderValue=true;} var cell=new tr.ui.analysis.MemoryCell(attr);cell.buildDetailsPane=buildVMRegionsPane;usedMemorySizes[columnTitle]=cell;}} @@ -4062,8 +4156,18 @@ selectedRowTitle=selectedRow.title;var selectedColumnName;var selectedColumnInde this.$.state.set({rowTitle:selectedRowTitle,columnName:selectedColumnName});},restoreSelection_:function(){var settings=this.$.state.get();if(settings===undefined||settings.rowTitle===undefined||settings.columnName===undefined) return;var selectedColumnName=settings.columnName;var selectedColumnIndex=tr.b.findFirstIndexInArray(this.$.table.tableColumns,function(column){return column.name===selectedColumnName;});if(selectedColumnIndex<0) return;var selectedRowTitle=settings.rowTitle;var selectedRow=tr.b.findFirstInArray(this.$.table.tableRows,function(row){return row.title===selectedRowTitle;});if(selectedRow===undefined) -return;this.$.table.selectedTableRow=selectedRow;this.$.table.selectedColumnIndex=selectedColumnIndex;}});})();'use strict';Polymer('tr-ui-a-memory-dump-view',{created:function(){this.processMemoryDumps_=undefined;},ready:function(){this.$.overview_pane.addEventListener('selected-memory-cell-changed',this.updateDetailsPane_.bind(this));},set processMemoryDumps(processMemoryDumps){this.processMemoryDumps_=processMemoryDumps;this.$.overview_pane.processMemoryDumps=this.processMemoryDumps_;this.updateDetailsPane_();},get processMemoryDumps(){return this.processMemoryDumps_;},updateDetailsPane_:function(){this.$.details_pane_container.textContent='';var selectedMemoryCell=this.$.overview_pane.selectedMemoryCell;if(!selectedMemoryCell||!selectedMemoryCell.buildDetailsPane) -return;this.$.details_pane_container.appendChild(selectedMemoryCell.buildDetailsPane());}});'use strict';Polymer('tr-ui-a-single-process-memory-dump-sub-view',{set selection(selection){if(selection.length!==1) +return;this.$.table.selectedTableRow=selectedRow;this.$.table.selectedColumnIndex=selectedColumnIndex;}});})();'use strict';Polymer('tr-ui-a-stacked-pane-view',{setPaneBuilder:function(paneBuilder,opt_parentPane){var paneContainer=this.$.pane_container;if(opt_parentPane){if(!(opt_parentPane instanceof HTMLElement)) +throw new Error('Parent pane must be an HTML element');if(opt_parentPane.parentElement!==paneContainer) +throw new Error('Parent pane must be a child of the pane container');} +while(paneContainer.lastElementChild!==null&&paneContainer.lastElementChild!==opt_parentPane){var removedPane=this.$.pane_container.lastElementChild;var listener=this.listeners_.get(removedPane);if(listener===undefined) +throw new Error('No listener associated with pane');this.listeners_.delete(removedPane);removedPane.removeEventListener('request-child-pane-change',listener);paneContainer.removeChild(removedPane);} +if(opt_parentPane&&opt_parentPane.parentElement!==paneContainer) +throw new Error('Parent pane was removed from the pane container');if(!paneBuilder) +return;var pane=paneBuilder();if(!pane) +return;if(!(pane instanceof HTMLElement)) +throw new Error('Pane must be an HTML element');var listener=function(event){this.setPaneBuilder(pane.childPaneBuilder,pane);}.bind(this);if(!this.listeners_){this.listeners_=new WeakMap();} +this.listeners_.set(pane,listener);pane.addEventListener('request-child-pane-change',listener);paneContainer.appendChild(pane);pane.appended();},rebuild:function(){var currentPane=this.$.pane_container.firstElementChild;while(currentPane){currentPane.rebuild();currentPane=currentPane.nextElementSibling;}},get panesForTesting(){var panes=[];var currentChild=this.$.pane_container.firstElementChild;while(currentChild){panes.push(currentChild);currentChild=currentChild.nextElementSibling;} +return panes;}});'use strict';Polymer('tr-ui-a-memory-dump-view',{created:function(){this.processMemoryDumps_=undefined;},set processMemoryDumps(processMemoryDumps){this.processMemoryDumps_=processMemoryDumps;this.setPaneBuilder(function(){var overviewPane=document.createElement('tr-ui-a-memory-dump-overview-pane');overviewPane.processMemoryDumps=this.processMemoryDumps_;return overviewPane;}.bind(this));},get processMemoryDumps(){return this.processMemoryDumps_;}});'use strict';Polymer('tr-ui-a-single-process-memory-dump-sub-view',{set selection(selection){if(selection.length!==1) throw new Error('Only supports a single process memory dump');if(!(selection[0]instanceof tr.model.ProcessMemoryDump)) throw new Error('Only supports process memory dumps');this.currentSelection_=selection;this.$.memory_dump_view.processMemoryDumps=[selection[0]];},get selection(){return this.currentSelection_;},get requiresTallView(){return true;}});'use strict';Polymer('tr-ui-a-multi-process-memory-dump-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;selection=tr.b.asArray(selection).sort(tr.b.Range.compareByMinTimes);var ownerDocument=this.ownerDocument;var table=this.$.content;table.tableColumns=[{title:'Dump',value:function(row){var linkEl=document.createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.model.EventSet(row);});var spanEl=document.createElement('span');spanEl.textContent='Process memory dump at ';linkEl.appendChild(spanEl);linkEl.appendChild(tr.ui.units.createTimeStampSpan(row.start,{ownerDocument:ownerDocument}));return linkEl;}}];table.showHeader=false;table.tableRows=selection;table.rebuild();}});'use strict';Polymer('tr-ui-a-single-global-memory-dump-sub-view',{set selection(selection){if(selection.length!==1) throw new Error('Only supports a single global memory dump');if(!(selection[0]instanceof tr.model.GlobalMemoryDump)) @@ -4111,23 +4215,11 @@ var event=new tr.b.Event('item-mousemove');event.data=this.data_[index];event.in return;this.chart_=this.createChart_(data);this.$.content.appendChild(this.chart_);},createChart_:function(data){var chart=new tr.ui.b.LineChart();var width=document.body.clientWidth*CHART_WIDTH_FRACTION_OF_BODY;chart.setSize({width:width,height:chart.height});chart.chartTitle=CHART_TITLE;chart.data=data;return chart;},clearChart_:function(){var content=this.$.content;while(content.firstChild) content.removeChild(content.firstChild);this.chart_=undefined;},getDataForLineChart_:function(){var sortedSamples=this.sortSamplesByTimestampAscending_(this.samples);var vSyncTimestamps=this.vSyncTimestamps.slice();var lastVSyncTimestamp=undefined;var points=[];var frameNumber=0;sortedSamples.forEach(function(sample){while(vSyncTimestamps.length>0&&vSyncTimestamps[0]<=sample.start){lastVSyncTimestamp=vSyncTimestamps.shift();frameNumber++;} if(lastVSyncTimestamp===undefined) -return;var point={x:sample.start-lastVSyncTimestamp};point['f'+frameNumber]=sample.power;points.push(point);});return points;},sortSamplesByTimestampAscending_:function(samples){return samples.toArray().sort(function(smpl1,smpl2){return smpl1.start-smpl2.start;});}});'use strict';tr.exportTo('tr.b.units',function(){function EnergyInJoules(numJoules){this.numJoules_=numJoules;};EnergyInJoules.prototype={toString:function(){return EnergyInJoules.format(this.numJoules_);}};EnergyInJoules.format=function(numJoules){return numJoules.toLocaleString(undefined,{minimumFractionDigits:3})+' J';};return{EnergyInJoules:EnergyInJoules};});'use strict';tr.exportTo('tr.b.units',function(){function PowerInWatts(numWatts){this.numWatts_=numWatts;};PowerInWatts.prototype={toString:function(){return PowerInWatts.format(this.numWatts_);}};PowerInWatts.format=function(numWatts){return(numWatts*1000.0).toLocaleString(undefined,{minimumFractionDigits:3})+' mW';};return{PowerInWatts:PowerInWatts};});'use strict';Polymer('tr-ui-a-power-sample-summary-table',{ready:function(){this.$.table.tableColumns=[{title:'Min power',width:'100px',value:function(row){return tr.b.units.PowerInWatts.format(row.min/1000.0);}},{title:'Max power',width:'100px',value:function(row){return tr.b.units.PowerInWatts.format(row.max/1000.0);}},{title:'Time-weighted average',width:'100px',value:function(row){return tr.b.units.PowerInWatts.format(row.timeWeightedAverage/1000.0);}},{title:'Energy consumed',width:'100px',value:function(row){return tr.b.units.EnergyInJoules.format(row.energyConsumed);}},{title:'Sample count',width:'100%',value:function(row){return row.sampleCount;}}];this.samples=new tr.model.EventSet();},get samples(){return this.samples_;},set samples(samples){if(samples===this.samples) +return;var point={x:sample.start-lastVSyncTimestamp};point['f'+frameNumber]=sample.power;points.push(point);});return points;},sortSamplesByTimestampAscending_:function(samples){return samples.toArray().sort(function(smpl1,smpl2){return smpl1.start-smpl2.start;});}});'use strict';Polymer('tr-ui-a-power-sample-summary-table',{ready:function(){this.$.table.tableColumns=[{title:'Min power',width:'100px',value:function(row){return tr.b.u.Units.powerInWatts.format(row.min/1000.0);}},{title:'Max power',width:'100px',value:function(row){return tr.b.u.Units.powerInWatts.format(row.max/1000.0);}},{title:'Time-weighted average',width:'100px',value:function(row){return tr.b.u.Units.powerInWatts.format(row.timeWeightedAverage/1000.0);}},{title:'Energy consumed',width:'100px',value:function(row){return tr.b.u.Units.energyInJoules.format(row.energyConsumed);}},{title:'Sample count',width:'100%',value:function(row){return row.sampleCount;}}];this.samples=new tr.model.EventSet();},get samples(){return this.samples_;},set samples(samples){if(samples===this.samples) return;this.samples_=(samples===undefined)?new tr.model.EventSet():samples;this.updateContents_();},updateContents_:function(){if(this.samples.length===0){this.$.table.tableRows=[];}else{this.$.table.tableRows=[{min:this.getMin(),max:this.getMax(),timeWeightedAverage:this.getTimeWeightedAverage(),energyConsumed:this.getEnergyConsumed(),sampleCount:this.samples.length}];} this.$.table.rebuild();},getMin:function(){return Math.min.apply(null,this.samples.map(function(sample){return sample.power;}));},getMax:function(){return Math.max.apply(null,this.samples.map(function(sample){return sample.power;}));},getTimeWeightedAverage:function(){var energyConsumed=this.getEnergyConsumed();if(energyConsumed==='N/A') return'N/A';return this.getEnergyConsumed()/this.samples.bounds.duration*1000;},getEnergyConsumed:function(){if(this.samples.length<2) -return'N/A';var bounds=this.samples.bounds;return this.samples[0].series.getEnergyConsumed(bounds.min,bounds.max);}});'use strict';var EventSet=tr.model.EventSet;Polymer('tr-ui-a-power-sample-table',{ready:function(){this.$.table.tableColumns=[{title:'Time',width:'100px',value:function(row){return tr.ui.units.createTimeStampSpan(row.start);}},{title:'Power (mW)',width:'100%',value:function(row){return row.power;}}];this.samples=new EventSet();},get samples(){return this.samples_;},set samples(samples){this.samples_=(samples===undefined)?new EventSet():samples;this.updateContents_();},updateContents_:function(){this.$.table.tableRows=this.samples.toArray();this.$.table.rebuild();}});'use strict';Polymer('tr-ui-a-multi-power-sample-sub-view',{ready:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},updateContents_:function(){var samples=this.selection;var vSyncTimestamps=(this.selection===undefined)?[]:this.selection[0].series.device.vSyncTimestamps;this.$.summaryTable.samples=samples;this.$.samplesTable.samples=samples;this.$.chart.setData(this.selection,vSyncTimestamps);}});'use strict';tr.exportTo('tr.ui.b',function(){Object.observe(Polymer.elements,clearPolymerElementCaches);var elementsByName=undefined;var elementsThatExtend=undefined;var elementSubclasses=undefined;function clearPolymerElementCaches(){elementsByName={};elementsThatExtend=undefined;elementSubclasses={};} -function buildElementMapsIfNeeded(){if(elementsThatExtend!==undefined&&elementsByName!==undefined) -return;elementsByName={};elementsThatExtend={};Polymer.elements.forEach(function(element){if(elementsByName[element.name]) -throw new Error('Something is strange: dupe polymer element names');elementsByName[element.name]=element;if(element.extends){if(elementsThatExtend[element.extends]===undefined) -elementsThatExtend[element.extends]=[];elementsThatExtend[element.extends].push(element.name);}});} -function getPolymerElementNamed(tagName){buildElementMapsIfNeeded();return elementsByName[tagName];} -function getPolymerElementsThatSubclass(tagName){if(Polymer.waitingFor().length){throw new Error('There are unresolved polymer elements. '+'Wait until Polymer.whenReady');} -buildElementMapsIfNeeded();var element=getPolymerElementNamed(tagName);if(!element) -throw new Error(tagName+' is not a polymer element');if(elementSubclasses===undefined) -elementSubclasses={};if(elementSubclasses[tagName]===undefined){var immediateSubElements=elementsThatExtend[element.name];var allSubElements=[];if(immediateSubElements!==undefined&&immediateSubElements.length){immediateSubElements.forEach(function(subElement){allSubElements.push(subElement);allSubElements.push.apply(allSubElements,getPolymerElementsThatSubclass(subElement));});} -elementSubclasses[tagName]=allSubElements;} -return elementSubclasses[tagName];} -return{getPolymerElementNamed:getPolymerElementNamed,getPolymerElementsThatSubclass:getPolymerElementsThatSubclass};});'use strict';(function(){var EventRegistry=tr.model.EventRegistry;Polymer('tr-ui-a-analysis-view',{ready:function(){this.tabView_=document.createElement('tr-ui-a-tab-view');this.tabView_.style.flex='1 1 auto';this.appendChild(this.tabView_);this.brushingStateController_=undefined;this.onSelectedTabChange_=this.onSelectedTabChange_.bind(this);this.onSelectionChanged_=this.onSelectionChanged_.bind(this);this.lastSeenSelection_=new tr.model.EventSet();},set tallMode(value){if(value) +return'N/A';var bounds=this.samples.bounds;return this.samples[0].series.getEnergyConsumed(bounds.min,bounds.max);}});'use strict';var EventSet=tr.model.EventSet;Polymer('tr-ui-a-power-sample-table',{ready:function(){this.$.table.tableColumns=[{title:'Time',width:'100px',value:function(row){return tr.ui.units.createTimeStampSpan(row.start);}},{title:'Power (mW)',width:'100%',value:function(row){return row.power;}}];this.samples=new EventSet();},get samples(){return this.samples_;},set samples(samples){this.samples_=(samples===undefined)?new EventSet():samples;this.updateContents_();},updateContents_:function(){this.$.table.tableRows=this.samples.toArray();this.$.table.rebuild();}});'use strict';Polymer('tr-ui-a-multi-power-sample-sub-view',{ready:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},updateContents_:function(){var samples=this.selection;var vSyncTimestamps=(this.selection===undefined)?[]:this.selection[0].series.device.vSyncTimestamps;this.$.summaryTable.samples=samples;this.$.samplesTable.samples=samples;this.$.chart.setData(this.selection,vSyncTimestamps);}});'use strict';(function(){var EventRegistry=tr.model.EventRegistry;Polymer('tr-ui-a-analysis-view',{ready:function(){this.tabView_=document.createElement('tr-ui-a-tab-view');this.tabView_.style.flex='1 1 auto';this.appendChild(this.tabView_);this.brushingStateController_=undefined;this.onSelectedTabChange_=this.onSelectedTabChange_.bind(this);this.onSelectionChanged_=this.onSelectionChanged_.bind(this);this.lastSeenSelection_=new tr.model.EventSet();},set tallMode(value){if(value) this.classList.add('tall-mode');else this.classList.remove('tall-mode');},get tallMode(){return this.classList.contains('tall-mode');},get tabView(){return this.tabView_;},get brushingStateController(){return this.brushingStateController_;},set brushingStateController(brushingStateController){if(this.brushingStateController){this.brushingStateController_.removeEventListener('change',this.onSelectionChanged_);} this.brushingStateController_=brushingStateController;if(this.brushingStateController){this.brushingStateController_.addEventListener('change',this.onSelectionChanged_);} @@ -4654,7 +4746,7 @@ if(this.viewport_.interestRange.min==selectionBounds.min&&this.viewport_.interes this.viewport_.interestRange.reset();else this.viewport_.interestRange.set(selectionBounds);},toggleHighDetails_:function(){this.viewport_.highDetails=!this.viewport_.highDetails;},hideDragBox_:function(){this.$.drag_box.style.left='-1000px';this.$.drag_box.style.top='-1000px';this.$.drag_box.style.width=0;this.$.drag_box.style.height=0;},setDragBoxPosition_:function(xStart,yStart,xEnd,yEnd){var loY=Math.min(yStart,yEnd);var hiY=Math.max(yStart,yEnd);var loX=Math.min(xStart,xEnd);var hiX=Math.max(xStart,xEnd);var modelTrackRect=this.modelTrack_.getBoundingClientRect();var dragRect={left:loX,top:loY,width:hiX-loX,height:hiY-loY};dragRect.right=dragRect.left+dragRect.width;dragRect.bottom=dragRect.top+dragRect.height;var modelTrackContainerRect=this.modelTrackContainer_.getBoundingClientRect();var clipRect={left:modelTrackContainerRect.left,top:modelTrackContainerRect.top,right:modelTrackContainerRect.right,bottom:modelTrackContainerRect.bottom};var headingWidth=window.getComputedStyle(this.querySelector('tr-ui-heading')).width;var trackTitleWidth=parseInt(headingWidth);clipRect.left=clipRect.left+trackTitleWidth;var intersectRect_=function(r1,r2){if(r2.left>r1.right||r2.right<r1.left||r2.top>r1.bottom||r2.bottom<r1.top) return false;var results={};results.left=Math.max(r1.left,r2.left);results.top=Math.max(r1.top,r2.top);results.right=Math.min(r1.right,r2.right);results.bottom=Math.min(r1.bottom,r2.bottom);results.width=results.right-results.left;results.height=results.bottom-results.top;return results;} -var finalDragBox=intersectRect_(clipRect,dragRect);this.$.drag_box.style.left=finalDragBox.left+'px';this.$.drag_box.style.width=finalDragBox.width+'px';this.$.drag_box.style.top=finalDragBox.top+'px';this.$.drag_box.style.height=finalDragBox.height+'px';this.$.drag_box.style.whiteSpace='nowrap';var pixelRatio=window.devicePixelRatio||1;var canv=this.modelTrackContainer_.canvas;var dt=this.viewport_.currentDisplayTransform;var loWX=dt.xViewToWorld((loX-canv.offsetLeft)*pixelRatio);var hiWX=dt.xViewToWorld((hiX-canv.offsetLeft)*pixelRatio);this.$.drag_box.textContent=tr.b.units.TimeDuration.format(hiWX-loWX);var e=new tr.b.Event('selectionChanging');e.loWX=loWX;e.hiWX=hiWX;this.dispatchEvent(e);},onGridToggle_:function(left){var selection=this.brushingStateController_.selection;var tb=left?selection.bounds.min:selection.bounds.max;if(this.viewport_.gridEnabled&&this.viewport_.gridSide===left&&this.viewport_.gridInitialTimebase===tb){this.viewport_.gridside=undefined;this.viewport_.gridEnabled=false;this.viewport_.gridInitialTimebase=undefined;return;} +var finalDragBox=intersectRect_(clipRect,dragRect);this.$.drag_box.style.left=finalDragBox.left+'px';this.$.drag_box.style.width=finalDragBox.width+'px';this.$.drag_box.style.top=finalDragBox.top+'px';this.$.drag_box.style.height=finalDragBox.height+'px';this.$.drag_box.style.whiteSpace='nowrap';var pixelRatio=window.devicePixelRatio||1;var canv=this.modelTrackContainer_.canvas;var dt=this.viewport_.currentDisplayTransform;var loWX=dt.xViewToWorld((loX-canv.offsetLeft)*pixelRatio);var hiWX=dt.xViewToWorld((hiX-canv.offsetLeft)*pixelRatio);this.$.drag_box.textContent=tr.b.u.TimeDuration.format(hiWX-loWX);var e=new tr.b.Event('selectionChanging');e.loWX=loWX;e.hiWX=hiWX;this.dispatchEvent(e);},onGridToggle_:function(left){var selection=this.brushingStateController_.selection;var tb=left?selection.bounds.min:selection.bounds.max;if(this.viewport_.gridEnabled&&this.viewport_.gridSide===left&&this.viewport_.gridInitialTimebase===tb){this.viewport_.gridside=undefined;this.viewport_.gridEnabled=false;this.viewport_.gridInitialTimebase=undefined;return;} var numIntervalsSinceStart=Math.ceil((tb-this.model_.bounds.min)/this.viewport_.gridStep_);this.viewport_.gridEnabled=true;this.viewport_.gridSide=left;this.viewport_.gridInitialTimebase=tb;this.viewport_.gridTimebase=tb- (numIntervalsSinceStart+1)*this.viewport_.gridStep_;},storeLastMousePos_:function(e){this.lastMouseViewPos_=this.extractRelativeMousePosition_(e);},storeLastTouchPositions_:function(e){this.lastTouchViewPositions_=this.extractRelativeTouchPositions_(e);},extractRelativeMousePosition_:function(e){var canv=this.modelTrackContainer_.canvas;return{x:e.clientX-canv.offsetLeft,y:e.clientY-canv.offsetTop};},extractRelativeTouchPositions_:function(e){var canv=this.modelTrackContainer_.canvas;var touches=[];for(var i=0;i<e.touches.length;++i){touches.push({x:e.touches[i].clientX-canv.offsetLeft,y:e.touches[i].clientY-canv.offsetTop});} return touches;},storeInitialMouseDownPos_:function(e){var position=this.extractRelativeMousePosition_(e);this.mouseViewPosAtMouseDown_.x=position.x;this.mouseViewPosAtMouseDown_.y=position.y;},focusElements_:function(){this.$.hotkey_controller.childRequestsGeneralFocus(this);},storeInitialInteractionPositionsAndFocus_:function(e){this.storeInitialMouseDownPos_(e);this.storeLastMousePos_(e);this.focusElements_();},onBeginPanScan_:function(e){var vp=this.viewport_;this.viewportDisplayTransformAtMouseDown_=vp.currentDisplayTransform.clone();this.isPanningAndScanning_=true;this.storeInitialInteractionPositionsAndFocus_(e);e.preventDefault();},onUpdatePanScan_:function(e){if(!this.isPanningAndScanning_) @@ -4726,7 +4818,7 @@ return undefined;},updateContents_:function(){var previouslyActivePanelType=this supported.reason;labelEl.style.display='none';} this.tabStrip_.appendChild(labelEl);},this);if(previouslyActivePanelType&&supportedPanelTypes.indexOf(previouslyActivePanelType)!=-1){this.activePanelType=previouslyActivePanelType;this.setAttribute('expanded',true);}else{this.activePanelContainer_.textContent='';this.removeAttribute('expanded');}},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(range){if(range==undefined) throw new Error('Must not be undefined');this.rangeOfInterest_=range;if(this.activePanel) -this.activePanel.rangeOfInterest=range;}});'use strict';Polymer('tr-ui-timeline-view-help-overlay',{ready:function(){var mod=tr.isMac?'cmd ':'ctrl';var spans=this.shadowRoot.querySelectorAll('span.mod');for(var i=0;i<spans.length;i++){spans[i].textContent=mod;}}});'use strict';tr.exportTo('tr.b.units',function(){function GenericTable(items){if(items!==undefined) +this.activePanel.rangeOfInterest=range;}});'use strict';Polymer('tr-ui-timeline-view-help-overlay',{ready:function(){var mod=tr.isMac?'cmd ':'ctrl';var spans=this.shadowRoot.querySelectorAll('span.mod');for(var i=0;i<spans.length;i++){spans[i].textContent=mod;}}});'use strict';tr.exportTo('tr.b.u',function(){function GenericTable(items){if(items!==undefined) this.items=items;else this.items=[];};GenericTable.prototype={};return{GenericTable:GenericTable};});'use strict';tr.exportTo('tr.ui.units',function(){var ArrayOfNumbersSummaryModes={AVERAGE_MODE:'average-mode',TOTAL_MODE:'total-mode'};return{ArrayOfNumbersSummaryModes:ArrayOfNumbersSummaryModes};});'use strict';Polymer('tr-ui-u-array-of-numbers-span',{created:function(){this.numbers_=undefined;this.summaryMode_=tr.ui.units.ArrayOfNumbersSummaryModes.AVERAGE_MODE;},get summaryMode(){return this.summaryMode_;},set summaryMode(summaryMode){this.summaryMode_=summaryMode;this.updateContents_();},get numbers(){return this.numbers_;},set numbers(numbers){if(numbers===undefined){this.numbers_=undefined;this.updateContents_();return;} if(!(numbers instanceof Array)) @@ -4754,7 +4846,7 @@ this.columnMode_=TEXT_COLUMN_MODE;},value:function(item){var fieldValue=item[thi if(fieldValue===undefined) return'-';if(fieldValue instanceof HTMLElement) return fieldValue;if(fieldValue instanceof Object){var gov=document.createElement('tr-ui-a-generic-object-view');gov.object=fieldValue;return gov;} -return fieldValue;}};Polymer('tr-ui-u-generic-table-view',{created:function(){this.items_=undefined;this.importantColumNames_=[];},get items(){return this.items_;},set items(itemsOrGenericTable){if(itemsOrGenericTable===undefined){this.items_=undefined;}else if(itemsOrGenericTable instanceof Array){this.items_=itemsOrGenericTable;}else if(itemsOrGenericTable instanceof tr.b.units.GenericTable){this.items_=itemsOrGenericTable.items;} +return fieldValue;}};Polymer('tr-ui-u-generic-table-view',{created:function(){this.items_=undefined;this.importantColumNames_=[];},get items(){return this.items_;},set items(itemsOrGenericTable){if(itemsOrGenericTable===undefined){this.items_=undefined;}else if(itemsOrGenericTable instanceof Array){this.items_=itemsOrGenericTable;}else if(itemsOrGenericTable instanceof tr.b.u.GenericTable){this.items_=itemsOrGenericTable.items;} this.updateContents_();},get importantColumNames(){return this.importantColumNames_;},set importantColumNames(importantColumNames){this.importantColumNames_=importantColumNames;this.updateContents_();},createColumns_:function(){var columnsByName={};this.items_.forEach(function(item){tr.b.iterItems(item,function(itemFieldName,itemFieldValue){var colDesc=columnsByName[itemFieldName];if(colDesc!==undefined){colDesc.updateModeGivenValue(itemFieldValue);return;} colDesc=new GenericTableViewColumnDescriptor(itemFieldName,itemFieldValue);columnsByName[itemFieldName]=colDesc;},this);},this);var columns=tr.b.dictionaryValues(columnsByName);if(columns.length===0) return undefined;var isColumnNameImportant={};var importantColumNames=this.importantColumNames||[];importantColumNames.forEach(function(icn){isColumnNameImportant[icn]=true;});columns.sort(function(a,b){var iA=isColumnNameImportant[a.title]?1:0;var iB=isColumnNameImportant[b.title]?1:0;if((iB-iA)!==0) @@ -4766,8 +4858,8 @@ return[];var totalsItems={};columns.forEach(function(column){if(!column.isInNume return;var totalsItem=new GenericTableViewTotalsItem();this.items_.forEach(function(item){var fieldValue=item[column.fieldName];if(fieldValue===undefined||fieldValue===null) return;totalsItem.values.push(fieldValue);});totalsItems[column.fieldName]=totalsItem;},this);return[totalsItems];},updateContents_:function(){var columns;if(this.items_!==undefined) columns=this.createColumns_();if(!columns){this.$.table.tableColumns=[];this.$.table.tableRows=[];this.$.table.footerRows=[];return;} -this.$.table.tableColumns=columns;this.$.table.tableRows=this.items_;this.$.table.footerRows=this.createFooterRowsIfNeeded_(columns);this.$.table.rebuild();}});return{GenericTableViewTotalsItem:GenericTableViewTotalsItem,GenericTableViewColumnDescriptor:GenericTableViewColumnDescriptor};});'use strict';Polymer('tr-ui-timeline-view-metadata-overlay',{created:function(){this.metadata_=undefined;},get metadata(){return this.metadata_;},set metadata(metadata){this.metadata_=metadata;this.$.gtv.items=this.metadata_;}});'use strict';Polymer('tr-ui-u-preferred-display-unit',{ready:function(){this.unit_=undefined;},attached:function(){tr.b.units.Time.didPreferredUnitChange();},detached:function(){tr.b.units.Time.didPreferredUnitChange();},get preferredDisplayUnit(){return this.unit_;},set preferredDisplayUnit(v){if(this.unit_===v) -return;this.unit_=v;tr.b.units.Time.didPreferredUnitChange();}});'use strict';Polymer('tr-ui-timeline-view',{ready:function(){this.tabIndex=0;this.titleEl_=this.$.title;this.leftControlsEl_=this.$.left_controls;this.rightControlsEl_=this.$.right_controls;this.collapsingControlsEl_=this.$.collapsing_controls;this.sidePanelContainer_=this.$.side_panel_container;this.brushingStateController_=new tr.c.BrushingStateController(this);this.findCtl_=this.$.view_find_control;this.findCtl_.controller=new tr.ui.FindController(this.brushingStateController_);this.scriptingCtl_=document.createElement('tr-ui-scripting-control');this.scriptingCtl_.controller=new tr.c.ScriptingController(this.brushingStateController_);this.sidePanelContainer_.brushingStateController=this.brushingStateController_;if(window.tr.e&&window.tr.e.rail&&window.tr.e.rail.RAILScore){this.railScoreSpan_=document.createElement('tr-ui-e-rail-rail-score-span');this.rightControls.appendChild(this.railScoreSpan_);}else{this.railScoreSpan_=undefined;} +this.$.table.tableColumns=columns;this.$.table.tableRows=this.items_;this.$.table.footerRows=this.createFooterRowsIfNeeded_(columns);this.$.table.rebuild();},get supportsSelection(){return this.$.supportsSelection;},set supportsSelection(supportsSelection){this.$.table.supportsSelection=supportsSelection;},get rowHighlightEnabled(){return this.$.rowHighlightEnabled;},set rowHighlightEnabled(rowHighlightEnabled){this.$.table.rowHighlightEnabled=rowHighlightEnabled;}});return{GenericTableViewTotalsItem:GenericTableViewTotalsItem,GenericTableViewColumnDescriptor:GenericTableViewColumnDescriptor};});'use strict';Polymer('tr-ui-timeline-view-metadata-overlay',{created:function(){this.metadata_=undefined;},get metadata(){return this.metadata_;},set metadata(metadata){this.metadata_=metadata;this.$.gtv.items=this.metadata_;}});'use strict';Polymer('tr-ui-u-preferred-display-unit',{ready:function(){this.preferredTimeDisplayMode_=undefined;},attached:function(){tr.b.u.Units.didPreferredTimeDisplayUnitChange();},detached:function(){tr.b.u.Units.didPreferredTimeDisplayUnitChange();},get preferredTimeDisplayMode(){return this.preferredTimeDisplayMode_;},set preferredTimeDisplayMode(v){if(this.preferredTimeDisplayMode_===v) +return;this.preferredTimeDisplayMode_=v;tr.b.u.Units.didPreferredTimeDisplayUnitChange();}});'use strict';Polymer('tr-ui-timeline-view',{ready:function(){this.tabIndex=0;this.titleEl_=this.$.title;this.leftControlsEl_=this.$.left_controls;this.rightControlsEl_=this.$.right_controls;this.collapsingControlsEl_=this.$.collapsing_controls;this.sidePanelContainer_=this.$.side_panel_container;this.brushingStateController_=new tr.c.BrushingStateController(this);this.findCtl_=this.$.view_find_control;this.findCtl_.controller=new tr.ui.FindController(this.brushingStateController_);this.scriptingCtl_=document.createElement('tr-ui-scripting-control');this.scriptingCtl_.controller=new tr.c.ScriptingController(this.brushingStateController_);this.sidePanelContainer_.brushingStateController=this.brushingStateController_;if(window.tr.e&&window.tr.e.rail&&window.tr.e.rail.RAILScore){this.railScoreSpan_=document.createElement('tr-ui-e-rail-rail-score-span');this.rightControls.appendChild(this.railScoreSpan_);}else{this.railScoreSpan_=undefined;} this.optionsDropdown_=this.$.view_options_dropdown;this.optionsDropdown_.iconElement.textContent='View Options';this.showFlowEvents_=false;this.optionsDropdown_.appendChild(tr.ui.b.createCheckBox(this,'showFlowEvents','tr.ui.TimelineView.showFlowEvents',false,'Flow events'));this.highlightVSync_=false;this.highlightVSyncCheckbox_=tr.ui.b.createCheckBox(this,'highlightVSync','tr.ui.TimelineView.highlightVSync',false,'Highlight VSync');this.optionsDropdown_.appendChild(this.highlightVSyncCheckbox_);this.initMetadataButton_();this.initConsoleButton_();this.initHelpButton_();this.collapsingControls.appendChild(this.scriptingCtl_);this.dragEl_=this.$.drag_handle;tr.ui.b.decorate(this.dragEl_,tr.ui.b.DragHandle);this.analysisEl_=this.$.analysis;this.analysisEl_.brushingStateController=this.brushingStateController_;this.addEventListener('requestSelectionChange',function(e){var sc=this.brushingStateController_;sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);}.bind(this));this.onViewportChanged_=this.onViewportChanged_.bind(this);this.bindKeyListeners_();this.dragEl_.target=this.analysisEl_;},domReady:function(){this.trackViewContainer_=this.querySelector('#track_view_container');},get globalMode(){return this.hotkeyController.globalMode;},set globalMode(globalMode){globalMode=!!globalMode;this.brushingStateController_.historyEnabled=globalMode;this.hotkeyController.globalMode=globalMode;},get hotkeyController(){return this.$.hkc;},updateDocumentFavicon:function(){var hue;if(!this.model) hue='blue';else hue=this.model.faviconHue;var faviconData=tr.ui.b.FaviconsByHue[hue];if(faviconData===undefined) @@ -4784,7 +4876,7 @@ this.railScoreSpan_.railScore=undefined;this.trackViewContainer_.textContent=''; this.brushingStateController_.modelWillChange();} if(modelValid&&!this.trackView_){this.trackView_=document.createElement('tr-ui-timeline-track-view');this.trackView_.timelineView=this;this.trackView.brushingStateController=this.brushingStateController_;this.trackViewContainer_.appendChild(this.trackView_);this.trackView_.viewport.addEventListener('change',this.onViewportChanged_);} if(modelValid){this.trackView_.model=model;this.trackView_.viewport.showFlowEvents=this.showFlowEvents;this.trackView_.viewport.highlightVSync=this.highlightVSync;if(this.railScoreSpan_){var railScore=tr.e.rail.RAILScore.fromModel(model);this.railScoreSpan_.railScore=railScore;} -this.$.display_unit.preferredDisplayUnit=model.intrinsicTimeUnit;} +this.$.display_unit.preferredTimeDisplayMode=model.intrinsicTimeUnit;} if(modelInstanceChanged){this.updateMetadataButtonVisibility_();this.brushingStateController_.modelDidChange();this.onViewportChanged_();}},get brushingStateController(){return this.brushingStateController_;},get trackView(){return this.trackView_;},get settings(){if(!this.settings_) this.settings_=new tr.b.Settings();return this.settings_;},set focusElement(value){throw new Error('This is deprecated. Please set globalMode to true.');},bindKeyListeners_:function(){var hkc=this.hotkeyController;hkc.addHotKey(new tr.ui.b.HotKey({eventType:'keypress',keyCode:'`'.charCodeAt(0),useCapture:true,thisArg:this,callback:function(e){this.scriptingCtl_.toggleVisibility();if(!this.scriptingCtl_.hasFocus) this.focus();e.stopPropagation();}}));hkc.addHotKey(new tr.ui.b.HotKey({eventType:'keypress',keyCode:'/'.charCodeAt(0),useCapture:true,thisArg:this,callback:function(e){if(this.scriptingCtl_.hasFocus) @@ -4829,5 +4921,15 @@ ChromeModelHelper.prototype={get pid(){throw new Error('woah');},get process(){t alertsByType[alert.title]=[];alertsByType[alert.title].push(alert);});return alertsByType;},alertsTableRows_:function(alertsByType){return Object.keys(alertsByType).map(function(key){return{alertType:key,count:alertsByType[key].length};});},alertsTableColumns_:function(){return[{title:'Alert type',value:function(row){return row.alertType;},width:'180px'},{title:'Count',width:'100%',value:function(row){return row.count;}}];},createAlertsTable_:function(alerts){var alertsByType=this.alertsByType_(alerts);var table=document.createElement('tr-ui-b-table');table.tableColumns=this.alertsTableColumns_();table.tableRows=this.alertsTableRows_(alertsByType);table.supportsSelection=true;table.addEventListener('selection-changed',function(e){var row=table.selectedTableRow;if(row) this.selectAlertsOfType(row.alertType);}.bind(this));return table;},updateContents_:function(){this.$.result_area.textContent='';if(this.model_===undefined) return;var panel=this.createAlertsTable_(this.model_.alerts);this.$.result_area.appendChild(panel);},supportsModel:function(m){if(m==undefined){return{supported:false,reason:'Unknown tracing model'};}else if(m.alerts.length===0){return{supported:false,reason:'No alerts in tracing model'};} -return{supported:true};},get textLabel(){return'Alerts';}}); +return{supported:true};},get textLabel(){return'Alerts';}});'use strict';tr.exportTo('tr.ui.e.highlighter',function(){var Highlighter=tr.ui.tracks.Highlighter;function VSyncHighlighter(viewport){Highlighter.call(this,viewport);this.times_=[];} +VSyncHighlighter.VSYNC_HIGHLIGHT_COLOR={r:0,g:0,b:255};VSyncHighlighter.VSYNC_HIGHLIGHT_ALPHA=0.1;VSyncHighlighter.VSYNC_DENSITY_TRANSPARENT=0.20;VSyncHighlighter.VSYNC_DENSITY_OPAQUE=0.10;VSyncHighlighter.VSYNC_DENSITY_RANGE=VSyncHighlighter.VSYNC_DENSITY_TRANSPARENT- +VSyncHighlighter.VSYNC_DENSITY_OPAQUE;VSyncHighlighter.generateStripes=function(times,minTime,maxTime){var stripes=[];var lowIndex=tr.b.findLowIndexInSortedArray(times,function(time){return time;},minTime);if(lowIndex>times.length){lowIndex=times.length;} +var highIndex=lowIndex-1;while(times[highIndex+1]<=maxTime){highIndex++;} +for(var i=lowIndex-(lowIndex%2);i<=highIndex;i+=2){var left=i<lowIndex?minTime:times[i];var right=i+1>highIndex?maxTime:times[i+1];stripes.push([left,right]);} +return stripes;} +VSyncHighlighter.prototype={__proto__:Highlighter.prototype,processModel:function(model){this.times_=model.device.vSyncTimestamps;},drawHighlight:function(ctx,dt,viewLWorld,viewRWorld,viewHeight){if(!this.viewport_.highlightVSync){return;} +var stripes=VSyncHighlighter.generateStripes(this.times_,viewLWorld,viewRWorld);if(stripes.length==0){return;} +var stripeRange=stripes[stripes.length-1][1]-stripes[0][0];var stripeDensity=stripes.length/(dt.scaleX*stripeRange);var clampedStripeDensity=tr.b.clamp(stripeDensity,VSyncHighlighter.VSYNC_DENSITY_OPAQUE,VSyncHighlighter.VSYNC_DENSITY_TRANSPARENT);var opacity=(VSyncHighlighter.VSYNC_DENSITY_TRANSPARENT-clampedStripeDensity)/VSyncHighlighter.VSYNC_DENSITY_RANGE;if(opacity==0){return;} +var pixelRatio=window.devicePixelRatio||1;var height=viewHeight*pixelRatio;ctx.fillStyle=tr.ui.b.colorToRGBAString(VSyncHighlighter.VSYNC_HIGHLIGHT_COLOR,VSyncHighlighter.VSYNC_HIGHLIGHT_ALPHA*opacity);for(var i=0;i<stripes.length;i++){var xLeftView=dt.xWorldToView(stripes[i][0]);var xRightView=dt.xWorldToView(stripes[i][1]);ctx.fillRect(xLeftView,0,xRightView-xLeftView,height);}}};tr.ui.tracks.Highlighter.register(VSyncHighlighter);return{VSyncHighlighter:VSyncHighlighter};}); </script> +<!--CATAPULT_REV=NO_AUTO_UPDATE-->
\ No newline at end of file @@ -2,16 +2,14 @@ import codecs, httplib, json, optparse, os, urllib, shutil, subprocess, sys -output_html_file = 'systrace_trace_viewer.html' - upstream_git = 'https://github.com/catapult-project/catapult.git' script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) -trace_viewer_dir = os.path.join(script_dir, 'catapult') +catapult_dir = os.path.join(script_dir, 'catapult') parser = optparse.OptionParser() parser.add_option('--local', dest='local_dir', metavar='DIR', - help='use a local trace-viewer') + help='use a local catapult') parser.add_option('--no-min', dest='no_min', default=False, action='store_true', help='skip minification') options, args = parser.parse_args() @@ -19,46 +17,39 @@ options, args = parser.parse_args() # Update the source if needed. if options.local_dir is None: # Remove the old source tree. - shutil.rmtree(trace_viewer_dir, True) + shutil.rmtree(catapult_dir, True) # Pull the latest source from the upstream git. - git_args = ['git', 'clone', upstream_git, trace_viewer_dir] + git_args = ['git', 'clone', upstream_git, catapult_dir] p = subprocess.Popen(git_args, stdout=subprocess.PIPE, cwd=script_dir) p.communicate() if p.wait() != 0: print 'Failed to checkout source from upstream git.' sys.exit(1) - trace_viewer_git_dir = os.path.join(trace_viewer_dir, '.git') + catapult_git_dir = os.path.join(catapult_dir, '.git') # Update the UPSTREAM_REVISION file git_args = ['git', 'rev-parse', 'HEAD'] p = subprocess.Popen(git_args, stdout=subprocess.PIPE, - cwd=trace_viewer_dir, - env={"GIT_DIR":trace_viewer_git_dir}) + cwd=catapult_dir, + env={"GIT_DIR":catapult_git_dir}) out, err = p.communicate() if p.wait() != 0: print 'Failed to get revision.' sys.exit(1) - shutil.rmtree(trace_viewer_git_dir, True) + shutil.rmtree(catapult_git_dir, True) rev = out.strip() with open('UPSTREAM_REVISION', 'wt') as f: f.write(rev + '\n') else: - trace_viewer_dir = options.local_dir - + catapult_dir = options.local_dir -# Generate the vulcanized result. -build_dir = os.path.join(trace_viewer_dir, 'tracing') -sys.path.append(build_dir) -from tracing_build import vulcanize_trace_viewer -with codecs.open(output_html_file, encoding='utf-8', mode='w') as f: - vulcanize_trace_viewer.WriteTraceViewer( - f, - config_name='systrace', - minify=(not options.no_min), - output_html_head_and_body=False) -print 'Generated %s' % output_html_file +# Update systrace_trace_viewer.html +systrace_dir = os.path.join(catapult_dir, 'systrace', 'systrace') +sys.path.append(systrace_dir) +import update_systrace_trace_viewer +update_systrace_trace_viewer.update(no_auto_update=True, no_min=options.no_min) |