Commit b9908a24 authored by akalin@chromium.org's avatar akalin@chromium.org

[Sync] Replace uses of ObserverListThreadSafe with WeakHandles

ObserverListThreadSafe was overkill since there was only two threads
involved, and only one observer.

Add MessageLoop member variables to various test classes that need it
(ObserverListThreadSafe had a hack that made it unnecessary before.)

BUG=103732
TEST=Start with a clean profile and set up sync.  about:profiler shouldn't
show ObserverListThreadSafe::Notify calls with sync threads anymore.


Review URL: http://codereview.chromium.org/8586014

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110836 0039d316-1c4b-4281-b951-d872f2087c98
parent 34825a53
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "chrome/browser/sync/engine/syncproto.h" #include "chrome/browser/sync/engine/syncproto.h"
#include "chrome/browser/sync/syncable/blob.h" #include "chrome/browser/sync/syncable/blob.h"
#include "chrome/browser/sync/syncable/directory_manager.h" #include "chrome/browser/sync/syncable/directory_manager.h"
...@@ -137,6 +138,7 @@ class SyncerProtoUtilTest : public testing::Test { ...@@ -137,6 +138,7 @@ class SyncerProtoUtilTest : public testing::Test {
} }
protected: protected:
MessageLoop message_loop_;
browser_sync::TestDirectorySetterUpper setter_upper_; browser_sync::TestDirectorySetterUpper setter_upper_;
}; };
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/location.h" #include "base/location.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/string_number_conversions.h" #include "base/string_number_conversions.h"
#include "base/stringprintf.h" #include "base/stringprintf.h"
#include "base/time.h" #include "base/time.h"
...@@ -468,6 +469,8 @@ class SyncerTest : public testing::Test, ...@@ -468,6 +469,8 @@ class SyncerTest : public testing::Test,
return GetField(metahandle, field, false); return GetField(metahandle, field, false);
} }
MessageLoop message_loop_;
// Some ids to aid tests. Only the root one's value is specific. The rest // Some ids to aid tests. Only the root one's value is specific. The rest
// are named for test clarity. // are named for test clarity.
// TODO(chron): Get rid of these inbuilt IDs. They only make it // TODO(chron): Get rid of these inbuilt IDs. They only make it
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_DEBUG_INFO_EVENT_LISTENER_H_ #ifndef CHROME_BROWSER_SYNC_INTERNAL_API_DEBUG_INFO_EVENT_LISTENER_H_
#define CHROME_BROWSER_SYNC_INTERNAL_API_DEBUG_INFO_EVENT_LISTENER_H_ #define CHROME_BROWSER_SYNC_INTERNAL_API_DEBUG_INFO_EVENT_LISTENER_H_
#include <queue>
#include <string> #include <string>
#include "chrome/browser/sync/internal_api/sync_manager.h" #include "chrome/browser/sync/internal_api/sync_manager.h"
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/observer_list_threadsafe.h"
#include "base/string_number_conversions.h" #include "base/string_number_conversions.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/sync/engine/all_status.h" #include "chrome/browser/sync/engine/all_status.h"
...@@ -131,8 +130,6 @@ class SyncManager::SyncInternal ...@@ -131,8 +130,6 @@ class SyncManager::SyncInternal
explicit SyncInternal(const std::string& name) explicit SyncInternal(const std::string& name)
: name_(name), : name_(name),
weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
change_observers_(
new ObserverListThreadSafe<SyncManager::ChangeObserver>()),
registrar_(NULL), registrar_(NULL),
change_delegate_(NULL), change_delegate_(NULL),
initialized_(false), initialized_(false),
...@@ -277,9 +274,6 @@ class SyncManager::SyncInternal ...@@ -277,9 +274,6 @@ class SyncManager::SyncInternal
virtual void StoreState(const std::string& cookie) OVERRIDE; virtual void StoreState(const std::string& cookie) OVERRIDE;
void AddChangeObserver(SyncManager::ChangeObserver* observer);
void RemoveChangeObserver(SyncManager::ChangeObserver* observer);
void AddObserver(SyncManager::Observer* observer); void AddObserver(SyncManager::Observer* observer);
void RemoveObserver(SyncManager::Observer* observer); void RemoveObserver(SyncManager::Observer* observer);
...@@ -495,11 +489,9 @@ class SyncManager::SyncInternal ...@@ -495,11 +489,9 @@ class SyncManager::SyncInternal
// constructing any transaction type. // constructing any transaction type.
UserShare share_; UserShare share_;
// Even though observers are always added/removed from the sync // This can be called from any thread, but only between calls to
// thread, we still need to use a thread-safe observer list as we // OpenDirectory() and ShutdownOnSyncThread().
// can notify from any thread. browser_sync::WeakHandle<SyncManager::ChangeObserver> change_observer_;
scoped_refptr<ObserverListThreadSafe<SyncManager::ChangeObserver> >
change_observers_;
ObserverList<SyncManager::Observer> observers_; ObserverList<SyncManager::Observer> observers_;
...@@ -893,7 +885,16 @@ void SyncManager::SyncInternal::StartSyncingNormally() { ...@@ -893,7 +885,16 @@ void SyncManager::SyncInternal::StartSyncingNormally() {
bool SyncManager::SyncInternal::OpenDirectory() { bool SyncManager::SyncInternal::OpenDirectory() {
DCHECK(!initialized_) << "Should only happen once"; DCHECK(!initialized_) << "Should only happen once";
bool share_opened = dir_manager()->Open(username_for_share(), this); // Set before Open().
change_observer_ =
browser_sync::MakeWeakHandle(js_mutation_event_observer_.AsWeakPtr());
bool share_opened =
dir_manager()->Open(
username_for_share(),
this,
browser_sync::MakeWeakHandle(
js_mutation_event_observer_.AsWeakPtr()));
if (!share_opened) { if (!share_opened) {
LOG(ERROR) << "Could not open share for:" << username_for_share(); LOG(ERROR) << "Could not open share for:" << username_for_share();
return false; return false;
...@@ -907,8 +908,6 @@ bool SyncManager::SyncInternal::OpenDirectory() { ...@@ -907,8 +908,6 @@ bool SyncManager::SyncInternal::OpenDirectory() {
} }
connection_manager()->set_client_id(lookup->cache_guid()); connection_manager()->set_client_id(lookup->cache_guid());
lookup->AddTransactionObserver(&js_mutation_event_observer_);
AddChangeObserver(&js_mutation_event_observer_);
return true; return true;
} }
...@@ -1223,16 +1222,6 @@ SyncManager::~SyncManager() { ...@@ -1223,16 +1222,6 @@ SyncManager::~SyncManager() {
delete data_; delete data_;
} }
void SyncManager::AddChangeObserver(ChangeObserver* observer) {
DCHECK(thread_checker_.CalledOnValidThread());
data_->AddChangeObserver(observer);
}
void SyncManager::RemoveChangeObserver(ChangeObserver* observer) {
DCHECK(thread_checker_.CalledOnValidThread());
data_->RemoveChangeObserver(observer);
}
void SyncManager::AddObserver(Observer* observer) { void SyncManager::AddObserver(Observer* observer) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
data_->AddObserver(observer); data_->AddObserver(observer);
...@@ -1268,8 +1257,9 @@ void SyncManager::SyncInternal::ShutdownOnSyncThread() { ...@@ -1268,8 +1257,9 @@ void SyncManager::SyncInternal::ShutdownOnSyncThread() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
// Prevent any in-flight method calls from running. Also // Prevent any in-flight method calls from running. Also
// invalidates |weak_handle_this_|. // invalidates |weak_handle_this_| and |change_observer_|.
weak_ptr_factory_.InvalidateWeakPtrs(); weak_ptr_factory_.InvalidateWeakPtrs();
js_mutation_event_observer_.InvalidateWeakPtrs();
scheduler_.reset(); scheduler_.reset();
...@@ -1297,9 +1287,6 @@ void SyncManager::SyncInternal::ShutdownOnSyncThread() { ...@@ -1297,9 +1287,6 @@ void SyncManager::SyncInternal::ShutdownOnSyncThread() {
// transaction. // transaction.
ReadTransaction trans(FROM_HERE, GetUserShare()); ReadTransaction trans(FROM_HERE, GetUserShare());
trans.GetCryptographer()->RemoveObserver(this); trans.GetCryptographer()->RemoveObserver(this);
trans.GetLookup()->
RemoveTransactionObserver(&js_mutation_event_observer_);
RemoveChangeObserver(&js_mutation_event_observer_);
} }
dir_manager()->FinalSaveChangesForAll(); dir_manager()->FinalSaveChangesForAll();
dir_manager()->Close(username_for_share()); dir_manager()->Close(username_for_share());
...@@ -1315,8 +1302,9 @@ void SyncManager::SyncInternal::ShutdownOnSyncThread() { ...@@ -1315,8 +1302,9 @@ void SyncManager::SyncInternal::ShutdownOnSyncThread() {
initialized_ = false; initialized_ = false;
// We reset this here, since only now we know it will not be // We reset these here, since only now we know they will not be
// accessed from other threads (since we shut down everything). // accessed from other threads (since we shut down everything).
change_observer_.Reset();
weak_handle_this_.Reset(); weak_handle_this_.Reset();
} }
...@@ -1382,7 +1370,7 @@ void SyncManager::SyncInternal::HandleTransactionCompleteChangeEvent( ...@@ -1382,7 +1370,7 @@ void SyncManager::SyncInternal::HandleTransactionCompleteChangeEvent(
const syncable::ModelType type = syncable::ModelTypeFromInt(i); const syncable::ModelType type = syncable::ModelTypeFromInt(i);
if (models_with_changes.test(type)) { if (models_with_changes.test(type)) {
change_delegate_->OnChangesComplete(type); change_delegate_->OnChangesComplete(type);
change_observers_->Notify( change_observer_.Call(FROM_HERE,
&SyncManager::ChangeObserver::OnChangesComplete, type); &SyncManager::ChangeObserver::OnChangesComplete, type);
} }
} }
...@@ -1418,7 +1406,7 @@ ModelTypeBitSet SyncManager::SyncInternal::HandleTransactionEndingChangeEvent( ...@@ -1418,7 +1406,7 @@ ModelTypeBitSet SyncManager::SyncInternal::HandleTransactionEndingChangeEvent(
if (!ordered_changes.Get().empty()) { if (!ordered_changes.Get().empty()) {
change_delegate_-> change_delegate_->
OnChangesApplied(type, &read_trans, ordered_changes); OnChangesApplied(type, &read_trans, ordered_changes);
change_observers_->Notify( change_observer_.Call(FROM_HERE,
&SyncManager::ChangeObserver::OnChangesApplied, &SyncManager::ChangeObserver::OnChangesApplied,
type, write_transaction_info.Get().id, ordered_changes); type, write_transaction_info.Get().id, ordered_changes);
models_with_changes.set(i, true); models_with_changes.set(i, true);
...@@ -1962,16 +1950,6 @@ void SyncManager::SyncInternal::StoreState( ...@@ -1962,16 +1950,6 @@ void SyncManager::SyncInternal::StoreState(
lookup->SaveChanges(); lookup->SaveChanges();
} }
void SyncManager::SyncInternal::AddChangeObserver(
SyncManager::ChangeObserver* observer) {
change_observers_->AddObserver(observer);
}
void SyncManager::SyncInternal::RemoveChangeObserver(
SyncManager::ChangeObserver* observer) {
change_observers_->RemoveObserver(observer);
}
void SyncManager::SyncInternal::AddObserver( void SyncManager::SyncInternal::AddObserver(
SyncManager::Observer* observer) { SyncManager::Observer* observer) {
observers_.AddObserver(observer); observers_.AddObserver(observer);
......
...@@ -496,10 +496,6 @@ class SyncManager { ...@@ -496,10 +496,6 @@ class SyncManager {
// Request a clearing of all data on the server // Request a clearing of all data on the server
void RequestClearServerData(); void RequestClearServerData();
// Add/remove change observers.
void AddChangeObserver(ChangeObserver* observer);
void RemoveChangeObserver(ChangeObserver* observer);
// Adds a listener to be notified of sync events. // Adds a listener to be notified of sync events.
// NOTE: It is OK (in fact, it's probably a good idea) to call this before // NOTE: It is OK (in fact, it's probably a good idea) to call this before
// having received OnInitializationCompleted. // having received OnInitializationCompleted.
......
...@@ -192,6 +192,7 @@ class SyncApiTest : public testing::Test { ...@@ -192,6 +192,7 @@ class SyncApiTest : public testing::Test {
} }
protected: protected:
MessageLoop message_loop_;
browser_sync::TestUserShare test_user_share_; browser_sync::TestUserShare test_user_share_;
}; };
......
...@@ -15,12 +15,21 @@ ...@@ -15,12 +15,21 @@
namespace browser_sync { namespace browser_sync {
JsMutationEventObserver::JsMutationEventObserver() {} JsMutationEventObserver::JsMutationEventObserver()
: weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
JsMutationEventObserver::~JsMutationEventObserver() { JsMutationEventObserver::~JsMutationEventObserver() {
DCHECK(non_thread_safe_.CalledOnValidThread()); DCHECK(non_thread_safe_.CalledOnValidThread());
} }
base::WeakPtr<JsMutationEventObserver> JsMutationEventObserver::AsWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
void JsMutationEventObserver::InvalidateWeakPtrs() {
weak_ptr_factory_.InvalidateWeakPtrs();
}
void JsMutationEventObserver::SetJsEventHandler( void JsMutationEventObserver::SetJsEventHandler(
const WeakHandle<JsEventHandler>& event_handler) { const WeakHandle<JsEventHandler>& event_handler) {
event_handler_ = event_handler; event_handler_ = event_handler;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h" #include "base/threading/non_thread_safe.h"
#include "chrome/browser/sync/internal_api/sync_manager.h" #include "chrome/browser/sync/internal_api/sync_manager.h"
#include "chrome/browser/sync/syncable/transaction_observer.h" #include "chrome/browser/sync/syncable/transaction_observer.h"
...@@ -34,6 +35,10 @@ class JsMutationEventObserver ...@@ -34,6 +35,10 @@ class JsMutationEventObserver
virtual ~JsMutationEventObserver(); virtual ~JsMutationEventObserver();
base::WeakPtr<JsMutationEventObserver> AsWeakPtr();
void InvalidateWeakPtrs();
void SetJsEventHandler(const WeakHandle<JsEventHandler>& event_handler); void SetJsEventHandler(const WeakHandle<JsEventHandler>& event_handler);
// sync_api::SyncManager::ChangeObserver implementation. // sync_api::SyncManager::ChangeObserver implementation.
...@@ -56,6 +61,7 @@ class JsMutationEventObserver ...@@ -56,6 +61,7 @@ class JsMutationEventObserver
private: private:
base::NonThreadSafe non_thread_safe_; base::NonThreadSafe non_thread_safe_;
base::WeakPtrFactory<JsMutationEventObserver> weak_ptr_factory_;
WeakHandle<JsEventHandler> event_handler_; WeakHandle<JsEventHandler> event_handler_;
void HandleJsEvent( void HandleJsEvent(
......
...@@ -7,10 +7,8 @@ ...@@ -7,10 +7,8 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/observer_list_threadsafe.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "chrome/browser/sync/notifier/invalidation_notifier.h" #include "chrome/browser/sync/notifier/invalidation_notifier.h"
#include "chrome/browser/sync/notifier/sync_notifier_observer.h"
namespace sync_notifier { namespace sync_notifier {
...@@ -18,12 +16,11 @@ class NonBlockingInvalidationNotifier::Core ...@@ -18,12 +16,11 @@ class NonBlockingInvalidationNotifier::Core
: public base::RefCountedThreadSafe<NonBlockingInvalidationNotifier::Core>, : public base::RefCountedThreadSafe<NonBlockingInvalidationNotifier::Core>,
public SyncNotifierObserver { public SyncNotifierObserver {
public: public:
// Called on parent thread. // Called on parent thread. |delegate_observer| should be
Core(); // initialized.
explicit Core(
// Called on parent thread. const browser_sync::WeakHandle<SyncNotifierObserver>&
void AddObserver(SyncNotifierObserver* observer); delegate_observer);
void RemoveObserver(SyncNotifierObserver* observer);
// Helpers called on I/O thread. // Helpers called on I/O thread.
void Initialize( void Initialize(
...@@ -50,14 +47,19 @@ class NonBlockingInvalidationNotifier::Core ...@@ -50,14 +47,19 @@ class NonBlockingInvalidationNotifier::Core
// Called on parent or I/O thread. // Called on parent or I/O thread.
~Core(); ~Core();
// The variables below should be used only on the I/O thread.
const browser_sync::WeakHandle<SyncNotifierObserver> delegate_observer_;
scoped_ptr<InvalidationNotifier> invalidation_notifier_; scoped_ptr<InvalidationNotifier> invalidation_notifier_;
scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
scoped_refptr<ObserverListThreadSafe<SyncNotifierObserver> > observers_;
DISALLOW_COPY_AND_ASSIGN(Core); DISALLOW_COPY_AND_ASSIGN(Core);
}; };
NonBlockingInvalidationNotifier::Core::Core() NonBlockingInvalidationNotifier::Core::Core(
: observers_(new ObserverListThreadSafe<SyncNotifierObserver>()) { const browser_sync::WeakHandle<SyncNotifierObserver>&
delegate_observer)
: delegate_observer_(delegate_observer) {
DCHECK(delegate_observer_.IsInitialized());
} }
NonBlockingInvalidationNotifier::Core::~Core() { NonBlockingInvalidationNotifier::Core::~Core() {
...@@ -92,16 +94,6 @@ void NonBlockingInvalidationNotifier::Core::Teardown() { ...@@ -92,16 +94,6 @@ void NonBlockingInvalidationNotifier::Core::Teardown() {
io_message_loop_proxy_ = NULL; io_message_loop_proxy_ = NULL;
} }
void NonBlockingInvalidationNotifier::Core::AddObserver(
SyncNotifierObserver* observer) {
observers_->AddObserver(observer);
}
void NonBlockingInvalidationNotifier::Core::RemoveObserver(
SyncNotifierObserver* observer) {
observers_->RemoveObserver(observer);
}
void NonBlockingInvalidationNotifier::Core::SetUniqueId( void NonBlockingInvalidationNotifier::Core::SetUniqueId(
const std::string& unique_id) { const std::string& unique_id) {
DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
...@@ -129,21 +121,24 @@ void NonBlockingInvalidationNotifier::Core::UpdateEnabledTypes( ...@@ -129,21 +121,24 @@ void NonBlockingInvalidationNotifier::Core::UpdateEnabledTypes(
void NonBlockingInvalidationNotifier::Core::OnIncomingNotification( void NonBlockingInvalidationNotifier::Core::OnIncomingNotification(
const syncable::ModelTypePayloadMap& type_payloads) { const syncable::ModelTypePayloadMap& type_payloads) {
DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
observers_->Notify(&SyncNotifierObserver::OnIncomingNotification, delegate_observer_.Call(FROM_HERE,
type_payloads); &SyncNotifierObserver::OnIncomingNotification,
type_payloads);
} }
void NonBlockingInvalidationNotifier::Core::OnNotificationStateChange( void NonBlockingInvalidationNotifier::Core::OnNotificationStateChange(
bool notifications_enabled) { bool notifications_enabled) {
DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
observers_->Notify(&SyncNotifierObserver::OnNotificationStateChange, delegate_observer_.Call(FROM_HERE,
notifications_enabled); &SyncNotifierObserver::OnNotificationStateChange,
notifications_enabled);
} }
void NonBlockingInvalidationNotifier::Core::StoreState( void NonBlockingInvalidationNotifier::Core::StoreState(
const std::string& state) { const std::string& state) {
DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
observers_->Notify(&SyncNotifierObserver::StoreState, state); delegate_observer_.Call(FROM_HERE,
&SyncNotifierObserver::StoreState, state);
} }
NonBlockingInvalidationNotifier::NonBlockingInvalidationNotifier( NonBlockingInvalidationNotifier::NonBlockingInvalidationNotifier(
...@@ -152,7 +147,10 @@ NonBlockingInvalidationNotifier::NonBlockingInvalidationNotifier( ...@@ -152,7 +147,10 @@ NonBlockingInvalidationNotifier::NonBlockingInvalidationNotifier(
const browser_sync::WeakHandle<InvalidationVersionTracker>& const browser_sync::WeakHandle<InvalidationVersionTracker>&
invalidation_version_tracker, invalidation_version_tracker,
const std::string& client_info) const std::string& client_info)
: core_(new Core), : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
core_(
new Core(browser_sync::MakeWeakHandle(
weak_ptr_factory_.GetWeakPtr()))),
parent_message_loop_proxy_( parent_message_loop_proxy_(
base::MessageLoopProxy::current()), base::MessageLoopProxy::current()),
io_message_loop_proxy_(notifier_options.request_context_getter-> io_message_loop_proxy_(notifier_options.request_context_getter->
...@@ -183,13 +181,13 @@ NonBlockingInvalidationNotifier::~NonBlockingInvalidationNotifier() { ...@@ -183,13 +181,13 @@ NonBlockingInvalidationNotifier::~NonBlockingInvalidationNotifier() {
void NonBlockingInvalidationNotifier::AddObserver( void NonBlockingInvalidationNotifier::AddObserver(
SyncNotifierObserver* observer) { SyncNotifierObserver* observer) {
DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
core_->AddObserver(observer); observers_.AddObserver(observer);
} }
void NonBlockingInvalidationNotifier::RemoveObserver( void NonBlockingInvalidationNotifier::RemoveObserver(
SyncNotifierObserver* observer) { SyncNotifierObserver* observer) {
DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
core_->RemoveObserver(observer); observers_.RemoveObserver(observer);
} }
void NonBlockingInvalidationNotifier::SetUniqueId( void NonBlockingInvalidationNotifier::SetUniqueId(
...@@ -242,4 +240,25 @@ void NonBlockingInvalidationNotifier::SendNotification( ...@@ -242,4 +240,25 @@ void NonBlockingInvalidationNotifier::SendNotification(
// need to forward on the call. // need to forward on the call.
} }
void NonBlockingInvalidationNotifier::OnIncomingNotification(
const syncable::ModelTypePayloadMap& type_payloads) {
DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
OnIncomingNotification(type_payloads));
}
void NonBlockingInvalidationNotifier::OnNotificationStateChange(
bool notifications_enabled) {
DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
OnNotificationStateChange(notifications_enabled));
}
void NonBlockingInvalidationNotifier::StoreState(
const std::string& state) {
DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
StoreState(state));
}
} // namespace sync_notifier } // namespace sync_notifier
...@@ -14,8 +14,11 @@ ...@@ -14,8 +14,11 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "chrome/browser/sync/notifier/invalidation_version_tracker.h" #include "chrome/browser/sync/notifier/invalidation_version_tracker.h"
#include "chrome/browser/sync/notifier/sync_notifier.h" #include "chrome/browser/sync/notifier/sync_notifier.h"
#include "chrome/browser/sync/notifier/sync_notifier_observer.h"
#include "chrome/browser/sync/util/weak_handle.h" #include "chrome/browser/sync/util/weak_handle.h"
#include "jingle/notifier/base/notifier_options.h" #include "jingle/notifier/base/notifier_options.h"
...@@ -25,7 +28,9 @@ class MessageLoopProxy; ...@@ -25,7 +28,9 @@ class MessageLoopProxy;
namespace sync_notifier { namespace sync_notifier {
class NonBlockingInvalidationNotifier : public SyncNotifier { class NonBlockingInvalidationNotifier
: public SyncNotifier,
public SyncNotifierObserver {
public: public:
// |invalidation_version_tracker| must be initialized. // |invalidation_version_tracker| must be initialized.
NonBlockingInvalidationNotifier( NonBlockingInvalidationNotifier(
...@@ -49,13 +54,26 @@ class NonBlockingInvalidationNotifier : public SyncNotifier { ...@@ -49,13 +54,26 @@ class NonBlockingInvalidationNotifier : public SyncNotifier {
virtual void SendNotification( virtual void SendNotification(
const syncable::ModelTypeSet& changed_types) OVERRIDE; const syncable::ModelTypeSet& changed_types) OVERRIDE;
// SyncNotifierObserver implementation.
virtual void OnIncomingNotification(
const syncable::ModelTypePayloadMap& type_payloads) OVERRIDE;
virtual void OnNotificationStateChange(bool notifications_enabled) OVERRIDE;
virtual void StoreState(const std::string& state) OVERRIDE;
private: private:
// The real guts of NonBlockingInvalidationNotifier, which allows this class
// to not be refcounted.
class Core; class Core;
base::WeakPtrFactory<NonBlockingInvalidationNotifier> weak_ptr_factory_;
// Our observers (which must live on the parent thread).
ObserverList<SyncNotifierObserver> observers_;
// The real guts of NonBlockingInvalidationNotifier, which allows
// this class to live completely on the parent thread.
scoped_refptr<Core> core_; scoped_refptr<Core> core_;
scoped_refptr<base::MessageLoopProxy> parent_message_loop_proxy_; scoped_refptr<base::MessageLoopProxy> parent_message_loop_proxy_;
scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
DISALLOW_COPY_AND_ASSIGN(NonBlockingInvalidationNotifier); DISALLOW_COPY_AND_ASSIGN(NonBlockingInvalidationNotifier);
}; };
......
...@@ -66,18 +66,29 @@ class NonBlockingInvalidationNotifierTest : public testing::Test { ...@@ -66,18 +66,29 @@ class NonBlockingInvalidationNotifierTest : public testing::Test {
}; };
TEST_F(NonBlockingInvalidationNotifierTest, Basic) { TEST_F(NonBlockingInvalidationNotifierTest, Basic) {
syncable::ModelTypeSet types; InSequence dummy;
types.insert(syncable::BOOKMARKS);
types.insert(syncable::AUTOFILL); syncable::ModelTypePayloadMap type_payloads;
type_payloads[syncable::PREFERENCES] = "payload";
type_payloads[syncable::BOOKMARKS] = "";
type_payloads[syncable::AUTOFILL] = "";
EXPECT_CALL(mock_observer_, OnNotificationStateChange(true));
EXPECT_CALL(mock_observer_, StoreState("new_fake_state"));
EXPECT_CALL(mock_observer_, OnIncomingNotification(type_payloads));
EXPECT_CALL(mock_observer_, OnNotificationStateChange(false));
invalidation_notifier_->SetUniqueId("fake_id");
invalidation_notifier_->SetState("fake_state"); invalidation_notifier_->SetState("fake_state");
invalidation_notifier_->SetUniqueId("fake_id");
invalidation_notifier_->UpdateCredentials("foo@bar.com", "fake_token"); invalidation_notifier_->UpdateCredentials("foo@bar.com", "fake_token");
invalidation_notifier_->UpdateEnabledTypes(types);
}
// TODO(akalin): Add synchronous operations for testing to invalidation_notifier_->OnNotificationStateChange(true);
// NonBlockingInvalidationNotifierTest and use that to test it. invalidation_notifier_->StoreState("new_fake_state");
invalidation_notifier_->OnIncomingNotification(type_payloads);
invalidation_notifier_->OnNotificationStateChange(false);
ui_loop_.RunAllPending();
}
} // namespace } // namespace
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/location.h" #include "base/location.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/message_loop.h"
#include "chrome/browser/sync/engine/conflict_resolver.h" #include "chrome/browser/sync/engine/conflict_resolver.h"
#include "chrome/browser/sync/engine/mock_model_safe_workers.h" #include "chrome/browser/sync/engine/mock_model_safe_workers.h"
#include "chrome/browser/sync/engine/syncer_types.h" #include "chrome/browser/sync/engine/syncer_types.h"
...@@ -101,6 +102,7 @@ class SyncSessionTest : public testing::Test, ...@@ -101,6 +102,7 @@ class SyncSessionTest : public testing::Test,
return request_params; return request_params;
} }
MessageLoop message_loop_;
bool controller_invocations_allowed_; bool controller_invocations_allowed_;
scoped_ptr<SyncSession> session_; scoped_ptr<SyncSession> session_;
scoped_ptr<SyncSessionContext> context_; scoped_ptr<SyncSessionContext> context_;
......
...@@ -42,19 +42,26 @@ DirectoryManager::~DirectoryManager() { ...@@ -42,19 +42,26 @@ DirectoryManager::~DirectoryManager() {
<< "Dir " << managed_directory_->name() << " not closed!"; << "Dir " << managed_directory_->name() << " not closed!";
} }
bool DirectoryManager::Open(const std::string& name, bool DirectoryManager::Open(
DirectoryChangeDelegate* delegate) { const std::string& name,
DirectoryChangeDelegate* delegate,
const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer) {
bool was_open = false; bool was_open = false;
const DirOpenResult result = const DirOpenResult result =
OpenImpl(name, GetSyncDataDatabasePath(), delegate, &was_open); OpenImpl(name, GetSyncDataDatabasePath(), delegate,
transaction_observer, &was_open);
return syncable::OPENED == result; return syncable::OPENED == result;
} }
// Opens a directory. Returns false on error. // Opens a directory. Returns false on error.
DirOpenResult DirectoryManager::OpenImpl(const std::string& name, DirOpenResult DirectoryManager::OpenImpl(
const FilePath& path, const std::string& name,
DirectoryChangeDelegate* delegate, const FilePath& path,
bool* was_open) { DirectoryChangeDelegate* delegate,
const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer,
bool* was_open) {
bool opened = false; bool opened = false;
{ {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
...@@ -72,7 +79,8 @@ DirOpenResult DirectoryManager::OpenImpl(const std::string& name, ...@@ -72,7 +79,8 @@ DirOpenResult DirectoryManager::OpenImpl(const std::string& name,
// Otherwise, open it. // Otherwise, open it.
scoped_ptr<Directory> dir(new Directory); scoped_ptr<Directory> dir(new Directory);
const DirOpenResult result = dir->Open(path, name, delegate); const DirOpenResult result =
dir->Open(path, name, delegate, transaction_observer);
if (syncable::OPENED == result) { if (syncable::OPENED == result) {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
managed_directory_ = dir.release(); managed_directory_ = dir.release();
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "chrome/browser/sync/syncable/dir_open_result.h" #include "chrome/browser/sync/syncable/dir_open_result.h"
#include "chrome/browser/sync/syncable/syncable.h" #include "chrome/browser/sync/syncable/syncable.h"
#include "chrome/browser/sync/util/cryptographer.h" #include "chrome/browser/sync/util/cryptographer.h"
#include "chrome/browser/sync/util/weak_handle.h"
namespace sync_api { class BaseTransaction; } namespace sync_api { class BaseTransaction; }
namespace syncable { class BaseTransaction; } namespace syncable { class BaseTransaction; }
...@@ -45,8 +46,10 @@ class DirectoryManager { ...@@ -45,8 +46,10 @@ class DirectoryManager {
// common case. Does not take ownership of |delegate|, which must // common case. Does not take ownership of |delegate|, which must
// be non-NULL. Starts sending events to |delegate| if the returned // be non-NULL. Starts sending events to |delegate| if the returned
// result is true. Note that events to |delegate| may be sent from // result is true. Note that events to |delegate| may be sent from
// *any* thread. // *any* thread. |transaction_observer| must be initialized.
bool Open(const std::string& name, DirectoryChangeDelegate* delegate); bool Open(const std::string& name, DirectoryChangeDelegate* delegate,
const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer);
// Marks a directory as closed and stops sending events to the // Marks a directory as closed and stops sending events to the
// delegate. It might take a while until all the file handles and // delegate. It might take a while until all the file handles and
...@@ -74,8 +77,12 @@ class DirectoryManager { ...@@ -74,8 +77,12 @@ class DirectoryManager {
return cryptographer_.get(); return cryptographer_.get();
} }
DirOpenResult OpenImpl(const std::string& name, const FilePath& path, DirOpenResult OpenImpl(
DirectoryChangeDelegate* delegate, bool* was_open); const std::string& name, const FilePath& path,
DirectoryChangeDelegate* delegate,
const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer,
bool* was_open);
// Helpers for friend class ScopedDirLookup: // Helpers for friend class ScopedDirLookup:
friend class ScopedDirLookup; friend class ScopedDirLookup;
......
...@@ -349,10 +349,14 @@ DictionaryValue* EntryKernel::ToValue() const { ...@@ -349,10 +349,14 @@ DictionaryValue* EntryKernel::ToValue() const {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Directory // Directory
void Directory::InitKernel(const std::string& name, void Directory::InitKernelForTest(
DirectoryChangeDelegate* delegate) { const std::string& name,
DCHECK(kernel_ == NULL); DirectoryChangeDelegate* delegate,
kernel_ = new Kernel(FilePath(), name, KernelLoadInfo(), delegate); const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer) {
DCHECK(!kernel_);
kernel_ = new Kernel(FilePath(), name, KernelLoadInfo(),
delegate, transaction_observer);
} }
Directory::PersistedKernelInfo::PersistedKernelInfo() Directory::PersistedKernelInfo::PersistedKernelInfo()
...@@ -378,10 +382,11 @@ Directory::SaveChangesSnapshot::SaveChangesSnapshot() ...@@ -378,10 +382,11 @@ Directory::SaveChangesSnapshot::SaveChangesSnapshot()
Directory::SaveChangesSnapshot::~SaveChangesSnapshot() {} Directory::SaveChangesSnapshot::~SaveChangesSnapshot() {}
Directory::Kernel::Kernel(const FilePath& db_path, Directory::Kernel::Kernel(
const string& name, const FilePath& db_path, const string& name,
const KernelLoadInfo& info, const KernelLoadInfo& info, DirectoryChangeDelegate* delegate,
DirectoryChangeDelegate* delegate) const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer)
: db_path(db_path), : db_path(db_path),
refcount(1), refcount(1),
next_write_transaction_id(0), next_write_transaction_id(0),
...@@ -399,8 +404,9 @@ Directory::Kernel::Kernel(const FilePath& db_path, ...@@ -399,8 +404,9 @@ Directory::Kernel::Kernel(const FilePath& db_path,
cache_guid(info.cache_guid), cache_guid(info.cache_guid),
next_metahandle(info.max_metahandle + 1), next_metahandle(info.max_metahandle + 1),
delegate(delegate), delegate(delegate),
observers(new ObserverListThreadSafe<TransactionObserver>()) { transaction_observer(transaction_observer) {
DCHECK(delegate); DCHECK(delegate);
DCHECK(transaction_observer.IsInitialized());
} }
void Directory::Kernel::AddRef() { void Directory::Kernel::AddRef() {
...@@ -432,9 +438,13 @@ Directory::~Directory() { ...@@ -432,9 +438,13 @@ Directory::~Directory() {
Close(); Close();
} }
DirOpenResult Directory::Open(const FilePath& file_path, const string& name, DirOpenResult Directory::Open(
DirectoryChangeDelegate* delegate) { const FilePath& file_path, const string& name,
const DirOpenResult result = OpenImpl(file_path, name, delegate); DirectoryChangeDelegate* delegate,
const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer) {
const DirOpenResult result =
OpenImpl(file_path, name, delegate, transaction_observer);
if (OPENED != result) if (OPENED != result)
Close(); Close();
return result; return result;
...@@ -461,9 +471,12 @@ DirectoryBackingStore* Directory::CreateBackingStore( ...@@ -461,9 +471,12 @@ DirectoryBackingStore* Directory::CreateBackingStore(
return new DirectoryBackingStore(dir_name, backing_filepath); return new DirectoryBackingStore(dir_name, backing_filepath);
} }
DirOpenResult Directory::OpenImpl(const FilePath& file_path, DirOpenResult Directory::OpenImpl(
const string& name, const FilePath& file_path,
DirectoryChangeDelegate* delegate) { const string& name,
DirectoryChangeDelegate* delegate,
const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer) {
DCHECK_EQ(static_cast<DirectoryBackingStore*>(NULL), store_); DCHECK_EQ(static_cast<DirectoryBackingStore*>(NULL), store_);
FilePath db_path(file_path); FilePath db_path(file_path);
file_util::AbsolutePath(&db_path); file_util::AbsolutePath(&db_path);
...@@ -477,7 +490,7 @@ DirOpenResult Directory::OpenImpl(const FilePath& file_path, ...@@ -477,7 +490,7 @@ DirOpenResult Directory::OpenImpl(const FilePath& file_path,
if (OPENED != result) if (OPENED != result)
return result; return result;
kernel_ = new Kernel(db_path, name, info, delegate); kernel_ = new Kernel(db_path, name, info, delegate, transaction_observer);
kernel_->metahandles_index->swap(metas_bucket); kernel_->metahandles_index->swap(metas_bucket);
InitializeIndices(); InitializeIndices();
return OPENED; return OPENED;
...@@ -1109,14 +1122,6 @@ void Directory::CheckTreeInvariants(syncable::BaseTransaction* trans, ...@@ -1109,14 +1122,6 @@ void Directory::CheckTreeInvariants(syncable::BaseTransaction* trans,
} }
} }
void Directory::AddTransactionObserver(TransactionObserver* observer) {
kernel_->observers->AddObserver(observer);
}
void Directory::RemoveTransactionObserver(TransactionObserver* observer) {
kernel_->observers->RemoveObserver(observer);
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// ScopedKernelLock // ScopedKernelLock
...@@ -1153,13 +1158,13 @@ BaseTransaction::BaseTransaction(const tracked_objects::Location& from_here, ...@@ -1153,13 +1158,13 @@ BaseTransaction::BaseTransaction(const tracked_objects::Location& from_here,
Directory* directory) Directory* directory)
: from_here_(from_here), name_(name), writer_(writer), : from_here_(from_here), name_(name), writer_(writer),
directory_(directory), dirkernel_(directory->kernel_) { directory_(directory), dirkernel_(directory->kernel_) {
dirkernel_->observers->Notify( dirkernel_->transaction_observer.Call(FROM_HERE,
&TransactionObserver::OnTransactionStart, from_here_, writer_); &TransactionObserver::OnTransactionStart, from_here_, writer_);
} }
BaseTransaction::~BaseTransaction() { BaseTransaction::~BaseTransaction() {
if (writer_ != INVALID) { if (writer_ != INVALID) {
dirkernel_->observers->Notify( dirkernel_->transaction_observer.Call(FROM_HERE,
&TransactionObserver::OnTransactionEnd, from_here_, writer_); &TransactionObserver::OnTransactionEnd, from_here_, writer_);
} }
} }
...@@ -1268,7 +1273,7 @@ ModelTypeBitSet WriteTransaction::NotifyTransactionChangingAndEnding( ...@@ -1268,7 +1273,7 @@ ModelTypeBitSet WriteTransaction::NotifyTransactionChangingAndEnding(
delegate->HandleTransactionEndingChangeEvent( delegate->HandleTransactionEndingChangeEvent(
immutable_write_transaction_info, this); immutable_write_transaction_info, this);
dirkernel_->observers->Notify( dirkernel_->transaction_observer.Call(FROM_HERE,
&TransactionObserver::OnTransactionWrite, &TransactionObserver::OnTransactionWrite,
immutable_write_transaction_info, models_with_changes); immutable_write_transaction_info, models_with_changes);
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "base/location.h" #include "base/location.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/observer_list_threadsafe.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "base/time.h" #include "base/time.h"
#include "chrome/browser/sync/protocol/sync.pb.h" #include "chrome/browser/sync/protocol/sync.pb.h"
...@@ -35,6 +34,7 @@ ...@@ -35,6 +34,7 @@
#include "chrome/browser/sync/syncable/model_type.h" #include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/util/immutable.h" #include "chrome/browser/sync/util/immutable.h"
#include "chrome/browser/sync/util/time.h" #include "chrome/browser/sync/util/time.h"
#include "chrome/browser/sync/util/weak_handle.h"
namespace base { namespace base {
class DictionaryValue; class DictionaryValue;
...@@ -821,11 +821,14 @@ class Directory { ...@@ -821,11 +821,14 @@ class Directory {
// Does not take ownership of |delegate|, which must not be NULL. // Does not take ownership of |delegate|, which must not be NULL.
// Starts sending events to |delegate| if the returned result is // Starts sending events to |delegate| if the returned result is
// OPENED. Note that events to |delegate| may be sent from *any* // OPENED. Note that events to |delegate| may be sent from *any*
// thread. // thread. |transaction_observer| must be initialized.
DirOpenResult Open(const FilePath& file_path, const std::string& name, DirOpenResult Open(const FilePath& file_path, const std::string& name,
DirectoryChangeDelegate* delegate); DirectoryChangeDelegate* delegate,
const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer);
// Stops sending events to the delegate. // Stops sending events to the delegate and the transaction
// observer.
void Close(); void Close();
int64 NextMetahandle(); int64 NextMetahandle();
...@@ -866,12 +869,6 @@ class Directory { ...@@ -866,12 +869,6 @@ class Directory {
// Unique to each account / client pair. // Unique to each account / client pair.
std::string cache_guid() const; std::string cache_guid() const;
// These are backed by a thread-safe observer list, and so can be
// called on any thread, and events will be sent to the observer on
// the same thread that it was added on.
void AddTransactionObserver(TransactionObserver* observer);
void RemoveTransactionObserver(TransactionObserver* observer);
protected: // for friends, mainly used by Entry constructors protected: // for friends, mainly used by Entry constructors
virtual EntryKernel* GetEntryByHandle(int64 handle); virtual EntryKernel* GetEntryByHandle(int64 handle);
virtual EntryKernel* GetEntryByHandle(int64 metahandle, virtual EntryKernel* GetEntryByHandle(int64 metahandle,
...@@ -900,8 +897,11 @@ class Directory { ...@@ -900,8 +897,11 @@ class Directory {
// before calling. // before calling.
EntryKernel* GetEntryById(const Id& id, ScopedKernelLock* const lock); EntryKernel* GetEntryById(const Id& id, ScopedKernelLock* const lock);
DirOpenResult OpenImpl(const FilePath& file_path, const std::string& name, DirOpenResult OpenImpl(
DirectoryChangeDelegate* delegate); const FilePath& file_path, const std::string& name,
DirectoryChangeDelegate* delegate,
const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer);
template <class T> void TestAndSet(T* kernel_data, const T* data_to_set); template <class T> void TestAndSet(T* kernel_data, const T* data_to_set);
...@@ -1049,14 +1049,22 @@ class Directory { ...@@ -1049,14 +1049,22 @@ class Directory {
typedef Index<ClientTagIndexer>::Set ClientTagIndex; typedef Index<ClientTagIndexer>::Set ClientTagIndex;
protected: protected:
// Used by tests. // Used by tests. |delegate| must not be NULL.
void InitKernel(const std::string& name, DirectoryChangeDelegate* delegate); // |transaction_observer| must be initialized.
void InitKernelForTest(
const std::string& name,
DirectoryChangeDelegate* delegate,
const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer);
private: private:
struct Kernel { struct Kernel {
// |delegate| can be NULL. // |delegate| must not be NULL. |transaction_observer| must be
// initialized.
Kernel(const FilePath& db_path, const std::string& name, Kernel(const FilePath& db_path, const std::string& name,
const KernelLoadInfo& info, DirectoryChangeDelegate* delegate); const KernelLoadInfo& info, DirectoryChangeDelegate* delegate,
const browser_sync::WeakHandle<TransactionObserver>&
transaction_observer);
~Kernel(); ~Kernel();
...@@ -1125,11 +1133,11 @@ class Directory { ...@@ -1125,11 +1133,11 @@ class Directory {
// The next metahandle is protected by kernel mutex. // The next metahandle is protected by kernel mutex.
int64 next_metahandle; int64 next_metahandle;
// The delegate for directory change events. Can be NULL. // The delegate for directory change events. Must not be NULL.
DirectoryChangeDelegate* const delegate; DirectoryChangeDelegate* const delegate;
// The transaction observers. // The transaction observer.
scoped_refptr<ObserverListThreadSafe<TransactionObserver> > observers; const browser_sync::WeakHandle<TransactionObserver> transaction_observer;
}; };
// Helper method used to do searches on |parent_id_child_index|. // Helper method used to do searches on |parent_id_child_index|.
......
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
#include "chrome/browser/sync/syncable/syncable_mock.h" #include "chrome/browser/sync/syncable/syncable_mock.h"
#include "base/location.h" #include "base/location.h"
#include "chrome/browser/sync/test/null_transaction_observer.h"
MockDirectory::MockDirectory() { MockDirectory::MockDirectory() {
InitKernel("myk", &delegate_); InitKernelForTest("myk", &delegate_, syncable::NullTransactionObserver());
} }
MockDirectory::~MockDirectory() {} MockDirectory::~MockDirectory() {}
......
...@@ -4,28 +4,15 @@ ...@@ -4,28 +4,15 @@
#include "chrome/browser/sync/syncable/syncable.h" #include "chrome/browser/sync/syncable/syncable.h"
#include "build/build_config.h"
#include <sys/types.h>
#include <limits>
#include <string> #include <string>
#if !defined(OS_WIN)
#define MAX_PATH PATH_MAX
#include <ostream>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/times.h>
#endif // !defined(OS_WIN)
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/file_path.h" #include "base/file_path.h"
#include "base/file_util.h" #include "base/file_util.h"
#include "base/location.h" #include "base/location.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/scoped_temp_dir.h" #include "base/scoped_temp_dir.h"
#include "base/stringprintf.h" #include "base/stringprintf.h"
#include "base/synchronization/condition_variable.h" #include "base/synchronization/condition_variable.h"
...@@ -39,6 +26,7 @@ ...@@ -39,6 +26,7 @@
#include "chrome/browser/sync/test/engine/test_id_factory.h" #include "chrome/browser/sync/test/engine/test_id_factory.h"
#include "chrome/browser/sync/test/engine/test_syncable_utils.h" #include "chrome/browser/sync/test/engine/test_syncable_utils.h"
#include "chrome/browser/sync/test/null_directory_change_delegate.h" #include "chrome/browser/sync/test/null_directory_change_delegate.h"
#include "chrome/browser/sync/test/null_transaction_observer.h"
#include "chrome/test/base/values_test_util.h" #include "chrome/test/base/values_test_util.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/sqlite/sqlite3.h" #include "third_party/sqlite/sqlite3.h"
...@@ -103,6 +91,7 @@ class SyncableGeneralTest : public testing::Test { ...@@ -103,6 +91,7 @@ class SyncableGeneralTest : public testing::Test {
virtual void TearDown() { virtual void TearDown() {
} }
protected: protected:
MessageLoop message_loop_;
ScopedTempDir temp_dir_; ScopedTempDir temp_dir_;
NullDirectoryChangeDelegate delegate_; NullDirectoryChangeDelegate delegate_;
FilePath db_path_; FilePath db_path_;
...@@ -110,7 +99,7 @@ class SyncableGeneralTest : public testing::Test { ...@@ -110,7 +99,7 @@ class SyncableGeneralTest : public testing::Test {
TEST_F(SyncableGeneralTest, General) { TEST_F(SyncableGeneralTest, General) {
Directory dir; Directory dir;
dir.Open(db_path_, "SimpleTest", &delegate_); dir.Open(db_path_, "SimpleTest", &delegate_, NullTransactionObserver());
int64 root_metahandle; int64 root_metahandle;
{ {
...@@ -209,7 +198,7 @@ TEST_F(SyncableGeneralTest, General) { ...@@ -209,7 +198,7 @@ TEST_F(SyncableGeneralTest, General) {
TEST_F(SyncableGeneralTest, ChildrenOps) { TEST_F(SyncableGeneralTest, ChildrenOps) {
Directory dir; Directory dir;
dir.Open(db_path_, "SimpleTest", &delegate_); dir.Open(db_path_, "SimpleTest", &delegate_, NullTransactionObserver());
int64 root_metahandle; int64 root_metahandle;
{ {
...@@ -289,7 +278,7 @@ TEST_F(SyncableGeneralTest, ClientIndexRebuildsProperly) { ...@@ -289,7 +278,7 @@ TEST_F(SyncableGeneralTest, ClientIndexRebuildsProperly) {
// Test creating a new meta entry. // Test creating a new meta entry.
{ {
Directory dir; Directory dir;
dir.Open(db_path_, "IndexTest", &delegate_); dir.Open(db_path_, "IndexTest", &delegate_, NullTransactionObserver());
{ {
WriteTransaction wtrans(FROM_HERE, UNITTEST, &dir); WriteTransaction wtrans(FROM_HERE, UNITTEST, &dir);
MutableEntry me(&wtrans, CREATE, wtrans.root_id(), name); MutableEntry me(&wtrans, CREATE, wtrans.root_id(), name);
...@@ -305,7 +294,7 @@ TEST_F(SyncableGeneralTest, ClientIndexRebuildsProperly) { ...@@ -305,7 +294,7 @@ TEST_F(SyncableGeneralTest, ClientIndexRebuildsProperly) {
// The DB was closed. Now reopen it. This will cause index regeneration. // The DB was closed. Now reopen it. This will cause index regeneration.
{ {
Directory dir; Directory dir;
dir.Open(db_path_, "IndexTest", &delegate_); dir.Open(db_path_, "IndexTest", &delegate_, NullTransactionObserver());
ReadTransaction trans(FROM_HERE, &dir); ReadTransaction trans(FROM_HERE, &dir);
Entry me(&trans, GET_BY_CLIENT_TAG, tag); Entry me(&trans, GET_BY_CLIENT_TAG, tag);
...@@ -325,7 +314,7 @@ TEST_F(SyncableGeneralTest, ClientIndexRebuildsDeletedProperly) { ...@@ -325,7 +314,7 @@ TEST_F(SyncableGeneralTest, ClientIndexRebuildsDeletedProperly) {
// Test creating a deleted, unsynced, server meta entry. // Test creating a deleted, unsynced, server meta entry.
{ {
Directory dir; Directory dir;
dir.Open(db_path_, "IndexTest", &delegate_); dir.Open(db_path_, "IndexTest", &delegate_, NullTransactionObserver());
{ {
WriteTransaction wtrans(FROM_HERE, UNITTEST, &dir); WriteTransaction wtrans(FROM_HERE, UNITTEST, &dir);
MutableEntry me(&wtrans, CREATE, wtrans.root_id(), "deleted"); MutableEntry me(&wtrans, CREATE, wtrans.root_id(), "deleted");
...@@ -343,7 +332,7 @@ TEST_F(SyncableGeneralTest, ClientIndexRebuildsDeletedProperly) { ...@@ -343,7 +332,7 @@ TEST_F(SyncableGeneralTest, ClientIndexRebuildsDeletedProperly) {
// Should still be present and valid in the client tag index. // Should still be present and valid in the client tag index.
{ {
Directory dir; Directory dir;
dir.Open(db_path_, "IndexTest", &delegate_); dir.Open(db_path_, "IndexTest", &delegate_, NullTransactionObserver());
ReadTransaction trans(FROM_HERE, &dir); ReadTransaction trans(FROM_HERE, &dir);
Entry me(&trans, GET_BY_CLIENT_TAG, tag); Entry me(&trans, GET_BY_CLIENT_TAG, tag);
...@@ -357,7 +346,7 @@ TEST_F(SyncableGeneralTest, ClientIndexRebuildsDeletedProperly) { ...@@ -357,7 +346,7 @@ TEST_F(SyncableGeneralTest, ClientIndexRebuildsDeletedProperly) {
TEST_F(SyncableGeneralTest, ToValue) { TEST_F(SyncableGeneralTest, ToValue) {
Directory dir; Directory dir;
dir.Open(db_path_, "SimpleTest", &delegate_); dir.Open(db_path_, "SimpleTest", &delegate_, NullTransactionObserver());
const Id id = TestIdFactory::FromNumber(99); const Id id = TestIdFactory::FromNumber(99);
{ {
...@@ -412,6 +401,7 @@ class TestUnsaveableDirectory : public Directory { ...@@ -412,6 +401,7 @@ class TestUnsaveableDirectory : public Directory {
// Test suite for syncable::Directory. // Test suite for syncable::Directory.
class SyncableDirectoryTest : public testing::Test { class SyncableDirectoryTest : public testing::Test {
protected: protected:
MessageLoop message_loop_;
ScopedTempDir temp_dir_; ScopedTempDir temp_dir_;
static const char kName[]; static const char kName[];
static const Id kId; static const Id kId;
...@@ -425,7 +415,8 @@ class SyncableDirectoryTest : public testing::Test { ...@@ -425,7 +415,8 @@ class SyncableDirectoryTest : public testing::Test {
file_util::Delete(file_path_, true); file_util::Delete(file_path_, true);
dir_.reset(new Directory()); dir_.reset(new Directory());
ASSERT_TRUE(dir_.get()); ASSERT_TRUE(dir_.get());
ASSERT_TRUE(OPENED == dir_->Open(file_path_, kName, &delegate_)); ASSERT_EQ(OPENED, dir_->Open(file_path_, kName,
&delegate_, NullTransactionObserver()));
ASSERT_TRUE(dir_->good()); ASSERT_TRUE(dir_->good());
} }
...@@ -439,7 +430,8 @@ class SyncableDirectoryTest : public testing::Test { ...@@ -439,7 +430,8 @@ class SyncableDirectoryTest : public testing::Test {
void ReloadDir() { void ReloadDir() {
dir_.reset(new Directory()); dir_.reset(new Directory());
ASSERT_TRUE(dir_.get()); ASSERT_TRUE(dir_.get());
ASSERT_TRUE(OPENED == dir_->Open(file_path_, kName, &delegate_)); ASSERT_EQ(OPENED, dir_->Open(file_path_, kName,
&delegate_, NullTransactionObserver()));
} }
void SaveAndReloadDir() { void SaveAndReloadDir() {
...@@ -1202,7 +1194,8 @@ TEST_F(SyncableDirectoryTest, TestSimpleFieldsPreservedDuringSaveChanges) { ...@@ -1202,7 +1194,8 @@ TEST_F(SyncableDirectoryTest, TestSimpleFieldsPreservedDuringSaveChanges) {
dir_->SaveChanges(); dir_->SaveChanges();
dir_.reset(new Directory()); dir_.reset(new Directory());
ASSERT_TRUE(dir_.get()); ASSERT_TRUE(dir_.get());
ASSERT_TRUE(OPENED == dir_->Open(file_path_, kName, &delegate_)); ASSERT_EQ(OPENED, dir_->Open(file_path_, kName,
&delegate_, NullTransactionObserver()));
ASSERT_TRUE(dir_->good()); ASSERT_TRUE(dir_->good());
{ {
...@@ -1301,7 +1294,8 @@ TEST_F(SyncableDirectoryTest, TestSaveChangesFailure) { ...@@ -1301,7 +1294,8 @@ TEST_F(SyncableDirectoryTest, TestSaveChangesFailure) {
// always fail. // always fail.
dir_.reset(new TestUnsaveableDirectory()); dir_.reset(new TestUnsaveableDirectory());
ASSERT_TRUE(dir_.get()); ASSERT_TRUE(dir_.get());
ASSERT_TRUE(OPENED == dir_->Open(file_path_, kName, &delegate_)); ASSERT_EQ(OPENED, dir_->Open(file_path_, kName,
&delegate_, NullTransactionObserver()));
ASSERT_TRUE(dir_->good()); ASSERT_TRUE(dir_->good());
int64 handle2 = 0; int64 handle2 = 0;
{ {
...@@ -1374,7 +1368,8 @@ TEST_F(SyncableDirectoryTest, TestSaveChangesFailureWithPurge) { ...@@ -1374,7 +1368,8 @@ TEST_F(SyncableDirectoryTest, TestSaveChangesFailureWithPurge) {
// always fail. // always fail.
dir_.reset(new TestUnsaveableDirectory()); dir_.reset(new TestUnsaveableDirectory());
ASSERT_TRUE(dir_.get()); ASSERT_TRUE(dir_.get());
ASSERT_TRUE(OPENED == dir_->Open(file_path_, kName, &delegate_)); ASSERT_EQ(OPENED, dir_->Open(file_path_, kName,
&delegate_, NullTransactionObserver()));
ASSERT_TRUE(dir_->good()); ASSERT_TRUE(dir_->good());
ModelTypeSet set; ModelTypeSet set;
...@@ -1496,13 +1491,14 @@ class SyncableDirectoryManager : public testing::Test { ...@@ -1496,13 +1491,14 @@ class SyncableDirectoryManager : public testing::Test {
virtual void TearDown() { virtual void TearDown() {
} }
protected: protected:
MessageLoop message_loop_;
ScopedTempDir temp_dir_; ScopedTempDir temp_dir_;
NullDirectoryChangeDelegate delegate_; NullDirectoryChangeDelegate delegate_;
}; };
TEST_F(SyncableDirectoryManager, TestFileRelease) { TEST_F(SyncableDirectoryManager, TestFileRelease) {
DirectoryManager dm(FilePath(temp_dir_.path())); DirectoryManager dm(FilePath(temp_dir_.path()));
ASSERT_TRUE(dm.Open("ScopeTest", &delegate_)); ASSERT_TRUE(dm.Open("ScopeTest", &delegate_, NullTransactionObserver()));
{ {
ScopedDirLookup(&dm, "ScopeTest"); ScopedDirLookup(&dm, "ScopeTest");
} }
...@@ -1520,7 +1516,8 @@ class ThreadOpenTestDelegate : public base::PlatformThread::Delegate { ...@@ -1520,7 +1516,8 @@ class ThreadOpenTestDelegate : public base::PlatformThread::Delegate {
private: private:
// PlatformThread::Delegate methods: // PlatformThread::Delegate methods:
virtual void ThreadMain() { virtual void ThreadMain() {
CHECK(directory_manager_->Open("Open", &delegate_)); CHECK(directory_manager_->Open(
"Open", &delegate_, NullTransactionObserver()));
} }
DISALLOW_COPY_AND_ASSIGN(ThreadOpenTestDelegate); DISALLOW_COPY_AND_ASSIGN(ThreadOpenTestDelegate);
...@@ -1564,6 +1561,7 @@ class ThreadBugDelegate : public base::PlatformThread::Delegate { ...@@ -1564,6 +1561,7 @@ class ThreadBugDelegate : public base::PlatformThread::Delegate {
// PlatformThread::Delegate methods: // PlatformThread::Delegate methods:
virtual void ThreadMain() { virtual void ThreadMain() {
MessageLoop message_loop;
const std::string dirname = "ThreadBug1"; const std::string dirname = "ThreadBug1";
base::AutoLock scoped_lock(step_->mutex); base::AutoLock scoped_lock(step_->mutex);
...@@ -1573,12 +1571,14 @@ class ThreadBugDelegate : public base::PlatformThread::Delegate { ...@@ -1573,12 +1571,14 @@ class ThreadBugDelegate : public base::PlatformThread::Delegate {
} }
switch (step_->number) { switch (step_->number) {
case 0: case 0:
directory_manager_->Open(dirname, &delegate_); directory_manager_->Open(
dirname, &delegate_, NullTransactionObserver());
break; break;
case 1: case 1:
{ {
directory_manager_->Close(dirname); directory_manager_->Close(dirname);
directory_manager_->Open(dirname, &delegate_); directory_manager_->Open(
dirname, &delegate_, NullTransactionObserver());
ScopedDirLookup dir(directory_manager_, dirname); ScopedDirLookup dir(directory_manager_, dirname);
CHECK(dir.good()); CHECK(dir.good());
WriteTransaction trans(FROM_HERE, UNITTEST, dir); WriteTransaction trans(FROM_HERE, UNITTEST, dir);
...@@ -1636,6 +1636,7 @@ class DirectoryKernelStalenessBugDelegate : public ThreadBugDelegate { ...@@ -1636,6 +1636,7 @@ class DirectoryKernelStalenessBugDelegate : public ThreadBugDelegate {
: ThreadBugDelegate(role, step, dirman) {} : ThreadBugDelegate(role, step, dirman) {}
virtual void ThreadMain() { virtual void ThreadMain() {
MessageLoop message_loop;
const char test_bytes[] = "test data"; const char test_bytes[] = "test data";
const std::string dirname = "DirectoryKernelStalenessBug"; const std::string dirname = "DirectoryKernelStalenessBug";
base::AutoLock scoped_lock(step_->mutex); base::AutoLock scoped_lock(step_->mutex);
...@@ -1652,7 +1653,8 @@ class DirectoryKernelStalenessBugDelegate : public ThreadBugDelegate { ...@@ -1652,7 +1653,8 @@ class DirectoryKernelStalenessBugDelegate : public ThreadBugDelegate {
file_util::Delete(directory_manager_->GetSyncDataDatabasePath(), file_util::Delete(directory_manager_->GetSyncDataDatabasePath(),
true); true);
// Test. // Test.
directory_manager_->Open(dirname, &delegate_); directory_manager_->Open(
dirname, &delegate_, NullTransactionObserver());
ScopedDirLookup dir(directory_manager_, dirname); ScopedDirLookup dir(directory_manager_, dirname);
CHECK(dir.good()); CHECK(dir.good());
WriteTransaction trans(FROM_HERE, UNITTEST, dir); WriteTransaction trans(FROM_HERE, UNITTEST, dir);
...@@ -1671,7 +1673,8 @@ class DirectoryKernelStalenessBugDelegate : public ThreadBugDelegate { ...@@ -1671,7 +1673,8 @@ class DirectoryKernelStalenessBugDelegate : public ThreadBugDelegate {
break; break;
case 1: case 1:
{ {
directory_manager_->Open(dirname, &delegate_); directory_manager_->Open(
dirname, &delegate_, NullTransactionObserver());
ScopedDirLookup dir(directory_manager_, dirname); ScopedDirLookup dir(directory_manager_, dirname);
CHECK(dir.good()); CHECK(dir.good());
} }
...@@ -1770,13 +1773,14 @@ class StressTransactionsDelegate : public base::PlatformThread::Delegate { ...@@ -1770,13 +1773,14 @@ class StressTransactionsDelegate : public base::PlatformThread::Delegate {
}; };
TEST(SyncableDirectory, StressTransactions) { TEST(SyncableDirectory, StressTransactions) {
MessageLoop message_loop;
ScopedTempDir temp_dir; ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
DirectoryManager dirman(FilePath(temp_dir.path())); DirectoryManager dirman(FilePath(temp_dir.path()));
std::string dirname = "stress"; std::string dirname = "stress";
file_util::Delete(dirman.GetSyncDataDatabasePath(), true); file_util::Delete(dirman.GetSyncDataDatabasePath(), true);
NullDirectoryChangeDelegate delegate; NullDirectoryChangeDelegate delegate;
dirman.Open(dirname, &delegate); dirman.Open(dirname, &delegate, NullTransactionObserver());
const int kThreadCount = 7; const int kThreadCount = 7;
base::PlatformThreadHandle threads[kThreadCount]; base::PlatformThreadHandle threads[kThreadCount];
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <vector> #include <vector>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "chrome/browser/sync/engine/model_safe_worker.h" #include "chrome/browser/sync/engine/model_safe_worker.h"
#include "chrome/browser/sync/sessions/debug_info_getter.h" #include "chrome/browser/sync/sessions/debug_info_getter.h"
#include "chrome/browser/sync/sessions/sync_session.h" #include "chrome/browser/sync/sessions/sync_session.h"
...@@ -157,6 +158,7 @@ class SyncerCommandTestWithParam : public testing::TestWithParam<T>, ...@@ -157,6 +158,7 @@ class SyncerCommandTestWithParam : public testing::TestWithParam<T>,
} }
private: private:
MessageLoop message_loop_;
scoped_ptr<TestDirectorySetterUpper> syncdb_; scoped_ptr<TestDirectorySetterUpper> syncdb_;
scoped_ptr<sessions::SyncSessionContext> context_; scoped_ptr<sessions::SyncSessionContext> context_;
scoped_ptr<MockConnectionManager> mock_server_; scoped_ptr<MockConnectionManager> mock_server_;
......
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
#include "base/string_util.h" #include "base/string_util.h"
#include "chrome/browser/sync/syncable/directory_manager.h" #include "chrome/browser/sync/syncable/directory_manager.h"
#include "chrome/browser/sync/syncable/syncable.h" #include "chrome/browser/sync/syncable/syncable.h"
#include "chrome/browser/sync/test/null_transaction_observer.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using syncable::DirectoryManager; using syncable::DirectoryManager;
using syncable::NullTransactionObserver;
using syncable::ReadTransaction; using syncable::ReadTransaction;
using syncable::ScopedDirLookup; using syncable::ScopedDirLookup;
...@@ -38,7 +40,7 @@ void TestDirectorySetterUpper::reset_directory_manager(DirectoryManager* d) { ...@@ -38,7 +40,7 @@ void TestDirectorySetterUpper::reset_directory_manager(DirectoryManager* d) {
void TestDirectorySetterUpper::SetUp() { void TestDirectorySetterUpper::SetUp() {
Init(); Init();
ASSERT_TRUE(manager()->Open(name(), &delegate_)); ASSERT_TRUE(manager()->Open(name(), &delegate_, NullTransactionObserver()));
} }
void TestDirectorySetterUpper::TearDown() { void TestDirectorySetterUpper::TearDown() {
...@@ -80,7 +82,8 @@ void ManuallyOpenedTestDirectorySetterUpper::SetUp() { ...@@ -80,7 +82,8 @@ void ManuallyOpenedTestDirectorySetterUpper::SetUp() {
} }
void ManuallyOpenedTestDirectorySetterUpper::Open() { void ManuallyOpenedTestDirectorySetterUpper::Open() {
ASSERT_TRUE(manager()->Open(name(), &delegate_)); ASSERT_TRUE(
manager()->Open(name(), &delegate_, NullTransactionObserver()));
was_opened_ = true; was_opened_ = true;
} }
...@@ -111,7 +114,7 @@ void TriggeredOpenTestDirectorySetterUpper::TearDown() { ...@@ -111,7 +114,7 @@ void TriggeredOpenTestDirectorySetterUpper::TearDown() {
MockDirectorySetterUpper::MockDirectory::MockDirectory( MockDirectorySetterUpper::MockDirectory::MockDirectory(
const std::string& name) { const std::string& name) {
InitKernel(name, &delegate_); InitKernelForTest(name, &delegate_, NullTransactionObserver());
} }
MockDirectorySetterUpper::MockDirectory::~MockDirectory() {} MockDirectorySetterUpper::MockDirectory::~MockDirectory() {}
......
// Copyright (c) 2011 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/sync/test/null_transaction_observer.h"
#include "base/memory/weak_ptr.h"
namespace syncable {
browser_sync::WeakHandle<TransactionObserver> NullTransactionObserver() {
return browser_sync::MakeWeakHandle(base::WeakPtr<TransactionObserver>());
}
} // namespace syncable
// Copyright (c) 2011 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_SYNC_TEST_NULL_TRANSACTION_OBSERVER_H_
#define CHROME_BROWSER_SYNC_TEST_NULL_TRANSACTION_OBSERVER_H_
#pragma once
#include "chrome/browser/sync/util/weak_handle.h"
namespace syncable {
class TransactionObserver;
// Returns an initialized weak handle to a transaction observer that
// does nothing.
browser_sync::WeakHandle<TransactionObserver> NullTransactionObserver();
} // namespace syncable
#endif // CHROME_BROWSER_SYNC_TEST_NULL_TRANSACTION_OBSERVER_H_
...@@ -356,6 +356,8 @@ ...@@ -356,6 +356,8 @@
'browser/sync/js/js_test_util.h', 'browser/sync/js/js_test_util.h',
'browser/sync/test/null_directory_change_delegate.cc', 'browser/sync/test/null_directory_change_delegate.cc',
'browser/sync/test/null_directory_change_delegate.h', 'browser/sync/test/null_directory_change_delegate.h',
'browser/sync/test/null_transaction_observer.cc',
'browser/sync/test/null_transaction_observer.h',
'browser/sync/test/engine/test_directory_setter_upper.cc', 'browser/sync/test/engine/test_directory_setter_upper.cc',
'browser/sync/test/engine/test_directory_setter_upper.h', 'browser/sync/test/engine/test_directory_setter_upper.h',
], ],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment