Index: content/browser/tracing/tracing_ui.cc |
diff --git a/content/browser/tracing/tracing_ui.cc b/content/browser/tracing/tracing_ui.cc |
index 0609e196eba7a62f4274077a7577a5aa340f8ce2..6e471c28a8418c09417ed323c65864298c7ba498 100644 |
--- a/content/browser/tracing/tracing_ui.cc |
+++ b/content/browser/tracing/tracing_ui.cc |
@@ -6,568 +6,144 @@ |
#include <string> |
+#include "base/base64.h" |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
-#include "base/command_line.h" |
-#include "base/debug/trace_event.h" |
#include "base/file_util.h" |
-#include "base/json/string_escape.h" |
+#include "base/json/json_reader.h" |
+#include "base/json/json_writer.h" |
#include "base/memory/scoped_ptr.h" |
-#include "base/safe_numerics.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/string_util.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/strings/utf_string_conversions.h" |
#include "base/values.h" |
#include "content/public/browser/browser_thread.h" |
-#include "content/public/browser/content_browser_client.h" |
-#include "content/public/browser/render_view_host.h" |
-#include "content/public/browser/trace_controller.h" |
-#include "content/public/browser/trace_subscriber.h" |
+#include "content/public/browser/tracing_controller.h" |
#include "content/public/browser/web_contents.h" |
-#include "content/public/browser/web_contents_view.h" |
#include "content/public/browser/web_ui.h" |
#include "content/public/browser/web_ui_data_source.h" |
-#include "content/public/browser/web_ui_message_handler.h" |
#include "content/public/common/url_constants.h" |
#include "grit/tracing_resources.h" |
-#include "ipc/ipc_channel.h" |
-#include "ui/shell_dialogs/select_file_dialog.h" |
- |
-#if defined(OS_CHROMEOS) |
-#include "chromeos/dbus/dbus_thread_manager.h" |
-#include "chromeos/dbus/debug_daemon_client.h" |
-#endif |
namespace content { |
namespace { |
-WebUIDataSource* CreateTracingHTMLSource() { |
- WebUIDataSource* source = WebUIDataSource::Create(kChromeUITracingHost); |
- |
- source->SetJsonPath("strings.js"); |
- source->SetDefaultResource(IDR_TRACING_HTML); |
- source->AddResourcePath("tracing.js", IDR_TRACING_JS); |
- 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 ui::SelectFileDialog::Listener, |
- public base::SupportsWeakPtr<TracingMessageHandler>, |
- public TraceSubscriber { |
- public: |
- TracingMessageHandler(); |
- virtual ~TracingMessageHandler(); |
- |
- // WebUIMessageHandler implementation. |
- virtual void RegisterMessages() OVERRIDE; |
- |
- // SelectFileDialog::Listener implementation |
- virtual void FileSelected(const base::FilePath& path, |
- int index, |
- void* params) OVERRIDE; |
- virtual void FileSelectionCanceled(void* params) OVERRIDE; |
- |
- // TraceSubscriber implementation. |
- virtual void OnEndTracingComplete() OVERRIDE; |
- virtual void OnTraceDataCollected( |
- const scoped_refptr<base::RefCountedString>& trace_fragment) OVERRIDE; |
- virtual void OnTraceBufferPercentFullReply(float percent_full) OVERRIDE; |
- virtual void OnKnownCategoriesCollected( |
- const std::set<std::string>& known_categories) OVERRIDE; |
- |
- // Messages. |
- void OnTracingControllerInitialized(const base::ListValue* list); |
- void OnBeginTracing(const base::ListValue* list); |
- void OnEndTracingAsync(const base::ListValue* list); |
- void OnBeginRequestBufferPercentFull(const base::ListValue* list); |
- void OnLoadTraceFile(const base::ListValue* list); |
- void OnSaveTraceFile(const base::ListValue* list); |
- void OnGetKnownCategories(const base::ListValue* list); |
- |
- // Callbacks. |
- void LoadTraceFileComplete(string16* file_contents, |
- const base::FilePath &path); |
- void SaveTraceFileComplete(); |
+void OnGotCategories(const WebUIDataSource::GotDataCallback& callback, |
+ const std::set<std::string>& categorySet) { |
- private: |
- // The file dialog to select a file for loading or saving traces. |
- scoped_refptr<ui::SelectFileDialog> select_trace_file_dialog_; |
- |
- // The type of the file dialog as the same one is used for loading or saving |
- // traces. |
- ui::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_; |
- |
- // True while system tracing is active. |
- bool system_trace_in_progress_; |
- |
- void OnEndSystemTracingAck( |
- const scoped_refptr<base::RefCountedString>& events_str_ptr); |
- |
- 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(string16* file_contents, |
- const base::FilePath& path) { |
- if (handler_.get()) |
- handler_->LoadTraceFileComplete(file_contents, path); |
- delete file_contents; |
- } |
- |
- void SaveTraceFileCompleteProxy() { |
- if (handler_.get()) |
- handler_->SaveTraceFileComplete(); |
+ scoped_ptr<base::ListValue> category_list(new base::ListValue()); |
+ for (std::set<std::string>::const_iterator it = categorySet.begin(); |
+ it != categorySet.end(); it++) { |
+ category_list->AppendString(*it); |
} |
- private: |
- friend class base::RefCountedThreadSafe<TaskProxy>; |
- ~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_(ui::SelectFileDialog::SELECT_NONE), |
- trace_enabled_(false), |
- system_trace_in_progress_(false) { |
+ base::RefCountedString* res = new base::RefCountedString(); |
+ base::JSONWriter::Write(category_list.get(), &res->data()); |
+ callback.Run(res); |
} |
-TracingMessageHandler::~TracingMessageHandler() { |
- if (select_trace_file_dialog_.get()) |
- select_trace_file_dialog_->ListenerDestroyed(); |
- |
- // If we are the current subscriber, this will result in ending tracing. |
- TraceController::GetInstance()->CancelSubscriber(this); |
- |
- // Shutdown any system tracing too. |
- if (system_trace_in_progress_) { |
-#if defined(OS_CHROMEOS) |
- chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> |
- RequestStopSystemTracing( |
- chromeos::DebugDaemonClient::EmptyStopSystemTracingCallback()); |
-#endif |
- } |
-} |
- |
-void TracingMessageHandler::RegisterMessages() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- web_ui()->RegisterMessageCallback("tracingControllerInitialized", |
- base::Bind(&TracingMessageHandler::OnTracingControllerInitialized, |
- base::Unretained(this))); |
- web_ui()->RegisterMessageCallback("beginTracing", |
- base::Bind(&TracingMessageHandler::OnBeginTracing, |
- base::Unretained(this))); |
- web_ui()->RegisterMessageCallback("endTracingAsync", |
- base::Bind(&TracingMessageHandler::OnEndTracingAsync, |
- base::Unretained(this))); |
- web_ui()->RegisterMessageCallback("beginRequestBufferPercentFull", |
- base::Bind(&TracingMessageHandler::OnBeginRequestBufferPercentFull, |
- base::Unretained(this))); |
- web_ui()->RegisterMessageCallback("loadTraceFile", |
- base::Bind(&TracingMessageHandler::OnLoadTraceFile, |
- base::Unretained(this))); |
- web_ui()->RegisterMessageCallback("saveTraceFile", |
- base::Bind(&TracingMessageHandler::OnSaveTraceFile, |
- base::Unretained(this))); |
- web_ui()->RegisterMessageCallback("getKnownCategories", |
- base::Bind(&TracingMessageHandler::OnGetKnownCategories, |
- base::Unretained(this))); |
-} |
- |
-void TracingMessageHandler::OnTracingControllerInitialized( |
- const base::ListValue* args) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // Send the client info to the tracingController |
- { |
- scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
- dict->SetString("version", GetContentClient()->GetProduct()); |
+void OnRecordingEnabledAck(const WebUIDataSource::GotDataCallback& callback); |
- dict->SetString("command_line", |
- CommandLine::ForCurrentProcess()->GetCommandLineString()); |
- |
- web_ui()->CallJavascriptFunction("tracingController.onClientInfoUpdate", |
- *dict); |
+bool OnBeginRecording(const std::string& data64, |
+ const WebUIDataSource::GotDataCallback& callback) { |
+ std::string data; |
+ if (!base::Base64Decode(data64, &data)) { |
+ LOG(ERROR) << "Options were not base64 encoded."; |
+ return false; |
} |
-} |
- |
-void TracingMessageHandler::OnBeginRequestBufferPercentFull( |
- const base::ListValue* list) { |
- TraceController::GetInstance()->GetTraceBufferPercentFullAsync(this); |
-} |
- |
-// A callback used for asynchronously reading a file to a string. Calls the |
-// TaskProxy callback when reading is complete. |
-void ReadTraceFileCallback(TaskProxy* proxy, const base::FilePath& path) { |
- std::string file_contents; |
- if (!base::ReadFileToString(path, &file_contents)) |
- return; |
- // We need to escape the file contents, because it will go into a javascript |
- // quoted string in TracingMessageHandler::LoadTraceFileComplete. We need to |
- // escape control characters (to have well-formed javascript statements), as |
- // well as \ and ' (the only special characters in a ''-quoted string). |
- // Do the escaping on this thread, it may take a little while for big files |
- // and we don't want to block the UI during that time. Also do the UTF-16 |
- // conversion here. |
- // Note: we're using UTF-16 because we'll need to cut the string into slices |
- // to give to Javascript, and it's easier to cut than UTF-8 (since JS strings |
- // are arrays of 16-bit values, UCS-2 really, whereas we can't cut inside of a |
- // multibyte UTF-8 codepoint). |
- size_t size = file_contents.size(); |
- std::string escaped_contents; |
- escaped_contents.reserve(size); |
- for (size_t i = 0; i < size; ++i) { |
- char c = file_contents[i]; |
- if (c < ' ' || c == 0x7f) { |
- escaped_contents += base::StringPrintf("\\u%04x", |
- static_cast<uint8_t>(c)); |
- continue; |
- } |
- if (c == '\\' || c == '\'') |
- escaped_contents.push_back('\\'); |
- escaped_contents.push_back(c); |
+ scoped_ptr<base::Value> optionsRaw(base::JSONReader::Read(data)); |
+ if (!optionsRaw) { |
+ LOG(ERROR) << "Options were not valid JSON"; |
+ return false; |
} |
- file_contents.clear(); |
- |
- scoped_ptr<string16> contents16(new string16); |
- UTF8ToUTF16(escaped_contents).swap(*contents16); |
- |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&TaskProxy::LoadTraceFileCompleteProxy, proxy, |
- contents16.release(), |
- path)); |
-} |
- |
-// A callback used for asynchronously writing a file from a string. Calls the |
-// TaskProxy callback when writing is complete. |
-void WriteTraceFileCallback(TaskProxy* proxy, |
- const base::FilePath& path, |
- std::string* contents) { |
- int size = base::checked_numeric_cast<int>(contents->size()); |
- if (file_util::WriteFile(path, contents->c_str(), size) != size) |
- return; |
- |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&TaskProxy::SaveTraceFileCompleteProxy, proxy)); |
-} |
- |
-void TracingMessageHandler::FileSelected( |
- const base::FilePath& path, int index, void* params) { |
- if (select_trace_file_dialog_type_ == |
- ui::SelectFileDialog::SELECT_OPEN_FILE) { |
- BrowserThread::PostTask( |
- BrowserThread::FILE, FROM_HERE, |
- base::Bind(&ReadTraceFileCallback, |
- make_scoped_refptr(new TaskProxy(AsWeakPtr())), path)); |
- } else { |
- BrowserThread::PostTask( |
- BrowserThread::FILE, FROM_HERE, |
- base::Bind(&WriteTraceFileCallback, |
- make_scoped_refptr(new TaskProxy(AsWeakPtr())), path, |
- trace_data_to_save_.release())); |
+ base::DictionaryValue* options; |
+ if (!optionsRaw->GetAsDictionary(&options)) { |
+ LOG(ERROR) << "Options must be dict"; |
+ return false; |
} |
- select_trace_file_dialog_ = NULL; |
-} |
- |
-void TracingMessageHandler::FileSelectionCanceled(void* params) { |
- select_trace_file_dialog_ = NULL; |
- if (select_trace_file_dialog_type_ == |
- ui::SelectFileDialog::SELECT_OPEN_FILE) { |
- web_ui()->CallJavascriptFunction( |
- "tracingController.onLoadTraceFileCanceled"); |
- } else { |
- web_ui()->CallJavascriptFunction( |
- "tracingController.onSaveTraceFileCanceled"); |
+ std::string category_filter_string; |
+ bool use_system_tracing; |
+ bool use_continuous_tracing; |
+ bool use_sampling; |
+ |
+ bool options_ok = true; |
+ options_ok &= options->GetString("categoryFilter", &category_filter_string); |
+ options_ok &= options->GetBoolean("useSystemTracing", &use_system_tracing); |
+ options_ok &= options->GetBoolean("useContinuousTracing", |
+ &use_continuous_tracing); |
+ options_ok &= options->GetBoolean("useSampling", &use_sampling); |
+ if (!options_ok) { |
+ LOG(ERROR) << "Malformed options"; |
+ return false; |
} |
-} |
- |
-void TracingMessageHandler::OnLoadTraceFile(const base::ListValue* list) { |
- // Only allow a single dialog at a time. |
- if (select_trace_file_dialog_.get()) |
- return; |
- select_trace_file_dialog_type_ = ui::SelectFileDialog::SELECT_OPEN_FILE; |
- select_trace_file_dialog_ = ui::SelectFileDialog::Create( |
- this, |
- GetContentClient()->browser()->CreateSelectFilePolicy( |
- web_ui()->GetWebContents())); |
- select_trace_file_dialog_->SelectFile( |
- ui::SelectFileDialog::SELECT_OPEN_FILE, |
- string16(), |
- base::FilePath(), |
- NULL, |
- 0, |
- base::FilePath::StringType(), |
- web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow(), |
- NULL); |
-} |
-void TracingMessageHandler::LoadTraceFileComplete(string16* contents, |
- const base::FilePath& path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ int tracing_options = 0; |
+ if (use_system_tracing) |
+ tracing_options |= TracingController::ENABLE_SYSTRACE; |
+ if (use_sampling) |
+ tracing_options |= TracingController::ENABLE_SAMPLING; |
+ if (use_continuous_tracing) |
+ tracing_options |= TracingController::RECORD_CONTINUOUSLY; |
- // We need to pass contents to tracingController.onLoadTraceFileComplete, but |
- // that may be arbitrarily big, and IPCs messages are limited in size. So we |
- // need to cut it into pieces and rebuild the string in Javascript. |
- // |contents| has already been escaped in ReadTraceFileCallback, so we need to |
- // avoid splitting escape sequences (e.g., \' or \u1234) to keep the data |
- // intact. IPC::Channel::kMaximumMessageSize is in bytes, and we need to |
- // account for overhead. |
- const size_t kMaxSize = IPC::Channel::kMaximumMessageSize / 2 - 128; |
- const size_t kControlCharEscapeSequenceSize = 5; |
- string16 first_prefix = UTF8ToUTF16("window.traceData = '"); |
- string16 prefix = UTF8ToUTF16("window.traceData += '"); |
- string16 suffix = UTF8ToUTF16("';"); |
- |
- RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost(); |
- |
- size_t flush_offset = 0; |
- size_t token_start = 0; |
- while (flush_offset < contents->size()) { |
- size_t token_end = token_start; |
- if ((*contents)[token_end] == '\\') { |
- token_end++; |
- DCHECK(token_end < contents->size()); |
- if (token_end < contents->size() && (*contents)[token_end] == 'u') { |
- token_end += kControlCharEscapeSequenceSize; |
- } else { |
- token_end++; |
- } |
- } else { |
- token_end++; |
- } |
- token_end = std::min(contents->size(), token_end); |
- size_t token_size = token_end - token_start; |
- size_t flush_size = token_start - flush_offset; |
- if (token_end == contents->size()) { |
- flush_size = contents->size() - flush_offset; |
- } else if (flush_size + token_size < kMaxSize) { |
- token_start += token_size; |
- continue; |
- } |
- string16 javascript = flush_offset == 0 ? first_prefix : prefix; |
- javascript += contents->substr(flush_offset, flush_size) + suffix; |
- rvh->ExecuteJavascriptInWebFrame(string16(), javascript); |
- flush_offset += flush_size; |
- } |
- |
- // The CallJavascriptFunction is not used because we need to pass |
- // the first param |window.traceData| through as an un-quoted string. |
- rvh->ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16( |
- "tracingController.onLoadTraceFileComplete(window.traceData," + |
- base::GetDoubleQuotedJson(path.value()) + ");" + |
- "delete window.traceData;")); |
+ base::debug::CategoryFilter category_filter(category_filter_string); |
+ return TracingController::GetInstance()->EnableRecording( |
+ category_filter, |
+ static_cast<TracingController::Options>(tracing_options), |
+ base::Bind(OnRecordingEnabledAck, callback)); |
} |
-void TracingMessageHandler::OnSaveTraceFile(const base::ListValue* list) { |
- // Only allow a single dialog at a time. |
- if (select_trace_file_dialog_.get()) |
- return; |
- |
- DCHECK_EQ(1U, list->GetSize()); |
- |
- 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_ = ui::SelectFileDialog::SELECT_SAVEAS_FILE; |
- select_trace_file_dialog_ = ui::SelectFileDialog::Create( |
- this, |
- GetContentClient()->browser()->CreateSelectFilePolicy( |
- web_ui()->GetWebContents())); |
- select_trace_file_dialog_->SelectFile( |
- ui::SelectFileDialog::SELECT_SAVEAS_FILE, |
- string16(), |
- base::FilePath(), |
- NULL, |
- 0, |
- base::FilePath::StringType(), |
- web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow(), |
- NULL); |
+void OnRecordingEnabledAck(const WebUIDataSource::GotDataCallback& callback) { |
+ base::RefCountedString* res = new base::RefCountedString(); |
+ callback.Run(res); |
} |
-void TracingMessageHandler::SaveTraceFileComplete() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- web_ui()->CallJavascriptFunction("tracingController.onSaveTraceFileComplete"); |
+void OnTraceBufferPercentFullResult( |
+ const WebUIDataSource::GotDataCallback& callback, float result) { |
+ std::string str = base::DoubleToString(result); |
+ callback.Run(base::RefCountedString::TakeString(&str)); |
} |
-void TracingMessageHandler::OnBeginTracing(const base::ListValue* args) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK_GE(args->GetSize(), (size_t) 2); |
- DCHECK_LE(args->GetSize(), (size_t) 3); |
- |
- bool system_tracing_requested = false; |
- bool ok = args->GetBoolean(0, &system_tracing_requested); |
- DCHECK(ok); |
- |
- std::string chrome_categories; |
- ok = args->GetString(1, &chrome_categories); |
- DCHECK(ok); |
- |
- base::debug::TraceLog::Options options = |
- base::debug::TraceLog::RECORD_UNTIL_FULL; |
- if (args->GetSize() >= 3) { |
- std::string options_; |
- ok = args->GetString(2, &options_); |
- DCHECK(ok); |
- options = base::debug::TraceLog::TraceOptionsFromString(options_); |
- } |
- |
- 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, chrome_categories, |
- options); |
- |
- if (system_tracing_requested) { |
-#if defined(OS_CHROMEOS) |
- DCHECK(!system_trace_in_progress_); |
- chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> |
- StartSystemTracing(); |
- // TODO(sleffler) async, could wait for completion |
- system_trace_in_progress_ = true; |
-#endif |
- } |
+void ReadRecordingResult(const WebUIDataSource::GotDataCallback& callback, |
+ const base::FilePath& path) { |
+ std::string tmp; |
+ if (!base::ReadFileToString(path, &tmp)) |
+ LOG(ERROR) << "Failed to read file " << path.value(); |
+ base::DeleteFile(path, false); |
+ callback.Run(base::RefCountedString::TakeString(&tmp)); |
} |
-void TracingMessageHandler::OnEndTracingAsync(const base::ListValue* list) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // This is really us beginning to end tracing, rather than tracing being truly |
- // over. When this function yields, we expect to get some number of |
- // OnTraceDataCollected callbacks, which will append data to window.traceData. |
- // To set up for this, set window.traceData to the empty string. |
- web_ui()->GetWebContents()->GetRenderViewHost()-> |
- ExecuteJavascriptInWebFrame(string16(), |
- UTF8ToUTF16("window.traceData = '';")); |
- |
- // 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 BeginReadingRecordingResult( |
+ const WebUIDataSource::GotDataCallback& callback, |
+ const base::FilePath& path) { |
+ BrowserThread::PostTask( |
+ BrowserThread::FILE, FROM_HERE, |
+ base::Bind(ReadRecordingResult, callback, path)); |
} |
-void TracingMessageHandler::OnEndTracingComplete() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- trace_enabled_ = false; |
- if (system_trace_in_progress_) { |
- // Disable system tracing now that the local trace has shutdown. |
- // This must be done last because we potentially need to push event |
- // records into the system event log for synchronizing system event |
- // timestamps with chrome event timestamps--and since the system event |
- // log is a ring-buffer (on linux) adding them at the end is the only |
- // way we're confident we'll have them in the final result. |
- system_trace_in_progress_ = false; |
-#if defined(OS_CHROMEOS) |
- chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> |
- RequestStopSystemTracing( |
- base::Bind(&TracingMessageHandler::OnEndSystemTracingAck, |
- base::Unretained(this))); |
- return; |
-#endif |
+bool OnBeginRequest(const std::string& path, |
+ const WebUIDataSource::GotDataCallback& callback) { |
+ if (path == "json/categories") { |
+ TracingController::GetInstance()->GetCategories( |
+ base::Bind(OnGotCategories, callback)); |
+ return true; |
} |
- |
- RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost(); |
- rvh->ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16( |
- "tracingController.onEndTracingComplete(window.traceData);" |
- "delete window.traceData;")); |
-} |
- |
-void TracingMessageHandler::OnEndSystemTracingAck( |
- const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- web_ui()->CallJavascriptFunction( |
- "tracingController.onSystemTraceDataCollected", |
- *scoped_ptr<base::Value>(new base::StringValue(events_str_ptr->data()))); |
- DCHECK(!system_trace_in_progress_); |
- |
- OnEndTracingComplete(); |
-} |
- |
-void TracingMessageHandler::OnTraceDataCollected( |
- const scoped_refptr<base::RefCountedString>& trace_fragment) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- std::string javascript; |
- javascript.reserve(trace_fragment->size() * 2); |
- javascript.append("window.traceData += \""); |
- base::JsonDoubleQuote(trace_fragment->data(), false, &javascript); |
- |
- // Intentionally append a , to the traceData. This technically causes all |
- // traceData that we pass back to JS to end with a comma, but that is actually |
- // something the JS side strips away anyway |
- javascript.append(",\";"); |
- |
- web_ui()->GetWebContents()->GetRenderViewHost()-> |
- ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(javascript)); |
-} |
- |
-void TracingMessageHandler::OnTraceBufferPercentFullReply(float percent_full) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- web_ui()->CallJavascriptFunction( |
- "tracingController.onRequestBufferPercentFullComplete", |
- *scoped_ptr<base::Value>(new base::FundamentalValue(percent_full))); |
-} |
- |
-void TracingMessageHandler::OnGetKnownCategories(const base::ListValue* list) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- if (!TraceController::GetInstance()->GetKnownCategoryGroupsAsync(this)) { |
- std::set<std::string> ret; |
- OnKnownCategoriesCollected(ret); |
+ const char* beginRecordingPath = "json/begin_recording?"; |
+ if (path.find(beginRecordingPath) == 0) { |
+ std::string data = path.substr(strlen(beginRecordingPath)); |
+ return OnBeginRecording(data, callback); |
} |
-} |
- |
-void TracingMessageHandler::OnKnownCategoriesCollected( |
- const std::set<std::string>& known_categories) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- scoped_ptr<base::ListValue> categories(new base::ListValue()); |
- for (std::set<std::string>::const_iterator iter = known_categories.begin(); |
- iter != known_categories.end(); |
- ++iter) { |
- categories->AppendString(*iter); |
+ if (path == "json/get_buffer_percent_full") { |
+ return TracingController::GetInstance()->GetTraceBufferPercentFull( |
+ base::Bind(OnTraceBufferPercentFullResult, callback)); |
} |
- |
- web_ui()->CallJavascriptFunction( |
- "tracingController.onKnownCategoriesCollected", *categories); |
+ if (path == "json/end_recording") { |
+ return TracingController::GetInstance()->DisableRecording( |
+ base::FilePath(), base::Bind(BeginReadingRecordingResult, callback)); |
+ } |
+ if (StartsWithASCII(path, "json/", true)) |
+ LOG(ERROR) << "Unhandled request to " << path; |
+ return false; |
} |
} // namespace |
@@ -580,12 +156,16 @@ void TracingMessageHandler::OnKnownCategoriesCollected( |
//////////////////////////////////////////////////////////////////////////////// |
TracingUI::TracingUI(WebUI* web_ui) : WebUIController(web_ui) { |
- web_ui->AddMessageHandler(new TracingMessageHandler()); |
- |
// Set up the chrome://tracing/ source. |
BrowserContext* browser_context = |
web_ui->GetWebContents()->GetBrowserContext(); |
- WebUIDataSource::Add(browser_context, CreateTracingHTMLSource()); |
+ |
+ WebUIDataSource* source = WebUIDataSource::Create(kChromeUITracingHost); |
+ source->SetJsonPath("strings.js"); |
+ source->SetDefaultResource(IDR_TRACING_HTML); |
+ source->AddResourcePath("tracing.js", IDR_TRACING_JS); |
+ source->SetRequestFilter(base::Bind(OnBeginRequest)); |
+ WebUIDataSource::Add(browser_context, source); |
} |
} // namespace content |