summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-21 17:26:53 +0000
committernick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-21 17:26:53 +0000
commit8d414d1745e35507538834873584874e2e84323b (patch)
tree95ff6d97a5300ff7abb8afa447a933795fd2d165
parent7aa0a96ae010300281e897ac9b8111683fb5672c (diff)
downloadchromium_src-8d414d1745e35507538834873584874e2e84323b.zip
chromium_src-8d414d1745e35507538834873584874e2e84323b.tar.gz
chromium_src-8d414d1745e35507538834873584874e2e84323b.tar.bz2
Sync: Check that the current thread is a ModelSafeWorker's home thread.
Use this in sync_backend_host.cc to avoid dispatching to a data type controller except when we're on the DTC's home thread. BUG=41824 TEST=during manual testing of 2-client sync; this code is never active during add/deletes and associates/disassociates. Review URL: http://codereview.chromium.org/1741001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45201 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/sync/engine/mock_model_safe_workers.h2
-rw-r--r--chrome/browser/sync/engine/model_safe_worker.h11
-rw-r--r--chrome/browser/sync/glue/database_model_worker.cc4
-rw-r--r--chrome/browser/sync/glue/database_model_worker.h1
-rw-r--r--chrome/browser/sync/glue/history_model_worker.cc5
-rw-r--r--chrome/browser/sync/glue/history_model_worker.h1
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.cc26
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.h3
-rw-r--r--chrome/browser/sync/glue/ui_model_worker.cc4
-rw-r--r--chrome/browser/sync/glue/ui_model_worker.h1
-rw-r--r--chrome/browser/sync/glue/ui_model_worker_unittest.cc2
11 files changed, 58 insertions, 2 deletions
diff --git a/chrome/browser/sync/engine/mock_model_safe_workers.h b/chrome/browser/sync/engine/mock_model_safe_workers.h
index e776596..13d66aa 100644
--- a/chrome/browser/sync/engine/mock_model_safe_workers.h
+++ b/chrome/browser/sync/engine/mock_model_safe_workers.h
@@ -12,11 +12,13 @@ namespace browser_sync {
class MockUIModelWorker : public ModelSafeWorker {
public:
virtual ModelSafeGroup GetModelSafeGroup() { return GROUP_UI; }
+ virtual bool CurrentThreadIsWorkThread() { return true; }
};
class MockDBModelWorker : public ModelSafeWorker {
public:
virtual ModelSafeGroup GetModelSafeGroup() { return GROUP_DB; }
+ virtual bool CurrentThreadIsWorkThread() { return true; }
};
} // namespace browser_sync
diff --git a/chrome/browser/sync/engine/model_safe_worker.h b/chrome/browser/sync/engine/model_safe_worker.h
index df2edae..7d7461a 100644
--- a/chrome/browser/sync/engine/model_safe_worker.h
+++ b/chrome/browser/sync/engine/model_safe_worker.h
@@ -49,9 +49,18 @@ class ModelSafeWorker : public base::RefCountedThreadSafe<ModelSafeWorker> {
return GROUP_PASSIVE;
}
+ // Check the current thread and see if it's the thread associated with
+ // this worker. If this returns true, then it should be safe to operate
+ // on models that are in this worker's group. If this returns false,
+ // such work should not be attempted.
+ virtual bool CurrentThreadIsWorkThread() {
+ // The passive group is not the work thread for any browser model.
+ return false;
+ }
+
private:
friend class base::RefCountedThreadSafe<ModelSafeWorker>;
-
+
DISALLOW_COPY_AND_ASSIGN(ModelSafeWorker);
};
diff --git a/chrome/browser/sync/glue/database_model_worker.cc b/chrome/browser/sync/glue/database_model_worker.cc
index 02516c7..95c49a6 100644
--- a/chrome/browser/sync/glue/database_model_worker.cc
+++ b/chrome/browser/sync/glue/database_model_worker.cc
@@ -33,4 +33,8 @@ void DatabaseModelWorker::CallDoWorkAndSignalTask(Closure* work,
done->Signal();
}
+bool DatabaseModelWorker::CurrentThreadIsWorkThread() {
+ return ChromeThread::CurrentlyOn(ChromeThread::DB);
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/database_model_worker.h b/chrome/browser/sync/glue/database_model_worker.h
index 64f53ed..fbaf2bd 100644
--- a/chrome/browser/sync/glue/database_model_worker.h
+++ b/chrome/browser/sync/glue/database_model_worker.h
@@ -21,6 +21,7 @@ class DatabaseModelWorker : public browser_sync::ModelSafeWorker {
// ModelSafeWorker implementation. Called on syncapi SyncerThread.
void DoWorkAndWaitUntilDone(Closure* work);
virtual ModelSafeGroup GetModelSafeGroup() { return GROUP_DB; }
+ virtual bool CurrentThreadIsWorkThread();
private:
void CallDoWorkAndSignalTask(Closure* work, base::WaitableEvent* done);
diff --git a/chrome/browser/sync/glue/history_model_worker.cc b/chrome/browser/sync/glue/history_model_worker.cc
index cab697c..74b914b 100644
--- a/chrome/browser/sync/glue/history_model_worker.cc
+++ b/chrome/browser/sync/glue/history_model_worker.cc
@@ -50,4 +50,9 @@ void HistoryModelWorker::DoWorkAndWaitUntilDone(Closure* work) {
done.Wait();
}
+bool HistoryModelWorker::CurrentThreadIsWorkThread() {
+ // TODO(ncarter): How to determine this?
+ return true;
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/history_model_worker.h b/chrome/browser/sync/glue/history_model_worker.h
index d9fa5ed..6fd65e8 100644
--- a/chrome/browser/sync/glue/history_model_worker.h
+++ b/chrome/browser/sync/glue/history_model_worker.h
@@ -30,6 +30,7 @@ class HistoryModelWorker : public browser_sync::ModelSafeWorker,
// ModelSafeWorker implementation. Called on syncapi SyncerThread.
void DoWorkAndWaitUntilDone(Closure* work);
virtual ModelSafeGroup GetModelSafeGroup() { return GROUP_HISTORY; }
+ virtual bool CurrentThreadIsWorkThread();
// CancelableRequestConsumerBase implementation.
virtual void OnRequestAdded(CancelableRequestProvider* provider,
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc
index 1d49bc6..647dbb1 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/chrome/browser/sync/glue/sync_backend_host.cc
@@ -420,6 +420,14 @@ void SyncBackendHost::Core::OnChangesApplied(
// association.
if (it == host_->processors_.end())
return;
+
+ if (!IsCurrentThreadSafeForModel(model_type)) {
+ NOTREACHED() << "Changes applied on wrong thread.";
+ return;
+ }
+
+ // Now that we're sure we're on the correct thread, we can access the
+ // ChangeProcessor.
ChangeProcessor* processor = it->second;
// Ensure the change processor is willing to accept changes.
@@ -484,6 +492,24 @@ void SyncBackendHost::Core::HandleInitalizationCompletedOnFrontendLoop() {
host_->frontend_->OnBackendInitialized();
}
+
+bool SyncBackendHost::Core::IsCurrentThreadSafeForModel(
+ syncable::ModelType model_type) {
+ AutoLock lock(host_->registrar_lock_);
+
+ browser_sync::ModelSafeRoutingInfo::const_iterator routing_it =
+ host_->registrar_.routing_info.find(model_type);
+ if (routing_it == host_->registrar_.routing_info.end())
+ return false;
+ browser_sync::ModelSafeGroup group = routing_it->second;
+ WorkerMap::const_iterator worker_it = host_->registrar_.workers.find(group);
+ if (worker_it == host_->registrar_.workers.end())
+ return false;
+ ModelSafeWorker* worker = worker_it->second;
+ return worker->CurrentThreadIsWorkThread();
+}
+
+
void SyncBackendHost::Core::OnAuthError(const AuthError& auth_error) {
// We could be on SyncEngine_AuthWatcherThread. Post to our core loop so
// we can modify state.
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h
index 574f299..4704f85 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/chrome/browser/sync/glue/sync_backend_host.h
@@ -343,6 +343,9 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
// frontend thread components.
void HandleInitalizationCompletedOnFrontendLoop();
+ // Return true if a model lives on the current thread.
+ bool IsCurrentThreadSafeForModel(syncable::ModelType model_type);
+
// Our parent SyncBackendHost
SyncBackendHost* host_;
diff --git a/chrome/browser/sync/glue/ui_model_worker.cc b/chrome/browser/sync/glue/ui_model_worker.cc
index 89a9c43..d1a12b6 100644
--- a/chrome/browser/sync/glue/ui_model_worker.cc
+++ b/chrome/browser/sync/glue/ui_model_worker.cc
@@ -81,6 +81,10 @@ void UIModelWorker::Stop() {
state_ = STOPPED;
}
+bool UIModelWorker::CurrentThreadIsWorkThread() {
+ return MessageLoop::current() == ui_loop_;
+}
+
void UIModelWorker::CallDoWorkAndSignalTask::Run() {
if (!work_) {
// This can happen during tests or cases where there are more than just the
diff --git a/chrome/browser/sync/glue/ui_model_worker.h b/chrome/browser/sync/glue/ui_model_worker.h
index 84833d5..f7d9188 100644
--- a/chrome/browser/sync/glue/ui_model_worker.h
+++ b/chrome/browser/sync/glue/ui_model_worker.h
@@ -70,6 +70,7 @@ class UIModelWorker : public browser_sync::ModelSafeWorker {
// ModelSafeWorker implementation. Called on syncapi SyncerThread.
virtual void DoWorkAndWaitUntilDone(Closure* work);
virtual ModelSafeGroup GetModelSafeGroup() { return GROUP_UI; }
+ virtual bool CurrentThreadIsWorkThread();
// Upon receiving this idempotent call, the ModelSafeWorker can
// assume no work will ever be scheduled again from now on. If it has any work
diff --git a/chrome/browser/sync/glue/ui_model_worker_unittest.cc b/chrome/browser/sync/glue/ui_model_worker_unittest.cc
index a61832b..e0ad82f 100644
--- a/chrome/browser/sync/glue/ui_model_worker_unittest.cc
+++ b/chrome/browser/sync/glue/ui_model_worker_unittest.cc
@@ -55,7 +55,7 @@ class Syncer {
};
// A task run from the SyncerThread to "sync share", ie tell the Syncer to
-// ask it's ModelSafeWorker to do something.
+// ask its ModelSafeWorker to do something.
class FakeSyncShareTask : public Task {
public:
FakeSyncShareTask(Syncer* syncer, UIModelWorkerVisitor* visitor)