Index: chrome/browser/profiles/profile_impl.cc |
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc |
index 3d399049478a2f60a7dbf500f407b096ec3b8a7d..1298800415798a35c44c1cc0c37f9cf4c18436d5 100644 |
--- a/chrome/browser/profiles/profile_impl.cc |
+++ b/chrome/browser/profiles/profile_impl.cc |
@@ -12,10 +12,13 @@ |
#include "base/file_util.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/path_service.h" |
+#include "base/prefs/json_pref_store.h" |
#include "base/string_number_conversions.h" |
#include "base/string_tokenizer.h" |
#include "base/string_util.h" |
#include "base/stringprintf.h" |
+#include "base/synchronization/waitable_event.h" |
+#include "base/threading/sequenced_worker_pool.h" |
#include "base/utf_string_conversions.h" |
#include "base/version.h" |
#include "chrome/browser/autocomplete/autocomplete_classifier.h" |
@@ -155,8 +158,33 @@ const char* const kPrefExitTypeSessionEnded = "SessionEnded"; |
// Helper method needed because PostTask cannot currently take a Callback |
// function with non-void return type. |
// TODO(jhawkins): Remove once IgnoreResult is fixed. |
-void CreateDirectoryNoResult(const FilePath& path) { |
+void CreateDirectoryNoResult(const FilePath& path, |
Mattias Nissler (ping if slow)
2012/10/24 17:07:49
nit: Rename to CreateDirectoryAndSignal or somesuc
zel
2012/10/24 17:23:14
Done.
|
+ base::WaitableEvent* done_creating) { |
file_util::CreateDirectory(path); |
+ done_creating->Signal(); |
+} |
+ |
+// Task that blocks the FILE thread until CreateDirectoryNoResult() finishes on |
+// blocking I/O pool. |
+void BlockFileThreadOnDirectoryCreate(base::WaitableEvent* done_creating) { |
+ done_creating->Wait(); |
+} |
+ |
+// Initiates creation of profile directory on |sequenced_task_runner| and |
+// ensures that FILE thread is blocked until that operation finishes. |
+void CreateProfileDirectory(base::SequencedTaskRunner* sequenced_task_runner, |
+ const FilePath& path) { |
+ base::WaitableEvent* done_creating = new base::WaitableEvent(false, false); |
+ sequenced_task_runner->PostTask(FROM_HERE, |
+ base::Bind(&CreateDirectoryNoResult, |
+ path, |
+ done_creating)); |
+ // Block the FILE thread until directory is created on I/O pool to make sure |
+ // that we don't attempt any operation until that part completes. |
+ BrowserThread::PostTask( |
+ BrowserThread::FILE, FROM_HERE, |
Mattias Nissler (ping if slow)
2012/10/24 17:07:49
nit: indentation
zel
2012/10/24 17:23:14
Done.
|
+ base::Bind(&BlockFileThreadOnDirectoryCreate, |
+ base::Owned(done_creating))); |
} |
FilePath GetCachePath(const FilePath& base) { |
@@ -205,16 +233,20 @@ std::string ExitTypeToSessionTypePrefValue(Profile::ExitType type) { |
} // namespace |
+ |
Mattias Nissler (ping if slow)
2012/10/24 17:07:49
remove extra newline
zel
2012/10/24 17:23:14
Done.
|
// static |
Profile* Profile::CreateProfile(const FilePath& path, |
Delegate* delegate, |
CreateMode create_mode) { |
+ // Get sequenced task runner for making sure that file operations of |
+ // this profile (defined by |path|) are executed in expected order |
+ // (what was previously assured by the FILE thread). |
+ scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner = |
+ JsonPrefStore::GetTaskRunnerForFile(path, |
+ BrowserThread::GetBlockingPool()); |
if (create_mode == CREATE_MODE_ASYNCHRONOUS) { |
DCHECK(delegate); |
- // This is safe while all file operations are done on the FILE thread. |
- BrowserThread::PostTask( |
- BrowserThread::FILE, FROM_HERE, |
- base::Bind(&CreateDirectoryNoResult, path)); |
+ CreateProfileDirectory(sequenced_task_runner, path); |
} else if (create_mode == CREATE_MODE_SYNCHRONOUS) { |
if (!file_util::PathExists(path)) { |
// TODO(tc): http://b/1094718 Bad things happen if we can't write to the |
@@ -227,7 +259,7 @@ Profile* Profile::CreateProfile(const FilePath& path, |
NOTREACHED(); |
} |
- return new ProfileImpl(path, delegate, create_mode); |
+ return new ProfileImpl(path, delegate, create_mode, sequenced_task_runner); |
} |
// static |
@@ -280,9 +312,11 @@ void ProfileImpl::RegisterUserPrefs(PrefService* prefs) { |
PrefService::SYNCABLE_PREF); |
} |
-ProfileImpl::ProfileImpl(const FilePath& path, |
- Delegate* delegate, |
- CreateMode create_mode) |
+ProfileImpl::ProfileImpl( |
+ const FilePath& path, |
+ Delegate* delegate, |
+ CreateMode create_mode, |
+ base::SequencedTaskRunner* sequenced_task_runner) |
: path_(path), |
ALLOW_THIS_IN_INITIALIZER_LIST(visited_link_event_listener_( |
new VisitedLinkEventListener(this))), |
@@ -329,6 +363,7 @@ ProfileImpl::ProfileImpl(const FilePath& path, |
if (create_mode == CREATE_MODE_ASYNCHRONOUS) { |
prefs_.reset(PrefService::CreatePrefService( |
GetPrefFilePath(), |
+ sequenced_task_runner, |
policy_service_.get(), |
new ExtensionPrefStore( |
ExtensionPrefValueMapFactory::GetForProfile(this), false), |
@@ -341,6 +376,7 @@ ProfileImpl::ProfileImpl(const FilePath& path, |
// Load prefs synchronously. |
prefs_.reset(PrefService::CreatePrefService( |
GetPrefFilePath(), |
+ sequenced_task_runner, |
policy_service_.get(), |
new ExtensionPrefStore( |
ExtensionPrefValueMapFactory::GetForProfile(this), false), |
@@ -364,9 +400,10 @@ void ProfileImpl::DoFinalInit(bool is_new_profile) { |
// to PathService. |
chrome::GetUserCacheDirectory(path_, &base_cache_path_); |
// Always create the cache directory asynchronously. |
- BrowserThread::PostTask( |
- BrowserThread::FILE, FROM_HERE, |
- base::Bind(&CreateDirectoryNoResult, base_cache_path_)); |
+ scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner = |
+ JsonPrefStore::GetTaskRunnerForFile(base_cache_path_, |
+ BrowserThread::GetBlockingPool()); |
+ CreateProfileDirectory(sequenced_task_runner, base_cache_path_); |
// Now that the profile is hooked up to receive pref change notifications to |
// kGoogleServicesUsername, initialize components that depend on it to reflect |