diff options
author | dominich@chromium.org <dominich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-09 15:40:31 +0000 |
---|---|---|
committer | dominich@chromium.org <dominich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-09 15:40:31 +0000 |
commit | 53dcc5cb1f0a7657590b16b1e171dc34ec01959b (patch) | |
tree | cc69c6912529b726257f29f2f4bb0f40bf4a2959 /chrome | |
parent | 5b4926e1893925ce5be80d1e43fe753f27952e9c (diff) | |
download | chromium_src-53dcc5cb1f0a7657590b16b1e171dc34ec01959b.zip chromium_src-53dcc5cb1f0a7657590b16b1e171dc34ec01959b.tar.gz chromium_src-53dcc5cb1f0a7657590b16b1e171dc34ec01959b.tar.bz2 |
Moving the contents of chrome://gpu Profiling to chrome://tracing.
BUG=91406
TEST=none
Review URL: http://codereview.chromium.org/7555005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95998 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/generated_resources.grd | 5 | ||||
-rw-r--r-- | chrome/browser/browser_about_handler.cc | 1 | ||||
-rw-r--r-- | chrome/browser/browser_resources.grd | 2 | ||||
-rw-r--r-- | chrome/browser/resources/gpu_internals.html | 14 | ||||
-rw-r--r-- | chrome/browser/resources/gpu_internals.js | 15 | ||||
-rw-r--r-- | chrome/browser/resources/gpu_internals/browser_bridge.js | 6 | ||||
-rw-r--r-- | chrome/browser/resources/gpu_internals/info_view.js | 2 | ||||
-rw-r--r-- | chrome/browser/resources/gpu_internals/tracing_controller_tests.js | 227 | ||||
-rw-r--r-- | chrome/browser/resources/tracing.html | 67 | ||||
-rw-r--r-- | chrome/browser/resources/tracing.js | 31 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/OWNERS | 1 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/fast_rect_renderer.js (renamed from chrome/browser/resources/gpu_internals/fast_rect_renderer.js) | 2 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/overlay.css (renamed from chrome/browser/resources/gpu_internals/overlay.css) | 0 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/overlay.js (renamed from chrome/browser/resources/gpu_internals/overlay.js) | 2 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/overlay_test.html (renamed from chrome/browser/resources/gpu_internals/overlay_test.html) | 0 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/profiling_view.css (renamed from chrome/browser/resources/gpu_internals/profiling_view.css) | 0 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/profiling_view.js (renamed from chrome/browser/resources/gpu_internals/profiling_view.js) | 12 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/sorted_array_utils.js (renamed from chrome/browser/resources/gpu_internals/sorted_array_utils.js) | 2 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/tests/big_trace.json (renamed from chrome/browser/resources/gpu_internals/tests/big_trace.json) | 0 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/tests/huge_trace.json (renamed from chrome/browser/resources/gpu_internals/tests/huge_trace.json) | 0 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/timeline.css (renamed from chrome/browser/resources/gpu_internals/timeline.css) | 0 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/timeline.js (renamed from chrome/browser/resources/gpu_internals/timeline.js) | 2 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/timeline_model.js (renamed from chrome/browser/resources/gpu_internals/timeline_model.js) | 2 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/timeline_track.js (renamed from chrome/browser/resources/gpu_internals/timeline_track.js) | 10 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/timeline_view.css (renamed from chrome/browser/resources/gpu_internals/timeline_view.css) | 0 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/timeline_view.js (renamed from chrome/browser/resources/gpu_internals/timeline_view.js) | 10 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/tracing_controller.css (renamed from chrome/browser/resources/gpu_internals/tracing_controller.css) | 4 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/tracing_controller.js (renamed from chrome/browser/resources/gpu_internals/tracing_controller.js) | 14 | ||||
-rw-r--r-- | chrome/browser/resources/tracing/tracing_controller_tests.js | 227 | ||||
-rw-r--r-- | chrome/browser/ui/webui/chrome_web_ui_factory.cc | 3 | ||||
-rw-r--r-- | chrome/browser/ui/webui/gpu_internals_ui.cc | 379 | ||||
-rw-r--r-- | chrome/browser/ui/webui/tracing_ui.cc | 525 | ||||
-rw-r--r-- | chrome/browser/ui/webui/tracing_ui.h | 20 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/common/url_constants.cc | 1 | ||||
-rw-r--r-- | chrome/common/url_constants.h | 1 |
36 files changed, 933 insertions, 656 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 56d8fdf..2774667 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -13300,6 +13300,11 @@ Keep your key file in a safe place. You will need it to create new versions of y <ph name="PROFILE_NAME">$1<ex>New User</ex></ph> (current) </message> + <!-- Tracing about page strings --> + <message name="IDS_TRACING_TITLE" desc="Title for the about:tracing page."> + Tracing + </message> + </messages> <includes> <if expr="pp_ifdef('_google_chrome')"> diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index effa66f..9745341 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc @@ -139,6 +139,7 @@ const char* const kChromePaths[] = { chrome::kChromeUISyncInternalsHost, chrome::kChromeUITCMallocHost, chrome::kChromeUITermsHost, + chrome::kChromeUITracingHost, chrome::kChromeUIVersionHost, chrome::kChromeUIWorkersHost, #ifdef TRACK_ALL_TASK_OBJECTS diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 120967d..27a62a6 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -103,6 +103,8 @@ <include name="IDR_CLOUD_PRINT_SETUP_LOGIN_HTML" file="printing\cloud_print\resources\cloud_print_setup_login.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_CLOUD_PRINT_SETUP_DONE_HTML" file="printing\cloud_print\resources\cloud_print_setup_done.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_TEXTFIELDS_HTML" file="resources\textfields.html" flattenhtml="true" type="BINDATA" /> + <include name="IDR_TRACING_HTML" file="resources\tracing.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> + <include name="IDR_TRACING_JS" file="resources\tracing.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_TRANSLATE_JS" file="resources\translate.js" type="BINDATA" /> <include name="IDR_BUGREPORT_HTML" file="resources\bug_report.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_BUGREPORT_HTML_INVALID" file="resources\bug_report_invalid.html" allowexternalscript="true" flattenhtml="true" type="BINDATA" /> diff --git a/chrome/browser/resources/gpu_internals.html b/chrome/browser/resources/gpu_internals.html index 338b203..33c55c7 100644 --- a/chrome/browser/resources/gpu_internals.html +++ b/chrome/browser/resources/gpu_internals.html @@ -40,11 +40,6 @@ tabbox tabpanels { </style> <link rel="stylesheet" href="gpu_internals/info_view.css"> -<link rel="stylesheet" href="gpu_internals/overlay.css"> -<link rel="stylesheet" href="gpu_internals/profiling_view.css"> -<link rel="stylesheet" href="gpu_internals/timeline_view.css"> -<link rel="stylesheet" href="gpu_internals/timeline.css"> -<link rel="stylesheet" href="gpu_internals/tracing_controller.css"> <link rel="stylesheet" href="chrome://resources/css/tabs.css"> <script src="chrome://resources/js/cr.js"></script> <script src="chrome://resources/js/cr/event_target.js"></script> @@ -66,9 +61,14 @@ tabbox tabpanels { </tabs> <tabpanels> <include src="gpu_internals/info_view.html"> - <tabpanel id="profiling-view"> + <tabpanel id="profiling-view-link"> + <div> + Profiling view has moved to <a + href="chrome://tracing">chrome://tracing</a>. + </div> + </tabpanel> </tabpanels> - </div> + </tabbox> <script src="chrome://resources/js/i18n_template.js"></script> <script src="chrome://resources/js/i18n_process.js"></script> <script src="chrome://resources/js/jstemplate_compiled.js"></script> diff --git a/chrome/browser/resources/gpu_internals.js b/chrome/browser/resources/gpu_internals.js index 57832f0..022372d 100644 --- a/chrome/browser/resources/gpu_internals.js +++ b/chrome/browser/resources/gpu_internals.js @@ -2,35 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -<include src="gpu_internals/overlay.js"/> <include src="gpu_internals/browser_bridge.js"/> -<include src="gpu_internals/tracing_controller.js"/> <include src="gpu_internals/info_view.js"/> -<include src="gpu_internals/timeline_model.js"/> -<include src="gpu_internals/sorted_array_utils.js"/> -<include src="gpu_internals/timeline.js"/> -<include src="gpu_internals/timeline_track.js"/> -<include src="gpu_internals/fast_rect_renderer.js"/> -<include src="gpu_internals/profiling_view.js"/> -<include src="gpu_internals/timeline_view.js"/> var browserBridge; -var tracingController; -var profilingView; // made global for debugging purposes only /** * Main entry point. called once the page has loaded. */ function onLoad() { browserBridge = new gpu.BrowserBridge(); - tracingController = new gpu.TracingController(); // Create the views. cr.ui.decorate('#info-view', gpu.InfoView); - profilingView = $('profiling-view'); - cr.ui.decorate(profilingView, gpu.ProfilingView); - // Create the main tab control var tabs = $('main-tabs'); cr.ui.decorate(tabs, cr.ui.TabBox); diff --git a/chrome/browser/resources/gpu_internals/browser_bridge.js b/chrome/browser/resources/gpu_internals/browser_bridge.js index bcc97b8..b632b35 100644 --- a/chrome/browser/resources/gpu_internals/browser_bridge.js +++ b/chrome/browser/resources/gpu_internals/browser_bridge.js @@ -11,13 +11,11 @@ cr.define('gpu', function() { function BrowserBridge() { // If we are not running inside WebUI, output chrome.send messages // to the console to help with quick-iteration debugging. - if (chrome.send === undefined && console.log) { - this.debugMode_ = true; + this.debugMode_ = (chrome.send === undefined && console.log); + if (this.debugMode_) { var browserBridgeTests = document.createElement('script'); browserBridgeTests.src = './gpu_internals/browser_bridge_tests.js'; document.body.appendChild(browserBridgeTests); - } else { - this.debugMode_ = false; } this.nextRequestId_ = 0; diff --git a/chrome/browser/resources/gpu_internals/info_view.js b/chrome/browser/resources/gpu_internals/info_view.js index 346cb09..ba088a6 100644 --- a/chrome/browser/resources/gpu_internals/info_view.js +++ b/chrome/browser/resources/gpu_internals/info_view.js @@ -12,7 +12,7 @@ cr.define('gpu', function() { /** * Provides information on the GPU process and underlying graphics hardware. * @constructor - * @extends {Tab} + * @extends {cr.ui.TabPanel} */ var InfoView = cr.ui.define(cr.ui.TabPanel); diff --git a/chrome/browser/resources/gpu_internals/tracing_controller_tests.js b/chrome/browser/resources/gpu_internals/tracing_controller_tests.js deleted file mode 100644 index dc791c9..0000000 --- a/chrome/browser/resources/gpu_internals/tracing_controller_tests.js +++ /dev/null @@ -1,227 +0,0 @@ -// 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. -cr.define('gpu', function() { - var dataSets = [ - { - name: "big_trace", - events_url: "./tests/big_trace.json" - }, - { - name: "trivial_trace", - events: [ - {"name":"a","args":{},"pid":52,"ts":9524,"cat":"foo","tid":53,"ph":"B"}, - {"name":"a","args":{},"pid":52,"ts":9560,"cat":"foo","tid":53,"ph":"E"}, - {"name":"b","args":{},"pid":52,"ts":9629,"cat":"foo","tid":53,"ph":"B"}, - {"name":"b","args":{},"pid":52,"ts":9631,"cat":"foo","tid":53,"ph":"E"} - ] - }, - { - name: "simple_trace", - events: [ - {"cat":"PERF","pid":22630,"tid":22630,"ts":826,"ph":"B", - "name":"A long name that doesn't fit but is exceedingly informative", - "args":{}}, - {"cat":"PERF","pid":22630,"tid":22630,"ts":827,"ph":"B", - "name":"Asub with a name that won't fit","args":{}}, - {"cat":"PERF","pid":22630,"tid":22630,"ts":828,"ph":"E", - "name":"Asub","args":{}}, - {"cat":"PERF","pid":22630,"tid":22630,"ts":829,"ph":"B", - "name":"Asub","args":{}}, - {"cat":"PERF","pid":22630,"tid":22630,"ts":832,"ph":"E", - "name":"Asub","args":{}}, - {"cat":"PERF","pid":22630,"tid":22630,"ts":833,"ph":"E", - "name":"","args":{}}, - - {"cat":"PERF","pid":22630,"tid":22630,"ts":835,"ph":"I", - "name":"I1","args":{}}, - {"cat":"PERF","pid":22630,"tid":22630,"ts":837,"ph":"I", - "name":"I2","args":{}}, - - {"cat":"PERF","pid":22630,"tid":22630,"ts":840,"ph":"B", - "name":"A not as long a name","args":{}}, - {"cat":"PERF","pid":22630,"tid":22630,"ts":848,"ph":"E", - "name":"A not as long a name","args":{}}, - - {"cat":"PERF","pid":22630,"tid":22630,"ts":850,"ph":"B", - "name":"B","args":{}}, - {"cat":"PERF","pid":22630,"tid":22630,"ts":854,"ph":"E", - "name":"B","args":{}}, - - {"cat":"PERF","pid":22630,"tid":22631,"ts":827,"ph":"B", - "name":"A","args":{}}, - {"cat":"PERF","pid":22630,"tid":22631,"ts":835,"ph":"I", - "name":"Immediate Three","args":{}}, - {"cat":"PERF","pid":22630,"tid":22631,"ts":845,"ph":"I", - "name":"I4","args":{}}, - {"cat":"PERF","pid":22630,"tid":22631,"ts":854,"ph":"E", - "name":"A","args":{}}, - - {"cat":"__metadata","pid":22630,"tid":22630,"ts":0,"ph":"M", - "name":"thread_name","args":{"name": "threadA"}}, - {"cat":"__metadata","pid":22630,"tid":22631,"ts":0,"ph":"M", - "name":"thread_name","args":{"name": "threadB"}}, - {"cat":"__metadata","pid":22630,"tid":22632,"ts":0,"ph":"M", - "name":"thread_name","args":{"name": "threadC"}} - ] - }, - { - name: "nonnested_trace", - events: [ - {'cat':'PERF','pid':22630,'tid':22630,'ts':826,'ph':'B', - 'name':'A','args':{}}, - {'cat':'PERF','pid':22630,'tid':22630,'ts':827,'ph':'B', - 'name':'Asub','args':{}}, - {'cat':'PERF','pid':22630,'tid':22630,'ts':829,'ph':'B', - 'name':'NonNest','args':{'id':'1','ui-nest':'0'}}, - {'cat':'PERF','pid':22630,'tid':22630,'ts':830,'ph':'B', - 'name':'NonNest','args':{'id':'2','ui-nest':'0'}}, - {'cat':'PERF','pid':22630,'tid':22630,'ts':831,'ph':'E', - 'name':'Asub','args':{}}, - {'cat':'PERF','pid':22630,'tid':22630,'ts':832,'ph':'E', - 'name':'NonNest','args':{'id':'1','ui-nest':'0'}}, - {'cat':'PERF','pid':22630,'tid':22630,'ts':833,'ph':'E', - 'name':'NonNest','args':{'id':'2','ui-nest':'0'}}, - {'cat':'PERF','pid':22630,'tid':22630,'ts':834,'ph':'E', - 'name':'A','args':{}}, - - {'cat':'PERF','pid':22630,'tid':22631,'ts':827,'ph':'B', - 'name':'A','args':{}}, - {'cat':'PERF','pid':22630,'tid':22631,'ts':854,'ph':'E', - 'name':'A','args':{}} - ] - }, - { - name: "tall_trace", - events: [ - {"cat":"X","pid":30,"tid":30,"ts":826,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":30,"ts":827,"ph":"B","name":"Asub","args":{}}, - {"cat":"X","pid":30,"tid":30,"ts":828,"ph":"E","name":"Asub","args":{}}, - {"cat":"X","pid":30,"tid":30,"ts":829,"ph":"B","name":"Asub","args":{}}, - {"cat":"X","pid":30,"tid":30,"ts":832,"ph":"E","name":"Asub","args":{}}, - {"cat":"X","pid":30,"tid":30,"ts":833,"ph":"E","name":"","args":{}}, - - {"cat":"X","pid":30,"tid":31,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":31,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":32,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":32,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":33,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":33,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":34,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":34,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":35,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":35,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":36,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":36,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":37,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":37,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":38,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":38,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":39,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":39,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":10,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":10,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":31,"tid":11,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":31,"tid":11,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":12,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":12,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":13,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":13,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":14,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":14,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"X","pid":30,"tid":15,"ts":840,"ph":"B","name":"A","args":{}}, - {"cat":"X","pid":30,"tid":15,"ts":848,"ph":"E","name":"A","args":{}}, - - {"cat":"__metadata","pid":30,"tid":14,"ts":0,"ph":"M", - "name":"thread_name","args":{"name": "threadB"}}, - {"cat":"__metadata","pid":30,"tid":15,"ts":0,"ph":"M", - "name":"thread_name","args":{"name": "threadA"}} - ] - }, - { - name: "huge_trace", - events_url: "./tests/huge_trace.json" - } - ]; - - // Create UI for controlling the test harness - var selectEl = document.createElement("select"); - for (var i = 0; i < dataSets.length; ++i) { - var optionEl = document.createElement("option"); - optionEl.textContent = dataSets[i].name; - optionEl.dataSet = dataSets[i]; - selectEl.appendChild(optionEl); - } - selectEl.addEventListener("change", function() { - tracingController.beginTracing(); - }); - selectEl.addEventListener("keydown", function() { - window.setTimeout(function() { - tracingController.beginTracing(); - }, 0); - }); - - var controlEl = document.createElement("div"); - var textEl = document.createElement("span"); - textEl.textContent = "Trace:"; - controlEl.appendChild(textEl); - controlEl.appendChild(selectEl); - - document.querySelector("#debug-div").appendChild(controlEl, - document.body.firstChild); - - return { - tracingControllerTestHarness : { - beginTracing: function() { - var dataSet = dataSets[selectEl.selectedIndex]; - if (dataSet.events) { - window.setTimeout(function() { - tracingController.onTraceDataCollected(dataSet.events); - tracingController.endTracing(); - window.setTimeout(function() { - tracingController.onEndTracingComplete(); - },0); - }, 0); - } else { - var req = new XMLHttpRequest(); - req.open('GET', "./gpu_internals/" + dataSet.events_url, true); - req.onreadystatechange = function (aEvt) { - if (req.readyState == 4) { - tracingController.endTracing(); - window.setTimeout(function() { - if(req.status == 200) { - var resp = JSON.parse(req.responseText); - if (resp.traceEvents) - tracingController.onTraceDataCollected(resp.traceEvents); - else - tracingController.onTraceDataCollected(resp); - } else { - console.log("collection failed."); - } - tracingController.onEndTracingComplete(); - }, 0); - } - }; - req.send(null); - } - }, - - endTracing: function() { - } - } - }; -}); diff --git a/chrome/browser/resources/tracing.html b/chrome/browser/resources/tracing.html new file mode 100644 index 0000000..cbebf57 --- /dev/null +++ b/chrome/browser/resources/tracing.html @@ -0,0 +1,67 @@ +<!DOCTYPE HTML> +<html> +<!-- +Copyright (c) 2010 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. +--> +<head i18n-values="dir:textdirection;"> +<include src="content_security_policy.html"/> + +<link rel="stylesheet" href="webui.css"> +<style> +* { + box-sizing: border-box; + -webkit-user-select: none; +} + +html, body, #main-tabs { + height: 100%; +} + +body { + cursor: default; + font-family: sans-serif; + padding: 0; + margin: 0; +} + +#debug-div { + display: -webkit-box; + position: fixed; + top: 0px; + left: 50%; + border: 1px solid red; +} + +tabbox tabpanels { + padding: 1px; +} + +</style> +<link rel="stylesheet" href="tracing/overlay.css"> +<link rel="stylesheet" href="tracing/profiling_view.css"> +<link rel="stylesheet" href="tracing/timeline_view.css"> +<link rel="stylesheet" href="tracing/timeline.css"> +<link rel="stylesheet" href="tracing/tracing_controller.css"> +<link rel="stylesheet" href="chrome://resources/css/tabs.css"> +<script src="chrome://resources/js/cr.js"></script> +<script src="chrome://resources/js/cr/event_target.js"></script> +<script src="chrome://resources/js/cr/ui.js"></script> +<script src="chrome://resources/js/cr/ui/focus_outline_manager.js"></script> +<script src="chrome://resources/js/cr/ui/tabs.js"></script> +<script src="chrome://resources/js/util.js"></script> +<script src="chrome://tracing/tracing.js"></script> +<script src="chrome://tracing/strings.js"></script> +</head> +<body> + <div id="debug-div"> + </div> + <h1 i18n-content="tracingTitle">TITLE</h1> + <div id="profiling-view"> + </div> + <script src="chrome://resources/js/i18n_template.js"></script> + <script src="chrome://resources/js/i18n_process.js"></script> + <script src="chrome://resources/js/jstemplate_compiled.js"></script> +</body> +</html> diff --git a/chrome/browser/resources/tracing.js b/chrome/browser/resources/tracing.js new file mode 100644 index 0000000..e8db8f5 --- /dev/null +++ b/chrome/browser/resources/tracing.js @@ -0,0 +1,31 @@ +// 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. + +<include src="gpu_internals/browser_bridge.js"> +<include src="tracing/overlay.js"> +<include src="tracing/tracing_controller.js"> +<include src="tracing/timeline_model.js"> +<include src="tracing/sorted_array_utils.js"> +<include src="tracing/timeline.js"> +<include src="tracing/timeline_track.js"> +<include src="tracing/fast_rect_renderer.js"> +<include src="tracing/profiling_view.js"> +<include src="tracing/timeline_view.js"> + +var browserBridge; +var tracingController; +var profilingView; // Made global for debugging purposes only. + +/** + * Main entry point called once the page has loaded. + */ +function onLoad() { + browserBridge = new gpu.BrowserBridge(); + tracingController = new tracing.TracingController(); + + profilingView = $('profiling-view'); + cr.ui.decorate(profilingView, tracing.ProfilingView); +} + +document.addEventListener('DOMContentLoaded', onLoad); diff --git a/chrome/browser/resources/tracing/OWNERS b/chrome/browser/resources/tracing/OWNERS new file mode 100644 index 0000000..93d1471 --- /dev/null +++ b/chrome/browser/resources/tracing/OWNERS @@ -0,0 +1 @@ +nduca@chromium.org diff --git a/chrome/browser/resources/gpu_internals/fast_rect_renderer.js b/chrome/browser/resources/tracing/fast_rect_renderer.js index ef80326b..2be5a97 100644 --- a/chrome/browser/resources/gpu_internals/fast_rect_renderer.js +++ b/chrome/browser/resources/tracing/fast_rect_renderer.js @@ -25,7 +25,7 @@ * Make sure to flush the trackRenderer before finishing drawing in order * to commit any queued drawing operations. */ -cr.define('gpu', function() { +cr.define('tracing', function() { /** * Creates a fast rect renderer with a specific set of culling rules diff --git a/chrome/browser/resources/gpu_internals/overlay.css b/chrome/browser/resources/tracing/overlay.css index 994b527..994b527 100644 --- a/chrome/browser/resources/gpu_internals/overlay.css +++ b/chrome/browser/resources/tracing/overlay.css diff --git a/chrome/browser/resources/gpu_internals/overlay.js b/chrome/browser/resources/tracing/overlay.js index 720065c..d01cb45 100644 --- a/chrome/browser/resources/gpu_internals/overlay.js +++ b/chrome/browser/resources/tracing/overlay.js @@ -12,7 +12,7 @@ * restores its original parentage. * */ -cr.define('gpu', function() { +cr.define('tracing', function() { /** * Manages a full-window div that darkens the window, disables * input, and hosts the currently-visible overlays. You shouldn't diff --git a/chrome/browser/resources/gpu_internals/overlay_test.html b/chrome/browser/resources/tracing/overlay_test.html index c06572c..c06572c 100644 --- a/chrome/browser/resources/gpu_internals/overlay_test.html +++ b/chrome/browser/resources/tracing/overlay_test.html diff --git a/chrome/browser/resources/gpu_internals/profiling_view.css b/chrome/browser/resources/tracing/profiling_view.css index 94b63a1..94b63a1 100644 --- a/chrome/browser/resources/gpu_internals/profiling_view.css +++ b/chrome/browser/resources/tracing/profiling_view.css diff --git a/chrome/browser/resources/gpu_internals/profiling_view.js b/chrome/browser/resources/tracing/profiling_view.js index eb8a2e2..a4f13de 100644 --- a/chrome/browser/resources/gpu_internals/profiling_view.js +++ b/chrome/browser/resources/tracing/profiling_view.js @@ -4,14 +4,14 @@ /** - * @fileoverview ProfilingView visualizes GPU_TRACE events using the - * gpu.Timeline component. + * @fileoverview ProfilingView visualizes TRACE_EVENT events using the + * tracing.Timeline component. */ -cr.define('gpu', function() { +cr.define('tracing', function() { /** * ProfilingView * @constructor - * @extends {gpu.Tab} + * @extends {ui.TabPanel} */ ProfilingView = cr.ui.define(cr.ui.TabPanel); @@ -99,7 +99,7 @@ cr.define('gpu', function() { /////////////////////////////////////////////////////////////////////////// onSave_: function() { - this.overlayEl_ = new gpu.Overlay(); + this.overlayEl_ = new tracing.Overlay(); this.overlayEl_.className = 'profiling-overlay'; var labelEl = document.createElement('div'); @@ -124,7 +124,7 @@ cr.define('gpu', function() { /////////////////////////////////////////////////////////////////////////// onLoad_: function() { - this.overlayEl_ = new gpu.Overlay(); + this.overlayEl_ = new tracing.Overlay(); this.overlayEl_.className = 'profiling-overlay'; var labelEl = document.createElement('div'); diff --git a/chrome/browser/resources/gpu_internals/sorted_array_utils.js b/chrome/browser/resources/tracing/sorted_array_utils.js index b99d369..6aac23a 100644 --- a/chrome/browser/resources/gpu_internals/sorted_array_utils.js +++ b/chrome/browser/resources/tracing/sorted_array_utils.js @@ -8,7 +8,7 @@ * over sorted arrays and intervals. * */ -cr.define('gpu', function() { +cr.define('tracing', function() { /** * Finds the first index in the array whose value is >= loVal. * diff --git a/chrome/browser/resources/gpu_internals/tests/big_trace.json b/chrome/browser/resources/tracing/tests/big_trace.json index 9db1a14..9db1a14 100644 --- a/chrome/browser/resources/gpu_internals/tests/big_trace.json +++ b/chrome/browser/resources/tracing/tests/big_trace.json diff --git a/chrome/browser/resources/gpu_internals/tests/huge_trace.json b/chrome/browser/resources/tracing/tests/huge_trace.json index fa1666d..fa1666d 100644 --- a/chrome/browser/resources/gpu_internals/tests/huge_trace.json +++ b/chrome/browser/resources/tracing/tests/huge_trace.json diff --git a/chrome/browser/resources/gpu_internals/timeline.css b/chrome/browser/resources/tracing/timeline.css index 2225831..2225831 100644 --- a/chrome/browser/resources/gpu_internals/timeline.css +++ b/chrome/browser/resources/tracing/timeline.css diff --git a/chrome/browser/resources/gpu_internals/timeline.js b/chrome/browser/resources/tracing/timeline.js index 79305cb..e942b2d 100644 --- a/chrome/browser/resources/gpu_internals/timeline.js +++ b/chrome/browser/resources/tracing/timeline.js @@ -15,7 +15,7 @@ * Thread2: CCCCCC CCCCC * */ -cr.define('gpu', function() { +cr.define('tracing', function() { /** * The TimelineViewport manages the transform used for navigating diff --git a/chrome/browser/resources/gpu_internals/timeline_model.js b/chrome/browser/resources/tracing/timeline_model.js index a92d6ac..3585818 100644 --- a/chrome/browser/resources/gpu_internals/timeline_model.js +++ b/chrome/browser/resources/tracing/timeline_model.js @@ -19,7 +19,7 @@ * nesting tasks. * */ -cr.define('gpu', function() { +cr.define('tracing', function() { /** * A TimelineSlice represents an interval of time on a given thread * associated with a specific trace event. For example, diff --git a/chrome/browser/resources/gpu_internals/timeline_track.js b/chrome/browser/resources/tracing/timeline_track.js index 34db08d..106cc2fd 100644 --- a/chrome/browser/resources/gpu_internals/timeline_track.js +++ b/chrome/browser/resources/tracing/timeline_track.js @@ -8,7 +8,7 @@ * using a child canvas element. Uses a FastRectRenderer to draw only * the visible slices. */ -cr.define('gpu', function() { +cr.define('tracing', function() { const palletteBase = [ {r: 138, g: 113, b: 152}, @@ -284,8 +284,8 @@ cr.define('gpu', function() { vp.applyTransformToCanavs(ctx); // tracks - var tr = new gpu.FastRectRenderer(ctx, viewLWorld, 2 * pixWidth, - 2 * pixWidth, viewRWorld, pallette); + var tr = new tracing.FastRectRenderer(ctx, viewLWorld, 2 * pixWidth, + 2 * pixWidth, viewRWorld, pallette); tr.setYandH(0, canvasH); var slices = this.slices_; for (var i = 0; i < slices.length; ++i) { @@ -367,7 +367,7 @@ cr.define('gpu', function() { var clientRect = this.getBoundingClientRect(); if (wY < clientRect.top || wY >= clientRect.bottom) return false; - var x = gpu.findLowIndexInSortedIntervals(this.slices_, + var x = tracing.findLowIndexInSortedIntervals(this.slices_, function(x) { return x.start; }, function(x) { return x.duration; }, wX); @@ -402,7 +402,7 @@ cr.define('gpu', function() { function onPickHit(slice) { onHitCallback('slice', that, slice); } - gpu.iterateOverIntersectingIntervals(this.slices_, + tracing.iterateOverIntersectingIntervals(this.slices_, function(x) { return x.start; }, function(x) { return x.duration; }, loWX, hiWX, diff --git a/chrome/browser/resources/gpu_internals/timeline_view.css b/chrome/browser/resources/tracing/timeline_view.css index 9828137..9828137 100644 --- a/chrome/browser/resources/gpu_internals/timeline_view.css +++ b/chrome/browser/resources/tracing/timeline_view.css diff --git a/chrome/browser/resources/gpu_internals/timeline_view.js b/chrome/browser/resources/tracing/timeline_view.js index c4e1c3e..107ba48 100644 --- a/chrome/browser/resources/gpu_internals/timeline_view.js +++ b/chrome/browser/resources/tracing/timeline_view.js @@ -4,10 +4,10 @@ /** - * @fileoverview TimelineView visualizes GPU_TRACE events using the - * gpu.Timeline component. + * @fileoverview TimelineView visualizes TRACE_EVENT events using the + * tracing.Timeline component. */ -cr.define('gpu', function() { +cr.define('tracing', function() { function tsRound(ts) { return Math.round(ts * 1000.0) / 1000.0; } @@ -65,14 +65,14 @@ cr.define('gpu', function() { set traceEvents(traceEvents) { console.log('TimelineView.refresh'); - this.timelineModel_ = new gpu.TimelineModel(traceEvents); + this.timelineModel_ = new tracing.TimelineModel(traceEvents); // remove old timeline this.timelineContainer_.textContent = ''; // create new timeline if needed if (traceEvents.length) { - this.timeline_ = new gpu.Timeline(); + this.timeline_ = new tracing.Timeline(); this.timeline_.model = this.timelineModel_; this.timelineContainer_.appendChild(this.timeline_); this.timeline_.onResize(); diff --git a/chrome/browser/resources/gpu_internals/tracing_controller.css b/chrome/browser/resources/tracing/tracing_controller.css index 895d695..b460ad9 100644 --- a/chrome/browser/resources/gpu_internals/tracing_controller.css +++ b/chrome/browser/resources/tracing/tracing_controller.css @@ -3,7 +3,7 @@ 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. */ -.gpu-tracing-overlay { +.tracing-overlay { text-align: center; display: -webkit-box; width: 200px; @@ -13,7 +13,7 @@ found in the LICENSE file. -webkit-box-align: center; } -.gpu-tracing-start-button { +.tracing-start-button { position: fixed; right: 3px; top: -1px; diff --git a/chrome/browser/resources/gpu_internals/tracing_controller.js b/chrome/browser/resources/tracing/tracing_controller.js index ff20234..494cf68 100644 --- a/chrome/browser/resources/gpu_internals/tracing_controller.js +++ b/chrome/browser/resources/tracing/tracing_controller.js @@ -6,13 +6,13 @@ /** * @fileoverview State and UI for trace data collection. */ -cr.define('gpu', function() { +cr.define('tracing', function() { function TracingController() { this.overlay_ = document.createElement('div'); - this.overlay_.className = 'gpu-tracing-overlay'; + this.overlay_.className = 'tracing-overlay'; - cr.ui.decorate(this.overlay_, gpu.Overlay); + cr.ui.decorate(this.overlay_, tracing.Overlay); this.statusDiv_ = document.createElement('div'); this.overlay_.appendChild(this.statusDiv_); @@ -30,7 +30,7 @@ cr.define('gpu', function() { if (browserBridge.debugMode) { var tracingControllerTests = document.createElement('script'); tracingControllerTests.src = - './gpu_internals/tracing_controller_tests.js'; + './tracing/tracing_controller_tests.js'; document.body.appendChild(tracingControllerTests); } @@ -81,7 +81,7 @@ cr.define('gpu', function() { chrome.send('beginTracing'); this.beginRequestBufferPercentFull_(); } else { - gpu.tracingControllerTestHarness.beginTracing(); + tracing.tracingControllerTestHarness.beginTracing(); } this.tracingEnabled_ = true; @@ -125,7 +125,7 @@ cr.define('gpu', function() { }, /** - * Callbed by gpu c++ code when new GPU trace data arrives. + * Called by tracing c++ code when new trace data arrives. */ onTraceDataCollected: function(events) { this.statusDiv_.textContent = 'Processing trace...'; @@ -150,7 +150,7 @@ cr.define('gpu', function() { if (!browserBridge.debugMode) { chrome.send('endTracingAsync'); } else { - gpu.tracingControllerTestHarness.endTracing(); + tracing.tracingControllerTestHarness.endTracing(); } }, 100); }, diff --git a/chrome/browser/resources/tracing/tracing_controller_tests.js b/chrome/browser/resources/tracing/tracing_controller_tests.js new file mode 100644 index 0000000..c57aca1 --- /dev/null +++ b/chrome/browser/resources/tracing/tracing_controller_tests.js @@ -0,0 +1,227 @@ +// 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. +cr.define('tracing', function() { + var dataSets = [ + { + name: 'big_trace', + events_url: './tests/big_trace.json' + }, + { + name: 'trivial_trace', + events: [ + {'name':'a','args':{},'pid':52,'ts':9524,'cat':'foo','tid':53,'ph':'B'}, + {'name':'a','args':{},'pid':52,'ts':9560,'cat':'foo','tid':53,'ph':'E'}, + {'name':'b','args':{},'pid':52,'ts':9629,'cat':'foo','tid':53,'ph':'B'}, + {'name':'b','args':{},'pid':52,'ts':9631,'cat':'foo','tid':53,'ph':'E'} + ] + }, + { + name: 'simple_trace', + events: [ + {'cat':'PERF','pid':22630,'tid':22630,'ts':826,'ph':'B', + 'name':'A long name that doesn't fit but is exceedingly informative', + 'args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':827,'ph':'B', + 'name':'Asub with a name that won't fit','args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':828,'ph':'E', + 'name':'Asub','args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':829,'ph':'B', + 'name':'Asub','args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':832,'ph':'E', + 'name':'Asub','args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':833,'ph':'E', + 'name':'','args':{}}, + + {'cat':'PERF','pid':22630,'tid':22630,'ts':835,'ph':'I', + 'name':'I1','args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':837,'ph':'I', + 'name':'I2','args':{}}, + + {'cat':'PERF','pid':22630,'tid':22630,'ts':840,'ph':'B', + 'name':'A not as long a name','args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':848,'ph':'E', + 'name':'A not as long a name','args':{}}, + + {'cat':'PERF','pid':22630,'tid':22630,'ts':850,'ph':'B', + 'name':'B','args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':854,'ph':'E', + 'name':'B','args':{}}, + + {'cat':'PERF','pid':22630,'tid':22631,'ts':827,'ph':'B', + 'name':'A','args':{}}, + {'cat':'PERF','pid':22630,'tid':22631,'ts':835,'ph':'I', + 'name':'Immediate Three','args':{}}, + {'cat':'PERF','pid':22630,'tid':22631,'ts':845,'ph':'I', + 'name':'I4','args':{}}, + {'cat':'PERF','pid':22630,'tid':22631,'ts':854,'ph':'E', + 'name':'A','args':{}}, + + {'cat':'__metadata','pid':22630,'tid':22630,'ts':0,'ph':'M', + 'name':'thread_name','args':{'name': 'threadA'}}, + {'cat':'__metadata','pid':22630,'tid':22631,'ts':0,'ph':'M', + 'name':'thread_name','args':{'name': 'threadB'}}, + {'cat':'__metadata','pid':22630,'tid':22632,'ts':0,'ph':'M', + 'name':'thread_name','args':{'name': 'threadC'}} + ] + }, + { + name: 'nonnested_trace', + events: [ + {'cat':'PERF','pid':22630,'tid':22630,'ts':826,'ph':'B', + 'name':'A','args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':827,'ph':'B', + 'name':'Asub','args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':829,'ph':'B', + 'name':'NonNest','args':{'id':'1','ui-nest':'0'}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':830,'ph':'B', + 'name':'NonNest','args':{'id':'2','ui-nest':'0'}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':831,'ph':'E', + 'name':'Asub','args':{}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':832,'ph':'E', + 'name':'NonNest','args':{'id':'1','ui-nest':'0'}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':833,'ph':'E', + 'name':'NonNest','args':{'id':'2','ui-nest':'0'}}, + {'cat':'PERF','pid':22630,'tid':22630,'ts':834,'ph':'E', + 'name':'A','args':{}}, + + {'cat':'PERF','pid':22630,'tid':22631,'ts':827,'ph':'B', + 'name':'A','args':{}}, + {'cat':'PERF','pid':22630,'tid':22631,'ts':854,'ph':'E', + 'name':'A','args':{}} + ] + }, + { + name: 'tall_trace', + events: [ + {'cat':'X','pid':30,'tid':30,'ts':826,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':30,'ts':827,'ph':'B','name':'Asub','args':{}}, + {'cat':'X','pid':30,'tid':30,'ts':828,'ph':'E','name':'Asub','args':{}}, + {'cat':'X','pid':30,'tid':30,'ts':829,'ph':'B','name':'Asub','args':{}}, + {'cat':'X','pid':30,'tid':30,'ts':832,'ph':'E','name':'Asub','args':{}}, + {'cat':'X','pid':30,'tid':30,'ts':833,'ph':'E','name':'','args':{}}, + + {'cat':'X','pid':30,'tid':31,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':31,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':32,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':32,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':33,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':33,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':34,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':34,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':35,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':35,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':36,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':36,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':37,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':37,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':38,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':38,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':39,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':39,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':10,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':10,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':31,'tid':11,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':31,'tid':11,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':12,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':12,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':13,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':13,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':14,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':14,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'X','pid':30,'tid':15,'ts':840,'ph':'B','name':'A','args':{}}, + {'cat':'X','pid':30,'tid':15,'ts':848,'ph':'E','name':'A','args':{}}, + + {'cat':'__metadata','pid':30,'tid':14,'ts':0,'ph':'M', + 'name':'thread_name','args':{'name': 'threadB'}}, + {'cat':'__metadata','pid':30,'tid':15,'ts':0,'ph':'M', + 'name':'thread_name','args':{'name': 'threadA'}} + ] + }, + { + name: 'huge_trace', + events_url: './tests/huge_trace.json' + } + ]; + + // Create UI for controlling the test harness + var selectEl = document.createElement('select'); + for (var i = 0; i < dataSets.length; ++i) { + var optionEl = document.createElement('option'); + optionEl.textContent = dataSets[i].name; + optionEl.dataSet = dataSets[i]; + selectEl.appendChild(optionEl); + } + selectEl.addEventListener('change', function() { + tracingController.beginTracing(); + }); + selectEl.addEventListener('keydown', function() { + window.setTimeout(function() { + tracingController.beginTracing(); + }, 0); + }); + + var controlEl = document.createElement('div'); + var textEl = document.createElement('span'); + textEl.textContent = 'Trace:'; + controlEl.appendChild(textEl); + controlEl.appendChild(selectEl); + + document.querySelector('#debug-div').appendChild(controlEl, + document.body.firstChild); + + return { + tracingControllerTestHarness : { + beginTracing: function() { + var dataSet = dataSets[selectEl.selectedIndex]; + if (dataSet.events) { + window.setTimeout(function() { + tracingController.onTraceDataCollected(dataSet.events); + tracingController.endTracing(); + window.setTimeout(function() { + tracingController.onEndTracingComplete(); + },0); + }, 0); + } else { + var req = new XMLHttpRequest(); + req.open('GET', './tracing/' + dataSet.events_url, true); + req.onreadystatechange = function (aEvt) { + if (req.readyState == 4) { + tracingController.endTracing(); + window.setTimeout(function() { + if(req.status == 200) { + var resp = JSON.parse(req.responseText); + if (resp.traceEvents) + tracingController.onTraceDataCollected(resp.traceEvents); + else + tracingController.onTraceDataCollected(resp); + } else { + console.log('collection failed.'); + } + tracingController.onEndTracingComplete(); + }, 0); + } + }; + req.send(null); + } + }, + + endTracing: function() { + } + } + }; +}); diff --git a/chrome/browser/ui/webui/chrome_web_ui_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_factory.cc index 7a9742c..ef25dbb 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_factory.cc @@ -36,6 +36,7 @@ #include "chrome/browser/ui/webui/sync_internals_ui.h" #include "chrome/browser/ui/webui/test_chrome_web_ui_factory.h" #include "chrome/browser/ui/webui/textfields_ui.h" +#include "chrome/browser/ui/webui/tracing_ui.h" #include "chrome/browser/ui/webui/workers_ui.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_constants.h" @@ -191,6 +192,8 @@ static WebUIFactoryFunction GetWebUIFactoryFunction(Profile* profile, return &NewWebUI<SyncInternalsUI>; if (url.host() == chrome::kChromeUISettingsHost) return &NewWebUI<OptionsUI>; + if (url.host() == chrome::kChromeUITracingHost) + return &NewWebUI<TracingUI>; if (url.host() == chrome::kChromeUIQuotaInternalsHost) return &NewWebUI<QuotaInternalsUI>; if (url.host() == chrome::kChromeUIWorkersHost) diff --git a/chrome/browser/ui/webui/gpu_internals_ui.cc b/chrome/browser/ui/webui/gpu_internals_ui.cc index 8088c55..93860ba 100644 --- a/chrome/browser/ui/webui/gpu_internals_ui.cc +++ b/chrome/browser/ui/webui/gpu_internals_ui.cc @@ -4,49 +4,21 @@ #include "chrome/browser/ui/webui/gpu_internals_ui.h" -#include <algorithm> -#include <string> -#include <utility> -#include <vector> - #include "base/command_line.h" -#include "base/file_util.h" -#include "base/memory/singleton.h" -#include "base/message_loop.h" -#include "base/path_service.h" -#include "base/scoped_ptr.h" -#include "base/stringprintf.h" #include "base/string_number_conversions.h" -#include "base/string_piece.h" -#include "base/utf_string_conversions.h" +#include "base/stringprintf.h" #include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/io_thread.h" -#include "chrome/browser/net/chrome_net_log.h" -#include "chrome/browser/net/connection_tester.h" -#include "chrome/browser/net/passive_log_collector.h" -#include "chrome/browser/net/url_fixer_upper.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/shell_dialogs.h" -#include "chrome/browser/ui/webui/chrome_url_data_manager.h" #include "chrome/browser/ui/webui/chrome_web_ui_data_source.h" -#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_version_info.h" -#include "chrome/common/jstemplate_builder.h" #include "chrome/common/url_constants.h" #include "content/browser/browser_thread.h" #include "content/browser/gpu/gpu_data_manager.h" -#include "content/browser/gpu/gpu_process_host.h" -#include "content/browser/renderer_host/render_view_host.h" #include "content/browser/tab_contents/tab_contents.h" -#include "content/browser/tab_contents/tab_contents_view.h" -#include "content/browser/trace_controller.h" +#include "content/browser/webui/web_ui.h" #include "grit/browser_resources.h" #include "grit/generated_resources.h" -#include "net/base/escape.h" -#include "net/url_request/url_request_context_getter.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" namespace { @@ -65,9 +37,7 @@ ChromeWebUIDataSource* CreateGpuHTMLSource() { // this class's methods are expected to run on the UI thread. class GpuMessageHandler : public WebUIMessageHandler, - public SelectFileDialog::Listener, - public base::SupportsWeakPtr<GpuMessageHandler>, - public TraceSubscriber { + public base::SupportsWeakPtr<GpuMessageHandler> { public: GpuMessageHandler(); virtual ~GpuMessageHandler(); @@ -77,33 +47,15 @@ class GpuMessageHandler virtual void RegisterMessages() OVERRIDE; // Messages - void OnBeginTracing(const ListValue* list); - void OnEndTracingAsync(const ListValue* list); void OnBrowserBridgeInitialized(const ListValue* list); void OnCallAsync(const ListValue* list); - void OnBeginRequestBufferPercentFull(const ListValue* list); - void OnLoadTraceFile(const ListValue* list); - void OnSaveTraceFile(const ListValue* list); // Submessages dispatched from OnCallAsync Value* OnRequestClientInfo(const ListValue* list); Value* OnRequestLogMessages(const ListValue* list); - // SelectFileDialog::Listener implementation - virtual void FileSelected(const FilePath& path, - int index, - void* params) OVERRIDE; - virtual void FileSelectionCanceled(void* params) OVERRIDE; - // Callbacks. void OnGpuInfoUpdate(); - void LoadTraceFileComplete(std::string* file_contents); - void SaveTraceFileComplete(); - - // TraceSubscriber implementation. - virtual void OnEndTracingComplete() OVERRIDE; - virtual void OnTraceDataCollected(const std::string& json_events) OVERRIDE; - virtual void OnTraceBufferPercentFullReply(float percent_full) OVERRIDE; // Executes the javascript function |function_name| in the renderer, passing // it the argument |value|. @@ -117,33 +69,6 @@ class GpuMessageHandler GpuDataManager* gpu_data_manager_; Callback0::Type* gpu_info_update_callback_; - - scoped_refptr<SelectFileDialog> select_trace_file_dialog_; - SelectFileDialog::Type select_trace_file_dialog_type_; - scoped_ptr<std::string> trace_data_to_save_; - - bool trace_enabled_; -}; - -class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> { - public: - explicit TaskProxy(const base::WeakPtr<GpuMessageHandler>& handler) - : handler_(handler) {} - void LoadTraceFileCompleteProxy(std::string* file_contents) { - if (handler_) - handler_->LoadTraceFileComplete(file_contents); - delete file_contents; - } - - void SaveTraceFileCompleteProxy() { - if (handler_) - handler_->SaveTraceFileComplete(); - } - - private: - base::WeakPtr<GpuMessageHandler> handler_; - friend class base::RefCountedThreadSafe<TaskProxy>; - DISALLOW_COPY_AND_ASSIGN(TaskProxy); }; //////////////////////////////////////////////////////////////////////////////// @@ -153,9 +78,7 @@ class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> { //////////////////////////////////////////////////////////////////////////////// GpuMessageHandler::GpuMessageHandler() - : gpu_info_update_callback_(NULL), - select_trace_file_dialog_type_(SelectFileDialog::SELECT_NONE), - trace_enabled_(false) { + : gpu_info_update_callback_(NULL) { gpu_data_manager_ = GpuDataManager::GetInstance(); DCHECK(gpu_data_manager_); } @@ -165,12 +88,6 @@ GpuMessageHandler::~GpuMessageHandler() { gpu_data_manager_->RemoveGpuInfoUpdateCallback(gpu_info_update_callback_); delete gpu_info_update_callback_; } - - if (select_trace_file_dialog_) - select_trace_file_dialog_->ListenerDestroyed(); - - // If we are the current subscriber, this will result in ending tracing. - TraceController::GetInstance()->CancelSubscriber(this); } WebUIMessageHandler* GpuMessageHandler::Attach(WebUI* web_ui) { @@ -184,26 +101,11 @@ void GpuMessageHandler::RegisterMessages() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); web_ui_->RegisterMessageCallback( - "beginTracing", - NewCallback(this, &GpuMessageHandler::OnBeginTracing)); - web_ui_->RegisterMessageCallback( - "endTracingAsync", - NewCallback(this, &GpuMessageHandler::OnEndTracingAsync)); - web_ui_->RegisterMessageCallback( "browserBridgeInitialized", NewCallback(this, &GpuMessageHandler::OnBrowserBridgeInitialized)); web_ui_->RegisterMessageCallback( "callAsync", NewCallback(this, &GpuMessageHandler::OnCallAsync)); - web_ui_->RegisterMessageCallback( - "beginRequestBufferPercentFull", - NewCallback(this, &GpuMessageHandler::OnBeginRequestBufferPercentFull)); - web_ui_->RegisterMessageCallback( - "loadTraceFile", - NewCallback(this, &GpuMessageHandler::OnLoadTraceFile)); - web_ui_->RegisterMessageCallback( - "saveTraceFile", - NewCallback(this, &GpuMessageHandler::OnSaveTraceFile)); } void GpuMessageHandler::OnCallAsync(const ListValue* args) { @@ -253,139 +155,6 @@ void GpuMessageHandler::OnCallAsync(const ListValue* args) { } } -void GpuMessageHandler::OnBeginRequestBufferPercentFull(const ListValue* list) { - TraceController::GetInstance()->GetTraceBufferPercentFullAsync(this); -} - -class ReadTraceFileTask : public Task { - public: - ReadTraceFileTask(TaskProxy* proxy, const FilePath& path) - : proxy_(proxy) - , path_(path) {} - - virtual void Run() { - std::string* file_contents = new std::string(); - if (!file_util::ReadFileToString(path_, file_contents)) { - delete file_contents; - return; - } - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - NewRunnableMethod(proxy_.get(), - &TaskProxy::LoadTraceFileCompleteProxy, - file_contents)); - } - - private: - scoped_refptr<TaskProxy> proxy_; - - // Path of the file to open. - const FilePath path_; -}; - -class WriteTraceFileTask : public Task { - public: - WriteTraceFileTask(TaskProxy* proxy, - const FilePath& path, - std::string* contents) - : proxy_(proxy) - , path_(path) - , contents_(contents) {} - - virtual void Run() { - if (!file_util::WriteFile(path_, contents_->c_str(), contents_->size())) - return; - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - NewRunnableMethod(proxy_.get(), - &TaskProxy::SaveTraceFileCompleteProxy)); - } - - private: - scoped_refptr<TaskProxy> proxy_; - - // Path of the file to save. - const FilePath path_; - - // What to save - scoped_ptr<std::string> contents_; -}; - -void GpuMessageHandler::FileSelected( - const FilePath& path, int index, void* params) { - if (select_trace_file_dialog_type_ == SelectFileDialog::SELECT_OPEN_FILE) - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - new ReadTraceFileTask(new TaskProxy(AsWeakPtr()), path)); - else - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - new WriteTraceFileTask(new TaskProxy(AsWeakPtr()), path, - trace_data_to_save_.release())); - select_trace_file_dialog_.release(); -} - -void GpuMessageHandler::FileSelectionCanceled(void* params) { - select_trace_file_dialog_.release(); - if (select_trace_file_dialog_type_ == SelectFileDialog::SELECT_OPEN_FILE) - web_ui_->CallJavascriptFunction("tracingController.onLoadTraceFileCanceled"); - else - web_ui_->CallJavascriptFunction("tracingController.onSaveTraceFileCanceled"); -} - -void GpuMessageHandler::OnLoadTraceFile(const ListValue* list) { - // Only allow a single dialog at a time. - if (select_trace_file_dialog_.get()) - return; - select_trace_file_dialog_type_ = SelectFileDialog::SELECT_OPEN_FILE; - select_trace_file_dialog_ = SelectFileDialog::Create(this); - select_trace_file_dialog_->SelectFile( - SelectFileDialog::SELECT_OPEN_FILE, - string16(), - FilePath(), - NULL, 0, FILE_PATH_LITERAL(""), web_ui_->tab_contents(), - web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL); -} - -void GpuMessageHandler::LoadTraceFileComplete(std::string* file_contents) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - std::wstring javascript; - javascript += L"tracingController.onLoadTraceFileComplete("; - javascript += UTF8ToWide(*file_contents); - javascript += L");"; - - web_ui_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(), - WideToUTF16Hack(javascript)); -} - -void GpuMessageHandler::OnSaveTraceFile(const ListValue* list) { - // Only allow a single dialog at a time. - if (select_trace_file_dialog_.get()) - return; - - DCHECK(list->GetSize() == 1); - - std::string* trace_data = new std::string(); - bool ok = list->GetString(0, trace_data); - DCHECK(ok); - trace_data_to_save_.reset(trace_data); - - select_trace_file_dialog_type_ = SelectFileDialog::SELECT_SAVEAS_FILE; - select_trace_file_dialog_ = SelectFileDialog::Create(this); - select_trace_file_dialog_->SelectFile( - SelectFileDialog::SELECT_SAVEAS_FILE, - string16(), - FilePath(), - NULL, 0, FILE_PATH_LITERAL(""), web_ui_->tab_contents(), - web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL); -} - -void GpuMessageHandler::SaveTraceFileComplete() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - std::wstring javascript; - web_ui_->CallJavascriptFunction("tracingController.onSaveTraceFileComplete"); -} - void GpuMessageHandler::OnBrowserBridgeInitialized(const ListValue* args) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -436,89 +205,6 @@ Value* GpuMessageHandler::OnRequestClientInfo(const ListValue* list) { return dict; } -DictionaryValue* NewDescriptionValuePair(const std::string& desc, - const std::string& value) { - DictionaryValue* dict = new DictionaryValue(); - dict->SetString("description", desc); - dict->SetString("value", value); - return dict; -} - -DictionaryValue* NewDescriptionValuePair(const std::string& desc, - Value* value) { - DictionaryValue* dict = new DictionaryValue(); - dict->SetString("description", desc); - dict->Set("value", value); - return dict; -} - -#if defined(OS_WIN) -// Output DxDiagNode tree as nested array of {description,value} pairs -ListValue* DxDiagNodeToList(const DxDiagNode& node) { - ListValue* list = new ListValue(); - for (std::map<std::string, std::string>::const_iterator it = - node.values.begin(); - it != node.values.end(); - ++it) { - list->Append(NewDescriptionValuePair(it->first, it->second)); - } - - for (std::map<std::string, DxDiagNode>::const_iterator it = - node.children.begin(); - it != node.children.end(); - ++it) { - ListValue* sublist = DxDiagNodeToList(it->second); - list->Append(NewDescriptionValuePair(it->first, sublist)); - } - return list; -} - -#endif // OS_WIN - -DictionaryValue* GpuInfoToDict(const GPUInfo& gpu_info) { - ListValue* basic_info = new ListValue(); - basic_info->Append(NewDescriptionValuePair("Initialization time", - base::Int64ToString(gpu_info.initialization_time.InMilliseconds()))); - basic_info->Append(NewDescriptionValuePair("Vendor Id", - base::StringPrintf("0x%04x", gpu_info.vendor_id))); - basic_info->Append(NewDescriptionValuePair("Device Id", - base::StringPrintf("0x%04x", gpu_info.device_id))); - basic_info->Append(NewDescriptionValuePair("Driver vendor", - gpu_info.driver_vendor)); - basic_info->Append(NewDescriptionValuePair("Driver version", - gpu_info.driver_version)); - basic_info->Append(NewDescriptionValuePair("Driver date", - gpu_info.driver_date)); - basic_info->Append(NewDescriptionValuePair("Pixel shader version", - gpu_info.pixel_shader_version)); - basic_info->Append(NewDescriptionValuePair("Vertex shader version", - gpu_info.vertex_shader_version)); - basic_info->Append(NewDescriptionValuePair("GL version", - gpu_info.gl_version)); - basic_info->Append(NewDescriptionValuePair("GL_VENDOR", - gpu_info.gl_vendor)); - basic_info->Append(NewDescriptionValuePair("GL_RENDERER", - gpu_info.gl_renderer)); - basic_info->Append(NewDescriptionValuePair("GL_VERSION", - gpu_info.gl_version_string)); - basic_info->Append(NewDescriptionValuePair("GL_EXTENSIONS", - gpu_info.gl_extensions)); - - DictionaryValue* info = new DictionaryValue(); - info->Set("basic_info", basic_info); - -#if defined(OS_WIN) - Value* dx_info; - if (gpu_info.dx_diagnostics.children.size()) - dx_info = DxDiagNodeToList(gpu_info.dx_diagnostics); - else - dx_info = Value::CreateNullValue(); - info->Set("diagnostics", dx_info); -#endif - - return info; -} - Value* GpuMessageHandler::OnRequestLogMessages(const ListValue*) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -526,10 +212,9 @@ Value* GpuMessageHandler::OnRequestLogMessages(const ListValue*) { } void GpuMessageHandler::OnGpuInfoUpdate() { - const GPUInfo& gpu_info = gpu_data_manager_->gpu_info(); - // Get GPU Info. - DictionaryValue* gpu_info_val = GpuInfoToDict(gpu_info); + scoped_ptr<base::DictionaryValue> gpu_info_val( + gpu_data_manager_->GpuInfoAsDictionaryValue()); // Add in blacklisting features Value* feature_status = gpu_data_manager_->GetFeatureStatus(); @@ -538,57 +223,7 @@ void GpuMessageHandler::OnGpuInfoUpdate() { // Send GPU Info to javascript. web_ui_->CallJavascriptFunction("browserBridge.onGpuInfoUpdate", - *gpu_info_val); - - delete gpu_info_val; -} - -void GpuMessageHandler::OnBeginTracing(const ListValue* args) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - trace_enabled_ = true; - // TODO(jbates) This may fail, but that's OK for current use cases. - // Ex: Multiple about:gpu traces can not trace simultaneously. - // TODO(nduca) send feedback to javascript about whether or not BeginTracing - // was successful. - TraceController::GetInstance()->BeginTracing(this); -} - -void GpuMessageHandler::OnEndTracingAsync(const ListValue* list) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - // TODO(nduca): fix javascript code to make sure trace_enabled_ is always true - // here. triggered a false condition by just clicking stop - // trace a few times when it was going slow, and maybe switching - // between tabs. - if (trace_enabled_ && - !TraceController::GetInstance()->EndTracingAsync(this)) { - // Set to false now, since it turns out we never were the trace subscriber. - OnEndTracingComplete(); - } -} - -void GpuMessageHandler::OnEndTracingComplete() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - trace_enabled_ = false; - web_ui_->CallJavascriptFunction("tracingController.onEndTracingComplete"); -} - -void GpuMessageHandler::OnTraceDataCollected(const std::string& json_events) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - std::wstring javascript; - javascript += L"tracingController.onTraceDataCollected("; - javascript += UTF8ToWide(json_events); - javascript += L");"; - - web_ui_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(), - WideToUTF16Hack(javascript)); -} - -void GpuMessageHandler::OnTraceBufferPercentFullReply(float percent_full) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - web_ui_->CallJavascriptFunction( - "tracingController.onRequestBufferPercentFullComplete", - *scoped_ptr<Value>(Value::CreateDoubleValue(percent_full))); + *(gpu_info_val.get())); } } // namespace diff --git a/chrome/browser/ui/webui/tracing_ui.cc b/chrome/browser/ui/webui/tracing_ui.cc new file mode 100644 index 0000000..7b277c0 --- /dev/null +++ b/chrome/browser/ui/webui/tracing_ui.cc @@ -0,0 +1,525 @@ +// 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. + +#include "chrome/browser/ui/webui/tracing_ui.h" + +#include <string> + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/scoped_ptr.h" +#include "base/string_number_conversions.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/shell_dialogs.h" +#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h" +#include "chrome/common/chrome_version_info.h" +#include "chrome/common/url_constants.h" +#include "content/browser/gpu/gpu_data_manager.h" +#include "content/browser/renderer_host/render_view_host.h" +#include "content/browser/tab_contents/tab_contents.h" +#include "content/browser/tab_contents/tab_contents_view.h" +#include "content/browser/trace_controller.h" +#include "grit/browser_resources.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +namespace { + +ChromeWebUIDataSource* CreateTracingHTMLSource() { + ChromeWebUIDataSource* source = + new ChromeWebUIDataSource(chrome::kChromeUITracingHost); + + source->set_json_path("strings.js"); + source->add_resource_path("tracing.js", IDR_TRACING_JS); + source->set_default_resource(IDR_TRACING_HTML); + source->AddLocalizedString("tracingTitle", IDS_TRACING_TITLE); + return source; +} + +// This class receives javascript messages from the renderer. +// Note that the WebUI infrastructure runs on the UI thread, therefore all of +// this class's methods are expected to run on the UI thread. +class TracingMessageHandler + : public WebUIMessageHandler, + public SelectFileDialog::Listener, + public base::SupportsWeakPtr<TracingMessageHandler>, + public TraceSubscriber { + public: + TracingMessageHandler(); + virtual ~TracingMessageHandler(); + + // WebUIMessageHandler implementation. + virtual WebUIMessageHandler* Attach(WebUI* web_ui); + virtual void RegisterMessages(); + + // SelectFileDialog::Listener implementation + virtual void FileSelected(const FilePath& path, int index, void* params); + virtual void FileSelectionCanceled(void* params); + + // TraceSubscriber implementation. + virtual void OnEndTracingComplete(); + virtual void OnTraceDataCollected(const std::string& json_events); + virtual void OnTraceBufferPercentFullReply(float percent_full); + + // Messages. + void OnBrowserBridgeInitialized(const ListValue* list); + void OnCallAsync(const ListValue* list); + void OnBeginTracing(const ListValue* list); + void OnEndTracingAsync(const ListValue* list); + void OnBeginRequestBufferPercentFull(const ListValue* list); + void OnLoadTraceFile(const ListValue* list); + void OnSaveTraceFile(const ListValue* list); + + // Submessages dispatched from OnCallAsync. + Value* OnRequestClientInfo(const ListValue* list); + Value* OnRequestLogMessages(const ListValue* list); + + // Callbacks. + void OnGpuInfoUpdate(); + + // Callbacks. + void LoadTraceFileComplete(std::string* file_contents); + void SaveTraceFileComplete(); + + // Executes the javascript function |function_name| in the renderer, passing + // it the argument |value|. + void CallJavascriptFunction(const std::wstring& function_name, + const Value* value); + + private: + // The file dialog to select a file for loading or saving traces. + scoped_refptr<SelectFileDialog> select_trace_file_dialog_; + + // The type of the file dialog as the same one is used for loading or saving + // traces. + SelectFileDialog::Type select_trace_file_dialog_type_; + + // The trace data that is to be written to the file on saving. + scoped_ptr<std::string> trace_data_to_save_; + + // True while tracing is active. + bool trace_enabled_; + + // Cache the Singleton for efficiency. + GpuDataManager* gpu_data_manager_; + + // Callback called when the GPU info is updated. + Callback0::Type* gpu_info_update_callback_; + + DISALLOW_COPY_AND_ASSIGN(TracingMessageHandler); +}; + +// A proxy passed to the Read and Write tasks used when loading or saving trace +// data. +class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> { + public: + explicit TaskProxy(const base::WeakPtr<TracingMessageHandler>& handler) + : handler_(handler) {} + void LoadTraceFileCompleteProxy(std::string* file_contents) { + if (handler_) + handler_->LoadTraceFileComplete(file_contents); + delete file_contents; + } + + void SaveTraceFileCompleteProxy() { + if (handler_) + handler_->SaveTraceFileComplete(); + } + + private: + friend class base::RefCountedThreadSafe<TaskProxy>; + + // The message handler to call callbacks on. + base::WeakPtr<TracingMessageHandler> handler_; + + DISALLOW_COPY_AND_ASSIGN(TaskProxy); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// TracingMessageHandler +// +//////////////////////////////////////////////////////////////////////////////// + +TracingMessageHandler::TracingMessageHandler() + : select_trace_file_dialog_type_(SelectFileDialog::SELECT_NONE), + trace_enabled_(false), + gpu_info_update_callback_(NULL) { + gpu_data_manager_ = GpuDataManager::GetInstance(); + DCHECK(gpu_data_manager_); +} + +TracingMessageHandler::~TracingMessageHandler() { + if (gpu_info_update_callback_) { + gpu_data_manager_->RemoveGpuInfoUpdateCallback(gpu_info_update_callback_); + delete gpu_info_update_callback_; + } + + if (select_trace_file_dialog_) + select_trace_file_dialog_->ListenerDestroyed(); + + // If we are the current subscriber, this will result in ending tracing. + TraceController::GetInstance()->CancelSubscriber(this); +} + +WebUIMessageHandler* TracingMessageHandler::Attach(WebUI* web_ui) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui); + return result; +} + +void TracingMessageHandler::RegisterMessages() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + web_ui_->RegisterMessageCallback( + "browserBridgeInitialized", + NewCallback(this, &TracingMessageHandler::OnBrowserBridgeInitialized)); + web_ui_->RegisterMessageCallback( + "callAsync", + NewCallback(this, &TracingMessageHandler::OnCallAsync)); + web_ui_->RegisterMessageCallback( + "beginTracing", + NewCallback(this, &TracingMessageHandler::OnBeginTracing)); + web_ui_->RegisterMessageCallback( + "endTracingAsync", + NewCallback(this, &TracingMessageHandler::OnEndTracingAsync)); + web_ui_->RegisterMessageCallback( + "beginRequestBufferPercentFull", + NewCallback(this, + &TracingMessageHandler::OnBeginRequestBufferPercentFull)); + web_ui_->RegisterMessageCallback( + "loadTraceFile", + NewCallback(this, &TracingMessageHandler::OnLoadTraceFile)); + web_ui_->RegisterMessageCallback( + "saveTraceFile", + NewCallback(this, &TracingMessageHandler::OnSaveTraceFile)); +} + +void TracingMessageHandler::OnCallAsync(const ListValue* args) { + DCHECK_GE(args->GetSize(), static_cast<size_t>(2)); + // unpack args into requestId, submessage and submessageArgs + bool ok; + Value* requestId; + ok = args->Get(0, &requestId); + DCHECK(ok); + + std::string submessage; + ok = args->GetString(1, &submessage); + DCHECK(ok); + + ListValue* submessageArgs = new ListValue(); + for (size_t i = 2; i < args->GetSize(); ++i) { + Value* arg; + ok = args->Get(i, &arg); + DCHECK(ok); + + Value* argCopy = arg->DeepCopy(); + submessageArgs->Append(argCopy); + } + + // call the submessage handler + Value* ret = NULL; + if (submessage == "requestClientInfo") { + ret = OnRequestClientInfo(submessageArgs); + } else if (submessage == "requestLogMessages") { + ret = OnRequestLogMessages(submessageArgs); + } else { // unrecognized submessage + NOTREACHED(); + delete submessageArgs; + return; + } + delete submessageArgs; + + // call BrowserBridge.onCallAsyncReply with result + if (ret) { + web_ui_->CallJavascriptFunction("browserBridge.onCallAsyncReply", + *requestId, + *ret); + delete ret; + } else { + web_ui_->CallJavascriptFunction("browserBridge.onCallAsyncReply", + *requestId); + } +} + +void TracingMessageHandler::OnBrowserBridgeInitialized(const ListValue* args) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + DCHECK(!gpu_info_update_callback_); + + // Watch for changes in GPUInfo + gpu_info_update_callback_ = + NewCallback(this, &TracingMessageHandler::OnGpuInfoUpdate); + gpu_data_manager_->AddGpuInfoUpdateCallback(gpu_info_update_callback_); + + // Tell GpuDataManager it should have full GpuInfo. If the + // Gpu process has not run yet, this will trigger its launch. + gpu_data_manager_->RequestCompleteGpuInfoIfNeeded(); + + // Run callback immediately in case the info is ready and no update in the + // future. + OnGpuInfoUpdate(); +} + +Value* TracingMessageHandler::OnRequestClientInfo(const ListValue* list) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + DictionaryValue* dict = new DictionaryValue(); + + chrome::VersionInfo version_info; + + if (!version_info.is_valid()) { + DLOG(ERROR) << "Unable to create chrome::VersionInfo"; + } else { + // We have everything we need to send the right values. + dict->SetString("version", version_info.Version()); + dict->SetString("cl", version_info.LastChange()); + dict->SetString("version_mod", + chrome::VersionInfo::GetVersionStringModifier()); + dict->SetString("official", + l10n_util::GetStringUTF16( + version_info.IsOfficialBuild() ? + IDS_ABOUT_VERSION_OFFICIAL : + IDS_ABOUT_VERSION_UNOFFICIAL)); + + dict->SetString("command_line", + CommandLine::ForCurrentProcess()->GetCommandLineString()); + } + + dict->SetString("blacklist_version", + GpuDataManager::GetInstance()->GetBlacklistVersion()); + + return dict; +} + +Value* TracingMessageHandler::OnRequestLogMessages(const ListValue*) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + return gpu_data_manager_->log_messages().DeepCopy(); +} + +void TracingMessageHandler::OnBeginRequestBufferPercentFull( + const ListValue* list) { + TraceController::GetInstance()->GetTraceBufferPercentFullAsync(this); +} + +void TracingMessageHandler::OnGpuInfoUpdate() { + // Get GPU Info. + scoped_ptr<base::DictionaryValue> gpu_info_val( + gpu_data_manager_->GpuInfoAsDictionaryValue()); + + // Add in blacklisting features + Value* feature_status = gpu_data_manager_->GetFeatureStatus(); + if (feature_status) + gpu_info_val->Set("featureStatus", feature_status); + + // Send GPU Info to javascript. + web_ui_->CallJavascriptFunction("browserBridge.onGpuInfoUpdate", + *(gpu_info_val.get())); +} + +// A task used for asynchronously reading a file to a string. Calls the +// TaskProxy callback when reading is complete. +class ReadTraceFileTask : public Task { + public: + ReadTraceFileTask(TaskProxy* proxy, const FilePath& path) + : proxy_(proxy), + path_(path) {} + + virtual void Run() { + std::string* file_contents = new std::string(); + if (!file_util::ReadFileToString(path_, file_contents)) { + delete file_contents; + return; + } + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + NewRunnableMethod(proxy_.get(), + &TaskProxy::LoadTraceFileCompleteProxy, + file_contents)); + } + + private: + // The proxy that defines the completion callback. + scoped_refptr<TaskProxy> proxy_; + + // Path of the file to open. + const FilePath path_; +}; + +// A task used for asynchronously writing a file from a string. Calls the +// TaskProxy callback when writing is complete. +class WriteTraceFileTask : public Task { + public: + WriteTraceFileTask(TaskProxy* proxy, + const FilePath& path, + std::string* contents) + : proxy_(proxy) + , path_(path) + , contents_(contents) {} + + virtual void Run() { + if (!file_util::WriteFile(path_, contents_->c_str(), contents_->size())) + return; + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + NewRunnableMethod(proxy_.get(), + &TaskProxy::SaveTraceFileCompleteProxy)); + } + + private: + // The proxy that defines the completion callback. + scoped_refptr<TaskProxy> proxy_; + + // Path of the file to save. + const FilePath path_; + + // What to save + scoped_ptr<std::string> contents_; +}; + +void TracingMessageHandler::FileSelected( + const FilePath& path, int index, void* params) { + if (select_trace_file_dialog_type_ == SelectFileDialog::SELECT_OPEN_FILE) + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + new ReadTraceFileTask(new TaskProxy(AsWeakPtr()), path)); + else + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + new WriteTraceFileTask(new TaskProxy(AsWeakPtr()), path, + trace_data_to_save_.release())); + select_trace_file_dialog_.release(); +} + +void TracingMessageHandler::FileSelectionCanceled(void* params) { + select_trace_file_dialog_.release(); + if (select_trace_file_dialog_type_ == SelectFileDialog::SELECT_OPEN_FILE) { + web_ui_->CallJavascriptFunction( + "tracingController.onLoadTraceFileCanceled"); + } else { + web_ui_->CallJavascriptFunction( + "tracingController.onSaveTraceFileCanceled"); + } +} + +void TracingMessageHandler::OnLoadTraceFile(const ListValue* list) { + // Only allow a single dialog at a time. + if (select_trace_file_dialog_.get()) + return; + select_trace_file_dialog_type_ = SelectFileDialog::SELECT_OPEN_FILE; + select_trace_file_dialog_ = SelectFileDialog::Create(this); + select_trace_file_dialog_->SelectFile( + SelectFileDialog::SELECT_OPEN_FILE, + string16(), + FilePath(), + NULL, 0, FILE_PATH_LITERAL(""), web_ui_->tab_contents(), + web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL); +} + +void TracingMessageHandler::LoadTraceFileComplete(std::string* file_contents) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::wstring javascript; + javascript += L"tracingController.onLoadTraceFileComplete("; + javascript += UTF8ToWide(*file_contents); + javascript += L");"; + + web_ui_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(), + WideToUTF16Hack(javascript)); +} + +void TracingMessageHandler::OnSaveTraceFile(const ListValue* list) { + // Only allow a single dialog at a time. + if (select_trace_file_dialog_.get()) + return; + + DCHECK(list->GetSize() == 1); + + std::string* trace_data = new std::string(); + bool ok = list->GetString(0, trace_data); + DCHECK(ok); + trace_data_to_save_.reset(trace_data); + + select_trace_file_dialog_type_ = SelectFileDialog::SELECT_SAVEAS_FILE; + select_trace_file_dialog_ = SelectFileDialog::Create(this); + select_trace_file_dialog_->SelectFile( + SelectFileDialog::SELECT_SAVEAS_FILE, + string16(), + FilePath(), + NULL, 0, FILE_PATH_LITERAL(""), web_ui_->tab_contents(), + web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL); +} + +void TracingMessageHandler::SaveTraceFileComplete() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::wstring javascript; + web_ui_->CallJavascriptFunction("tracingController.onSaveTraceFileComplete"); +} + +void TracingMessageHandler::OnBeginTracing(const ListValue* args) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + trace_enabled_ = true; + // TODO(jbates) This may fail, but that's OK for current use cases. + // Ex: Multiple about:gpu traces can not trace simultaneously. + // TODO(nduca) send feedback to javascript about whether or not BeginTracing + // was successful. + TraceController::GetInstance()->BeginTracing(this); +} + +void TracingMessageHandler::OnEndTracingAsync(const ListValue* list) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // TODO(nduca): fix javascript code to make sure trace_enabled_ is always true + // here. triggered a false condition by just clicking stop + // trace a few times when it was going slow, and maybe switching + // between tabs. + if (trace_enabled_ && + !TraceController::GetInstance()->EndTracingAsync(this)) { + // Set to false now, since it turns out we never were the trace subscriber. + OnEndTracingComplete(); + } +} + +void TracingMessageHandler::OnEndTracingComplete() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + trace_enabled_ = false; + web_ui_->CallJavascriptFunction("tracingController.onEndTracingComplete"); +} + +void TracingMessageHandler::OnTraceDataCollected( + const std::string& json_events) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::wstring javascript; + javascript += L"tracingController.onTraceDataCollected("; + javascript += UTF8ToWide(json_events); + javascript += L");"; + + web_ui_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(), + WideToUTF16Hack(javascript)); +} + +void TracingMessageHandler::OnTraceBufferPercentFullReply(float percent_full) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + web_ui_->CallJavascriptFunction( + "tracingController.onRequestBufferPercentFullComplete", + *scoped_ptr<Value>(Value::CreateDoubleValue(percent_full))); +} + +} // namespace + + +//////////////////////////////////////////////////////////////////////////////// +// +// TracingUI +// +//////////////////////////////////////////////////////////////////////////////// + +TracingUI::TracingUI(TabContents* contents) : ChromeWebUI(contents) { + AddMessageHandler((new TracingMessageHandler())->Attach(this)); + + // Set up the chrome://tracing/ source. + Profile::FromBrowserContext(contents->browser_context())-> + GetChromeURLDataManager()->AddDataSource(CreateTracingHTMLSource()); +} diff --git a/chrome/browser/ui/webui/tracing_ui.h b/chrome/browser/ui/webui/tracing_ui.h new file mode 100644 index 0000000..ba7fad0 --- /dev/null +++ b/chrome/browser/ui/webui/tracing_ui.h @@ -0,0 +1,20 @@ +// 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. + +#ifndef CHROME_BROWSER_UI_WEBUI_TRACING_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_TRACING_UI_H_ +#pragma once + +#include "chrome/browser/ui/webui/chrome_web_ui.h" + +// The C++ back-end for the chrome://tracing webui page. +class TracingUI : public ChromeWebUI { + public: + explicit TracingUI(TabContents* contents); + + private: + DISALLOW_COPY_AND_ASSIGN(TracingUI); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_TRACING_UI_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index b555ced..7eb244c 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3666,6 +3666,8 @@ 'browser/ui/webui/textfields_ui.h', 'browser/ui/webui/theme_source.cc', 'browser/ui/webui/theme_source.h', + 'browser/ui/webui/tracing_ui.cc', + 'browser/ui/webui/tracing_ui.h', 'browser/ui/webui/web_ui_util.cc', 'browser/ui/webui/web_ui_util.h', 'browser/ui/webui/workers_ui.cc', diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 0e7b571..72002df 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc @@ -151,6 +151,7 @@ const char kChromeUITCMallocHost[] = "tcmalloc"; const char kChromeUITextfieldsHost[] = "textfields"; const char kChromeUITermsHost[] = "terms"; const char kChromeUITouchIconHost[] = "touch-icon"; +const char kChromeUITracingHost[] = "tracing"; const char kChromeUIVersionHost[] = "version"; const char kChromeUIWorkersHost[] = "workers"; diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index 6cb79e4..19d2034 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h @@ -149,6 +149,7 @@ extern const char kChromeUITCMallocHost[]; extern const char kChromeUITextfieldsHost[]; extern const char kChromeUITermsHost[]; extern const char kChromeUITouchIconHost[]; +extern const char kChromeUITracingHost[]; extern const char kChromeUIVersionHost[]; extern const char kChromeUIWorkersHost[]; |