reland: Moves loading of local_state and field trials to early initialization
Original is here: https://chromium-review.googlesource.com/c/chromium/src/+/882558
This differs from the patch that landed in two ways:
1. I completely misunderstood RunsTasksInCurrentSequence(). It may be
called on any thread and basically comes down to checking if the
current thread matches the thread the TaskRunner runs on. Changed
implementation of DeferredSequencedTaskRunner and
DeferringTaskRunner appropriately (added test for this).
2. Master prefs need ResourceBundle loaded with the data pack, so,
shuffled around loading of that. This is covered by browser_tests
that sadly only run on official builder.
There are two motivations for this change:
1. In order to run a field trial for state setup in creating toolkit.
2. To have local state ready at the time ash is created.
In order to have field trial ready I need to load local state and
everything it touches. This ended up including ResourceBundle (not
really the ResourceBundle, but the ResourceBundle code is used to
determine the locale, and the locale is needed by code related to
metrics, specifically ChromeMetricsServiceClient::GetApplicationLocale).
As much of this code was previously created at a time when task runners
were available I had to create a deferring task runner that queues up
tasks and then flushes them when the real task runner is available.
I've tried to only move what is necessary and leave as mush
initialization as possible in the place before this change.
You'll notice this creates g_browser_process early on. I explored not
doing this, but it turns out very painful as instead some code then
has to cache state that is later available in g_browser_process. The
camel that broke the straws back was the application locale. See
https://chromium-review.googlesource.com/c/chromium/src/+/853300 for
the early approach.
BUG=800358
[email protected],[email protected],[email protected]
Change-Id: I3343e8959321900daec0de16f6a86715d3760f29
Reviewed-on: https://chromium-review.googlesource.com/898070
Commit-Queue: Scott Violet <[email protected]>
Reviewed-by: Lei Zhang <[email protected]>
Cr-Commit-Position: refs/heads/master@{#533989}
diff --git a/ash/shell/content/client/shell_browser_main_parts.cc b/ash/shell/content/client/shell_browser_main_parts.cc
index 82cc2a3..eaa1199 100644
--- a/ash/shell/content/client/shell_browser_main_parts.cc
+++ b/ash/shell/content/client/shell_browser_main_parts.cc
@@ -57,8 +57,7 @@
void ShellBrowserMainParts::PreMainMessageLoopStart() {}
void ShellBrowserMainParts::PostMainMessageLoopStart() {
- chromeos::DBusThreadManager::Initialize(
- chromeos::DBusThreadManager::PROCESS_ASH);
+ chromeos::DBusThreadManager::Initialize(chromeos::DBusThreadManager::kShared);
}
void ShellBrowserMainParts::ToolkitInitialized() {
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index 9679bb5..59899d1 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -138,7 +138,7 @@
if (!chromeos::DBusThreadManager::IsInitialized()) {
chromeos::DBusThreadManager::Initialize(
- chromeos::DBusThreadManager::PROCESS_ASH);
+ chromeos::DBusThreadManager::kShared);
dbus_thread_manager_initialized_ = true;
}
diff --git a/ash/window_manager_service.cc b/ash/window_manager_service.cc
index 97045ac..bf264e1 100644
--- a/ash/window_manager_service.cc
+++ b/ash/window_manager_service.cc
@@ -88,7 +88,7 @@
// before WindowManager::Init(). Tests might initialize their own instance.
if (!chromeos::DBusThreadManager::IsInitialized()) {
chromeos::DBusThreadManager::Initialize(
- chromeos::DBusThreadManager::PROCESS_ASH);
+ chromeos::DBusThreadManager::kShared);
dbus_thread_manager_initialized_ = true;
}
diff --git a/base/deferred_sequenced_task_runner.cc b/base/deferred_sequenced_task_runner.cc
index 9830402..f88170c 100644
--- a/base/deferred_sequenced_task_runner.cc
+++ b/base/deferred_sequenced_task_runner.cc
@@ -26,9 +26,13 @@
DeferredSequencedTaskRunner::DeferredSequencedTaskRunner(
scoped_refptr<SequencedTaskRunner> target_task_runner)
- : started_(false), target_task_runner_(std::move(target_task_runner)) {}
+ : DeferredSequencedTaskRunner() {
+ DCHECK(target_task_runner);
+ target_task_runner_ = std::move(target_task_runner);
+}
-DeferredSequencedTaskRunner::~DeferredSequencedTaskRunner() = default;
+DeferredSequencedTaskRunner::DeferredSequencedTaskRunner()
+ : created_thread_id_(PlatformThread::CurrentId()) {}
bool DeferredSequencedTaskRunner::PostDelayedTask(const Location& from_here,
OnceClosure task,
@@ -46,7 +50,11 @@
}
bool DeferredSequencedTaskRunner::RunsTasksInCurrentSequence() const {
- return target_task_runner_->RunsTasksInCurrentSequence();
+ AutoLock lock(lock_);
+ if (target_task_runner_)
+ return target_task_runner_->RunsTasksInCurrentSequence();
+
+ return created_thread_id_ == PlatformThread::CurrentId();
}
bool DeferredSequencedTaskRunner::PostNonNestableDelayedTask(
@@ -64,10 +72,28 @@
return true;
}
+void DeferredSequencedTaskRunner::Start() {
+ AutoLock lock(lock_);
+ StartImpl();
+}
+
+void DeferredSequencedTaskRunner::StartWithTaskRunner(
+ scoped_refptr<SequencedTaskRunner> target_task_runner) {
+ AutoLock lock(lock_);
+ DCHECK(!target_task_runner_);
+ DCHECK(target_task_runner);
+ target_task_runner_ = std::move(target_task_runner);
+ StartImpl();
+}
+
+DeferredSequencedTaskRunner::~DeferredSequencedTaskRunner() = default;
+
void DeferredSequencedTaskRunner::QueueDeferredTask(const Location& from_here,
OnceClosure task,
TimeDelta delay,
bool is_non_nestable) {
+ lock_.AssertAcquired();
+
// Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167
// for details.
CHECK(task);
@@ -80,10 +106,11 @@
deferred_tasks_queue_.push_back(std::move(deferred_task));
}
-void DeferredSequencedTaskRunner::Start() {
- AutoLock lock(lock_);
+void DeferredSequencedTaskRunner::StartImpl() {
+ lock_.AssertAcquired(); // Callers should have grabbed the lock.
DCHECK(!started_);
started_ = true;
+ DCHECK(target_task_runner_);
for (std::vector<DeferredTask>::iterator i = deferred_tasks_queue_.begin();
i != deferred_tasks_queue_.end();
++i) {
diff --git a/base/deferred_sequenced_task_runner.h b/base/deferred_sequenced_task_runner.h
index a30487d..2805f47 100644
--- a/base/deferred_sequenced_task_runner.h
+++ b/base/deferred_sequenced_task_runner.h
@@ -14,17 +14,26 @@
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/threading/platform_thread.h"
#include "base/time/time.h"
namespace base {
// A DeferredSequencedTaskRunner is a subclass of SequencedTaskRunner that
// queues up all requests until the first call to Start() is issued.
+// DeferredSequencedTaskRunner may be created in two ways:
+// . with an explicit SequencedTaskRunner that the events are flushed to
+// . without a SequencedTaskRunner. In this configuration the
+// SequencedTaskRunner is supplied in StartWithTaskRunner().
class BASE_EXPORT DeferredSequencedTaskRunner : public SequencedTaskRunner {
public:
explicit DeferredSequencedTaskRunner(
scoped_refptr<SequencedTaskRunner> target_runner);
+ // Use this constructor when you don't have the target SequencedTaskRunner.
+ // When using this call StartWithTaskRunner().
+ DeferredSequencedTaskRunner();
+
// TaskRunner implementation
bool PostDelayedTask(const Location& from_here,
OnceClosure task,
@@ -42,6 +51,10 @@
// Fails when called a second time.
void Start();
+ // Same as Start(), but must be used with the no-arg constructor.
+ void StartWithTaskRunner(
+ scoped_refptr<SequencedTaskRunner> target_task_runner);
+
private:
struct DeferredTask {
DeferredTask();
@@ -58,6 +71,9 @@
~DeferredSequencedTaskRunner() override;
+ // Both variants of Start() call into this.
+ void StartImpl();
+
// Creates a |Task| object and adds it to |deferred_tasks_queue_|.
void QueueDeferredTask(const Location& from_here,
OnceClosure task,
@@ -67,8 +83,10 @@
// // Protects |started_| and |deferred_tasks_queue_|.
mutable Lock lock_;
- bool started_;
- const scoped_refptr<SequencedTaskRunner> target_task_runner_;
+ const PlatformThreadId created_thread_id_;
+
+ bool started_ = false;
+ scoped_refptr<SequencedTaskRunner> target_task_runner_;
std::vector<DeferredTask> deferred_tasks_queue_;
DISALLOW_COPY_AND_ASSIGN(DeferredSequencedTaskRunner);
diff --git a/base/deferred_sequenced_task_runner_unittest.cc b/base/deferred_sequenced_task_runner_unittest.cc
index a96befa..5cb220f 100644
--- a/base/deferred_sequenced_task_runner_unittest.cc
+++ b/base/deferred_sequenced_task_runner_unittest.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/callback_forward.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
@@ -15,12 +16,12 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace base {
namespace {
class DeferredSequencedTaskRunnerTest : public testing::Test {
public:
- class ExecuteTaskOnDestructor :
- public base::RefCounted<ExecuteTaskOnDestructor> {
+ class ExecuteTaskOnDestructor : public RefCounted<ExecuteTaskOnDestructor> {
public:
ExecuteTaskOnDestructor(
DeferredSequencedTaskRunnerTest* executor,
@@ -29,23 +30,21 @@
task_id_(task_id) {
}
private:
- friend class base::RefCounted<ExecuteTaskOnDestructor>;
- virtual ~ExecuteTaskOnDestructor() {
- executor_->ExecuteTask(task_id_);
- }
- DeferredSequencedTaskRunnerTest* executor_;
- int task_id_;
+ friend class RefCounted<ExecuteTaskOnDestructor>;
+ virtual ~ExecuteTaskOnDestructor() { executor_->ExecuteTask(task_id_); }
+ DeferredSequencedTaskRunnerTest* executor_;
+ int task_id_;
};
void ExecuteTask(int task_id) {
- base::AutoLock lock(lock_);
+ AutoLock lock(lock_);
executed_task_ids_.push_back(task_id);
}
void PostExecuteTask(int task_id) {
- runner_->PostTask(
- FROM_HERE, base::BindOnce(&DeferredSequencedTaskRunnerTest::ExecuteTask,
- base::Unretained(this), task_id));
+ runner_->PostTask(FROM_HERE,
+ BindOnce(&DeferredSequencedTaskRunnerTest::ExecuteTask,
+ Unretained(this), task_id));
}
void StartRunner() {
@@ -58,24 +57,24 @@
protected:
DeferredSequencedTaskRunnerTest()
: loop_(),
- runner_(new base::DeferredSequencedTaskRunner(loop_.task_runner())) {}
+ runner_(new DeferredSequencedTaskRunner(loop_.task_runner())) {}
- base::MessageLoop loop_;
- scoped_refptr<base::DeferredSequencedTaskRunner> runner_;
- mutable base::Lock lock_;
+ MessageLoop loop_;
+ scoped_refptr<DeferredSequencedTaskRunner> runner_;
+ mutable Lock lock_;
std::vector<int> executed_task_ids_;
};
TEST_F(DeferredSequencedTaskRunnerTest, Stopped) {
PostExecuteTask(1);
- base::RunLoop().RunUntilIdle();
+ RunLoop().RunUntilIdle();
EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
}
TEST_F(DeferredSequencedTaskRunnerTest, Start) {
StartRunner();
PostExecuteTask(1);
- base::RunLoop().RunUntilIdle();
+ RunLoop().RunUntilIdle();
EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
}
@@ -84,71 +83,68 @@
for (int i = 1; i < 5; ++i)
PostExecuteTask(i);
- base::RunLoop().RunUntilIdle();
+ RunLoop().RunUntilIdle();
EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4));
}
TEST_F(DeferredSequencedTaskRunnerTest, DeferredStart) {
PostExecuteTask(1);
- base::RunLoop().RunUntilIdle();
+ RunLoop().RunUntilIdle();
EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
StartRunner();
- base::RunLoop().RunUntilIdle();
+ RunLoop().RunUntilIdle();
EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
PostExecuteTask(2);
- base::RunLoop().RunUntilIdle();
+ RunLoop().RunUntilIdle();
EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2));
}
TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleElements) {
for (int i = 1; i < 5; ++i)
PostExecuteTask(i);
- base::RunLoop().RunUntilIdle();
+ RunLoop().RunUntilIdle();
EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
StartRunner();
for (int i = 5; i < 9; ++i)
PostExecuteTask(i);
- base::RunLoop().RunUntilIdle();
+ RunLoop().RunUntilIdle();
EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4, 5, 6, 7, 8));
}
TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleThreads) {
{
- base::Thread thread1("DeferredSequencedTaskRunnerTestThread1");
- base::Thread thread2("DeferredSequencedTaskRunnerTestThread2");
+ Thread thread1("DeferredSequencedTaskRunnerTestThread1");
+ Thread thread2("DeferredSequencedTaskRunnerTestThread2");
thread1.Start();
thread2.Start();
for (int i = 0; i < 5; ++i) {
thread1.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
- base::Unretained(this), 2 * i));
+ FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
+ Unretained(this), 2 * i));
thread2.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
- base::Unretained(this), 2 * i + 1));
+ FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
+ Unretained(this), 2 * i + 1));
if (i == 2) {
thread1.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&DeferredSequencedTaskRunnerTest::StartRunner,
- base::Unretained(this)));
+ FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::StartRunner,
+ Unretained(this)));
}
}
}
- base::RunLoop().RunUntilIdle();
+ RunLoop().RunUntilIdle();
EXPECT_THAT(executed_task_ids_,
testing::WhenSorted(testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)));
}
TEST_F(DeferredSequencedTaskRunnerTest, ObjectDestructionOrder) {
{
- base::Thread thread("DeferredSequencedTaskRunnerTestThread");
+ Thread thread("DeferredSequencedTaskRunnerTestThread");
thread.Start();
- runner_ = new base::DeferredSequencedTaskRunner(thread.task_runner());
+ runner_ = new DeferredSequencedTaskRunner(thread.task_runner());
for (int i = 0; i < 5; ++i) {
{
// Use a block to ensure that no reference to |short_lived_object|
@@ -157,9 +153,8 @@
new ExecuteTaskOnDestructor(this, 2 * i);
runner_->PostTask(
FROM_HERE,
- base::BindOnce(&DeferredSequencedTaskRunnerTest::DoNothing,
- base::Unretained(this),
- base::RetainedRef(short_lived_object)));
+ BindOnce(&DeferredSequencedTaskRunnerTest::DoNothing,
+ Unretained(this), RetainedRef(short_lived_object)));
}
// |short_lived_object| with id |2 * i| should be destroyed before the
// task |2 * i + 1| is executed.
@@ -174,4 +169,46 @@
testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
}
+void GetRunsTasksInCurrentSequence(bool* result,
+ scoped_refptr<SequencedTaskRunner> runner,
+ OnceClosure quit) {
+ *result = runner->RunsTasksInCurrentSequence();
+ std::move(quit).Run();
+}
+
+TEST_F(DeferredSequencedTaskRunnerTest, RunsTasksInCurrentSequence) {
+ scoped_refptr<DeferredSequencedTaskRunner> runner =
+ MakeRefCounted<DeferredSequencedTaskRunner>();
+ EXPECT_TRUE(runner->RunsTasksInCurrentSequence());
+
+ Thread thread1("DeferredSequencedTaskRunnerTestThread1");
+ thread1.Start();
+ bool runs_task_in_current_thread = true;
+ base::RunLoop run_loop;
+ thread1.task_runner()->PostTask(
+ FROM_HERE,
+ BindOnce(&GetRunsTasksInCurrentSequence, &runs_task_in_current_thread,
+ runner, run_loop.QuitClosure()));
+ run_loop.Run();
+ EXPECT_FALSE(runs_task_in_current_thread);
+}
+
+TEST_F(DeferredSequencedTaskRunnerTest, StartWithTaskRunner) {
+ scoped_refptr<DeferredSequencedTaskRunner> runner =
+ MakeRefCounted<DeferredSequencedTaskRunner>();
+ bool run_called = false;
+ base::RunLoop run_loop;
+ runner->PostTask(FROM_HERE,
+ BindOnce(
+ [](bool* run_called, base::Closure quit_closure) {
+ *run_called = true;
+ std::move(quit_closure).Run();
+ },
+ &run_called, run_loop.QuitClosure()));
+ runner->StartWithTaskRunner(loop_.task_runner());
+ run_loop.Run();
+ EXPECT_TRUE(run_called);
+}
+
} // namespace
+} // namespace base
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index b47e61a..fd81da3 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -212,13 +212,27 @@
BrowserProcessImpl::BrowserProcessImpl(
base::SequencedTaskRunner* local_state_task_runner)
- : download_status_updater_(std::make_unique<DownloadStatusUpdater>()),
- local_state_task_runner_(local_state_task_runner),
+ : local_state_task_runner_(local_state_task_runner),
pref_service_factory_(
base::MakeUnique<prefs::InProcessPrefServiceFactory>()) {
g_browser_process = this;
- rappor::SetDefaultServiceAccessor(&GetBrowserRapporService);
platform_part_ = base::MakeUnique<BrowserProcessPlatformPart>();
+ // Most work should be done in Init().
+}
+
+void BrowserProcessImpl::Init() {
+#if defined(OS_CHROMEOS)
+ // Forces creation of |metrics_services_manager_client_| if neccessary
+ // (typically this call is a no-op as MetricsServicesManager has already been
+ // created).
+ GetMetricsServicesManager();
+ DCHECK(metrics_services_manager_client_);
+ metrics_services_manager_client_->OnCrosSettingsCreated();
+#endif
+
+ download_status_updater_ = std::make_unique<DownloadStatusUpdater>();
+
+ rappor::SetDefaultServiceAccessor(&GetBrowserRapporService);
#if BUILDFLAG(ENABLE_PRINTING)
// Must be created after the NotificationService.
@@ -259,6 +273,30 @@
KeepAliveRegistry::GetInstance()->SetIsShuttingDown(false);
KeepAliveRegistry::GetInstance()->AddObserver(this);
#endif // !defined(OS_ANDROID)
+
+ pref_change_registrar_.Init(local_state());
+
+ // Initialize the notification for the default browser setting policy.
+ pref_change_registrar_.Add(
+ prefs::kDefaultBrowserSettingEnabled,
+ base::Bind(&BrowserProcessImpl::ApplyDefaultBrowserPolicy,
+ base::Unretained(this)));
+
+#if !defined(OS_ANDROID)
+ // This preference must be kept in sync with external values; update them
+ // whenever the preference or its controlling policy changes.
+ pref_change_registrar_.Add(
+ metrics::prefs::kMetricsReportingEnabled,
+ base::Bind(&BrowserProcessImpl::ApplyMetricsReportingPolicy,
+ base::Unretained(this)));
+#endif
+
+ int max_per_proxy = local_state_->GetInteger(prefs::kMaxConnectionsPerProxy);
+ net::ClientSocketPoolManager::set_max_sockets_per_proxy_server(
+ net::HttpNetworkSession::NORMAL_SOCKET_POOL,
+ std::max(std::min(max_per_proxy, 99),
+ net::ClientSocketPoolManager::max_sockets_per_group(
+ net::HttpNetworkSession::NORMAL_SOCKET_POOL)));
}
BrowserProcessImpl::~BrowserProcessImpl() {
@@ -528,11 +566,10 @@
if (!metrics_services_manager_) {
auto client =
base::MakeUnique<ChromeMetricsServicesManagerClient>(local_state());
- ChromeMetricsServicesManagerClient* client_ptr = client.get();
+ metrics_services_manager_client_ = client.get();
metrics_services_manager_ =
base::MakeUnique<metrics_services_manager::MetricsServicesManager>(
std::move(client));
- client_ptr->OnMetricsServiceManagerCreated(metrics_services_manager_.get());
}
return metrics_services_manager_.get();
}
@@ -749,6 +786,8 @@
}
void BrowserProcessImpl::SetApplicationLocale(const std::string& locale) {
+ // NOTE: this is called before any threads have been created in non-test
+ // environments.
locale_ = locale;
#if BUILDFLAG(ENABLE_EXTENSIONS)
extension_l10n_util::SetProcessLocale(locale);
@@ -1035,30 +1074,6 @@
local_state_path, local_state_task_runner_.get(), policy_service(),
pref_registry, false, std::move(delegate));
DCHECK(local_state_);
-
- pref_change_registrar_.Init(local_state_.get());
-
- // Initialize the notification for the default browser setting policy.
- pref_change_registrar_.Add(
- prefs::kDefaultBrowserSettingEnabled,
- base::Bind(&BrowserProcessImpl::ApplyDefaultBrowserPolicy,
- base::Unretained(this)));
-
- // This preference must be kept in sync with external values; update them
- // whenever the preference or its controlling policy changes.
-#if !defined(OS_ANDROID)
- pref_change_registrar_.Add(
- metrics::prefs::kMetricsReportingEnabled,
- base::Bind(&BrowserProcessImpl::ApplyMetricsReportingPolicy,
- base::Unretained(this)));
-#endif
-
- int max_per_proxy = local_state_->GetInteger(prefs::kMaxConnectionsPerProxy);
- net::ClientSocketPoolManager::set_max_sockets_per_proxy_server(
- net::HttpNetworkSession::NORMAL_SOCKET_POOL,
- std::max(std::min(max_per_proxy, 99),
- net::ClientSocketPoolManager::max_sockets_per_group(
- net::HttpNetworkSession::NORMAL_SOCKET_POOL)));
}
void BrowserProcessImpl::PreCreateThreads(
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index 6f8a5e7..a2d22608 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -34,6 +34,7 @@
class ChromeChildProcessWatcher;
class ChromeDeviceClient;
+class ChromeMetricsServicesManagerClient;
class ChromeResourceDispatcherHostDelegate;
class DevToolsAutoOpener;
class RemoteDebuggingServer;
@@ -74,6 +75,9 @@
base::SequencedTaskRunner* local_state_task_runner);
~BrowserProcessImpl() override;
+ // Called to complete initialization.
+ void Init();
+
// Called before the browser threads are created.
void PreCreateThreads(const base::CommandLine& command_line);
@@ -198,6 +202,10 @@
void Pin();
void Unpin();
+ // |metrics_services_manager_| owns this.
+ ChromeMetricsServicesManagerClient* metrics_services_manager_client_ =
+ nullptr;
+
std::unique_ptr<metrics_services_manager::MetricsServicesManager>
metrics_services_manager_;
diff --git a/chrome/browser/browser_process_impl_unittest.cc b/chrome/browser/browser_process_impl_unittest.cc
index f607d55..84a7d8e0a 100644
--- a/chrome/browser/browser_process_impl_unittest.cc
+++ b/chrome/browser/browser_process_impl_unittest.cc
@@ -108,6 +108,7 @@
#endif
TEST_F(BrowserProcessImplTest, MAYBE_LifeCycle) {
// Setup the BrowserProcessImpl and the threads.
+ browser_process_impl()->Init();
browser_process_impl()->PreCreateThreads(*command_line());
StartSecondaryThreads();
browser_process_impl()->PreMainMessageLoopRun();
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 2c66036..8c74bac0 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -19,12 +19,14 @@
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
#include "base/debug/debugger.h"
+#include "base/deferred_sequenced_task_runner.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
@@ -55,6 +57,7 @@
#include "chrome/browser/browser_process_impl.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/browser_shutdown.h"
+#include "chrome/browser/chrome_browser_field_trials.h"
#include "chrome/browser/chrome_browser_main_extra_parts.h"
#include "chrome/browser/component_updater/crl_set_component_installer.h"
#include "chrome/browser/component_updater/downloadable_strings_component_installer.h"
@@ -202,6 +205,7 @@
#endif
#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/settings/cros_settings_names.h"
@@ -334,18 +338,13 @@
}
#endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
-// Returns the new local state object, guaranteed non-NULL.
-// |local_state_task_runner| must be a shutdown-blocking task runner.
-PrefService* InitializeLocalState(
- base::SequencedTaskRunner* local_state_task_runner,
- const base::CommandLine& parsed_command_line) {
+void InitializeLocalState(base::SequencedTaskRunner* local_state_task_runner) {
TRACE_EVENT0("startup", "ChromeBrowserMainParts::InitializeLocalState")
// Load local state. This includes the application locale so we know which
// locale dll to load. This also causes local state prefs to be registered.
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
-
#if defined(OS_WIN)
if (first_run::IsChromeFirstRun()) {
// During first run we read the google_update registry key to find what
@@ -382,13 +381,14 @@
// JSONPrefStore here instead of an entire PrefService. Once this is
// addressed, the call to browser_prefs::RegisterLocalState can move
// to chrome_prefs::CreateLocalState.
- if (parsed_command_line.HasSwitch(switches::kParentProfile)) {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kParentProfile)) {
base::FilePath local_state_path;
PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
bool local_state_file_exists = base::PathExists(local_state_path);
if (!local_state_file_exists) {
base::FilePath parent_profile =
- parsed_command_line.GetSwitchValuePath(switches::kParentProfile);
+ command_line->GetSwitchValuePath(switches::kParentProfile);
scoped_refptr<PrefRegistrySimple> registry = new PrefRegistrySimple();
std::unique_ptr<PrefService> parent_local_state(
chrome_prefs::CreateLocalState(
@@ -403,7 +403,7 @@
}
#if defined(OS_CHROMEOS)
- if (parsed_command_line.HasSwitch(chromeos::switches::kLoginManager)) {
+ if (command_line->HasSwitch(chromeos::switches::kLoginManager)) {
std::string owner_locale = local_state->GetString(prefs::kOwnerLocale);
// Ensure that we start with owner's locale.
if (!owner_locale.empty() &&
@@ -413,8 +413,24 @@
}
}
#endif // defined(OS_CHROMEOS)
+}
- return local_state;
+void ConvertFlagsToSwitches() {
+#if !defined(OS_CHROMEOS)
+ // Convert active flags into switches. This needs to be done before
+ // ui::ResourceBundle::InitSharedInstanceWithLocale as some loaded resources
+ // are affected by experiment flags (--touch-optimized-ui in particular). On
+ // ChromeOS system level flags are applied from the device settings from the
+ // session manager.
+ DCHECK(!ui::ResourceBundle::HasSharedInstance());
+ TRACE_EVENT0("startup",
+ "ChromeBrowserMainParts::PreCreateThreadsImpl:ConvertFlags");
+ flags_ui::PrefServiceFlagsStorage flags_storage(
+ g_browser_process->local_state());
+ about_flags::ConvertFlagsToSwitches(&flags_storage,
+ base::CommandLine::ForCurrentProcess(),
+ flags_ui::kAddSentinels);
+#endif // !defined(OS_CHROMEOS)
}
// Initializes the primary profile, possibly doing some user prompting to pick
@@ -659,6 +675,61 @@
prefs::kWebDriverOverridesIncompatiblePolicies)));
}
+// The initial read is done synchronously, the TaskPriority is thus only used
+// for flushes to disks and BACKGROUND is therefore appropriate. Priority of
+// remaining BACKGROUND+BLOCK_SHUTDOWN tasks is bumped by the TaskScheduler on
+// shutdown. However, some shutdown use cases happen without
+// TaskScheduler::Shutdown() (e.g. ChromeRestartRequest::Start() and
+// BrowserProcessImpl::EndSession()) and we must thus unfortunately make this
+// USER_VISIBLE until we solve https://crbug.com/747495 to allow bumping
+// priority of a sequence on demand.
+scoped_refptr<base::SequencedTaskRunner> CreateLocalStateTaskRunner() {
+ return base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
+}
+
+// Initializes the shared instance of ResourceBundle and returns the locale. An
+// empty string return value indicates failure.
+std::string InitResourceBundleAndDetermineLocale(
+ const content::MainFunctionParams& params) {
+#if defined(OS_MACOSX)
+ // TODO(markusheintz): Read preference pref::kApplicationLocale in order
+ // to enforce the application locale.
+ // Tests always get en-US.
+ std::string locale = params.ui_task ? "en-US" : std::string();
+#else
+ std::string locale =
+ g_browser_process->local_state()->GetString(prefs::kApplicationLocale);
+#endif
+
+ TRACE_EVENT0("startup",
+ "ChromeBrowserMainParts::InitResourceBundleAndDetermineLocale");
+ // On a POSIX OS other than ChromeOS, the parameter that is passed to the
+ // method InitSharedInstance is ignored.
+ locale = ui::ResourceBundle::InitSharedInstanceWithLocale(
+ locale, nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
+ if (locale.empty())
+ return locale;
+
+ // First run prefs needs data from the ResourceBundle, so load it now.
+ {
+ TRACE_EVENT0("startup",
+ "ChromeBrowserMainParts::InitResourceBundleAndDetermineLocale:"
+ ":AddDataPack");
+ base::FilePath resources_pack_path;
+ PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path);
+#if defined(OS_ANDROID)
+ ui::LoadMainAndroidPackFile("assets/resources.pak", resources_pack_path);
+#else
+ ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
+ resources_pack_path, ui::SCALE_FACTOR_NONE);
+#endif // defined(OS_ANDROID)
+ }
+
+ return locale;
+}
+
} // namespace
namespace chrome_browser {
@@ -677,6 +748,133 @@
} // namespace chrome_browser
+#if !defined(OS_ANDROID)
+// A TaskRunner that defers tasks until the real task runner is up and running.
+// This is used during early initialization, before the real task runner has
+// been created. DeferredTaskRunner has the following states.
+//
+// . kInstalled: the initial state. Tasks are added to |deferred_runner_|. In
+// this state this is installed as the active ThreadTaskRunnerHandle.
+// . kWaitingForMainToStart: this is no longer the active
+// ThreadTaskRunnerHandle, tasks are still deferred though.
+// . kMessageLoopRunning: last state, all deferred tasks are flushed to the
+// active ThreadTaskRunnerHandle.
+//
+// The state changes by calling AdvanceToNextState(), and state changes in
+// order.
+class ChromeBrowserMainParts::DeferringTaskRunner
+ : public base::SingleThreadTaskRunner {
+ public:
+ DeferringTaskRunner() {
+ deferred_runner_ =
+ base::MakeRefCounted<base::DeferredSequencedTaskRunner>();
+ thread_task_runner_handle_ =
+ std::make_unique<base::ThreadTaskRunnerHandle>(this);
+ }
+
+ bool is_at_end_state() const {
+ base::AutoLock lock(lock_);
+ return state_ == State::kMessageLoopRunning;
+ }
+
+ // See description above class for details.
+ void AdvanceToNextState() {
+ std::unique_ptr<base::ThreadTaskRunnerHandle> thread_task_runner_handle;
+ {
+ base::AutoLock lock(lock_);
+ switch (state_) {
+ case State::kInstalled:
+ state_ = State::kWaitingForMainToStart;
+ // ~ThreadTaskRunnerHandle calls back to
+ // RunsTasksInCurrentSequence(), so destruction has to happen when
+ // the lock isn't held.
+ thread_task_runner_handle = std::move(thread_task_runner_handle_);
+ break;
+
+ case State::kWaitingForMainToStart:
+ state_ = State::kMessageLoopRunning;
+ deferred_runner_->StartWithTaskRunner(
+ base::ThreadTaskRunnerHandle::Get());
+ deferred_runner_ = nullptr;
+ main_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+ break;
+
+ case State::kMessageLoopRunning:
+ NOTREACHED();
+ }
+ }
+ }
+
+ // base::SequencedTaskRunner:
+ bool PostDelayedTask(const base::Location& from_here,
+ base::OnceClosure task,
+ base::TimeDelta delay) override {
+ base::AutoLock lock(lock_);
+ switch (state_) {
+ case State::kInstalled:
+ case State::kWaitingForMainToStart:
+ return deferred_runner_->PostDelayedTask(from_here, std::move(task),
+ delay);
+
+ case State::kMessageLoopRunning:
+ return main_thread_task_runner_->PostDelayedTask(
+ from_here, std::move(task), delay);
+ }
+ NOTREACHED();
+ return false;
+ }
+ bool RunsTasksInCurrentSequence() const override {
+ base::AutoLock lock(lock_);
+ switch (state_) {
+ case State::kInstalled:
+ case State::kWaitingForMainToStart:
+ return deferred_runner_->RunsTasksInCurrentSequence();
+
+ case State::kMessageLoopRunning:
+ return main_thread_task_runner_->RunsTasksInCurrentSequence();
+ }
+ NOTREACHED();
+ return false;
+ }
+ bool PostNonNestableDelayedTask(const base::Location& from_here,
+ base::OnceClosure task,
+ base::TimeDelta delay) override {
+ base::AutoLock lock(lock_);
+ switch (state_) {
+ case State::kInstalled:
+ case State::kWaitingForMainToStart:
+ return deferred_runner_->PostNonNestableDelayedTask(
+ from_here, std::move(task), delay);
+
+ case State::kMessageLoopRunning:
+ return main_thread_task_runner_->PostNonNestableDelayedTask(
+ from_here, std::move(task), delay);
+ }
+ NOTREACHED();
+ return false;
+ }
+
+ private:
+ // See class description for details on states.
+ enum class State {
+ kInstalled,
+ kWaitingForMainToStart,
+ kMessageLoopRunning,
+ };
+
+ ~DeferringTaskRunner() override = default;
+
+ // |lock_| protects *all* members.
+ mutable base::Lock lock_;
+ scoped_refptr<base::DeferredSequencedTaskRunner> deferred_runner_;
+ scoped_refptr<SingleThreadTaskRunner> main_thread_task_runner_;
+ std::unique_ptr<base::ThreadTaskRunnerHandle> thread_task_runner_handle_;
+ State state_ = State::kInstalled;
+
+ DISALLOW_COPY_AND_ASSIGN(DeferringTaskRunner);
+};
+#endif
+
// BrowserMainParts ------------------------------------------------------------
ChromeBrowserMainParts::ChromeBrowserMainParts(
@@ -710,6 +908,13 @@
std::make_unique<metrics::ExpiredHistogramsChecker>(
chrome_metrics::kExpiredHistogramsHashes,
chrome_metrics::kNumExpiredHistograms));
+
+#if !defined(OS_ANDROID)
+ // This needs to be created in the constructor as Chrome OS now creates some
+ // classes that depend upon a ThreadTaskRunnerHandle in
+ // PreEarlyInitialization().
+ initial_task_runner_ = base::MakeRefCounted<DeferringTaskRunner>();
+#endif
}
ChromeBrowserMainParts::~ChromeBrowserMainParts() {
@@ -718,15 +923,14 @@
chrome_extra_parts_.clear();
}
-// This will be called after the command-line has been mutated by about:flags
void ChromeBrowserMainParts::SetupFieldTrials() {
// Initialize FieldTrialList to support FieldTrials that use one-time
// randomization.
DCHECK(!field_trial_list_);
- field_trial_list_.reset(new base::FieldTrialList(
- browser_process_->GetMetricsServicesManager()->CreateEntropyProvider()));
+ field_trial_list_ = std::make_unique<base::FieldTrialList>(
+ browser_process_->GetMetricsServicesManager()->CreateEntropyProvider());
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+ auto feature_list = std::make_unique<base::FeatureList>();
// Associate parameters chosen in about:flags and create trial/group for them.
flags_ui::PrefServiceFlagsStorage flags_storage(
@@ -747,25 +951,11 @@
switches::kDisableFeatures, unforceable_field_trials,
std::move(feature_list), &variation_ids, &browser_field_trials_);
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- // Enable Navigation Tracing only if a trace upload url is specified.
- if (command_line->HasSwitch(switches::kEnableNavigationTracing) &&
- command_line->HasSwitch(switches::kTraceUploadURL)) {
- tracing::SetupNavigationTracing();
- }
-
// Initialize FieldTrialSynchronizer system. This is a singleton and is used
// for posting tasks via base::Bind. Its deleted when it goes out of scope.
// Even though base::Bind does AddRef and Release, the object will not be
// deleted after the Task is executed.
field_trial_synchronizer_ = new FieldTrialSynchronizer();
-
-#if defined(OS_WIN) || defined(OS_MACOSX) || \
- (defined(OS_LINUX) && !defined(OS_CHROMEOS))
- metrics::DesktopSessionDurationTracker::Initialize();
-#endif
- metrics::RendererUptimeTracker::Initialize();
}
void ChromeBrowserMainParts::SetupMetrics() {
@@ -893,7 +1083,28 @@
TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreEarlyInitialization");
for (size_t i = 0; i < chrome_extra_parts_.size(); ++i)
chrome_extra_parts_[i]->PreEarlyInitialization();
- return content::RESULT_CODE_NORMAL_EXIT;
+
+ // Create BrowserProcess in PreEarlyInitialization() so that we can load
+ // field trials (and all it depends upon).
+ scoped_refptr<base::SequencedTaskRunner> local_state_task_runner =
+ CreateLocalStateTaskRunner();
+ browser_process_ =
+ std::make_unique<BrowserProcessImpl>(local_state_task_runner.get());
+
+ bool failed_to_load_resource_bundle = false;
+ const int load_local_state_result = LoadLocalState(
+ local_state_task_runner.get(), &failed_to_load_resource_bundle);
+ if (load_local_state_result == chrome::RESULT_CODE_MISSING_DATA &&
+ failed_to_load_resource_bundle) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kNoErrorDialogs)) {
+ return chrome::RESULT_CODE_MISSING_DATA;
+ }
+ // Continue on and show error later (once UI has been initialized and main
+ // message loop is running).
+ return content::RESULT_CODE_NORMAL_EXIT;
+ }
+ return load_local_state_result;
}
void ChromeBrowserMainParts::PostEarlyInitialization() {
@@ -909,6 +1120,10 @@
}
void ChromeBrowserMainParts::PreMainMessageLoopStart() {
+#if !defined(OS_ANDROID)
+ initial_task_runner_->AdvanceToNextState();
+#endif
+
TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreMainMessageLoopStart");
for (size_t i = 0; i < chrome_extra_parts_.size(); ++i)
@@ -953,14 +1168,117 @@
return result_code_;
}
+int ChromeBrowserMainParts::LoadLocalState(
+ base::SequencedTaskRunner* local_state_task_runner,
+ bool* failed_to_load_resource_bundle) {
+ *failed_to_load_resource_bundle = false;
+ if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_))
+ return chrome::RESULT_CODE_MISSING_DATA;
+
+ InitializeLocalState(local_state_task_runner);
+
+ ConvertFlagsToSwitches();
+
+ browser_process_->local_state()->UpdateCommandLinePrefStore(
+ new ChromeCommandLinePrefStore(base::CommandLine::ForCurrentProcess()));
+
+#if !defined(OS_ANDROID)
+ master_prefs_ = std::make_unique<first_run::MasterPrefs>();
+#endif
+
+ // First run prefs may use the ResourceBundle (and get data from it), so this
+ // needs to be before ApplyFirstRunPrefs().
+ std::string locale = InitResourceBundleAndDetermineLocale(parameters());
+ if (locale.empty()) {
+ *failed_to_load_resource_bundle = true;
+ return chrome::RESULT_CODE_MISSING_DATA;
+ }
+
+ const int apply_first_run_result = ApplyFirstRunPrefs();
+ if (apply_first_run_result != content::RESULT_CODE_NORMAL_EXIT)
+ return apply_first_run_result;
+
+ browser_process_->SetApplicationLocale(locale);
+
+ SetupOriginTrialsCommandLine(browser_process_->local_state());
+
+ // Now that the command line has been mutated based on about:flags, we can
+ // initialize field trials. The field trials are needed by IOThread's
+ // initialization which happens in BrowserProcess:PreCreateThreads. Metrics
+ // initialization is handled in PreMainMessageLoopRunImpl since it posts
+ // tasks.
+ SetupFieldTrials();
+
+ return content::RESULT_CODE_NORMAL_EXIT;
+}
+
+int ChromeBrowserMainParts::ApplyFirstRunPrefs() {
+// Android does first run in Java instead of native.
+// Chrome OS has its own out-of-box-experience code.
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+ // On first run, we need to process the predictor preferences before the
+ // browser's profile_manager object is created, but after ResourceBundle
+ // is initialized.
+ if (!first_run::IsChromeFirstRun())
+ return content::RESULT_CODE_NORMAL_EXIT;
+
+ first_run::ProcessMasterPreferencesResult pmp_result =
+ first_run::ProcessMasterPreferences(user_data_dir_, master_prefs_.get());
+ if (pmp_result == first_run::EULA_EXIT_NOW)
+ return chrome::RESULT_CODE_EULA_REFUSED;
+
+ // TODO(macourteau): refactor preferences that are copied from
+ // master_preferences into local_state, as a "local_state" section in
+ // master preferences. If possible, a generic solution would be preferred
+ // over a copy one-by-one of specific preferences. Also see related TODO
+ // in first_run.h.
+
+ PrefService* local_state = g_browser_process->local_state();
+ // Store the initial VariationsService seed in local state, if it exists
+ // in master prefs.
+ if (!master_prefs_->compressed_variations_seed.empty()) {
+ local_state->SetString(variations::prefs::kVariationsCompressedSeed,
+ master_prefs_->compressed_variations_seed);
+ if (!master_prefs_->variations_seed_signature.empty()) {
+ local_state->SetString(variations::prefs::kVariationsSeedSignature,
+ master_prefs_->variations_seed_signature);
+ }
+ // Set the variation seed date to the current system time. If the user's
+ // clock is incorrect, this may cause some field trial expiry checks to
+ // not do the right thing until the next seed update from the server,
+ // when this value will be updated.
+ local_state->SetInt64(variations::prefs::kVariationsSeedDate,
+ base::Time::Now().ToInternalValue());
+ }
+
+ if (!master_prefs_->suppress_default_browser_prompt_for_version.empty()) {
+ local_state->SetString(
+ prefs::kBrowserSuppressDefaultBrowserPrompt,
+ master_prefs_->suppress_default_browser_prompt_for_version);
+ }
+
+#if defined(OS_WIN)
+ if (!master_prefs_->welcome_page_on_os_upgrade_enabled)
+ local_state->SetBoolean(prefs::kWelcomePageOnOSUpgradeEnabled, false);
+#endif
+#endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+ return content::RESULT_CODE_NORMAL_EXIT;
+}
+
int ChromeBrowserMainParts::PreCreateThreadsImpl() {
TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreCreateThreadsImpl")
run_message_loop_ = false;
+
+ if (browser_process_->GetApplicationLocale().empty()) {
+ ShowMissingLocaleMessageBox();
+ return chrome::RESULT_CODE_MISSING_DATA;
+ }
+
#if !defined(OS_ANDROID)
chrome::MaybeShowInvalidUserDataDirWarningDialog();
#endif // !defined(OS_ANDROID)
- if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_))
- return chrome::RESULT_CODE_MISSING_DATA;
+
+ DCHECK(!user_data_dir_.empty());
// Force MediaCaptureDevicesDispatcher to be created on UI thread.
MediaCaptureDevicesDispatcher::GetInstance();
@@ -972,56 +1290,35 @@
// Cache first run state early.
first_run::IsChromeFirstRun();
+
+ // The real ThreadTaskRunnerHandle has been installed. Flush all the tasks
+ // and release the ref to |initial_task_runner_| so that it may be destroyed.
+ initial_task_runner_->AdvanceToNextState();
+ DCHECK(initial_task_runner_->is_at_end_state());
+ initial_task_runner_ = nullptr;
#endif // !defined(OS_ANDROID)
- // The initial read is done synchronously, the TaskPriority is thus only used
- // for flushes to disks and BACKGROUND is therefore appropriate. Priority of
- // remaining BACKGROUND+BLOCK_SHUTDOWN tasks is bumped by the TaskScheduler on
- // shutdown. However, some shutdown use cases happen without
- // TaskScheduler::Shutdown() (e.g. ChromeRestartRequest::Start() and
- // BrowserProcessImpl::EndSession()) and we must thus unfortunately make this
- // USER_VISIBLE until we solve https://crbug.com/747495 to allow bumping
- // priority of a sequence on demand.
- scoped_refptr<base::SequencedTaskRunner> local_state_task_runner =
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
+ PrefService* local_state = browser_process_->local_state();
+
+#if defined(OS_CHROMEOS)
+ chromeos::CrosSettings::Initialize();
+#endif // defined(OS_CHROMEOS)
{
- TRACE_EVENT0("startup",
- "ChromeBrowserMainParts::PreCreateThreadsImpl:InitBrowswerProcessImpl");
- browser_process_ =
- std::make_unique<BrowserProcessImpl>(local_state_task_runner.get());
+ TRACE_EVENT0(
+ "startup",
+ "ChromeBrowserMainParts::PreCreateThreadsImpl:InitBrowserProcessImpl");
+ browser_process_->Init();
}
- PrefService* local_state = InitializeLocalState(local_state_task_runner.get(),
- parsed_command_line());
-
#if !defined(OS_ANDROID)
// These members must be initialized before returning from this function.
- master_prefs_.reset(new first_run::MasterPrefs);
// Android doesn't use StartupBrowserCreator.
browser_creator_.reset(new StartupBrowserCreator);
// TODO(yfriedman): Refactor Android to re-use UMABrowsingActivityObserver
chrome::UMABrowsingActivityObserver::Init();
#endif // !defined(OS_ANDROID)
-#if !defined(OS_CHROMEOS)
- // Convert active labs into switches. This needs to be done before
- // ui::ResourceBundle::InitSharedInstanceWithLocale as some loaded resources
- // are affected by experiment flags (--touch-optimized-ui in particular). On
- // ChromeOS system level flags are applied from the device settings from the
- // session manager.
- {
- TRACE_EVENT0("startup",
- "ChromeBrowserMainParts::PreCreateThreadsImpl:ConvertFlags");
- flags_ui::PrefServiceFlagsStorage flags_storage(
- g_browser_process->local_state());
- about_flags::ConvertFlagsToSwitches(&flags_storage,
- base::CommandLine::ForCurrentProcess(),
- flags_ui::kAddSentinels);
- }
-#endif // !defined(OS_CHROMEOS)
// The MaterialDesignController needs to look at command line flags, which
// are not available until this point. Now that they are, proceed with
// initializing the MaterialDesignController.
@@ -1039,101 +1336,23 @@
base::trace_event::TraceEventETWExport::EnableETWExport();
#endif // OS_WIN
- local_state->UpdateCommandLinePrefStore(
- new ChromeCommandLinePrefStore(base::CommandLine::ForCurrentProcess()));
-
// Reset the command line in the crash report details, since we may have
// just changed it to include experiments.
crash_keys::SetCrashKeysFromCommandLine(
*base::CommandLine::ForCurrentProcess());
- // Mac starts it earlier in |PreMainMessageLoopStart()| (because it is
- // needed when loading the MainMenu.nib and the language doesn't depend on
- // anything since it comes from Cocoa.
-#if defined(OS_MACOSX)
- std::string locale =
- parameters().ui_task ? "en-US" : l10n_util::GetLocaleOverride();
- browser_process_->SetApplicationLocale(locale);
-#else
- const std::string locale = local_state->GetString(prefs::kApplicationLocale);
-
- // On a POSIX OS other than ChromeOS, the parameter that is passed to the
- // method InitSharedInstance is ignored.
-
- TRACE_EVENT_BEGIN0("startup",
- "ChromeBrowserMainParts::PreCreateThreadsImpl:InitResourceBundle");
- const std::string loaded_locale =
- ui::ResourceBundle::InitSharedInstanceWithLocale(
- locale, NULL, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
- TRACE_EVENT_END0("startup",
- "ChromeBrowserMainParts::PreCreateThreadsImpl:InitResourceBundle");
-
- if (loaded_locale.empty() &&
- !parsed_command_line().HasSwitch(switches::kNoErrorDialogs)) {
- ShowMissingLocaleMessageBox();
- return chrome::RESULT_CODE_MISSING_DATA;
- }
- CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale;
- browser_process_->SetApplicationLocale(loaded_locale);
-
- {
- TRACE_EVENT0("startup",
- "ChromeBrowserMainParts::PreCreateThreadsImpl:AddDataPack");
- base::FilePath resources_pack_path;
- PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path);
-#if defined(OS_ANDROID)
- ui::LoadMainAndroidPackFile("assets/resources.pak", resources_pack_path);
-#else
- ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
- resources_pack_path, ui::SCALE_FACTOR_NONE);
-#endif // defined(OS_ANDROID)
- }
-#endif // defined(OS_MACOSX)
-
browser_process_->browser_policy_connector()->OnResourceBundleCreated();
// Android does first run in Java instead of native.
// Chrome OS has its own out-of-box-experience code.
#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
- // On first run, we need to process the predictor preferences before the
- // browser's profile_manager object is created, but after ResourceBundle
- // is initialized.
if (first_run::IsChromeFirstRun()) {
- first_run::ProcessMasterPreferencesResult pmp_result =
- first_run::ProcessMasterPreferences(user_data_dir_,
- master_prefs_.get());
- if (pmp_result == first_run::EULA_EXIT_NOW)
- return chrome::RESULT_CODE_EULA_REFUSED;
-
if (!parsed_command_line().HasSwitch(switches::kApp) &&
!parsed_command_line().HasSwitch(switches::kAppId) &&
!parsed_command_line().HasSwitch(switches::kShowAppList)) {
AddFirstRunNewTabs(browser_creator_.get(), master_prefs_->new_tabs);
}
- // TODO(macourteau): refactor preferences that are copied from
- // master_preferences into local_state, as a "local_state" section in
- // master preferences. If possible, a generic solution would be preferred
- // over a copy one-by-one of specific preferences. Also see related TODO
- // in first_run.h.
-
- // Store the initial VariationsService seed in local state, if it exists
- // in master prefs.
- if (!master_prefs_->compressed_variations_seed.empty()) {
- local_state->SetString(variations::prefs::kVariationsCompressedSeed,
- master_prefs_->compressed_variations_seed);
- if (!master_prefs_->variations_seed_signature.empty()) {
- local_state->SetString(variations::prefs::kVariationsSeedSignature,
- master_prefs_->variations_seed_signature);
- }
- // Set the variation seed date to the current system time. If the user's
- // clock is incorrect, this may cause some field trial expiry checks to
- // not do the right thing until the next seed update from the server,
- // when this value will be updated.
- local_state->SetInt64(variations::prefs::kVariationsSeedDate,
- base::Time::Now().ToInternalValue());
- }
-
#if defined(OS_MACOSX) || defined(OS_LINUX)
// Create directory for user-level Native Messaging manifest files. This
// makes it less likely that the directory will be created by third-party
@@ -1144,17 +1363,6 @@
if (!base::PathExists(user_native_messaging_dir))
base::CreateDirectory(user_native_messaging_dir);
#endif // defined(OS_MACOSX) || defined(OS_LINUX)
-
- if (!master_prefs_->suppress_default_browser_prompt_for_version.empty()) {
- local_state->SetString(
- prefs::kBrowserSuppressDefaultBrowserPrompt,
- master_prefs_->suppress_default_browser_prompt_for_version);
- }
-
-#if defined(OS_WIN)
- if (!master_prefs_->welcome_page_on_os_upgrade_enabled)
- local_state->SetBoolean(prefs::kWelcomePageOnOSUpgradeEnabled, false);
-#endif
}
#endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
@@ -1173,25 +1381,22 @@
SecKeychainAddCallback(&KeychainCallback, 0, NULL);
#endif // defined(OS_MACOSX)
-#if defined(OS_CHROMEOS)
- // Must be done after g_browser_process is constructed, before
- // SetupFieldTrials() and SetupMetrics().
- chromeos::CrosSettings::Initialize();
-#endif // defined(OS_CHROMEOS)
-
- SetupOriginTrialsCommandLine(local_state);
-
#if BUILDFLAG(ENABLE_VR)
content::WebvrServiceProvider::SetWebvrServiceCallback(
base::Bind(&vr::VRServiceImpl::Create));
#endif
- // Now that the command line has been mutated based on about:flags, we can
- // initialize field trials. The field trials are needed by IOThread's
- // initialization which happens in BrowserProcess:PreCreateThreads. Metrics
- // initialization is handled in PreMainMessageLoopRunImpl since it posts
- // tasks.
- SetupFieldTrials();
+ // Enable Navigation Tracing only if a trace upload url is specified.
+ if (parsed_command_line_.HasSwitch(switches::kEnableNavigationTracing) &&
+ parsed_command_line_.HasSwitch(switches::kTraceUploadURL)) {
+ tracing::SetupNavigationTracing();
+ }
+
+#if defined(OS_WIN) || defined(OS_MACOSX) || \
+ (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+ metrics::DesktopSessionDurationTracker::Initialize();
+#endif
+ metrics::RendererUptimeTracker::Initialize();
if (IsWebDriverOverridingPolicy(local_state)) {
auto* command_line = base::CommandLine::ForCurrentProcess();
diff --git a/chrome/browser/chrome_browser_main.h b/chrome/browser/chrome_browser_main.h
index 2ed10976..1d39768 100644
--- a/chrome/browser/chrome_browser_main.h
+++ b/chrome/browser/chrome_browser_main.h
@@ -33,6 +33,10 @@
class ThreeDAPIObserver;
class WebUsbDetector;
+namespace base {
+class SequencedTaskRunner;
+}
+
namespace chrome_browser {
// For use by ShowMissingLocaleMessageBox.
#if defined(OS_WIN)
@@ -52,6 +56,10 @@
virtual void AddParts(ChromeBrowserMainExtraParts* parts);
protected:
+#if !defined(OS_ANDROID)
+ class DeferringTaskRunner;
+#endif
+
explicit ChromeBrowserMainParts(
const content::MainFunctionParams& parameters);
@@ -115,6 +123,19 @@
// for child processes.
void SetupOriginTrialsCommandLine(PrefService* local_state);
+ // Calling during PreEarlyInitialization() to load local state. Return value
+ // is an exit status, RESULT_CODE_NORMAL_EXIT indicates success.
+ // If the return value is RESULT_CODE_MISSING_DATA, then
+ // |failed_to_load_resource_bundle| indicates if the ResourceBundle couldn't
+ // be loaded.
+ int LoadLocalState(base::SequencedTaskRunner* local_state_task_runner,
+ bool* failed_to_load_resource_bundle);
+
+ // Applies any preferences (to local state) needed for first run. This is
+ // always called and early outs if not first-run. Return value is an exit
+ // status, RESULT_CODE_NORMAL_EXIT indicates success.
+ int ApplyFirstRunPrefs();
+
// Methods for Main Message Loop -------------------------------------------
int PreCreateThreadsImpl();
@@ -123,6 +144,8 @@
// Members initialized on construction ---------------------------------------
const content::MainFunctionParams parameters_;
+ // TODO(sky): remove this. This class (and related calls), may mutate the
+ // CommandLine, so it is misleading keeping a const ref here.
const base::CommandLine& parsed_command_line_;
int result_code_;
@@ -182,6 +205,13 @@
base::FilePath user_data_dir_;
+#if !defined(OS_ANDROID)
+ // This TaskRunner is created and the constructor and destroyed in
+ // PreCreateThreadsImpl(). It's used to queue any tasks scheduled before the
+ // real task scheduler has been created.
+ scoped_refptr<DeferringTaskRunner> initial_task_runner_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainParts);
};
diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm
index 8bf53d1..1fbbb77 100644
--- a/chrome/browser/chrome_browser_main_mac.mm
+++ b/chrome/browser/chrome_browser_main_mac.mm
@@ -89,14 +89,6 @@
singleton_command_line->AppendSwitch(switches::kNoStartupWindow);
}
- return content::RESULT_CODE_NORMAL_EXIT;
-}
-
-void ChromeBrowserMainPartsMac::PreMainMessageLoopStart() {
- MacStartupProfiler::GetInstance()->Profile(
- MacStartupProfiler::PRE_MAIN_MESSAGE_LOOP_START);
- ChromeBrowserMainPartsPosix::PreMainMessageLoopStart();
-
// Tell Cocoa to finish its initialization, which we want to do manually
// instead of calling NSApplicationMain(). The primary reason is that NSAM()
// never returns, which would leave all the objects currently on the stack
@@ -115,19 +107,17 @@
l10n_util::OverrideLocaleWithCocoaLocale();
}
- // Before we load the nib, we need to start up the resource bundle so we
- // have the strings avaiable for localization.
- // TODO(markusheintz): Read preference pref::kApplicationLocale in order
- // to enforce the application locale.
- const std::string loaded_locale =
- ui::ResourceBundle::InitSharedInstanceWithLocale(
- std::string(), nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
- CHECK(!loaded_locale.empty()) << "Default locale could not be found";
+ return content::RESULT_CODE_NORMAL_EXIT;
+}
- base::FilePath resources_pack_path;
- PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path);
- ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
- resources_pack_path, ui::SCALE_FACTOR_NONE);
+void ChromeBrowserMainPartsMac::PreMainMessageLoopStart() {
+ MacStartupProfiler::GetInstance()->Profile(
+ MacStartupProfiler::PRE_MAIN_MESSAGE_LOOP_START);
+ ChromeBrowserMainPartsPosix::PreMainMessageLoopStart();
+
+ // ChromeBrowserMainParts should have loaded the resource bundle by this
+ // point (needed to load the nib).
+ CHECK(ui::ResourceBundle::HasSharedInstance());
// This is a no-op if the KeystoneRegistration framework is not present.
// The framework is only distributed with branded Google Chrome builds.
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index d487466e3..bc5bdfb 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -867,21 +867,21 @@
// static
void ChromeContentBrowserClient::SetApplicationLocale(
const std::string& locale) {
+ // The common case is that this function is called early in Chrome startup
+ // before any threads are created or registered. When there are no threads,
+ // we can just set the string without worrying about threadsafety.
+ if (!BrowserThread::IsThreadInitialized(BrowserThread::UI)) {
+ g_io_thread_application_locale.Get() = locale;
+ return;
+ }
+
+ // Otherwise we're being called to change the locale. In this case set it on
+ // the IO thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // This object is guaranteed to outlive all threads so we don't have to
- // worry about the lack of refcounting and can just post as Unretained.
- //
- // The common case is that this function is called early in Chrome startup
- // before any threads are created (it will also be called later if the user
- // changes the pref). In this case, there will be no threads created and
- // posting will fail. When there are no threads, we can just set the string
- // without worrying about threadsafety.
- if (!BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SetApplicationLocaleOnIOThread, locale))) {
- g_io_thread_application_locale.Get() = locale;
- }
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&SetApplicationLocaleOnIOThread, locale));
}
content::BrowserMainParts* ChromeContentBrowserClient::CreateBrowserMainParts(
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 6185b63..6939e65d 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -268,31 +268,38 @@
namespace internal {
+// Contains state created in PreEarlyInitialization(). This is just the state
+// needed for field trials.
+class DBusPreEarlyInit {
+ public:
+ DBusPreEarlyInit() {
+ SystemSaltGetter::Initialize();
+
+ // Initialize the device settings service so that we'll take actions per
+ // signals sent from the session manager. This needs to happen before
+ // g_browser_process initializes BrowserPolicyConnector.
+ DeviceSettingsService::Initialize();
+
+ // Initialize DBusThreadManager for the browser.
+ DBusThreadManager::Initialize(DBusThreadManager::kAll);
+ }
+
+ ~DBusPreEarlyInit() {
+ // NOTE: This must only be called if Initialize() was called.
+ DBusThreadManager::Shutdown();
+ SystemSaltGetter::Shutdown();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DBusPreEarlyInit);
+};
+
// Wrapper class for initializing dbus related services and shutting them
// down. This gets instantiated in a scoped_ptr so that shutdown methods in the
// destructor will get called if and only if this has been instantiated.
class DBusServices {
public:
explicit DBusServices(const content::MainFunctionParams& parameters) {
- // Under mash, some D-Bus clients are owned by other processes.
- DBusThreadManager::ProcessMask process_mask;
- switch (GetAshConfig()) {
- case ash::Config::CLASSIC:
- process_mask = DBusThreadManager::PROCESS_ALL;
- break;
- case ash::Config::MUS:
- // TODO(jamescook|derat): We need another category for mushrome.
- process_mask = DBusThreadManager::PROCESS_ALL;
- break;
- case ash::Config::MASH:
- process_mask = DBusThreadManager::PROCESS_BROWSER;
- break;
- }
-
- // Initialize DBusThreadManager for the browser. This must be done after
- // the main message loop is started, as it uses the message loop.
- DBusThreadManager::Initialize(process_mask);
-
bluez::BluezDBusManager::Initialize(
DBusThreadManager::Get()->GetSystemBus(),
chromeos::DBusThreadManager::Get()->IsUsingFakes());
@@ -378,7 +385,6 @@
PowerDataCollector::Initialize();
LoginState::Initialize();
- SystemSaltGetter::Initialize();
TPMTokenLoader::Initialize();
CertLoader::Initialize();
@@ -398,10 +404,6 @@
// detector starts to monitor changes from the update engine.
UpgradeDetectorChromeos::GetInstance()->Init();
- // Initialize the device settings service so that we'll take actions per
- // signals sent from the session manager. This needs to happen before
- // g_browser_process initializes BrowserPolicyConnector.
- DeviceSettingsService::Initialize();
DeviceSettingsService::Get()->SetSessionManager(
DBusThreadManager::Get()->GetSessionManagerClient(),
OwnerSettingsServiceChromeOSFactory::GetInstance()->GetOwnerKeyUtil());
@@ -412,7 +414,6 @@
NetworkHandler::Shutdown();
cryptohome::AsyncMethodCaller::Shutdown();
disks::DiskMountManager::Shutdown();
- SystemSaltGetter::Shutdown();
LoginState::Shutdown();
CertLoader::Shutdown();
TPMTokenLoader::Shutdown();
@@ -428,9 +429,6 @@
PowerPolicyController::Shutdown();
device::BluetoothAdapterFactory::Shutdown();
bluez::BluezDBusManager::Shutdown();
-
- // NOTE: This must only be called if Initialize() was called.
- DBusThreadManager::Shutdown();
}
void ServiceManagerConnectionStarted(
@@ -607,6 +605,8 @@
chrome::SetChannel(channel);
#endif
+ dbus_pre_early_init_ = std::make_unique<internal::DBusPreEarlyInit>();
+
return ChromeBrowserMainPartsLinux::PreEarlyInitialization();
}
@@ -1192,6 +1192,8 @@
// Destroy DBus services immediately after threads are stopped.
dbus_services_.reset();
+ dbus_pre_early_init_.reset();
+
// Reset SystemTokenCertDBInitializer after DBus services because it should
// outlive CertLoader.
system_token_certdb_initializer_.reset();
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
index 03aede8..44d0c00 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -46,6 +46,7 @@
}
namespace internal {
+class DBusPreEarlyInit;
class DBusServices;
class SystemTokenCertDBInitializer;
}
@@ -94,6 +95,7 @@
std::unique_ptr<WakeOnWifiManager> wake_on_wifi_manager_;
std::unique_ptr<NetworkThrottlingObserver> network_throttling_observer_;
+ std::unique_ptr<internal::DBusPreEarlyInit> dbus_pre_early_init_;
std::unique_ptr<internal::DBusServices> dbus_services_;
std::unique_ptr<internal::SystemTokenCertDBInitializer>
diff --git a/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc b/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
index 68934112..efd8145 100644
--- a/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
+++ b/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
@@ -4,7 +4,6 @@
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "chrome/browser/chromeos/login/test/oobe_base_test.h"
#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
@@ -166,7 +165,6 @@
pairing_chromeos::BluetoothHostPairingController* controller_ = nullptr;
bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client_ = nullptr;
- base::MessageLoopForUI message_loop_;
DISALLOW_COPY_AND_ASSIGN(BluetoothHostPairingNoInputTest);
};
diff --git a/chrome/browser/extensions/api/image_writer_private/image_writer_private_apitest.cc b/chrome/browser/extensions/api/image_writer_private/image_writer_private_apitest.cc
index 2c4dc2e..ddcd1a3 100644
--- a/chrome/browser/extensions/api/image_writer_private/image_writer_private_apitest.cc
+++ b/chrome/browser/extensions/api/image_writer_private/image_writer_private_apitest.cc
@@ -69,7 +69,6 @@
protected:
- base::MessageLoopForUI message_loop_;
image_writer::ImageWriterTestUtils test_utils_;
};
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
index 9c33e0e4..2472f8ec 100644
--- a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
@@ -151,17 +151,6 @@
DCHECK(local_state);
}
-void ChromeMetricsServicesManagerClient::OnMetricsServiceManagerCreated(
- metrics_services_manager::MetricsServicesManager* manager) {
-#if defined(OS_CHROMEOS)
- cros_settings_observer_ = chromeos::CrosSettings::Get()->AddSettingsObserver(
- chromeos::kStatsReportingPref,
- base::Bind(&OnCrosMetricsReportingSettingChange, local_state_, manager));
- // Invoke the callback once initially to set the metrics reporting state.
- OnCrosMetricsReportingSettingChange(local_state_, manager);
-#endif
-}
-
ChromeMetricsServicesManagerClient::~ChromeMetricsServicesManagerClient() {}
// static
@@ -238,6 +227,18 @@
return true;
}
+#if defined(OS_CHROMEOS)
+void ChromeMetricsServicesManagerClient::OnCrosSettingsCreated() {
+ metrics_services_manager::MetricsServicesManager* manager =
+ g_browser_process->GetMetricsServicesManager();
+ cros_settings_observer_ = chromeos::CrosSettings::Get()->AddSettingsObserver(
+ chromeos::kStatsReportingPref,
+ base::Bind(&OnCrosMetricsReportingSettingChange, local_state_, manager));
+ // Invoke the callback once initially to set the metrics reporting state.
+ OnCrosMetricsReportingSettingChange(local_state_, manager);
+}
+#endif
+
std::unique_ptr<rappor::RapporServiceImpl>
ChromeMetricsServicesManagerClient::CreateRapporServiceImpl() {
DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.h b/chrome/browser/metrics/chrome_metrics_services_manager_client.h
index f15093f..d6615bb2 100644
--- a/chrome/browser/metrics/chrome_metrics_services_manager_client.h
+++ b/chrome/browser/metrics/chrome_metrics_services_manager_client.h
@@ -19,10 +19,6 @@
class PrefService;
-namespace metrics_services_manager {
-class MetricsServicesManager;
-}
-
namespace metrics {
class EnabledStateProvider;
class MetricsStateManager;
@@ -44,11 +40,6 @@
explicit ChromeMetricsServicesManagerClient(PrefService* local_state);
~ChromeMetricsServicesManagerClient() override;
- // Called once MetricsServicesManager has been created. Used to attach state
- // associated with the MetricsServicesManager.
- void OnMetricsServiceManagerCreated(
- metrics_services_manager::MetricsServicesManager* manager);
-
// Unconditionally attempts to create a field trial to control client side
// metrics/crash sampling to use as a fallback when one hasn't been
// provided. This is expected to occur on first-run on platforms that don't
@@ -70,6 +61,10 @@
// eligible for sampling.
static bool GetSamplingRatePerMille(int* rate);
+#if defined(OS_CHROMEOS)
+ void OnCrosSettingsCreated();
+#endif
+
private:
// This is defined as a member class to get access to
// ChromeMetricsServiceAccessor through ChromeMetricsServicesManagerClient's
diff --git a/chrome/browser/metrics/metrics_reporting_state_browsertest.cc b/chrome/browser/metrics/metrics_reporting_state_browsertest.cc
index 76f1105..bb3745f 100644
--- a/chrome/browser/metrics/metrics_reporting_state_browsertest.cc
+++ b/chrome/browser/metrics/metrics_reporting_state_browsertest.cc
@@ -55,7 +55,7 @@
expected_metrics_reporting_enabled) {}
// ChromeBrowserMainExtraParts:
- void PreCreateThreads() override;
+ void PostEarlyInitialization() override;
private:
// Expected value of reporting state.
@@ -138,7 +138,7 @@
DISALLOW_COPY_AND_ASSIGN(MetricsReportingStateTest);
};
-void ChromeBrowserMainExtraPartsChecker::PreCreateThreads() {
+void ChromeBrowserMainExtraPartsChecker::PostEarlyInitialization() {
ASSERT_EQ(expected_metrics_reporting_enabled_,
MetricsReportingStateTest::IsMetricsAndCrashReportingEnabled());
}
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc
index d6297d9..2327ea1 100644
--- a/chromeos/dbus/dbus_thread_manager.cc
+++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -53,11 +53,11 @@
static DBusThreadManager* g_dbus_thread_manager = nullptr;
static bool g_using_dbus_thread_manager_for_testing = false;
-DBusThreadManager::DBusThreadManager(ProcessMask process_mask,
+DBusThreadManager::DBusThreadManager(ClientSet client_set,
bool use_real_clients)
: use_real_clients_(use_real_clients),
clients_common_(new DBusClientsCommon(use_real_clients)) {
- if (process_mask & PROCESS_BROWSER)
+ if (client_set == DBusThreadManager::kAll)
clients_browser_.reset(new DBusClientsBrowser(use_real_clients));
// NOTE: When there are clients only used by ash, create them here.
@@ -270,7 +270,7 @@
}
// static
-void DBusThreadManager::Initialize(ProcessMask process_mask) {
+void DBusThreadManager::Initialize(ClientSet client_set) {
// If we initialize DBusThreadManager twice we may also be shutting it down
// early; do not allow that.
if (g_using_dbus_thread_manager_for_testing)
@@ -280,13 +280,13 @@
bool use_real_clients = base::SysInfo::IsRunningOnChromeOS() &&
!base::CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kDbusStub);
- g_dbus_thread_manager = new DBusThreadManager(process_mask, use_real_clients);
+ g_dbus_thread_manager = new DBusThreadManager(client_set, use_real_clients);
g_dbus_thread_manager->InitializeClients();
}
// static
void DBusThreadManager::Initialize() {
- Initialize(PROCESS_ALL);
+ Initialize(kAll);
}
// static
@@ -298,7 +298,7 @@
// TODO(jamescook): Don't initialize clients as a side-effect of using a
// test API. For now, assume the caller wants all clients.
g_dbus_thread_manager =
- new DBusThreadManager(PROCESS_ALL, false /* use_real_clients */);
+ new DBusThreadManager(kAll, false /* use_real_clients */);
g_dbus_thread_manager->InitializeClients();
}
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h
index 2fd9f30..7a544316 100644
--- a/chromeos/dbus/dbus_thread_manager.h
+++ b/chromeos/dbus/dbus_thread_manager.h
@@ -82,10 +82,13 @@
// Processes for which to create and initialize the D-Bus clients.
// TODO(jamescook): Move creation of clients into //ash and //chrome/browser.
// http://crbug.com/647367
- enum ProcessMask {
- PROCESS_ASH = 1 << 0,
- PROCESS_BROWSER = 1 << 1,
- PROCESS_ALL = ~0,
+ enum ClientSet {
+ // Common clients needed by both ash and the browser.
+ kShared,
+
+ // Includes the client in |kShared| as well as the clients used only by
+ // the browser (and not ash).
+ kAll
};
// Sets the global instance. Must be called before any calls to Get().
// We explicitly initialize and shut down the global object, rather than
@@ -94,9 +97,9 @@
// arguments and whether this process runs in a ChromeOS environment.
// Only D-Bus clients available in the processes in |process_mask| will be
// created.
- static void Initialize(ProcessMask process_mask);
+ static void Initialize(ClientSet client_set);
- // Equivalent to Initialize(PROCESS_ALL).
+ // Equivalent to Initialize(kAll).
static void Initialize();
// Returns a DBusThreadManagerSetter instance that allows tests to
@@ -159,9 +162,9 @@
private:
friend class DBusThreadManagerSetter;
- // Creates dbus clients for all process types in |process_mask|. Creates real
- // clients if |use_real_clients| is set, otherwise creates fakes.
- DBusThreadManager(ProcessMask process_mask, bool use_real_clients);
+ // Creates dbus clients based on |client_set|. Creates real clients if
+ // |use_real_clients| is set, otherwise creates fakes.
+ DBusThreadManager(ClientSet client_set, bool use_real_clients);
~DBusThreadManager();
// Initializes all currently stored DBusClients with the system bus and
diff --git a/chromeos/dbus/dbus_thread_manager_unittest.cc b/chromeos/dbus/dbus_thread_manager_unittest.cc
index a199bfe..9fea5c6 100644
--- a/chromeos/dbus/dbus_thread_manager_unittest.cc
+++ b/chromeos/dbus/dbus_thread_manager_unittest.cc
@@ -51,7 +51,7 @@
// Tests that clients can be created for the browser process.
TEST(DBusThreadManagerTest, InitializeForBrowser) {
- DBusThreadManager::Initialize(DBusThreadManager::PROCESS_BROWSER);
+ DBusThreadManager::Initialize(DBusThreadManager::kAll);
DBusThreadManager* manager = DBusThreadManager::Get();
ASSERT_TRUE(manager);
@@ -88,7 +88,7 @@
// Tests that clients can be created for the ash process.
TEST(DBusThreadManagerTest, InitializeForAsh) {
- DBusThreadManager::Initialize(DBusThreadManager::PROCESS_ASH);
+ DBusThreadManager::Initialize(DBusThreadManager::kShared);
DBusThreadManager* manager = DBusThreadManager::Get();
ASSERT_TRUE(manager);