Index: chrome/browser/sync/glue/sync_backend_host.h |
=================================================================== |
--- chrome/browser/sync/glue/sync_backend_host.h (revision 0) |
+++ chrome/browser/sync/glue/sync_backend_host.h (revision 0) |
@@ -0,0 +1,274 @@ |
+// Copyright (c) 2006-2008 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. |
+ |
+#ifdef CHROME_PERSONALIZATION |
+ |
+#ifndef CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_ |
+#define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_ |
+ |
+#include <string> |
+ |
+#include "base/file_path.h" |
+#include "base/lock.h" |
+#include "base/message_loop.h" |
+#include "base/ref_counted.h" |
+#include "base/thread.h" |
+#include "base/timer.h" |
+#include "chrome/browser/sync/auth_error_state.h" |
+#include "chrome/browser/sync/engine/syncapi.h" |
+#include "chrome/browser/sync/glue/bookmark_model_worker.h" |
+#include "googleurl/src/gurl.h" |
+ |
+namespace browser_sync { |
+ |
+class SyncFrontend; |
+ |
+// A UI-thread safe API into the sync backend that "hosts" the top-level |
+// syncapi element, the SyncManager, on its own thread. This class handles |
+// dispatch of potentially blocking calls to appropriate threads and ensures |
+// that the SyncFrontend is only accessed on the UI loop. |
+class SyncBackendHost { |
+ public: |
+ typedef sync_api::UserShare* UserShareHandle; |
+ typedef sync_api::SyncManager::Status::Summary StatusSummary; |
+ typedef sync_api::SyncManager::Status Status; |
+ |
+ // Create a SyncBackendHost with a reference to the |frontend| that it serves |
+ // and communicates to via the SyncFrontend interface (on the same thread |
+ // it used to call the constructor). |
+ SyncBackendHost(SyncFrontend* frontend, const FilePath& proifle_path); |
+ ~SyncBackendHost(); |
+ |
+ // Called on |frontend_loop_| to kick off asynchronous initialization. |
+ void Initialize(const GURL& service_url); |
+ |
+ // Called on |frontend_loop_| to kick off asynchronous authentication. |
+ void Authenticate(const std::string& username, const std::string& password); |
+ |
+ // Called on |frontend_loop_| to kick off shutdown. |
+ // |sync_disabled| indicates if syncing is being disabled or not. |
+ // See the implementation and Core::DoShutdown for details. |
+ void Shutdown(bool sync_disabled); |
+ |
+ // Called on |frontend_loop_| to obtain a handle to the UserShare needed |
+ // for creating transactions. |
+ UserShareHandle GetUserShareHandle() const; |
+ |
+ // Called from any thread to obtain current status information in detailed or |
+ // summarized form. |
+ Status GetDetailedStatus(); |
+ StatusSummary GetStatusSummary(); |
+ AuthErrorState GetAuthErrorState() const; |
+ |
+ const FilePath& sync_data_folder_path() const { |
+ return sync_data_folder_path_; |
+ } |
+ |
+ // Returns the authenticated username of the sync user, or empty if none |
+ // exists. It will only exist if the authentication service provider (e.g |
+ // GAIA) has confirmed the username is authentic. |
+ string16 GetAuthenticatedUsername() const; |
+ |
+#ifdef UNIT_TEST |
+ // Called from unit test to bypass authentication and initialize the syncapi |
+ // to a state suitable for testing but not production. |
+ void InitializeForTestMode(const std::wstring& test_user) { |
+ if (!core_thread_.Start()) |
+ return; |
+ bookmark_model_worker_ = new BookmarkModelWorker(frontend_loop_); |
+ core_thread_.message_loop()->PostTask(FROM_HERE, |
+ NewRunnableMethod(core_.get(), |
+ &SyncBackendHost::Core::DoInitializeForTest, |
+ bookmark_model_worker_, |
+ test_user)); |
+ } |
+#endif |
+ |
+ private: |
+ // The real guts of SyncBackendHost, to keep the public client API clean. |
+ class Core : public base::RefCountedThreadSafe<SyncBackendHost::Core>, |
+ public sync_api::SyncManager::Observer { |
+ public: |
+ explicit Core(SyncBackendHost* backend); |
+ |
+ // Note: This destructor should *always* be called from the thread that |
+ // created it, and *always* after core_thread_ has exited. The syncapi |
+ // watches thread exit events and keeps pointers to objects this dtor will |
+ // destroy, so this ordering is important. |
+ ~Core() { |
+ } |
+ |
+ // SyncManager::Observer implementation. The Core just acts like an air |
+ // traffic controller here, forwarding incoming messages to appropriate |
+ // landing threads. |
+ virtual void OnChangesApplied( |
+ const sync_api::BaseTransaction* trans, |
+ const sync_api::SyncManager::ChangeRecord* changes, |
+ int change_count); |
+ virtual void OnSyncCycleCompleted(); |
+ virtual void OnInitializationComplete(); |
+ virtual void OnAuthProblem( |
+ sync_api::SyncManager::AuthProblem auth_problem); |
+ |
+ // Note: |
+ // |
+ // The Do* methods are the various entry points from our SyncBackendHost. |
+ // It calls us on a dedicated thread to actually perform synchronous |
+ // (and potentially blocking) syncapi operations. |
+ // |
+ // Called on the SyncBackendHost core_thread_ to perform initialization |
+ // of the syncapi on behalf of SyncBackendHost::Initialize. |
+ void DoInitialize(const GURL& service_url, |
+ BookmarkModelWorker* bookmark_model_worker_, |
+ bool attempt_last_user_authentication); |
+ |
+ // Called on our SyncBackendHost's core_thread_ to perform authentication |
+ // on behalf of SyncBackendHost::Authenticate. |
+ void DoAuthenticate(const std::string& username, |
+ const std::string& password); |
+ |
+ // The shutdown order is a bit complicated: |
+ // 1) From |core_thread_|, invoke the syncapi Shutdown call to do a final |
+ // SaveChanges, close sqlite handles, and halt the syncer thread (which |
+ // could potentially block for 1 minute). |
+ // 2) Then, from |frontend_loop_|, halt the core_thread_. This causes |
+ // syncapi thread-exit handlers to run and make use of cached pointers to |
+ // various components owned implicitly by us. |
+ // 3) Destroy this Core. That will delete syncapi components in a safe order |
+ // because the thread that was using them has exited (in step 2). |
+ void DoShutdown(bool stopping_sync); |
+ |
+ sync_api::SyncManager* syncapi() { return syncapi_.get(); } |
+ |
+#ifdef UNIT_TEST |
+ // Special form of initialization that does not try and authenticate the |
+ // last known user (since it will fail in test mode) and does some extra |
+ // setup to nudge the syncapi into a useable state. |
+ void DoInitializeForTest(BookmarkModelWorker* bookmark_model_worker, |
+ const std::wstring& test_user) { |
+ DoInitialize(GURL(), bookmark_model_worker, false); |
+ syncapi_->SetupForTestMode(WideToUTF16(test_user).c_str()); |
+ } |
+#endif |
+ |
+ private: |
+ // FrontendNotification defines parameters for NotifyFrontend. Each enum |
+ // value corresponds to the one SyncFrontend interface method that |
+ // NotifyFrontend should invoke. |
+ enum FrontendNotification { |
+ INITIALIZED, // OnBackendInitialized. |
+ SYNC_CYCLE_COMPLETED, // A round-trip sync-cycle took place and |
+ // the syncer has resolved any conflicts |
+ // that may have arisen. |
+ }; |
+ |
+ // NotifyFrontend is how the Core communicates with the frontend across |
+ // threads. Having this extra method (rather than having the Core PostTask |
+ // to the frontend explicitly) means SyncFrontend implementations don't |
+ // need to be RefCountedThreadSafe because NotifyFrontend is invoked on the |
+ // |frontend_loop_|. |
+ void NotifyFrontend(FrontendNotification notification); |
+ |
+ // Invoked when initialization of syncapi is complete and we can start |
+ // our timer. |
+ // This must be called from the thread on which SaveChanges is intended to |
+ // be run on; the host's |core_thread_|. |
+ void StartSavingChanges(); |
+ |
+ // Invoked periodically to tell the syncapi to persist its state |
+ // by writing to disk. |
+ // This is called from the thread we were created on (which is the |
+ // SyncBackendHost |core_thread_|), using a repeating timer that is kicked |
+ // off as soon as the SyncManager tells us it completed |
+ // initialization. |
+ void SaveChanges(); |
+ |
+ // Dispatched to from HandleAuthErrorEventOnCoreLoop to handle updating |
+ // frontend UI components. |
+ void HandleAuthErrorEventOnFrontendLoop(AuthErrorState new_auth_error); |
+ |
+ // Our parent SyncBackendHost |
+ SyncBackendHost* host_; |
+ |
+ // The timer used to periodically call SaveChanges. |
+ base::RepeatingTimer<Core> save_changes_timer_; |
+ |
+ // The top-level syncapi entry point. |
+ scoped_ptr<sync_api::SyncManager> syncapi_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Core); |
+ }; |
+ |
+ // A thread we dedicate for use by our Core to perform initialization, |
+ // authentication, handle messages from the syncapi, and periodically tell |
+ // the syncapi to persist itself. |
+ base::Thread core_thread_; |
+ |
+ // Our core, which communicates directly to the syncapi. |
+ scoped_refptr<Core> core_; |
+ |
+ // A reference to the MessageLoop used to construct |this|, so we know how |
+ // to safely talk back to the SyncFrontend. |
+ MessageLoop* const frontend_loop_; |
+ |
+ // We hold on to the BookmarkModelWorker created for the syncapi to ensure |
+ // shutdown occurs in the sequence we expect by calling Stop() at the |
+ // appropriate time. It is guaranteed to be valid because the worker is |
+ // only destroyed when the SyncManager is destroyed, which happens when |
+ // our Core is destroyed, which happens in Shutdown(). |
+ BookmarkModelWorker* bookmark_model_worker_; |
+ |
+ // The frontend which we serve (and are owned by). |
+ SyncFrontend* frontend_; |
+ |
+ // Path of the folder that stores the sync data files. |
+ FilePath sync_data_folder_path_; |
+ |
+ // UI-thread cache of the last AuthErrorState received from syncapi. |
+ AuthErrorState last_auth_error_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SyncBackendHost); |
+}; |
+ |
+// SyncFrontend is the interface used by SyncBackendHost to communicate with |
+// the entity that created it and, presumably, is interested in sync-related |
+// activity. |
+// NOTE: All methods will be invoked by a SyncBackendHost on the same thread |
+// used to create that SyncBackendHost. |
+class SyncFrontend { |
+ public: |
+ typedef sync_api::BaseTransaction BaseTransaction; |
+ typedef sync_api::SyncManager::ChangeRecord ChangeRecord; |
+ SyncFrontend() { |
+ } |
+ |
+ // The backend has completed initialization and it is now ready to accept and |
+ // process changes. |
+ virtual void OnBackendInitialized() = 0; |
+ |
+ // The backend queried the server recently and received some updates. |
+ virtual void OnSyncCycleCompleted() = 0; |
+ |
+ // The backend encountered an authentication problem and requests new |
+ // credentials to be provided. See SyncBackendHost::Authenticate for details. |
+ virtual void OnAuthError() = 0; |
+ |
+ // Changes have been applied to the backend model and are ready to be |
+ // applied to the frontend model. See syncapi.h for detailed instructions on |
+ // how to interpret and process |changes|. |
+ virtual void ApplyModelChanges(const BaseTransaction* trans, |
+ const ChangeRecord* changes, |
+ int change_count) = 0; |
+ protected: |
+ // Don't delete through SyncFrontend interface. |
+ virtual ~SyncFrontend() { |
+ } |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(SyncFrontend); |
+}; |
+ |
+} // namespace browser_sync |
+ |
+#endif // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_ |
+#endif // CHROME_PERSONALIZATION |
Property changes on: chrome\browser\sync\glue\sync_backend_host.h |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |