Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(362)

Unified Diff: chrome/browser/sync/glue/sync_backend_host.cc

Issue 160598: Add files to browser/sync. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/sync/glue/sync_backend_host.h ('k') | chrome/browser/sync/personalization.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/sync/glue/sync_backend_host.cc
===================================================================
--- chrome/browser/sync/glue/sync_backend_host.cc (revision 0)
+++ chrome/browser/sync/glue/sync_backend_host.cc (revision 0)
@@ -0,0 +1,308 @@
+// 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
+
+#include "base/file_version_info.h"
+#include "base/file_util.h"
+#include "base/string_util.h"
+#include "chrome/browser/sync/glue/sync_backend_host.h"
+#include "chrome/browser/sync/glue/http_bridge.h"
+#include "chrome/browser/sync/glue/bookmark_model_worker.h"
+#include "webkit/glue/webkit_glue.h"
+
+static const char kSwitchSyncServiceURL[] = "sync-url";
+static const char kSwitchSyncServicePort[] = "sync-port";
+static const int kSaveChangesIntervalSeconds = 10;
+static const char kGaiaServiceId[] = "chromiumsync";
+static const char kGaiaSourceForChrome[] = "ChromiumBrowser";
+static const FilePath::CharType kSyncDataFolderName[] =
+ FILE_PATH_LITERAL("Sync Data");
+
+namespace browser_sync {
+
+SyncBackendHost::SyncBackendHost(SyncFrontend* frontend,
+ const FilePath& profile_path)
+ : core_thread_("Chrome_SyncCoreThread"),
+ frontend_loop_(MessageLoop::current()),
+ bookmark_model_worker_(NULL),
+ frontend_(frontend),
+ sync_data_folder_path_(profile_path.Append(kSyncDataFolderName)),
+ last_auth_error_(AUTH_ERROR_NONE) {
+ core_ = new Core(this);
+}
+
+SyncBackendHost::~SyncBackendHost() {
+ DCHECK(!core_ && !frontend_) << "Must call Shutdown before destructor.";
+}
+
+void SyncBackendHost::Initialize(const GURL& sync_service_url) {
+ if (!core_thread_.Start())
+ return;
+
+ bookmark_model_worker_ = new BookmarkModelWorker(frontend_loop_);
+ core_thread_.message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoInitialize,
+ sync_service_url, bookmark_model_worker_, true));
+}
+
+void SyncBackendHost::Authenticate(const std::string& username,
+ const std::string& password) {
+ core_thread_.message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoAuthenticate,
+ username, password));
+}
+
+void SyncBackendHost::Shutdown(bool sync_disabled) {
+ // Thread shutdown should occur in the following order:
+ // - SyncerThread
+ // - CoreThread
+ // - UI Thread (stops some time after we return from this call).
+ core_thread_.message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(core_.get(),
+ &SyncBackendHost::Core::DoShutdown,
+ sync_disabled));
+
+ // Before joining the core_thread_, we wait for the BookmarkModelWorker to
+ // give us the green light that it is not depending on the frontend_loop_ to
+ // process any more tasks. Stop() blocks until this termination condition
+ // is true.
+ bookmark_model_worker_->Stop();
+
+ // Stop will return once the thread exits, which will be after DoShutdown
+ // runs. DoShutdown needs to run from core_thread_ because the sync backend
+ // requires any thread that opened sqlite handles to relinquish them
+ // personally. We need to join threads, because otherwise the main Chrome
+ // thread (ui loop) can exit before DoShutdown finishes, at which point
+ // virtually anything the sync backend does (or the post-back to
+ // frontend_loop_ by our Core) will epically fail because the CRT won't be
+ // initialized. For now this only ever happens at sync-enabled-Chrome exit,
+ // meaning bug 1482548 applies to prolonged "waiting" that may occur in
+ // DoShutdown.
+ core_thread_.Stop();
+
+ bookmark_model_worker_ = NULL;
+ frontend_ = NULL;
+ core_ = NULL; // Releases reference to core_.
+}
+
+void SyncBackendHost::Core::NotifyFrontend(FrontendNotification notification) {
+ if (!host_ || !host_->frontend_) {
+ return; // This can happen in testing because the UI loop processes tasks
+ // after an instance of SyncBackendHost was destroyed. In real
+ // life this doesn't happen.
+ }
+ switch (notification) {
+ case INITIALIZED:
+ host_->frontend_->OnBackendInitialized();
+ return;
+ case SYNC_CYCLE_COMPLETED:
+ host_->frontend_->OnSyncCycleCompleted();
+ return;
+ }
+}
+
+SyncBackendHost::UserShareHandle SyncBackendHost::GetUserShareHandle() const {
+ return core_->syncapi()->GetUserShare();
+}
+
+SyncBackendHost::Status SyncBackendHost::GetDetailedStatus() {
+ return core_->syncapi()->GetDetailedStatus();
+}
+
+SyncBackendHost::StatusSummary SyncBackendHost::GetStatusSummary() {
+ return core_->syncapi()->GetStatusSummary();
+}
+
+string16 SyncBackendHost::GetAuthenticatedUsername() const {
+ return UTF8ToUTF16(core_->syncapi()->GetAuthenticatedUsername());
+}
+
+AuthErrorState SyncBackendHost::GetAuthErrorState() const {
+ return last_auth_error_;
+}
+
+SyncBackendHost::Core::Core(SyncBackendHost* backend)
+ : host_(backend),
+ syncapi_(new sync_api::SyncManager()) {
+}
+
+// Helper to construct a user agent string (ASCII) suitable for use by
+// the syncapi for any HTTP communication. This string is used by the sync
+// backend for classifying client types when calculating statistics.
+std::string MakeUserAgentForSyncapi() {
+ std::string user_agent;
+ user_agent = "Chrome ";
+#if defined(OS_WIN)
+ user_agent += "WIN ";
+#elif defined(OS_LINUX)
+ user_agent += "LINUX ";
+#elif defined(OS_MACOSX)
+ user_agent += "MAC ";
+#endif
+ scoped_ptr<FileVersionInfo> version_info(
+ FileVersionInfo::CreateFileVersionInfoForCurrentModule());
+ if (version_info == NULL) {
+ DLOG(ERROR) << "Unable to create FileVersionInfo object";
+ return user_agent;
+ }
+
+ user_agent += WideToASCII(version_info->product_version());
+ user_agent += " (" + WideToASCII(version_info->last_change()) + ")";
+ if (!version_info->is_official_build())
+ user_agent += "-devel";
+ return user_agent;
+}
+
+void SyncBackendHost::Core::DoInitialize(
+ const GURL& service_url,
+ BookmarkModelWorker* bookmark_model_worker,
+ bool attempt_last_user_authentication) {
+ DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
+
+ // Make sure that the directory exists before initializing the backend.
+ // If it already exists, this will do no harm.
+ bool success = file_util::CreateDirectory(host_->sync_data_folder_path());
+ DCHECK(success);
+
+ syncapi_->SetObserver(this);
+ string16 path_str;
+#if defined (OS_WIN)
+ path_str = host_->sync_data_folder_path().value();
+#elif (defined(OS_LINUX) || defined(OS_MACOSX))
+ path_str = UTF8ToUTF16(sync_data_folder_path().value());
+#endif
+ success = syncapi_->Init(path_str.c_str(),
+ (service_url.host() + service_url.path()).c_str(),
+ service_url.EffectiveIntPort(),
+ kGaiaServiceId,
+ kGaiaSourceForChrome,
+ service_url.SchemeIsSecure(),
+ new HttpBridgeFactory(),
+ new HttpBridgeFactory(),
+ bookmark_model_worker,
+ attempt_last_user_authentication,
+ MakeUserAgentForSyncapi().c_str());
+ DCHECK(success) << "Syncapi initialization failed!";
+}
+
+void SyncBackendHost::Core::DoAuthenticate(const std::string& username,
+ const std::string& password) {
+ DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
+ syncapi_->Authenticate(username.c_str(), password.c_str());
+}
+
+void SyncBackendHost::Core::DoShutdown(bool sync_disabled) {
+ DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
+
+ save_changes_timer_.Stop();
+ syncapi_->Shutdown(); // Stops the SyncerThread.
+ syncapi_->RemoveObserver();
+ host_->bookmark_model_worker_->OnSyncerShutdownComplete();
+
+ if (sync_disabled &&
+ file_util::DirectoryExists(host_->sync_data_folder_path())) {
+ // Delete the sync data folder to cleanup backend data.
+ bool success = file_util::Delete(host_->sync_data_folder_path(), true);
+ DCHECK(success);
+ }
+
+ host_ = NULL;
+}
+
+static AuthErrorState AuthProblemToAuthError(
+ const sync_api::SyncManager::AuthProblem& auth_problem) {
+ switch (auth_problem) {
+ case sync_api::SyncManager::AUTH_PROBLEM_NONE:
+ return AUTH_ERROR_NONE;
+ case sync_api::SyncManager::AUTH_PROBLEM_INVALID_GAIA_CREDENTIALS:
+ return AUTH_ERROR_INVALID_GAIA_CREDENTIALS;
+ case sync_api::SyncManager::AUTH_PROBLEM_CONNECTION_FAILED:
+ return AUTH_ERROR_CONNECTION_FAILED;
+ case sync_api::SyncManager::AUTH_PROBLEM_USER_NOT_SIGNED_UP:
+ return AUTH_ERROR_USER_NOT_SIGNED_UP;
+ }
+
+ NOTREACHED() << "Unknown AuthProblem.";
+ return AUTH_ERROR_NONE;
+}
+
+void SyncBackendHost::Core::OnChangesApplied(
+ const sync_api::BaseTransaction* trans,
+ const sync_api::SyncManager::ChangeRecord* changes,
+ int change_count) {
+ if (!host_ || !host_->frontend_) {
+ DCHECK(false) << "OnChangesApplied called after Shutdown?";
+ return;
+ }
+
+ // ChangesApplied is the one exception that should come over from the sync
+ // backend already on the service_loop_ thanks to our BookmarkModelWorker.
+ // SyncFrontend changes exclusively on the UI loop, because it updates
+ // the bookmark model. As such, we don't need to worry about changes that
+ // have been made to the bookmark model but not yet applied to the sync
+ // model -- such changes only happen on the UI loop, and there's no
+ // contention.
+ if (host_->frontend_loop_ != MessageLoop::current()) {
+ // TODO(ncarter): Bug 1480644. Make this a DCHECK once syncapi filters
+ // out all irrelevant changes.
+ DLOG(WARNING) << "Could not update bookmark model from non-UI thread";
+ return;
+ }
+ host_->frontend_->ApplyModelChanges(trans, changes, change_count);
+}
+
+void SyncBackendHost::Core::OnSyncCycleCompleted() {
+ host_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &Core::NotifyFrontend, SYNC_CYCLE_COMPLETED));
+}
+
+void SyncBackendHost::Core::OnInitializationComplete() {
+ if (!host_ || !host_->frontend_)
+ return; // We may have been told to Shutdown before initialization
+ // completed.
+
+ // We could be on some random sync backend thread, so MessageLoop::current()
+ // can definitely be null in here.
+ host_->frontend_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &Core::NotifyFrontend, INITIALIZED));
+
+ // Initialization is complete, so we can schedule recurring SaveChanges.
+ host_->core_thread_.message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &Core::StartSavingChanges));
+}
+
+void SyncBackendHost::Core::OnAuthProblem(
+ sync_api::SyncManager::AuthProblem auth_problem) {
+ // We could be on SyncEngine_AuthWatcherThread. Post to our core loop so
+ // we can modify state.
+ host_->frontend_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &Core::HandleAuthErrorEventOnFrontendLoop,
+ AuthProblemToAuthError(auth_problem)));
+}
+
+void SyncBackendHost::Core::HandleAuthErrorEventOnFrontendLoop(
+ AuthErrorState new_auth_error) {
+ if (!host_ || !host_->frontend_)
+ return;
+
+ DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
+
+ host_->last_auth_error_ = new_auth_error;
+ host_->frontend_->OnAuthError();
+}
+
+void SyncBackendHost::Core::StartSavingChanges() {
+ save_changes_timer_.Start(
+ base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
+ this, &Core::SaveChanges);
+}
+
+void SyncBackendHost::Core::SaveChanges() {
+ syncapi_->SaveChanges();
+}
+
+} // namespace browser_sync
+
+#endif
Property changes on: chrome\browser\sync\glue\sync_backend_host.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « chrome/browser/sync/glue/sync_backend_host.h ('k') | chrome/browser/sync/personalization.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698