blob: 71ee2f3c48b29dc4ed16b63534cbb4c5691fa289 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/test/base/in_process_browser_test.h"
#include <signal.h>
#include "base/command_line.h"
#include "chrome/browser/first_run/first_run_dialog.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
namespace first_run {
class FirstRunInternalPosixTest : public InProcessBrowserTest {
protected:
FirstRunInternalPosixTest() = default;
// InProcessBrowserTest:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kForceFirstRun);
command_line->AppendSwitch(switches::kForceFirstRunDialog);
}
void SetUpInProcessBrowserTestFixture() override {
InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
// The modal dialog will spawn and spin a nested RunLoop when
// content::BrowserTestBase::SetUp() invokes content::ContentMain().
// BrowserTestBase sets GetContentMainParams()->ui_task before this, but the
// ui_task isn't actually Run() until after the dialog is spawned in
// ChromeBrowserMainParts::PreMainMessageLoopRunImpl(). Instead, try to
// inspect state by posting a task to run in that nested RunLoop.
// There's no MessageLoop to enqueue a task on yet, there's also no
// content::NotificationService, or anything else sensible that would allow
// us to hook in a task. So use a testing-only Closure.
GetBeforeShowFirstRunDialogHookForTesting() = base::BindOnce(
&FirstRunInternalPosixTest::SetupNestedTask, base::Unretained(this));
EXPECT_FALSE(inspected_state_);
}
void TearDownInProcessBrowserTestFixture() override {
EXPECT_TRUE(inspected_state_);
// The test closure should have run. But clear the global in case it hasn't.
EXPECT_FALSE(GetBeforeShowFirstRunDialogHookForTesting());
GetBeforeShowFirstRunDialogHookForTesting().Reset();
InProcessBrowserTest::TearDownInProcessBrowserTestFixture();
}
private:
// A task run immediately before first_run::DoPostImportPlatformSpecificTasks
// shows the first-run dialog.
void SetupNestedTask() {
EXPECT_TRUE(base::SequencedTaskRunnerHandle::Get());
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&FirstRunInternalPosixTest::InspectState,
base::Unretained(this)));
}
// A task queued up to run once the first-run dialog starts pumping messages
// in its modal loop.
void InspectState() {
// Send a signal to myself. This should post a task for the next run loop
// iteration to set browser_shutdown::IsTryingToQuit(), and interrupt the
// RunLoop.
raise(SIGTERM);
inspected_state_ = true;
}
bool inspected_state_ = false;
DISALLOW_COPY_AND_ASSIGN(FirstRunInternalPosixTest);
};
// Test the first run flow for showing the modal dialog that surfaces the first
// run dialog. Ensure browser startup safely handles a signal while the modal
// RunLoop is running.
IN_PROC_BROWSER_TEST_F(FirstRunInternalPosixTest, HandleSigterm) {
// Never reached. PreMainMessageLoopRunImpl() should return before this task
// is run.
ADD_FAILURE() << "Should never be called";
}
} // namespace first_run