summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzhenw <zhenw@chromium.org>2015-08-27 20:07:16 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-28 03:07:55 +0000
commitde52fb95509666be1062b50a78bea36adfbac183 (patch)
tree626db79aacf3f16bea4ac54e5d5b77572df9faa1
parent9478f58e1bfc86d7732dd864a374a445e88ddceb (diff)
downloadchromium_src-de52fb95509666be1062b50a78bea36adfbac183.zip
chromium_src-de52fb95509666be1062b50a78bea36adfbac183.tar.gz
chromium_src-de52fb95509666be1062b50a78bea36adfbac183.tar.bz2
[Startup Tracing] Add --trace-config-file flag
This CL adds --trace-config-file flag. Please see trace_config_file.h for details. Design doc: https://docs.google.com/document/d/1PgdXUOJF3WtEmYWUyGRbC2Fz2ICCZKO9jPvpLPRSHH8/edit?usp=sharing BUG=317481, 482098 Review URL: https://codereview.chromium.org/1315463002 Cr-Commit-Position: refs/heads/master@{#346062}
-rw-r--r--components/BUILD.gn1
-rw-r--r--components/components_tests.gyp5
-rw-r--r--components/tracing.gyp4
-rw-r--r--components/tracing/BUILD.gn18
-rw-r--r--components/tracing/startup_tracing.cc66
-rw-r--r--components/tracing/startup_tracing.h20
-rw-r--r--components/tracing/trace_config_file.cc140
-rw-r--r--components/tracing/trace_config_file.h94
-rw-r--r--components/tracing/trace_config_file_unittest.cc225
-rw-r--r--components/tracing/tracing_switches.cc4
-rw-r--r--components/tracing/tracing_switches.h1
-rw-r--r--components/tracing_nacl.gyp4
-rw-r--r--content/app/android/library_loader_hooks.cc8
-rw-r--r--content/app/content_main_runner.cc10
-rw-r--r--content/browser/browser_main_loop.cc70
-rw-r--r--content/browser/browser_main_loop.h12
-rw-r--r--content/browser/browser_main_runner.cc20
-rw-r--r--content/browser/gpu/gpu_process_host.cc1
-rw-r--r--content/browser/plugin_process_host.cc1
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc3
-rw-r--r--mandoline/app/DEPS2
-rw-r--r--mandoline/app/desktop/launcher_process.cc11
-rw-r--r--mojo/runner/desktop/launcher_process.cc11
23 files changed, 588 insertions, 143 deletions
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 4964c31..fc26388 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -419,6 +419,7 @@ test("components_unittests") {
"//components/proximity_auth:unit_tests",
"//components/sessions:unit_tests",
"//components/storage_monitor:unit_tests",
+ "//components/tracing:unit_tests",
]
}
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index e989e35..fad29eb 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -618,6 +618,9 @@
'sync_driver/tab_node_pool_unittest.cc',
'sync_driver/ui_data_type_controller_unittest.cc',
],
+ 'tracing_unittest_sources': [
+ 'tracing/trace_config_file_unittest.cc',
+ ],
'translate_unittest_sources': [
'translate/core/browser/language_state_unittest.cc',
'translate/core/browser/translate_browser_metrics_unittest.cc',
@@ -1174,6 +1177,7 @@
'<@(copresence_unittest_sources)',
'<@(feedback_unittest_sources)',
'<@(proximity_auth_unittest_sources)',
+ '<@(tracing_unittest_sources)',
],
'sources!': [
'variations/variations_request_scheduler_mobile_unittest.cc',
@@ -1193,6 +1197,7 @@
'components.gyp:pref_registry_test_support',
'components.gyp:proximity_auth',
'components.gyp:proximity_auth_test_support',
+ 'tracing.gyp:tracing',
],
}],
['chromeos==1', {
diff --git a/components/tracing.gyp b/components/tracing.gyp
index cd7bc4f..8bf23d2 100644
--- a/components/tracing.gyp
+++ b/components/tracing.gyp
@@ -30,8 +30,8 @@
'tracing/child_memory_dump_manager_delegate_impl.h',
'tracing/child_trace_message_filter.cc',
'tracing/child_trace_message_filter.h',
- 'tracing/startup_tracing.cc',
- 'tracing/startup_tracing.h',
+ 'tracing/trace_config_file.cc',
+ 'tracing/trace_config_file.h',
'tracing/tracing_export.h',
'tracing/tracing_messages.cc',
'tracing/tracing_messages.h',
diff --git a/components/tracing/BUILD.gn b/components/tracing/BUILD.gn
index 059f4f1..bd5b271 100644
--- a/components/tracing/BUILD.gn
+++ b/components/tracing/BUILD.gn
@@ -23,8 +23,8 @@ component("tracing") {
component("startup_tracing") {
sources = [
- "startup_tracing.cc",
- "startup_tracing.h",
+ "trace_config_file.cc",
+ "trace_config_file.h",
"tracing_export.h",
"tracing_switches.cc",
"tracing_switches.h",
@@ -36,3 +36,17 @@ component("startup_tracing") {
"//base",
]
}
+
+source_set("unit_tests") {
+ testonly = true
+
+ sources = [
+ "trace_config_file_unittest.cc",
+ ]
+
+ deps = [
+ ":startup_tracing",
+ "//base/test:test_support",
+ "//testing/gtest",
+ ]
+}
diff --git a/components/tracing/startup_tracing.cc b/components/tracing/startup_tracing.cc
deleted file mode 100644
index 321b950..0000000
--- a/components/tracing/startup_tracing.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/tracing/startup_tracing.h"
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/trace_event/trace_event.h"
-
-namespace tracing {
-
-namespace {
-
-// Maximum trace config file size that will be loaded, in bytes.
-const size_t kTraceConfigFileSizeLimit = 64 * 1024;
-
-// Trace config file path:
-// - Android: /data/local/.config/chrome-trace-config.json
-// - POSIX other than Android: $HOME/.config/chrome-trace-config.json
-// - Win: %USERPROFILE%/.config/chrome-trace-config.json
-#if defined(OS_ANDROID)
-const base::FilePath::CharType kAndroidTraceConfigDir[] =
- FILE_PATH_LITERAL("/data/local");
-#endif
-
-const base::FilePath::CharType kChromeConfigDir[] =
- FILE_PATH_LITERAL(".config");
-const base::FilePath::CharType kTraceConfigFileName[] =
- FILE_PATH_LITERAL("chrome-trace-config.json");
-
-base::FilePath GetTraceConfigFilePath() {
-#if defined(OS_ANDROID)
- base::FilePath path(kAndroidTraceConfigDir);
-#elif defined(OS_POSIX) || defined(OS_WIN)
- base::FilePath path;
- PathService::Get(base::DIR_HOME, &path);
-#else
- base::FilePath path;
-#endif
- path = path.Append(kChromeConfigDir);
- path = path.Append(kTraceConfigFileName);
- return path;
-}
-
-} // namespace
-
-void EnableStartupTracingIfConfigFileExists() {
- base::FilePath trace_config_file_path = GetTraceConfigFilePath();
- if (!base::PathExists(trace_config_file_path))
- return;
-
- std::string trace_config_str;
- if (!base::ReadFileToString(trace_config_file_path,
- &trace_config_str,
- kTraceConfigFileSizeLimit)) {
- return;
- }
-
- base::trace_event::TraceConfig trace_config(trace_config_str);
- base::trace_event::TraceLog::GetInstance()->SetEnabled(
- trace_config, base::trace_event::TraceLog::RECORDING_MODE);
-}
-
-} // namespace tracing
diff --git a/components/tracing/startup_tracing.h b/components/tracing/startup_tracing.h
deleted file mode 100644
index 5d1c74d..0000000
--- a/components/tracing/startup_tracing.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_TRACING_STARTUP_TRACING_H_
-#define COMPONENTS_TRACING_STARTUP_TRACING_H_
-
-#include "components/tracing/tracing_export.h"
-
-namespace tracing {
-
-// Enable startup tracing according to the trace config file. If the trace
-// config file does not exist, it will do nothing. This is designed to be used
-// by Telemetry. Telemetry will stop tracing via DevTools later. To avoid
-// conflict, this should not be used when --trace-startup is enabled.
-void TRACING_EXPORT EnableStartupTracingIfConfigFileExists();
-
-} // namespace tracing
-
-#endif // COMPONENTS_TRACING_STARTUP_TRACING_H_
diff --git a/components/tracing/trace_config_file.cc b/components/tracing/trace_config_file.cc
new file mode 100644
index 0000000..e1cbc5c
--- /dev/null
+++ b/components/tracing/trace_config_file.cc
@@ -0,0 +1,140 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/tracing/trace_config_file.h"
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/values.h"
+#include "components/tracing/tracing_switches.h"
+
+namespace tracing {
+
+namespace {
+
+// Maximum trace config file size that will be loaded, in bytes.
+const size_t kTraceConfigFileSizeLimit = 64 * 1024;
+
+// Trace config file path:
+// - Android: /data/local/chrome-trace-config.json
+// - Others: specified by --trace-config-file flag.
+#if defined(OS_ANDROID)
+const base::FilePath::CharType kAndroidTraceConfigFile[] =
+ FILE_PATH_LITERAL("/data/local/chrome-trace-config.json");
+#endif
+
+const base::FilePath::CharType kDefaultResultFile[] =
+ FILE_PATH_LITERAL("chrometrace.log");
+
+// String parameters that can be used to parse the trace config file content.
+const char kTraceConfigParam[] = "trace_config";
+const char kStartupDurationParam[] = "startup_duration";
+const char kResultFileParam[] = "result_file";
+
+} // namespace
+
+TraceConfigFile* TraceConfigFile::GetInstance() {
+ return Singleton<TraceConfigFile,
+ DefaultSingletonTraits<TraceConfigFile>>::get();
+}
+
+TraceConfigFile::TraceConfigFile()
+ : is_enabled_(false),
+ trace_config_(base::trace_event::TraceConfig()),
+ startup_duration_(0),
+ result_file_(kDefaultResultFile) {
+#if defined(OS_ANDROID)
+ base::FilePath trace_config_file(kAndroidTraceConfigFile);
+#else
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ if (!command_line.HasSwitch(switches::kTraceConfigFile) ||
+ command_line.HasSwitch(switches::kTraceStartup) ||
+ command_line.HasSwitch(switches::kTraceShutdown)) {
+ return;
+ }
+ base::FilePath trace_config_file =
+ command_line.GetSwitchValuePath(switches::kTraceConfigFile);
+#endif
+
+ if (trace_config_file.empty()) {
+ // If the trace config file path is not specified, trace Chrome with the
+ // default configuration for 5 sec.
+ startup_duration_ = 5;
+ is_enabled_ = true;
+ return;
+ }
+
+ if (!base::PathExists(trace_config_file))
+ return;
+
+ std::string trace_config_file_content;
+ if (!base::ReadFileToString(trace_config_file,
+ &trace_config_file_content,
+ kTraceConfigFileSizeLimit)) {
+ return;
+ }
+ is_enabled_ = ParseTraceConfigFileContent(trace_config_file_content);
+}
+
+TraceConfigFile::~TraceConfigFile() {
+}
+
+bool TraceConfigFile::ParseTraceConfigFileContent(std::string content) {
+ scoped_ptr<base::Value> value(base::JSONReader::Read(content));
+ if (!value || !value->IsType(base::Value::TYPE_DICTIONARY))
+ return false;
+
+ scoped_ptr<base::DictionaryValue> dict(
+ static_cast<base::DictionaryValue*>(value.release()));
+
+ base::DictionaryValue* trace_config_dict = NULL;
+ if (!dict->GetDictionary(kTraceConfigParam, &trace_config_dict))
+ return false;
+
+ std::string trace_config_str;
+ base::JSONWriter::Write(*trace_config_dict, &trace_config_str);
+ trace_config_ = base::trace_event::TraceConfig(trace_config_str);
+
+ if (!dict->GetInteger(kStartupDurationParam, &startup_duration_))
+ startup_duration_ = 0;
+
+ if (startup_duration_ < 0)
+ startup_duration_ = 0;
+
+ std::string result_file_str;
+ if (dict->GetString(kResultFileParam, &result_file_str))
+ result_file_ = base::FilePath().AppendASCII(result_file_str);
+
+ return true;
+}
+
+bool TraceConfigFile::IsEnabled() const {
+ return is_enabled_;
+}
+
+base::trace_event::TraceConfig TraceConfigFile::GetTraceConfig() const {
+ DCHECK(IsEnabled());
+ return trace_config_;
+}
+
+int TraceConfigFile::GetStartupDuration() const {
+ DCHECK(IsEnabled());
+ return startup_duration_;
+}
+
+#if !defined(OS_ANDROID)
+base::FilePath TraceConfigFile::GetResultFile() const {
+ DCHECK(IsEnabled());
+ return result_file_;
+}
+#endif
+
+} // namespace tracing
diff --git a/components/tracing/trace_config_file.h b/components/tracing/trace_config_file.h
new file mode 100644
index 0000000..273f9f1
--- /dev/null
+++ b/components/tracing/trace_config_file.h
@@ -0,0 +1,94 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_TRACING_TRACE_CONFIG_FILE_H_
+#define COMPONENTS_TRACING_TRACE_CONFIG_FILE_H_
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/trace_event/trace_config.h"
+#include "components/tracing/tracing_export.h"
+
+template <typename Type> struct DefaultSingletonTraits;
+
+namespace tracing {
+
+// TraceConfigFile is a singleton that contains the configurations of tracing.
+// One can create a trace config file and use it to configure startup and/or
+// shutdown tracing.
+//
+// The trace config file should be JSON formated. One example is:
+// {
+// "trace_config": {
+// "record_mode": "record-until-full",
+// "included_categories": ["cc", "skia"]
+// },
+// "startup_duration": 5,
+// "result_file": "chrometrace.log"
+// }
+//
+// trace_config: The configuration of tracing. Please see the details in
+// base/trace_event/trace_config.h.
+//
+// startup_duration: The duration for startup tracing in terms of seconds.
+// Tracing will stop automatically after the duration. If this
+// value is not specified, the duration is 0 and one needs
+// to stop tracing by other ways, e.g., by DevTools, or get
+// the result file after shutting the browser down.
+//
+// result_file: The file that contains the trace log. The default result
+// file path is chrometrace.log. Chrome will dump the trace
+// log to this file
+// 1) after startup_duration if it is specified;
+// 2) or after browser shutdown if startup duration is 0.
+// One can also stop tracing and get the result by other ways,
+// e.g., by DevTools. In that case, the trace log will not be
+// saved to this file.
+// Notice: This is not supported on Android. The result file
+// path will be generated by tracing controller.
+//
+// The trace config file can be specified by the --trace-config-file flag on
+// most platforms except on Android, e.g., --trace-config-file=path/to/file/.
+// This flag should not be used with --trace-startup or --trace-shutdown. If
+// those two flags are used, --trace-config-file flag will be ignored. If the
+// --trace-config-file flag is used without the file path, Chrome will do
+// startup tracing with 5 seconds' startup duration.
+//
+// On Android, Chrome does not read the --trace-config-file flag, because not
+// all Chrome based browsers read customized flag, e.g., Android WebView. Chrome
+// on Android reads from a fixed file location:
+// /data/local/chrome-trace-config.json
+// If this file exists, Chrome will start tracing according to the configuration
+// specified in the file, otherwise, Chrome will not start tracing.
+class TRACING_EXPORT TraceConfigFile {
+ public:
+ static TraceConfigFile* GetInstance();
+
+ bool IsEnabled() const;
+ base::trace_event::TraceConfig GetTraceConfig() const;
+ int GetStartupDuration() const;
+#if !defined(OS_ANDROID)
+ base::FilePath GetResultFile() const;
+#endif
+
+ private:
+ // This allows constructor and destructor to be private and usable only
+ // by the Singleton class.
+ friend struct DefaultSingletonTraits<TraceConfigFile>;
+ TraceConfigFile();
+ ~TraceConfigFile();
+
+ bool ParseTraceConfigFileContent(std::string content);
+
+ bool is_enabled_;
+ base::trace_event::TraceConfig trace_config_;
+ int startup_duration_;
+ base::FilePath result_file_;
+
+ DISALLOW_COPY_AND_ASSIGN(TraceConfigFile);
+};
+
+} // namespace tracing
+
+#endif // COMPONENTS_TRACING_TRACE_CONFIG_FILE_H_
diff --git a/components/tracing/trace_config_file_unittest.cc b/components/tracing/trace_config_file_unittest.cc
new file mode 100644
index 0000000..3cb32af
--- /dev/null
+++ b/components/tracing/trace_config_file_unittest.cc
@@ -0,0 +1,225 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "components/tracing/trace_config_file.h"
+#include "components/tracing/tracing_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace tracing {
+
+namespace {
+
+const char kTraceConfig[] =
+ "{"
+ "\"enable_argument_filter\":true,"
+ "\"enable_sampling\":true,"
+ "\"enable_systrace\":true,"
+ "\"excluded_categories\":[\"excluded\",\"exc_pattern*\"],"
+ "\"included_categories\":[\"included\","
+ "\"inc_pattern*\","
+ "\"disabled-by-default-cc\"],"
+ "\"record_mode\":\"record-continuously\","
+ "\"synthetic_delays\":[\"test.Delay1;16\",\"test.Delay2;32\"]"
+ "}";
+
+std::string GetTraceConfigFileContent(std::string trace_config,
+ std::string startup_duration,
+ std::string result_file) {
+ std::string content = "{";
+ if (!trace_config.empty())
+ content += "\"trace_config\":" + trace_config;
+
+ if (!startup_duration.empty()) {
+ if (content != "{")
+ content += ",";
+ content += "\"startup_duration\":" + startup_duration;
+ }
+
+ if (!result_file.empty()) {
+ if (content != "{")
+ content += ",";
+ content += "\"result_file\":\"" + result_file + "\"";
+ }
+
+ content += "}";
+ return content;
+}
+
+} // namespace
+
+TEST(TraceConfigFileTest, TraceStartupEnabled) {
+ base::ShadowingAtExitManager sem;
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kTraceStartup);
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kTraceConfigFile);
+
+ EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled());
+}
+
+TEST(TraceConfigFileTest, TraceShutdownEnabled) {
+ base::ShadowingAtExitManager sem;
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kTraceShutdown);
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kTraceConfigFile);
+
+ EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled());
+}
+
+TEST(TraceConfigFileTest, TraceConfigFileNotEnabled) {
+ base::ShadowingAtExitManager sem;
+ EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled());
+}
+
+TEST(TraceConfigFileTest, TraceConfigFileEnabledWithoutPath) {
+ base::ShadowingAtExitManager sem;
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kTraceConfigFile);
+
+ ASSERT_TRUE(TraceConfigFile::GetInstance()->IsEnabled());
+ EXPECT_EQ(base::trace_event::TraceConfig().ToString(),
+ TraceConfigFile::GetInstance()->GetTraceConfig().ToString());
+ EXPECT_EQ(5, TraceConfigFile::GetInstance()->GetStartupDuration());
+ EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("chrometrace.log")),
+ TraceConfigFile::GetInstance()->GetResultFile());
+}
+
+TEST(TraceConfigFileTest, TraceConfigFileEnabledWithInvalidPath) {
+ base::ShadowingAtExitManager sem;
+ base::CommandLine::ForCurrentProcess()->AppendSwitchPath(
+ switches::kTraceConfigFile,
+ base::FilePath(FILE_PATH_LITERAL("invalid-trace-config-file-path")));
+
+ EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled());
+}
+
+TEST(TraceConfigFileTest, ValidContent) {
+ base::ShadowingAtExitManager sem;
+ std::string content = GetTraceConfigFileContent(
+ kTraceConfig, "10", "trace_result_file.log");
+
+ base::FilePath trace_config_file;
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ ASSERT_TRUE(
+ base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file));
+ ASSERT_NE(
+ -1,
+ base::WriteFile(trace_config_file, content.c_str(), content.length()));
+ base::CommandLine::ForCurrentProcess()->AppendSwitchPath(
+ switches::kTraceConfigFile, trace_config_file);
+
+ ASSERT_TRUE(TraceConfigFile::GetInstance()->IsEnabled());
+ EXPECT_STREQ(
+ kTraceConfig,
+ TraceConfigFile::GetInstance()->GetTraceConfig().ToString().c_str());
+ EXPECT_EQ(10, TraceConfigFile::GetInstance()->GetStartupDuration());
+ EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("trace_result_file.log")),
+ TraceConfigFile::GetInstance()->GetResultFile());
+}
+
+TEST(TraceConfigFileTest, ValidContentWithOnlyTraceConfig) {
+ base::ShadowingAtExitManager sem;
+ std::string content = GetTraceConfigFileContent(kTraceConfig, "", "");
+
+ base::FilePath trace_config_file;
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ ASSERT_TRUE(
+ base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file));
+ ASSERT_NE(
+ -1,
+ base::WriteFile(trace_config_file, content.c_str(), content.length()));
+ base::CommandLine::ForCurrentProcess()->AppendSwitchPath(
+ switches::kTraceConfigFile, trace_config_file);
+
+ ASSERT_TRUE(TraceConfigFile::GetInstance()->IsEnabled());
+ EXPECT_STREQ(
+ kTraceConfig,
+ TraceConfigFile::GetInstance()->GetTraceConfig().ToString().c_str());
+ EXPECT_EQ(0, TraceConfigFile::GetInstance()->GetStartupDuration());
+ EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("chrometrace.log")),
+ TraceConfigFile::GetInstance()->GetResultFile());
+}
+
+TEST(TraceConfigFileTest, ContentWithNegtiveDuration) {
+ base::ShadowingAtExitManager sem;
+ std::string content = GetTraceConfigFileContent(kTraceConfig, "-1", "");
+
+ base::FilePath trace_config_file;
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ ASSERT_TRUE(
+ base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file));
+ ASSERT_NE(
+ -1,
+ base::WriteFile(trace_config_file, content.c_str(), content.length()));
+ base::CommandLine::ForCurrentProcess()->AppendSwitchPath(
+ switches::kTraceConfigFile, trace_config_file);
+
+ ASSERT_TRUE(TraceConfigFile::GetInstance()->IsEnabled());
+ EXPECT_STREQ(
+ kTraceConfig,
+ TraceConfigFile::GetInstance()->GetTraceConfig().ToString().c_str());
+ EXPECT_EQ(0, TraceConfigFile::GetInstance()->GetStartupDuration());
+ EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("chrometrace.log")),
+ TraceConfigFile::GetInstance()->GetResultFile());
+}
+
+TEST(TraceConfigFileTest, ContentWithoutTraceConfig) {
+ base::ShadowingAtExitManager sem;
+ std::string content = GetTraceConfigFileContent(
+ "", "10", "trace_result_file.log");
+
+ base::FilePath trace_config_file;
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ ASSERT_TRUE(
+ base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file));
+ ASSERT_NE(
+ -1,
+ base::WriteFile(trace_config_file, content.c_str(), content.length()));
+ base::CommandLine::ForCurrentProcess()->AppendSwitchPath(
+ switches::kTraceConfigFile, trace_config_file);
+
+ EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled());
+}
+
+TEST(TraceConfigFileTest, InvalidContent) {
+ base::ShadowingAtExitManager sem;
+ std::string content = "invalid trace config file content";
+
+ base::FilePath trace_config_file;
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ ASSERT_TRUE(
+ base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file));
+ ASSERT_NE(
+ -1,
+ base::WriteFile(trace_config_file, content.c_str(), content.length()));
+ base::CommandLine::ForCurrentProcess()->AppendSwitchPath(
+ switches::kTraceConfigFile, trace_config_file);
+
+ EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled());
+}
+
+TEST(TraceConfigFileTest, EmptyContent) {
+ base::ShadowingAtExitManager sem;
+ base::FilePath trace_config_file;
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ ASSERT_TRUE(
+ base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file));
+ base::CommandLine::ForCurrentProcess()->AppendSwitchPath(
+ switches::kTraceConfigFile, trace_config_file);
+
+ EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled());
+}
+
+} // namespace tracing
diff --git a/components/tracing/tracing_switches.cc b/components/tracing/tracing_switches.cc
index fcec5ee..ba3c1b1 100644
--- a/components/tracing/tracing_switches.cc
+++ b/components/tracing/tracing_switches.cc
@@ -6,6 +6,10 @@
namespace switches {
+// Causes TRACE_EVENT flags to be recorded from startup.
+// This flag will be ignored if --trace-startup or --trace-shutdown is provided.
+const char kTraceConfigFile[] = "trace-config-file";
+
// Causes TRACE_EVENT flags to be recorded beginning with shutdown. Optionally,
// can specify the specific trace categories to include (e.g.
// --trace-shutdown=base,net) otherwise, all events are recorded.
diff --git a/components/tracing/tracing_switches.h b/components/tracing/tracing_switches.h
index dba13da..263a49b 100644
--- a/components/tracing/tracing_switches.h
+++ b/components/tracing/tracing_switches.h
@@ -9,6 +9,7 @@
namespace switches {
+TRACING_EXPORT extern const char kTraceConfigFile[];
TRACING_EXPORT extern const char kTraceShutdown[];
TRACING_EXPORT extern const char kTraceShutdownFile[];
TRACING_EXPORT extern const char kTraceStartup[];
diff --git a/components/tracing_nacl.gyp b/components/tracing_nacl.gyp
index 287b613..1260e85 100644
--- a/components/tracing_nacl.gyp
+++ b/components/tracing_nacl.gyp
@@ -37,8 +37,8 @@
'tracing/child_memory_dump_manager_delegate_impl.h',
'tracing/child_trace_message_filter.cc',
'tracing/child_trace_message_filter.h',
- 'tracing/startup_tracing.cc',
- 'tracing/startup_tracing.h',
+ 'tracing/trace_config_file.cc',
+ 'tracing/trace_config_file.h',
'tracing/tracing_export.h',
'tracing/tracing_messages.cc',
'tracing/tracing_messages.h',
diff --git a/content/app/android/library_loader_hooks.cc b/content/app/android/library_loader_hooks.cc
index 39ef2b0..2a1a3df 100644
--- a/content/app/android/library_loader_hooks.cc
+++ b/content/app/android/library_loader_hooks.cc
@@ -16,7 +16,7 @@
#include "base/strings/string_util.h"
#include "base/trace_event/trace_event.h"
#include "base/tracked_objects.h"
-#include "components/tracing/startup_tracing.h"
+#include "components/tracing/trace_config_file.h"
#include "components/tracing/tracing_switches.h"
#include "content/app/android/app_jni_registrar.h"
#include "content/browser/android/browser_jni_registrar.h"
@@ -94,7 +94,11 @@ bool LibraryLoaded(JNIEnv* env, jclass clazz) {
base::trace_event::TraceLog::GetInstance()->SetEnabled(
trace_config, base::trace_event::TraceLog::RECORDING_MODE);
} else {
- tracing::EnableStartupTracingIfConfigFileExists();
+ if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) {
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(
+ tracing::TraceConfigFile::GetInstance()->GetTraceConfig(),
+ base::trace_event::TraceLog::RECORDING_MODE);
+ }
}
// Android's main browser loop is custom so we set the browser
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index 1a5e950..f35ed29 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -28,7 +28,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
-#include "components/tracing/startup_tracing.h"
+#include "components/tracing/trace_config_file.h"
#include "components/tracing/tracing_switches.h"
#include "content/browser/browser_main.h"
#include "content/common/set_process_title.h"
@@ -629,9 +629,11 @@ class ContentMainRunnerImpl : public ContentMainRunner {
base::trace_event::TraceLog::RECORDING_MODE);
} else if (process_type != switches::kZygoteProcess &&
process_type != switches::kRendererProcess) {
- // There is no need to schedule stopping tracing in this case. Telemetry
- // will stop tracing on demand later.
- tracing::EnableStartupTracingIfConfigFileExists();
+ if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) {
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(
+ tracing::TraceConfigFile::GetInstance()->GetTraceConfig(),
+ base::trace_event::TraceLog::RECORDING_MODE);
+ }
}
#if defined(OS_WIN)
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index b5159df..df19ee8 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -26,6 +26,7 @@
#include "base/timer/hi_res_timer_manager.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
+#include "components/tracing/trace_config_file.h"
#include "components/tracing/tracing_switches.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/device_sensors/device_inertial_sensor_service.h"
@@ -390,9 +391,11 @@ BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters)
result_code_(RESULT_CODE_NORMAL_EXIT),
created_threads_(false),
// ContentMainRunner should have enabled tracing of the browser process
- // when kTraceStartup is in the command line.
- is_tracing_startup_(
- parameters.command_line.HasSwitch(switches::kTraceStartup)) {
+ // when kTraceStartup or kTraceConfigFile is in the command line.
+ is_tracing_startup_for_duration_(
+ parameters.command_line.HasSwitch(switches::kTraceStartup) ||
+ (tracing::TraceConfigFile::GetInstance()->IsEnabled() &&
+ tracing::TraceConfigFile::GetInstance()->GetStartupDuration() > 0)) {
DCHECK(!g_current_browser_main_loop);
g_current_browser_main_loop = this;
}
@@ -578,9 +581,9 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
// Start tracing to a file if needed. Only do this after starting the main
// message loop to avoid calling MessagePumpForUI::ScheduleWork() before
// MessagePumpForUI::Start() as it will crash the browser.
- if (is_tracing_startup_) {
- TRACE_EVENT0("startup", "BrowserMainLoop::InitStartupTracing");
- InitStartupTracing(parsed_command_line_);
+ if (is_tracing_startup_for_duration_) {
+ TRACE_EVENT0("startup", "BrowserMainLoop::InitStartupTracingForDuration");
+ InitStartupTracingForDuration(parsed_command_line_);
}
#endif // !defined(OS_IOS)
@@ -1316,39 +1319,52 @@ void BrowserMainLoop::MainMessageLoopRun() {
base::FilePath BrowserMainLoop::GetStartupTraceFileName(
const base::CommandLine& command_line) const {
- base::FilePath trace_file = command_line.GetSwitchValuePath(
- switches::kTraceStartupFile);
- // trace_file = "none" means that startup events will show up for the next
- // begin/end tracing (via about:tracing or AutomationProxy::BeginTracing/
- // EndTracing, for example).
- if (trace_file == base::FilePath().AppendASCII("none"))
- return trace_file;
-
- if (trace_file.empty()) {
+ base::FilePath trace_file;
+ if (command_line.HasSwitch(switches::kTraceStartup)) {
+ trace_file = command_line.GetSwitchValuePath(
+ switches::kTraceStartupFile);
+ // trace_file = "none" means that startup events will show up for the next
+ // begin/end tracing (via about:tracing or AutomationProxy::BeginTracing/
+ // EndTracing, for example).
+ if (trace_file == base::FilePath().AppendASCII("none"))
+ return trace_file;
+
+ if (trace_file.empty()) {
+#if defined(OS_ANDROID)
+ TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
+#else
+ // Default to saving the startup trace into the current dir.
+ trace_file = base::FilePath().AppendASCII("chrometrace.log");
+#endif
+ }
+ } else {
#if defined(OS_ANDROID)
TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
#else
- // Default to saving the startup trace into the current dir.
- trace_file = base::FilePath().AppendASCII("chrometrace.log");
+ trace_file = tracing::TraceConfigFile::GetInstance()->GetResultFile();
#endif
}
return trace_file;
}
-void BrowserMainLoop::InitStartupTracing(
+void BrowserMainLoop::InitStartupTracingForDuration(
const base::CommandLine& command_line) {
- DCHECK(is_tracing_startup_);
+ DCHECK(is_tracing_startup_for_duration_);
startup_trace_file_ = GetStartupTraceFileName(parsed_command_line_);
- std::string delay_str = command_line.GetSwitchValueASCII(
- switches::kTraceStartupDuration);
int delay_secs = 5;
- if (!delay_str.empty() && !base::StringToInt(delay_str, &delay_secs)) {
- DLOG(WARNING) << "Could not parse --" << switches::kTraceStartupDuration
- << "=" << delay_str << " defaulting to 5 (secs)";
- delay_secs = 5;
+ if (command_line.HasSwitch(switches::kTraceStartup)) {
+ std::string delay_str = command_line.GetSwitchValueASCII(
+ switches::kTraceStartupDuration);
+ if (!delay_str.empty() && !base::StringToInt(delay_str, &delay_secs)) {
+ DLOG(WARNING) << "Could not parse --" << switches::kTraceStartupDuration
+ << "=" << delay_str << " defaulting to 5 (secs)";
+ delay_secs = 5;
+ }
+ } else {
+ delay_secs = tracing::TraceConfigFile::GetInstance()->GetStartupDuration();
}
startup_trace_timer_.Start(FROM_HERE,
@@ -1358,9 +1374,9 @@ void BrowserMainLoop::InitStartupTracing(
}
void BrowserMainLoop::EndStartupTracing() {
- DCHECK(is_tracing_startup_);
+ DCHECK(is_tracing_startup_for_duration_);
- is_tracing_startup_ = false;
+ is_tracing_startup_for_duration_ = false;
TracingController::GetInstance()->DisableRecording(
TracingController::CreateFileSink(
startup_trace_file_,
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index 5f87e69..822589e7 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -116,7 +116,9 @@ class CONTENT_EXPORT BrowserMainLoop {
media::midi::MidiManager* midi_manager() const { return midi_manager_.get(); }
base::Thread* indexed_db_thread() const { return indexed_db_thread_.get(); }
- bool is_tracing_startup() const { return is_tracing_startup_; }
+ bool is_tracing_startup_for_duration() const {
+ return is_tracing_startup_for_duration_;
+ }
const base::FilePath& startup_trace_file() const {
return startup_trace_file_;
@@ -152,7 +154,7 @@ class CONTENT_EXPORT BrowserMainLoop {
base::FilePath GetStartupTraceFileName(
const base::CommandLine& command_line) const;
- void InitStartupTracing(const base::CommandLine& command_line);
+ void InitStartupTracingForDuration(const base::CommandLine& command_line);
void EndStartupTracing();
bool UsingInProcessGpu() const;
@@ -166,7 +168,7 @@ class CONTENT_EXPORT BrowserMainLoop {
// MainMessageLoopStart()
// InitializeMainThread()
// PostMainMessageLoopStart()
- // InitStartupTracing()
+ // InitStartupTracingForDuration()
// CreateStartupTasks()
// PreCreateThreads()
// CreateThreads()
@@ -177,7 +179,7 @@ class CONTENT_EXPORT BrowserMainLoop {
const base::CommandLine& parsed_command_line_;
int result_code_;
bool created_threads_; // True if the non-UI threads were created.
- bool is_tracing_startup_;
+ bool is_tracing_startup_for_duration_;
// Members initialized in |MainMessageLoopStart()| ---------------------------
scoped_ptr<base::MessageLoop> main_message_loop_;
@@ -206,7 +208,7 @@ class CONTENT_EXPORT BrowserMainLoop {
scoped_ptr<MemoryObserver> memory_observer_;
scoped_ptr<base::trace_event::TraceMemoryController> trace_memory_controller_;
- // Members initialized in |InitStartupTracing()| -----------------------------
+ // Members initialized in |InitStartupTracingForDuration()| ------------------
base::FilePath startup_trace_file_;
// This timer initiates trace file saving.
diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc
index d7575f6..5b2f7f5 100644
--- a/content/browser/browser_main_runner.cc
+++ b/content/browser/browser_main_runner.cc
@@ -14,14 +14,20 @@
#include "base/profiler/scoped_tracker.h"
#include "base/trace_event/trace_event.h"
#include "base/tracked_objects.h"
+#include "components/tracing/trace_config_file.h"
#include "components/tracing/tracing_switches.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/browser_shutdown_profile_dumper.h"
#include "content/browser/notification_service_impl.h"
+#include "content/public/browser/tracing_controller.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "ui/base/ime/input_method_initializer.h"
+#if defined(OS_ANDROID)
+#include "content/browser/android/tracing_controller_android.h"
+#endif
+
#if defined(OS_WIN)
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
@@ -229,14 +235,26 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
// If startup tracing has not been finished yet, replace it's dumper
// with special version, which would save trace file on exit (i.e.
// startup tracing becomes a version of shutdown tracing).
+ // There are two cases:
+ // 1. Startup duration is not reached.
+ // 2. Or startup duration is not specified for --trace-config-file flag.
scoped_ptr<BrowserShutdownProfileDumper> startup_profiler;
- if (main_loop_->is_tracing_startup()) {
+ if (main_loop_->is_tracing_startup_for_duration()) {
main_loop_->StopStartupTracingTimer();
if (main_loop_->startup_trace_file() !=
base::FilePath().AppendASCII("none")) {
startup_profiler.reset(
new BrowserShutdownProfileDumper(main_loop_->startup_trace_file()));
}
+ } else if (tracing::TraceConfigFile::GetInstance()->IsEnabled() &&
+ TracingController::GetInstance()->IsRecording()) {
+ base::FilePath result_file;
+#if defined(OS_ANDROID)
+ TracingControllerAndroid::GenerateTracingFilePath(&result_file);
+#else
+ result_file = tracing::TraceConfigFile::GetInstance()->GetResultFile();
+#endif
+ startup_profiler.reset(new BrowserShutdownProfileDumper(result_file));
}
// The shutdown tracing got enabled in AttemptUserExit earlier, but someone
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 4c05b63..30446d2 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -113,6 +113,7 @@ static const char* const kSwitchNames[] = {
switches::kNoSandbox,
switches::kProfilerTiming,
switches::kTestGLLib,
+ switches::kTraceConfigFile,
switches::kTraceStartup,
switches::kTraceToConsole,
switches::kV,
diff --git a/content/browser/plugin_process_host.cc b/content/browser/plugin_process_host.cc
index 61deb77..3d73d26 100644
--- a/content/browser/plugin_process_host.cc
+++ b/content/browser/plugin_process_host.cc
@@ -222,6 +222,7 @@ bool PluginProcessHost::Init(const WebPluginInfo& info) {
switches::kLogPluginMessages,
switches::kNoSandbox,
switches::kPluginStartupDialog,
+ switches::kTraceConfigFile,
switches::kTraceStartup,
switches::kUseGL,
switches::kForceDeviceScaleFactor,
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 48665d5..0a8a297 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1349,6 +1349,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kTestType,
switches::kTouchEvents,
switches::kTouchTextSelectionStrategy,
+ switches::kTraceConfigFile,
switches::kTraceToConsole,
// This flag needs to be propagated to the renderer process for
// --in-process-webgl.
@@ -1418,7 +1419,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
arraysize(kSwitchNames));
if (browser_cmd.HasSwitch(switches::kTraceStartup) &&
- BrowserMainLoop::GetInstance()->is_tracing_startup()) {
+ BrowserMainLoop::GetInstance()->is_tracing_startup_for_duration()) {
// Pass kTraceStartup switch to renderer only if startup tracing has not
// finished.
renderer_cmd->AppendSwitchASCII(
diff --git a/mandoline/app/DEPS b/mandoline/app/DEPS
index 788a657..44f4e66 100644
--- a/mandoline/app/DEPS
+++ b/mandoline/app/DEPS
@@ -1,5 +1,5 @@
include_rules = [
- "+components/tracing/startup_tracing.h",
+ "+components/tracing",
"+mojo",
"+third_party/mojo/src/mojo/edk",
"-third_party/mojo/src/mojo/edk/system",
diff --git a/mandoline/app/desktop/launcher_process.cc b/mandoline/app/desktop/launcher_process.cc
index afa1d15..132d033 100644
--- a/mandoline/app/desktop/launcher_process.cc
+++ b/mandoline/app/desktop/launcher_process.cc
@@ -15,7 +15,7 @@
#include "base/message_loop/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/trace_event/trace_event.h"
-#include "components/tracing/startup_tracing.h"
+#include "components/tracing/trace_config_file.h"
#include "components/tracing/tracing_switches.h"
#include "mandoline/app/core_services_initialization.h"
#include "mandoline/app/desktop/launcher_process.h"
@@ -90,10 +90,11 @@ int LauncherProcessMain(int argc, char** argv) {
base::trace_event::RECORD_UNTIL_FULL);
base::trace_event::TraceLog::GetInstance()->SetEnabled(
trace_config, base::trace_event::TraceLog::RECORDING_MODE);
- } else {
- // |g_tracing| is not touched in this case and Telemetry will stop tracing
- // on demand later.
- tracing::EnableStartupTracingIfConfigFileExists();
+ } else if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) {
+ g_tracing = true;
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(
+ tracing::TraceConfigFile::GetInstance()->GetTraceConfig(),
+ base::trace_event::TraceLog::RECORDING_MODE);
}
// We want the runner::Context to outlive the MessageLoop so that pipes are
diff --git a/mojo/runner/desktop/launcher_process.cc b/mojo/runner/desktop/launcher_process.cc
index 946f61f..c2ed3c3 100644
--- a/mojo/runner/desktop/launcher_process.cc
+++ b/mojo/runner/desktop/launcher_process.cc
@@ -15,7 +15,7 @@
#include "base/message_loop/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/trace_event/trace_event.h"
-#include "components/tracing/startup_tracing.h"
+#include "components/tracing/trace_config_file.h"
#include "components/tracing/tracing_switches.h"
#include "mojo/runner/context.h"
#include "mojo/runner/switches.h"
@@ -89,10 +89,11 @@ int LauncherProcessMain(int argc, char** argv) {
base::trace_event::RECORD_UNTIL_FULL);
base::trace_event::TraceLog::GetInstance()->SetEnabled(
trace_config, base::trace_event::TraceLog::RECORDING_MODE);
- } else {
- // |g_tracing| is not touched in this case and Telemetry will stop tracing
- // on demand later.
- tracing::EnableStartupTracingIfConfigFileExists();
+ } else if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) {
+ g_tracing = true;
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(
+ tracing::TraceConfigFile::GetInstance()->GetTraceConfig(),
+ base::trace_event::TraceLog::RECORDING_MODE);
}
// We want the shell::Context to outlive the MessageLoop so that pipes are