summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/base.gyp1
-rw-r--r--base/base.gypi2
-rw-r--r--base/deferred_sequenced_task_runner.cc99
-rw-r--r--base/deferred_sequenced_task_runner.h79
-rw-r--r--base/deferred_sequenced_task_runner_unittest.cc184
-rw-r--r--chrome/browser/bookmarks/DEPS2
-rw-r--r--chrome/browser/bookmarks/bookmark_model.cc5
-rw-r--r--chrome/browser/bookmarks/bookmark_model.h7
-rw-r--r--chrome/browser/bookmarks/bookmark_model_factory.cc6
-rw-r--r--chrome/browser/profiles/profile_manager.cc13
-rw-r--r--chrome/browser/profiles/profile_manager.h10
-rw-r--r--chrome/browser/profiles/startup_task_runner_service.cc30
-rw-r--r--chrome/browser/profiles/startup_task_runner_service.h45
-rw-r--r--chrome/browser/profiles/startup_task_runner_service_factory.cc33
-rw-r--r--chrome/browser/profiles/startup_task_runner_service_factory.h39
-rw-r--r--chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc4
-rw-r--r--chrome/browser/sync/test/integration/sync_test.cc4
-rw-r--r--chrome/browser/ui/views/avatar_menu_button_browsertest.cc2
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/test/base/testing_profile.cc2
20 files changed, 558 insertions, 13 deletions
diff --git a/base/base.gyp b/base/base.gyp
index 290961e..b026dcb 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -463,6 +463,7 @@
'debug/trace_event_unittest.cc',
'debug/trace_event_unittest.h',
'debug/trace_event_win_unittest.cc',
+ 'deferred_sequenced_task_runner_unittest.cc',
'environment_unittest.cc',
'file_util_unittest.cc',
'file_version_info_unittest.cc',
diff --git a/base/base.gypi b/base/base.gypi
index f26c4c7..164aa23 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -137,6 +137,8 @@
'debug/trace_event_impl.cc',
'debug/trace_event_impl.h',
'debug/trace_event_win.cc',
+ 'deferred_sequenced_task_runner.cc',
+ 'deferred_sequenced_task_runner.h',
'environment.cc',
'environment.h',
'file_descriptor_posix.h',
diff --git a/base/deferred_sequenced_task_runner.cc b/base/deferred_sequenced_task_runner.cc
new file mode 100644
index 0000000..c96704c
--- /dev/null
+++ b/base/deferred_sequenced_task_runner.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2013 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/deferred_sequenced_task_runner.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+
+namespace base {
+
+DeferredSequencedTaskRunner::DeferredTask::DeferredTask() {
+}
+
+DeferredSequencedTaskRunner::DeferredTask::~DeferredTask() {
+}
+
+DeferredSequencedTaskRunner::DeferredSequencedTaskRunner(
+ const scoped_refptr<SequencedTaskRunner>& target_task_runner)
+ : started_(false),
+ target_task_runner_(target_task_runner) {
+}
+
+DeferredSequencedTaskRunner::~DeferredSequencedTaskRunner() {
+}
+
+bool DeferredSequencedTaskRunner::PostDelayedTask(
+ const tracked_objects::Location& from_here,
+ const Closure& task,
+ TimeDelta delay) {
+ AutoLock lock(lock_);
+ if (started_) {
+ DCHECK(deferred_tasks_queue_.empty());
+ return target_task_runner_->PostDelayedTask(from_here, task, delay);
+ }
+
+ QueueDeferredTask(from_here, task, delay, false /* is_non_nestable */);
+ return true;
+}
+
+bool DeferredSequencedTaskRunner::RunsTasksOnCurrentThread() const {
+ return target_task_runner_->RunsTasksOnCurrentThread();
+}
+
+bool DeferredSequencedTaskRunner::PostNonNestableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const Closure& task,
+ TimeDelta delay) {
+ AutoLock lock(lock_);
+ if (started_) {
+ DCHECK(deferred_tasks_queue_.empty());
+ return target_task_runner_->PostNonNestableDelayedTask(from_here,
+ task,
+ delay);
+ }
+ QueueDeferredTask(from_here, task, delay, true /* is_non_nestable */);
+ return true;
+}
+
+void DeferredSequencedTaskRunner::QueueDeferredTask(
+ const tracked_objects::Location& from_here,
+ const Closure& task,
+ TimeDelta delay,
+ bool is_non_nestable) {
+ DeferredTask deferred_task;
+ deferred_task.posted_from = from_here;
+ deferred_task.task = task;
+ deferred_task.delay = delay;
+ deferred_task.is_non_nestable = is_non_nestable;
+ deferred_tasks_queue_.push_back(deferred_task);
+}
+
+
+void DeferredSequencedTaskRunner::Start() {
+ AutoLock lock(lock_);
+ DCHECK(!started_);
+ started_ = true;
+ for (std::vector<DeferredTask>::iterator i = deferred_tasks_queue_.begin();
+ i != deferred_tasks_queue_.end();
+ ++i) {
+ const DeferredTask& task = *i;
+ if (task.is_non_nestable) {
+ target_task_runner_->PostNonNestableDelayedTask(task.posted_from,
+ task.task,
+ task.delay);
+ } else {
+ target_task_runner_->PostDelayedTask(task.posted_from,
+ task.task,
+ task.delay);
+ }
+ // Replace the i-th element in the |deferred_tasks_queue_| with an empty
+ // |DelayedTask| to ensure that |task| is destroyed before the next task
+ // is posted.
+ *i = DeferredTask();
+ }
+ deferred_tasks_queue_.clear();
+}
+
+} // namespace base
diff --git a/base/deferred_sequenced_task_runner.h b/base/deferred_sequenced_task_runner.h
new file mode 100644
index 0000000..d1cdb43
--- /dev/null
+++ b/base/deferred_sequenced_task_runner.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2013 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 BASE_DEFERRED_SEQUENCED_TASKRUNNER_H_
+#define BASE_DEFERRED_SEQUENCED_TASKRUNNER_H_
+
+#include <vector>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "base/time.h"
+#include "base/tracked_objects.h"
+
+namespace base {
+
+// A DeferredSequencedTaskRunner is a subclass of SequencedTaskRunner that
+// queues up all requests until the first call to Start() is issued.
+class BASE_EXPORT DeferredSequencedTaskRunner : public SequencedTaskRunner {
+ public:
+ explicit DeferredSequencedTaskRunner(
+ const scoped_refptr<SequencedTaskRunner>& target_runner);
+
+ // TaskRunner implementation
+ virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const Closure& task,
+ TimeDelta delay) OVERRIDE;
+ virtual bool RunsTasksOnCurrentThread() const OVERRIDE;
+
+ // SequencedTaskRunner implementation
+ virtual bool PostNonNestableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const Closure& task,
+ TimeDelta delay) OVERRIDE;
+
+ // Start the execution - posts all queued tasks to the target executor. The
+ // deferred tasks are posted with their initial delay, meaning that the task
+ // execution delay is actually measured from Start.
+ // Fails when called a second time.
+ void Start();
+
+ private:
+ struct DeferredTask {
+ DeferredTask();
+ ~DeferredTask();
+
+ tracked_objects::Location posted_from;
+ Closure task;
+ // The delay this task was initially posted with.
+ TimeDelta delay;
+ bool is_non_nestable;
+ };
+
+ virtual ~DeferredSequencedTaskRunner();
+
+ // Creates a |Task| object and adds it to |deferred_tasks_queue_|.
+ void QueueDeferredTask(const tracked_objects::Location& from_here,
+ const Closure& task,
+ TimeDelta delay,
+ bool is_non_nestable);
+
+ // // Protects |started_| and |deferred_tasks_queue_|.
+ mutable Lock lock_;
+
+ bool started_;
+ const scoped_refptr<SequencedTaskRunner> target_task_runner_;
+ std::vector<DeferredTask> deferred_tasks_queue_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeferredSequencedTaskRunner);
+};
+
+} // namespace base
+
+#endif // BASE_DEFERRED_SEQUENCED_TASKRUNNER_H_
diff --git a/base/deferred_sequenced_task_runner_unittest.cc b/base/deferred_sequenced_task_runner_unittest.cc
new file mode 100644
index 0000000..c033ba8
--- /dev/null
+++ b/base/deferred_sequenced_task_runner_unittest.cc
@@ -0,0 +1,184 @@
+// Copyright (c) 2013 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/deferred_sequenced_task_runner.h"
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/threading/non_thread_safe.h"
+#include "base/threading/thread.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class DeferredSequencedTaskRunnerTest : public testing::Test,
+ public base::NonThreadSafe {
+ public:
+ class ExecuteTaskOnDestructor :
+ public base::RefCounted<ExecuteTaskOnDestructor> {
+ public:
+ ExecuteTaskOnDestructor(
+ DeferredSequencedTaskRunnerTest* executor,
+ int task_id)
+ : executor_(executor),
+ task_id_(task_id) {
+ }
+ private:
+ friend class base::RefCounted<ExecuteTaskOnDestructor>;
+ virtual ~ExecuteTaskOnDestructor() {
+ executor_->ExecuteTask(task_id_);
+ }
+ DeferredSequencedTaskRunnerTest* executor_;
+ int task_id_;
+ };
+
+ void ExecuteTask(int task_id) {
+ base::AutoLock lock(lock_);
+ executed_task_ids_.push_back(task_id);
+ }
+
+ void PostExecuteTask(int task_id) {
+ runner_->PostTask(FROM_HERE,
+ base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask,
+ base::Unretained(this),
+ task_id));
+ }
+
+ void StartRunner() {
+ runner_->Start();
+ }
+
+ void DoNothing(ExecuteTaskOnDestructor* object) {
+ }
+
+ protected:
+ DeferredSequencedTaskRunnerTest() :
+ loop_(),
+ runner_(
+ new base::DeferredSequencedTaskRunner(loop_.message_loop_proxy())) {
+ }
+
+ MessageLoop loop_;
+ scoped_refptr<base::DeferredSequencedTaskRunner> runner_;
+ mutable base::Lock lock_;
+ std::vector<int> executed_task_ids_;
+};
+
+TEST_F(DeferredSequencedTaskRunnerTest, Stopped) {
+ PostExecuteTask(1);
+ loop_.RunUntilIdle();
+ EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
+}
+
+TEST_F(DeferredSequencedTaskRunnerTest, Start) {
+ StartRunner();
+ PostExecuteTask(1);
+ loop_.RunUntilIdle();
+ EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
+}
+
+TEST_F(DeferredSequencedTaskRunnerTest, StartWithMultipleElements) {
+ StartRunner();
+ for (int i = 1; i < 5; ++i)
+ PostExecuteTask(i);
+
+ loop_.RunUntilIdle();
+ EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4));
+}
+
+TEST_F(DeferredSequencedTaskRunnerTest, DeferredStart) {
+ PostExecuteTask(1);
+ loop_.RunUntilIdle();
+ EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
+
+ StartRunner();
+ loop_.RunUntilIdle();
+ EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
+
+ PostExecuteTask(2);
+ loop_.RunUntilIdle();
+ EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2));
+}
+
+TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleElements) {
+ for (int i = 1; i < 5; ++i)
+ PostExecuteTask(i);
+ loop_.RunUntilIdle();
+ EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
+
+ StartRunner();
+ for (int i = 5; i < 9; ++i)
+ PostExecuteTask(i);
+ loop_.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");
+ thread1.Start();
+ thread2.Start();
+ for (int i = 0; i < 5; ++i) {
+ thread1.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
+ base::Unretained(this),
+ 2 * i));
+ thread2.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
+ base::Unretained(this),
+ 2 * i + 1));
+ if (i == 2) {
+ thread1.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeferredSequencedTaskRunnerTest::StartRunner,
+ base::Unretained(this)));
+ }
+ }
+ }
+
+ loop_.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.Start();
+ runner_ =
+ new base::DeferredSequencedTaskRunner(thread.message_loop_proxy());
+ for (int i = 0; i < 5; ++i) {
+ {
+ // Use a block to ensure that no reference to |short_lived_object|
+ // is kept on the main thread after it is posted to |runner_|.
+ scoped_refptr<ExecuteTaskOnDestructor> short_lived_object =
+ new ExecuteTaskOnDestructor(this, 2 * i);
+ runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DeferredSequencedTaskRunnerTest::DoNothing,
+ base::Unretained(this),
+ short_lived_object));
+ }
+ // |short_lived_object| with id |2 * i| should be destroyed before the
+ // task |2 * i + 1| is executed.
+ PostExecuteTask(2 * i + 1);
+ }
+ StartRunner();
+ }
+
+ // All |short_lived_object| with id |2 * i| are destroyed before the task
+ // |2 * i + 1| is executed.
+ EXPECT_THAT(executed_task_ids_,
+ testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
+}
+
+} // namespace
diff --git a/chrome/browser/bookmarks/DEPS b/chrome/browser/bookmarks/DEPS
index 104e900..4c3d5ac 100644
--- a/chrome/browser/bookmarks/DEPS
+++ b/chrome/browser/bookmarks/DEPS
@@ -22,6 +22,8 @@ include_rules = [
"!chrome/browser/profiles/profile_dependency_manager.h",
"!chrome/browser/profiles/profile_keyed_service.h",
"!chrome/browser/profiles/profile_keyed_service_factory.h",
+ "!chrome/browser/profiles/startup_task_runner_service.h",
+ "!chrome/browser/profiles/startup_task_runner_service_factory.h",
# Do not add to the list of temporarily-allowed dependencies above,
# and please do not introduce more #includes of these files.
]
diff --git a/chrome/browser/bookmarks/bookmark_model.cc b/chrome/browser/bookmarks/bookmark_model.cc
index 150afd4..d23f645 100644
--- a/chrome/browser/bookmarks/bookmark_model.cc
+++ b/chrome/browser/bookmarks/bookmark_model.cc
@@ -232,7 +232,8 @@ void BookmarkModel::Shutdown() {
loaded_signal_.Signal();
}
-void BookmarkModel::Load() {
+void BookmarkModel::Load(
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner) {
if (store_.get()) {
// If the store is non-null, it means Load was already invoked. Load should
// only be invoked once.
@@ -249,7 +250,7 @@ void BookmarkModel::Load() {
content::Source<Profile>(profile_));
// Load the bookmarks. BookmarkStorage notifies us when done.
- store_ = new BookmarkStorage(profile_, this, profile_->GetIOTaskRunner());
+ store_ = new BookmarkStorage(profile_, this, task_runner);
store_->LoadBookmarks(CreateLoadDetails());
}
diff --git a/chrome/browser/bookmarks/bookmark_model.h b/chrome/browser/bookmarks/bookmark_model.h
index 1d846d7..9853d38 100644
--- a/chrome/browser/bookmarks/bookmark_model.h
+++ b/chrome/browser/bookmarks/bookmark_model.h
@@ -33,6 +33,10 @@ class BookmarkModelObserver;
class BookmarkStorage;
class Profile;
+namespace base {
+class SequencedTaskRunner;
+}
+
namespace bookmark_utils {
struct TitleMatch;
}
@@ -236,7 +240,8 @@ class BookmarkModel : public content::NotificationObserver,
// Loads the bookmarks. This is called upon creation of the
// BookmarkModel. You need not invoke this directly.
- void Load();
+ // All load operations will be executed on |task_runner|.
+ void Load(const scoped_refptr<base::SequencedTaskRunner>& task_runner);
// Returns true if the model finished loading.
// This is virtual so it can be mocked.
diff --git a/chrome/browser/bookmarks/bookmark_model_factory.cc b/chrome/browser/bookmarks/bookmark_model_factory.cc
index 1f63b6d..73da8cb 100644
--- a/chrome/browser/bookmarks/bookmark_model_factory.cc
+++ b/chrome/browser/bookmarks/bookmark_model_factory.cc
@@ -4,11 +4,14 @@
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "base/deferred_sequenced_task_runner.h"
#include "base/memory/singleton.h"
#include "base/values.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_dependency_manager.h"
+#include "chrome/browser/profiles/startup_task_runner_service.h"
+#include "chrome/browser/profiles/startup_task_runner_service_factory.h"
#include "chrome/common/pref_names.h"
#include "components/user_prefs/pref_registry_syncable.h"
@@ -38,7 +41,8 @@ BookmarkModelFactory::~BookmarkModelFactory() {}
ProfileKeyedService* BookmarkModelFactory::BuildServiceInstanceFor(
Profile* profile) const {
BookmarkModel* bookmark_model = new BookmarkModel(profile);
- bookmark_model->Load();
+ bookmark_model->Load(StartupTaskRunnerServiceFactory::GetForProfile(profile)->
+ GetBookmarkTaskRunner());
return bookmark_model;
}
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index e157d1f..ce4ff02 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/deferred_sequenced_task_runner.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/metrics/histogram.h"
@@ -25,6 +26,8 @@
#include "chrome/browser/profiles/profile_destroyer.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_metrics.h"
+#include "chrome/browser/profiles/startup_task_runner_service.h"
+#include "chrome/browser/profiles/startup_task_runner_service_factory.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/browser.h"
@@ -847,6 +850,9 @@ void ProfileManager::DoFinalInitForServices(Profile* profile,
// initializing the managed flag if necessary).
ManagedUserServiceFactory::GetForProfile(profile)->Init();
#endif
+ // Start the deferred task runners once the profile is loaded.
+ StartupTaskRunnerServiceFactory::GetForProfile(profile)->
+ StartDeferredTaskRunners();
}
void ProfileManager::DoFinalInitLogging(Profile* profile) {
@@ -1173,12 +1179,17 @@ ProfileManagerWithoutInit::ProfileManagerWithoutInit(
}
void ProfileManager::RegisterTestingProfile(Profile* profile,
- bool add_to_cache) {
+ bool add_to_cache,
+ bool start_deferred_task_runners) {
RegisterProfile(profile, true);
if (add_to_cache) {
InitProfileUserPrefs(profile);
AddProfileToCache(profile);
}
+ if (start_deferred_task_runners) {
+ StartupTaskRunnerServiceFactory::GetForProfile(profile)->
+ StartDeferredTaskRunners();
+ }
}
void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks,
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h
index a93d457..6cee37b8 100644
--- a/chrome/browser/profiles/profile_manager.h
+++ b/chrome/browser/profiles/profile_manager.h
@@ -211,10 +211,14 @@ class ProfileManager : public base::NonThreadSafe,
// Autoloads profiles if they are running background apps.
void AutoloadProfiles();
- // Register and add testing profile to the ProfileManager. Use ONLY in tests.
+ // Registers and adds testing profile to the ProfileManager.
// This allows the creation of Profiles outside of the standard creation path
- // for testing. If |addToCache|, add to ProfileInfoCache as well.
- void RegisterTestingProfile(Profile* profile, bool addToCache);
+ // for testing. If |addToCache|, adds to ProfileInfoCache as well.
+ // If |start_deferred_task_runners|, starts the deferred task runners.
+ // Use ONLY in tests.
+ void RegisterTestingProfile(Profile* profile,
+ bool addToCache,
+ bool start_deferred_task_runners);
const base::FilePath& user_data_dir() const { return user_data_dir_; }
diff --git a/chrome/browser/profiles/startup_task_runner_service.cc b/chrome/browser/profiles/startup_task_runner_service.cc
new file mode 100644
index 0000000..60407e1
--- /dev/null
+++ b/chrome/browser/profiles/startup_task_runner_service.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2013 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/browser/profiles/startup_task_runner_service.h"
+
+#include "base/deferred_sequenced_task_runner.h"
+#include "base/logging.h"
+#include "chrome/browser/profiles/profile.h"
+
+StartupTaskRunnerService::StartupTaskRunnerService(Profile* profile)
+ : profile_(profile) {
+}
+
+StartupTaskRunnerService::~StartupTaskRunnerService() {
+}
+
+scoped_refptr<base::DeferredSequencedTaskRunner>
+ StartupTaskRunnerService::GetBookmarkTaskRunner() {
+ DCHECK(CalledOnValidThread());
+ if (!bookmark_task_runner_) {
+ bookmark_task_runner_ =
+ new base::DeferredSequencedTaskRunner(profile_->GetIOTaskRunner());
+ }
+ return bookmark_task_runner_;
+}
+
+void StartupTaskRunnerService::StartDeferredTaskRunners() {
+ GetBookmarkTaskRunner()->Start();
+}
diff --git a/chrome/browser/profiles/startup_task_runner_service.h b/chrome/browser/profiles/startup_task_runner_service.h
new file mode 100644
index 0000000..f6298a3
--- /dev/null
+++ b/chrome/browser/profiles/startup_task_runner_service.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2013 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 CHROME_BROWSER_PROFILES_STARTUP_TASK_RUNNER_SERVICE_H_
+#define CHROME_BROWSER_PROFILES_STARTUP_TASK_RUNNER_SERVICE_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/non_thread_safe.h"
+#include "chrome/browser/profiles/profile_keyed_service.h"
+
+class Profile;
+
+namespace base {
+class DeferredSequencedTaskRunner;
+} // namespace base
+
+// This service manages the startup task runners.
+class StartupTaskRunnerService : public base::NonThreadSafe,
+ public ProfileKeyedService {
+ public:
+ explicit StartupTaskRunnerService(Profile* profile);
+ virtual ~StartupTaskRunnerService();
+
+ // Returns sequenced task runner where all bookmarks I/O operations are
+ // performed.
+ // This method should only be called from the UI thread.
+ // Note: Using a separate task runner per profile service gives a better
+ // management of the sequence in which the task are started in order to avoid
+ // congestion during start-up (e.g the caller may decide to start loading the
+ // bookmarks only after the history finished).
+ scoped_refptr<base::DeferredSequencedTaskRunner> GetBookmarkTaskRunner();
+
+ // Starts the task runners that are deferred during start-up.
+ void StartDeferredTaskRunners();
+
+ private:
+ Profile* profile_;
+ scoped_refptr<base::DeferredSequencedTaskRunner> bookmark_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(StartupTaskRunnerService);
+};
+
+#endif // CHROME_BROWSER_PROFILES_STARTUP_TASK_RUNNER_SERVICE_H_
diff --git a/chrome/browser/profiles/startup_task_runner_service_factory.cc b/chrome/browser/profiles/startup_task_runner_service_factory.cc
new file mode 100644
index 0000000..eaff6a8
--- /dev/null
+++ b/chrome/browser/profiles/startup_task_runner_service_factory.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2013 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/browser/profiles/startup_task_runner_service_factory.h"
+
+#include "chrome/browser/profiles/profile_dependency_manager.h"
+#include "chrome/browser/profiles/startup_task_runner_service.h"
+
+StartupTaskRunnerServiceFactory::StartupTaskRunnerServiceFactory()
+ : ProfileKeyedServiceFactory("StartupTaskRunnerServiceFactory",
+ ProfileDependencyManager::GetInstance()) {
+}
+
+StartupTaskRunnerServiceFactory::~StartupTaskRunnerServiceFactory() {}
+
+// static
+StartupTaskRunnerService* StartupTaskRunnerServiceFactory::GetForProfile(
+ Profile* profile) {
+ return static_cast<StartupTaskRunnerService*>(
+ GetInstance()->GetServiceForProfile(profile, true));
+}
+
+// static
+StartupTaskRunnerServiceFactory*
+ StartupTaskRunnerServiceFactory::GetInstance() {
+ return Singleton<StartupTaskRunnerServiceFactory>::get();
+}
+
+ProfileKeyedService* StartupTaskRunnerServiceFactory::BuildServiceInstanceFor(
+ Profile* profile) const {
+ return new StartupTaskRunnerService(profile);
+}
diff --git a/chrome/browser/profiles/startup_task_runner_service_factory.h b/chrome/browser/profiles/startup_task_runner_service_factory.h
new file mode 100644
index 0000000..58bb4db
--- /dev/null
+++ b/chrome/browser/profiles/startup_task_runner_service_factory.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2013 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 CHROME_BROWSER_PROFILES_STARTUP_TASK_RUNNER_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_PROFILES_STARTUP_TASK_RUNNER_SERVICE_FACTORY_H_
+
+#include "base/basictypes.h"
+#include "base/memory/singleton.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
+
+class StartupTaskRunnerService;
+class PrefRegistrySyncable;
+class Profile;
+
+// Singleton that owns the start-up task runner service.
+class StartupTaskRunnerServiceFactory : public ProfileKeyedServiceFactory {
+ public:
+ // Returns the instance of StartupTaskRunnerService associated with this
+ // profile (creating one if none exists).
+ static StartupTaskRunnerService* GetForProfile(Profile* profile);
+
+ // Returns an instance of the StartupTaskRunnerServiceFactory singleton.
+ static StartupTaskRunnerServiceFactory* GetInstance();
+
+ private:
+ friend struct DefaultSingletonTraits<StartupTaskRunnerServiceFactory>;
+
+ StartupTaskRunnerServiceFactory();
+ virtual ~StartupTaskRunnerServiceFactory();
+
+ // ProfileKeyedServiceFactory:
+ virtual ProfileKeyedService* BuildServiceInstanceFor(
+ Profile* profile) const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(StartupTaskRunnerServiceFactory);
+};
+
+#endif // CHROME_BROWSER_PROFILES_STARTUP_TASK_RUNNER_SERVICE_FACTORY_H_
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc b/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
index bfa351b..3f3e27b 100644
--- a/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
@@ -56,7 +56,7 @@ class HistoryMock : public HistoryService {
ProfileKeyedService* BuildBookmarkModel(Profile* profile) {
BookmarkModel* bookmark_model = new BookmarkModel(profile);
- bookmark_model->Load();
+ bookmark_model->Load(profile->GetIOTaskRunner());
return bookmark_model;
}
@@ -177,7 +177,7 @@ TEST_F(SyncBookmarkDataTypeControllerTest, StartBookmarkModelNotReady) {
base::Unretained(&model_load_callback_)));
EXPECT_EQ(DataTypeController::MODEL_STARTING, bookmark_dtc_->state());
- bookmark_model_->Load();
+ bookmark_model_->Load(profile_.GetIOTaskRunner());
ui_test_utils::WaitForBookmarkModelToLoad(bookmark_model_);
EXPECT_EQ(DataTypeController::MODEL_LOADED, bookmark_dtc_->state());
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index fbe9500..d2facba 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -231,7 +231,9 @@ Profile* SyncTest::MakeProfile(const base::FilePath::StringType name) {
Profile* profile =
Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
- g_browser_process->profile_manager()->RegisterTestingProfile(profile, true);
+ g_browser_process->profile_manager()->RegisterTestingProfile(profile,
+ true,
+ true);
return profile;
}
diff --git a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
index ca14d6e..498919c 100644
--- a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
+++ b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
@@ -25,7 +25,7 @@ void CreateTestingProfile() {
CHECK(file_util::CreateDirectory(path));
Profile* profile =
Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
- profile_manager->RegisterTestingProfile(profile, true);
+ profile_manager->RegisterTestingProfile(profile, true, false);
EXPECT_EQ(2u, profile_manager->GetNumberOfProfiles());
}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 1ea871f..46dda1a 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1536,6 +1536,10 @@
'browser/profiles/refcounted_profile_keyed_service.h',
'browser/profiles/refcounted_profile_keyed_service_factory.cc',
'browser/profiles/refcounted_profile_keyed_service_factory.h',
+ 'browser/profiles/startup_task_runner_service.cc',
+ 'browser/profiles/startup_task_runner_service.h',
+ 'browser/profiles/startup_task_runner_service_factory.cc',
+ 'browser/profiles/startup_task_runner_service_factory.h',
'browser/profiles/storage_partition_descriptor.h',
'browser/remove_rows_table_model.h',
'browser/renderer_host/chrome_render_message_filter.cc',
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index fed2377..92e1286 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -392,7 +392,7 @@ void TestingProfile::DestroyTopSites() {
static ProfileKeyedService* BuildBookmarkModel(Profile* profile) {
BookmarkModel* bookmark_model = new BookmarkModel(profile);
- bookmark_model->Load();
+ bookmark_model->Load(profile->GetIOTaskRunner());
return bookmark_model;
}