blob: 1b146c976cec20655ec6cb5114cbd710d9802119 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/tracing/background_tracing_field_trial.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/variations/variations_params_manager.h"
#include "content/public/browser/background_tracing_config.h"
#include "content/public/browser/background_tracing_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_utils.h"
namespace {
class ChromeTracingDelegateBrowserTest : public InProcessBrowserTest {
public:
ChromeTracingDelegateBrowserTest()
: receive_count_(0),
started_finalizations_count_(0),
last_on_started_finalizing_success_(false) {}
#if !defined(OS_CHROMEOS)
void SetUpOnMainThread() override {
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
local_state->SetBoolean(metrics::prefs::kMetricsReportingEnabled, true);
}
#endif
bool StartPreemptiveScenario(
const base::Closure& on_upload_callback,
content::BackgroundTracingManager::DataFiltering data_filtering) {
on_upload_callback_ = on_upload_callback;
base::DictionaryValue dict;
dict.SetString("mode", "PREEMPTIVE_TRACING_MODE");
dict.SetString("category", "BENCHMARK");
std::unique_ptr<base::ListValue> rules_list(new base::ListValue());
{
std::unique_ptr<base::DictionaryValue> rules_dict(
new base::DictionaryValue());
rules_dict->SetString("rule", "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED");
rules_dict->SetString("trigger_name", "test");
rules_list->Append(std::move(rules_dict));
}
dict.Set("configs", std::move(rules_list));
std::unique_ptr<content::BackgroundTracingConfig> config(
content::BackgroundTracingConfig::FromDict(&dict));
DCHECK(config);
content::BackgroundTracingManager::ReceiveCallback receive_callback =
base::BindRepeating(&ChromeTracingDelegateBrowserTest::OnUpload,
base::Unretained(this));
return content::BackgroundTracingManager::GetInstance()->SetActiveScenario(
std::move(config), std::move(receive_callback), data_filtering);
}
void TriggerPreemptiveScenario(
const base::Closure& on_started_finalization_callback) {
on_started_finalization_callback_ = on_started_finalization_callback;
trigger_handle_ =
content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
"test");
content::BackgroundTracingManager::StartedFinalizingCallback
started_finalizing_callback =
base::Bind(&ChromeTracingDelegateBrowserTest::OnStartedFinalizing,
base::Unretained(this));
content::BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
trigger_handle_, started_finalizing_callback);
}
int get_receive_count() const { return receive_count_; }
bool get_started_finalizations() const {
return started_finalizations_count_;
}
bool get_last_started_finalization_success() const {
return last_on_started_finalizing_success_;
}
private:
void OnUpload(const scoped_refptr<base::RefCountedString>& file_contents,
std::unique_ptr<const base::DictionaryValue> metadata,
content::BackgroundTracingManager::FinishedProcessingCallback
done_callback) {
receive_count_ += 1;
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(done_callback), true));
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
on_upload_callback_);
}
void OnStartedFinalizing(bool success) {
started_finalizations_count_++;
last_on_started_finalizing_success_ = success;
if (!on_started_finalization_callback_.is_null()) {
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
on_started_finalization_callback_);
}
}
base::Closure on_upload_callback_;
base::Closure on_started_finalization_callback_;
int receive_count_;
int started_finalizations_count_;
content::BackgroundTracingManager::TriggerHandle trigger_handle_;
bool last_on_started_finalizing_success_;
};
IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest,
BackgroundTracingTimeThrottled) {
base::RunLoop wait_for_upload;
EXPECT_TRUE(StartPreemptiveScenario(
wait_for_upload.QuitClosure(),
content::BackgroundTracingManager::NO_DATA_FILTERING));
TriggerPreemptiveScenario(base::Closure());
wait_for_upload.Run();
EXPECT_TRUE(get_receive_count() == 1);
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
const base::Time last_upload_time = base::Time::FromInternalValue(
local_state->GetInt64(prefs::kBackgroundTracingLastUpload));
EXPECT_FALSE(last_upload_time.is_null());
// We should not be able to start a new reactive scenario immediately after
// a previous one gets uploaded.
EXPECT_FALSE(StartPreemptiveScenario(
base::Closure(), content::BackgroundTracingManager::NO_DATA_FILTERING));
}
// Flaky on Linux and Windows. See https://crbug.com/723933.
#if defined(OS_LINUX) || defined(OS_WIN)
#define MAYBE_BackgroundTracingThrottleTimeElapsed \
DISABLED_BackgroundTracingThrottleTimeElapsed
#else
#define MAYBE_BackgroundTracingThrottleTimeElapsed \
BackgroundTracingThrottleTimeElapsed
#endif
IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest,
MAYBE_BackgroundTracingThrottleTimeElapsed) {
base::RunLoop wait_for_upload;
EXPECT_TRUE(StartPreemptiveScenario(
wait_for_upload.QuitClosure(),
content::BackgroundTracingManager::NO_DATA_FILTERING));
TriggerPreemptiveScenario(base::Closure());
wait_for_upload.Run();
EXPECT_TRUE(get_receive_count() == 1);
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
const base::Time last_upload_time = base::Time::FromInternalValue(
local_state->GetInt64(prefs::kBackgroundTracingLastUpload));
EXPECT_FALSE(last_upload_time.is_null());
// We move the last upload time to eight days in the past,
// and at that point should be able to start a scenario again.
base::Time new_upload_time = last_upload_time - base::TimeDelta::FromDays(8);
local_state->SetInt64(prefs::kBackgroundTracingLastUpload,
new_upload_time.ToInternalValue());
EXPECT_TRUE(StartPreemptiveScenario(
base::Closure(), content::BackgroundTracingManager::NO_DATA_FILTERING));
}
#if defined(OS_MACOSX) && defined(ADDRESS_SANITIZER)
// Flaky on ASAN on Mac. See https://crbug.com/674497.
#define MAYBE_ExistingIncognitoSessionBlockingTraceStart \
DISABLED_ExistingIncognitoSessionBlockingTraceStart
#else
#define MAYBE_ExistingIncognitoSessionBlockingTraceStart \
ExistingIncognitoSessionBlockingTraceStart
#endif
// If we need a PII-stripped trace, any existing OTR session should block the
// trace.
IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest,
MAYBE_ExistingIncognitoSessionBlockingTraceStart) {
EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_NEW_INCOGNITO_WINDOW));
EXPECT_TRUE(BrowserList::IsIncognitoSessionActive());
EXPECT_FALSE(StartPreemptiveScenario(
base::Closure(), content::BackgroundTracingManager::ANONYMIZE_DATA));
}
#if defined(OS_MACOSX) && defined(ADDRESS_SANITIZER)
// Flaky on ASAN on Mac. See https://crbug.com/674497.
#define MAYBE_NewIncognitoSessionBlockingTraceFinalization \
DISABLED_NewIncognitoSessionBlockingTraceFinalization
#else
#define MAYBE_NewIncognitoSessionBlockingTraceFinalization \
NewIncognitoSessionBlockingTraceFinalization
#endif
// If we need a PII-stripped trace, any new OTR session during tracing should
// block the finalization of the trace.
IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest,
MAYBE_NewIncognitoSessionBlockingTraceFinalization) {
EXPECT_TRUE(StartPreemptiveScenario(
base::Closure(), content::BackgroundTracingManager::ANONYMIZE_DATA));
EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_NEW_INCOGNITO_WINDOW));
EXPECT_TRUE(BrowserList::IsIncognitoSessionActive());
base::RunLoop wait_for_finalization_start;
TriggerPreemptiveScenario(wait_for_finalization_start.QuitClosure());
wait_for_finalization_start.Run();
EXPECT_TRUE(get_started_finalizations() == 1);
EXPECT_FALSE(get_last_started_finalization_success());
}
class ChromeTracingDelegateBrowserTestOnStartup
: public ChromeTracingDelegateBrowserTest {
protected:
ChromeTracingDelegateBrowserTestOnStartup() {}
static void FieldTrialConfigTextFilter(std::string* config_text) {
ASSERT_TRUE(config_text);
// We need to replace the config JSON with the full one here, as we can't
// pass JSON through the fieldtrial switch parsing.
if (*config_text == "default_config_for_testing") {
*config_text =
"{\"mode\":\"PREEMPTIVE_TRACING_MODE\", \"category\": "
"\"BENCHMARK\",\"configs\": [{\"rule\": "
"\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\",\"trigger_name\":"
"\"test\"}]}";
}
}
void SetUpCommandLine(base::CommandLine* command_line) override {
variations::testing::VariationParamsManager::AppendVariationParams(
"BackgroundTracing", "TestGroup",
{{"config", "default_config_for_testing"}}, command_line);
tracing::SetConfigTextFilterForTesting(&FieldTrialConfigTextFilter);
}
};
IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestOnStartup,
PRE_ScenarioSetFromFieldtrial) {
// This test exists just to make sure the browser is created at least once and
// so a default profile is created. Then, the next time the browser is
// created, kMetricsReportingEnabled is explicitly read from the profile and
// the startup scenario can be activated.
}
IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestOnStartup,
ScenarioSetFromFieldtrial) {
// We should reach this point without crashing.
EXPECT_TRUE(
content::BackgroundTracingManager::GetInstance()->HasActiveScenario());
}
IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestOnStartup,
PRE_PRE_StartupTracingThrottle) {
// This test exists just to make sure the browser is created at least once and
// so a default profile is created. Then, the next time the browser is
// created, kMetricsReportingEnabled is explicitly read from the profile and
// the startup scenario can be activated.
}
IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestOnStartup,
PRE_StartupTracingThrottle) {
EXPECT_TRUE(
content::BackgroundTracingManager::GetInstance()->HasActiveScenario());
// Simulate a trace upload.
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
local_state->SetInt64(prefs::kBackgroundTracingLastUpload,
base::Time::Now().ToInternalValue());
}
// https://crbug.com/832981
IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestOnStartup,
DISABLED_StartupTracingThrottle) {
// The startup scenario should *not* be started, since not enough
// time has elapsed since the last upload (set in the PRE_ above).
EXPECT_FALSE(
content::BackgroundTracingManager::GetInstance()->HasActiveScenario());
}
} // namespace