15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/tracing/tracing_ui.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <set> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/base64.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/command_line.h" 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/debug/trace_event.h" 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/format_macros.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/json/json_reader.h" 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/json/json_writer.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/string_split.h" 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/stringprintf.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/browser/tracing/grit/tracing_resources.h" 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/tracing/trace_uploader.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/tracing/tracing_controller_impl.h" 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/browser/browser_context.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/public/browser/tracing_controller.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_ui_data_source.h" 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/common/content_client.h" 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/common/content_switches.h" 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/url_constants.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kUploadURL[] = "https://clients2.google.com/cr/staging_report"; 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OnGotCategories(const WebUIDataSource::GotDataCallback& callback, 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::set<std::string>& categorySet) { 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<base::ListValue> category_list(new base::ListValue()); 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (std::set<std::string>::const_iterator it = categorySet.begin(); 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it != categorySet.end(); it++) { 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) category_list->AppendString(*it); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::RefCountedString* res = new base::RefCountedString(); 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::JSONWriter::Write(category_list.get(), &res->data()); 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) callback.Run(res); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GetTracingOptions(const std::string& data64, 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::CategoryFilter* category_filter, 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::TraceOptions* tracing_options) { 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string data; 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!base::Base64Decode(data64, &data)) { 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << "Options were not base64 encoded."; 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<base::Value> optionsRaw(base::JSONReader::Read(data)); 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!optionsRaw) { 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << "Options were not valid JSON"; 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::DictionaryValue* options; 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!optionsRaw->GetAsDictionary(&options)) { 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << "Options must be dict"; 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!category_filter) { 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "category_filter can't be passed as NULL"; 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!tracing_options) { 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "tracing_options can't be passed as NULL"; 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool options_ok = true; 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string category_filter_string; 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) options_ok &= options->GetString("categoryFilter", &category_filter_string); 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *category_filter = base::debug::CategoryFilter(category_filter_string); 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) options_ok &= options->GetBoolean("useSystemTracing", 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &tracing_options->enable_systrace); 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) options_ok &= 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) options->GetBoolean("useSampling", &tracing_options->enable_sampling); 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool use_continuous_tracing; 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) options_ok &= 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) options->GetBoolean("useContinuousTracing", &use_continuous_tracing); 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (use_continuous_tracing) 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tracing_options->record_mode = base::debug::RECORD_CONTINUOUSLY; 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tracing_options->record_mode = base::debug::RECORD_UNTIL_FULL; 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!options_ok) { 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << "Malformed options"; 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OnRecordingEnabledAck(const WebUIDataSource::GotDataCallback& callback); 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BeginRecording(const std::string& data64, 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const WebUIDataSource::GotDataCallback& callback) { 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::CategoryFilter category_filter(""); 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::TraceOptions tracing_options; 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!GetTracingOptions(data64, &category_filter, &tracing_options)) 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return TracingController::GetInstance()->EnableRecording( 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) category_filter, 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tracing_options, 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&OnRecordingEnabledAck, callback)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OnRecordingEnabledAck(const WebUIDataSource::GotDataCallback& callback) { 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::RefCountedString* res = new base::RefCountedString(); 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) callback.Run(res); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OnTraceBufferPercentFullResult( 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const WebUIDataSource::GotDataCallback& callback, float result) { 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string str = base::DoubleToString(result); 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) callback.Run(base::RefCountedString::TakeString(&str)); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OnMonitoringEnabledAck(const WebUIDataSource::GotDataCallback& callback); 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool EnableMonitoring(const std::string& data64, 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const WebUIDataSource::GotDataCallback& callback) { 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::TraceOptions tracing_options; 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::CategoryFilter category_filter(""); 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!GetTracingOptions(data64, &category_filter, &tracing_options)) 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return TracingController::GetInstance()->EnableMonitoring( 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) category_filter, 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tracing_options, 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(OnMonitoringEnabledAck, callback)); 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OnMonitoringEnabledAck(const WebUIDataSource::GotDataCallback& callback) { 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::RefCountedString* res = new base::RefCountedString(); 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(res); 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OnMonitoringDisabled(const WebUIDataSource::GotDataCallback& callback) { 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::RefCountedString* res = new base::RefCountedString(); 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(res); 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GetMonitoringStatus(const WebUIDataSource::GotDataCallback& callback) { 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_monitoring; 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::CategoryFilter category_filter(""); 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::TraceOptions options; 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TracingController::GetInstance()->GetMonitoringStatus( 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &is_monitoring, &category_filter, &options); 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) monitoring_options(new base::DictionaryValue()); 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) monitoring_options->SetBoolean("isMonitoring", is_monitoring); 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) monitoring_options->SetString("categoryFilter", category_filter.ToString()); 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) monitoring_options->SetBoolean("useSystemTracing", options.enable_systrace); 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) monitoring_options->SetBoolean( 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "useContinuousTracing", 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) options.record_mode == base::debug::RECORD_CONTINUOUSLY); 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) monitoring_options->SetBoolean("useSampling", options.enable_sampling); 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string monitoring_options_json; 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::JSONWriter::Write(monitoring_options.get(), &monitoring_options_json); 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::RefCountedString* monitoring_options_base64 = 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new base::RefCountedString(); 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Base64Encode(monitoring_options_json, 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &monitoring_options_base64->data()); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(monitoring_options_base64); 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid TracingCallbackWrapper(const WebUIDataSource::GotDataCallback& callback, 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::RefCountedString* data) { 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(data); 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool OnBeginJSONRequest(const std::string& path, 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const WebUIDataSource::GotDataCallback& callback) { 197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (path == "json/categories") { 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return TracingController::GetInstance()->GetCategories( 199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(OnGotCategories, callback)); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const char* beginRecordingPath = "json/begin_recording?"; 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (StartsWithASCII(path, beginRecordingPath, true)) { 204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string data = path.substr(strlen(beginRecordingPath)); 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return BeginRecording(data, callback); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (path == "json/get_buffer_percent_full") { 208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return TracingController::GetInstance()->GetTraceBufferPercentFull( 209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(OnTraceBufferPercentFullResult, callback)); 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (path == "json/end_recording") { 212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return TracingController::GetInstance()->DisableRecording( 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TracingControllerImpl::CreateStringSink( 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(TracingCallbackWrapper, callback))); 215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char* enableMonitoringPath = "json/begin_monitoring?"; 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (path.find(enableMonitoringPath) == 0) { 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string data = path.substr(strlen(enableMonitoringPath)); 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return EnableMonitoring(data, callback); 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (path == "json/end_monitoring") { 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return TracingController::GetInstance()->DisableMonitoring( 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(OnMonitoringDisabled, callback)); 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (path == "json/capture_monitoring") { 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TracingController::GetInstance()->CaptureMonitoringSnapshot( 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TracingControllerImpl::CreateStringSink( 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(TracingCallbackWrapper, callback))); 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (path == "json/get_monitoring_status") { 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetMonitoringStatus(callback); 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Unhandled request to " << path; 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool OnTracingRequest(const std::string& path, 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const WebUIDataSource::GotDataCallback& callback) { 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (StartsWithASCII(path, "json/", true)) { 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!OnBeginJSONRequest(path, callback)) { 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string error("##ERROR##"); 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(base::RefCountedString::TakeString(&error)); 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TracingUI 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 262116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTracingUI::TracingUI(WebUI* web_ui) 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : WebUIController(web_ui), 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_factory_(this) { 265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch web_ui->RegisterMessageCallback( 266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch "doUpload", 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&TracingUI::DoUpload, base::Unretained(this))); 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set up the chrome://tracing/ source. 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserContext* browser_context = 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_ui->GetWebContents()->GetBrowserContext(); 272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) WebUIDataSource* source = WebUIDataSource::Create(kChromeUITracingHost); 274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) source->SetJsonPath("strings.js"); 275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) source->SetDefaultResource(IDR_TRACING_HTML); 276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) source->AddResourcePath("tracing.js", IDR_TRACING_JS); 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) source->SetRequestFilter(base::Bind(OnTracingRequest)); 278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) WebUIDataSource::Add(browser_context, source); 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TracingControllerImpl::GetInstance()->RegisterTracingUI(this); 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TracingUI::~TracingUI() { 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TracingControllerImpl::GetInstance()->UnregisterTracingUI(this); 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TracingUI::OnMonitoringStateChanged(bool is_monitoring) { 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) web_ui()->CallJavascriptFunction( 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "onMonitoringStateChanged", base::FundamentalValue(is_monitoring)); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TracingUI::DoUpload(const base::ListValue* args) { 2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const base::CommandLine& command_line = 2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) *base::CommandLine::ForCurrentProcess(); 294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::string upload_url = kUploadURL; 295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (command_line.HasSwitch(switches::kTraceUploadURL)) { 296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch upload_url = 297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch command_line.GetSwitchValueASCII(switches::kTraceUploadURL); 298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!GURL(upload_url).is_valid()) { 300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch upload_url.clear(); 301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (upload_url.empty()) { 304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch web_ui()->CallJavascriptFunction("onUploadError", 305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringValue("Upload URL empty or invalid")); 306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::string file_contents; 310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!args || args->empty() || !args->GetString(0, &file_contents)) { 311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch web_ui()->CallJavascriptFunction("onUploadError", 312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringValue("Missing data")); 313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TraceUploader::UploadProgressCallback progress_callback = 317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&TracingUI::OnTraceUploadProgress, 318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_factory_.GetWeakPtr()); 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TraceUploader::UploadDoneCallback done_callback = 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&TracingUI::OnTraceUploadComplete, 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_factory_.GetWeakPtr()); 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_WIN) 324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const char product[] = "Chrome"; 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(OS_MACOSX) 326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const char product[] = "Chrome_Mac"; 327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(OS_LINUX) 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const char product[] = "Chrome_Linux"; 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(OS_ANDROID) 330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const char product[] = "Chrome_Android"; 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(OS_CHROMEOS) 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const char product[] = "Chrome_ChromeOS"; 333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#else 334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#error Platform not supported. 335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif 336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // GetProduct() returns a string like "Chrome/aa.bb.cc.dd", split out 338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the part before the "/". 339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::vector<std::string> product_components; 340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::SplitString(content::GetContentClient()->GetProduct(), '/', 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &product_components); 342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(2U, product_components.size()); 343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::string version; 344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (product_components.size() == 2U) { 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch version = product_components[1]; 346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch version = "unknown"; 348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserContext* browser_context = 351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch web_ui()->GetWebContents()->GetBrowserContext(); 352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TraceUploader* uploader = new TraceUploader( 353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch product, version, upload_url, browser_context->GetRequestContext()); 354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind( 356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &TraceUploader::DoUpload, 357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Unretained(uploader), 358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch file_contents, 359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch progress_callback, 360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch done_callback)); 361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(mmandlis): Add support for stopping the upload in progress. 362116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 363116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 364116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TracingUI::OnTraceUploadProgress(int64 current, int64 total) { 365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(current <= total); 366116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int percent = (current / total) * 100; 367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch web_ui()->CallJavascriptFunction( 368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch "onUploadProgress", 369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::FundamentalValue(percent), 370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringValue(base::StringPrintf("%" PRId64, current)), 371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringValue(base::StringPrintf("%" PRId64, total))); 372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 374116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TracingUI::OnTraceUploadComplete(bool success, 375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& report_id, 376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& error_message) { 377116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (success) { 378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch web_ui()->CallJavascriptFunction("onUploadComplete", 379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringValue(report_id)); 380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch web_ui()->CallJavascriptFunction("onUploadError", 382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringValue(error_message)); 383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace content 387