summaryrefslogtreecommitdiffstats
path: root/ios/chrome/browser/sync
diff options
context:
space:
mode:
authorsdefresne <sdefresne@chromium.org>2015-05-20 08:26:52 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-20 15:27:00 +0000
commit5548199bedbf5452f0655aa236bebed3726ea1f2 (patch)
treece383c529af1a67e37f3bcf21612e02a6b2a5bce /ios/chrome/browser/sync
parent2d90256078aca21c9ada9ec7699662596796d65c (diff)
downloadchromium_src-5548199bedbf5452f0655aa236bebed3726ea1f2.zip
chromium_src-5548199bedbf5452f0655aa236bebed3726ea1f2.tar.gz
chromium_src-5548199bedbf5452f0655aa236bebed3726ea1f2.tar.bz2
[iOS] Upstream SyncSetupService (and mock)
SyncSetupService allows configuring sync. It handles enabling and disabling it, as well as choosing datatypes. Most actions are delayed until a commit is done, to allow the complex sync setup flow on iOS. BUG=429756 Review URL: https://codereview.chromium.org/1148573002 Cr-Commit-Position: refs/heads/master@{#330736}
Diffstat (limited to 'ios/chrome/browser/sync')
-rw-r--r--ios/chrome/browser/sync/sync_setup_service.cc196
-rw-r--r--ios/chrome/browser/sync/sync_setup_service.h111
-rw-r--r--ios/chrome/browser/sync/sync_setup_service_mock.cc14
-rw-r--r--ios/chrome/browser/sync/sync_setup_service_mock.h28
4 files changed, 349 insertions, 0 deletions
diff --git a/ios/chrome/browser/sync/sync_setup_service.cc b/ios/chrome/browser/sync/sync_setup_service.cc
new file mode 100644
index 0000000..d617324
--- /dev/null
+++ b/ios/chrome/browser/sync/sync_setup_service.cc
@@ -0,0 +1,196 @@
+// Copyright 2012 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 "ios/chrome/browser/sync/sync_setup_service.h"
+
+#include <stdio.h>
+
+#include "base/prefs/pref_service.h"
+#include "components/sync_driver/sync_prefs.h"
+#include "components/sync_driver/sync_service.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "ios/chrome/browser/pref_names.h"
+#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h"
+#include "net/base/network_change_notifier.h"
+#include "sync/protocol/sync_protocol_error.h"
+
+namespace {
+// The set of user-selectable datatypes. This must be in the same order as
+// |SyncSetupService::SyncableDatatype|.
+syncer::ModelType kDataTypes[] = {
+ syncer::BOOKMARKS,
+ syncer::TYPED_URLS,
+ syncer::PASSWORDS,
+ syncer::PROXY_TABS,
+ syncer::AUTOFILL,
+};
+} // namespace
+
+SyncSetupService::SyncSetupService(sync_driver::SyncService* sync_service,
+ PrefService* prefs)
+ : sync_service_(sync_service), prefs_(prefs) {
+ DCHECK(sync_service_);
+ DCHECK(prefs_);
+ for (unsigned int i = 0; i < arraysize(kDataTypes); ++i) {
+ user_selectable_types_.Put(kDataTypes[i]);
+ }
+}
+
+SyncSetupService::~SyncSetupService() {
+}
+
+syncer::ModelType SyncSetupService::GetModelType(SyncableDatatype datatype) {
+ DCHECK(datatype < arraysize(kDataTypes));
+ return kDataTypes[datatype];
+}
+
+syncer::ModelTypeSet SyncSetupService::GetDataTypes() const {
+ return sync_service_->GetPreferredDataTypes();
+}
+
+bool SyncSetupService::IsDataTypeEnabled(syncer::ModelType datatype) const {
+ return GetDataTypes().Has(datatype);
+}
+
+void SyncSetupService::SetDataTypeEnabled(syncer::ModelType datatype,
+ bool enabled) {
+ sync_service_->SetSetupInProgress(true);
+ syncer::ModelTypeSet types = GetDataTypes();
+ if (enabled)
+ types.Put(datatype);
+ else
+ types.Remove(datatype);
+ types.RetainAll(user_selectable_types_);
+ if (enabled && !IsSyncEnabled())
+ SetSyncEnabledWithoutChangingDatatypes(true);
+ sync_service_->OnUserChoseDatatypes(IsSyncingAllDataTypes(), types);
+ if (GetDataTypes().Empty())
+ SetSyncEnabled(false);
+}
+
+bool SyncSetupService::UserActionIsRequiredToHaveSyncWork() {
+ if (!IsSyncEnabled() || !IsDataTypeEnabled(syncer::PROXY_TABS)) {
+ return true;
+ }
+ switch (this->GetSyncServiceState()) {
+ // No error.
+ case SyncSetupService::kNoSyncServiceError:
+ // These errors are transient and don't mean that sync is off.
+ case SyncSetupService::kSyncServiceCouldNotConnect:
+ case SyncSetupService::kSyncServiceServiceUnavailable:
+ return false;
+ // These errors effectively amount to disabled sync and require a signin.
+ case SyncSetupService::kSyncServiceSignInNeedsUpdate:
+ case SyncSetupService::kSyncServiceNeedsPassphrase:
+ case SyncSetupService::kSyncServiceUnrecoverableError:
+ return true;
+ default:
+ NOTREACHED() << "Unknown sync service state.";
+ return true;
+ }
+}
+
+bool SyncSetupService::IsSyncingAllDataTypes() const {
+ sync_driver::SyncPrefs sync_prefs(prefs_);
+ return sync_prefs.HasKeepEverythingSynced();
+}
+
+void SyncSetupService::SetSyncingAllDataTypes(bool sync_all) {
+ sync_service_->SetSetupInProgress(true);
+ if (sync_all && !IsSyncEnabled())
+ SetSyncEnabled(true);
+ sync_service_->OnUserChoseDatatypes(sync_all, GetDataTypes());
+}
+
+bool SyncSetupService::IsSyncEnabled() const {
+ return sync_service_->IsSyncEnabledAndLoggedIn();
+}
+
+void SyncSetupService::SetSyncEnabled(bool sync_enabled) {
+ SetSyncEnabledWithoutChangingDatatypes(sync_enabled);
+ if (sync_enabled && GetDataTypes().Empty())
+ SetSyncingAllDataTypes(true);
+}
+
+SyncSetupService::SyncServiceState SyncSetupService::GetSyncServiceState() {
+ switch (sync_service_->GetAuthError().state()) {
+ case GoogleServiceAuthError::REQUEST_CANCELED:
+ return kSyncServiceCouldNotConnect;
+ // Based on sync_ui_util::GetStatusLabelsForAuthError, SERVICE_UNAVAILABLE
+ // corresponds to sync having been disabled for the user's domain.
+ case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
+ return kSyncServiceServiceUnavailable;
+ case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
+ return kSyncServiceSignInNeedsUpdate;
+ // The following errors are not shown to the user.
+ case GoogleServiceAuthError::NONE:
+ // Connection failed is not shown to the user, as this will happen if the
+ // service retuned a 500 error. A more detail error can always be checked
+ // on about:sync.
+ case GoogleServiceAuthError::CONNECTION_FAILED:
+ case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
+ case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE:
+ break;
+ // The following errors are unexpected on iOS.
+ case GoogleServiceAuthError::CAPTCHA_REQUIRED:
+ case GoogleServiceAuthError::ACCOUNT_DELETED:
+ case GoogleServiceAuthError::ACCOUNT_DISABLED:
+ case GoogleServiceAuthError::TWO_FACTOR:
+ case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
+ case GoogleServiceAuthError::SERVICE_ERROR:
+ case GoogleServiceAuthError::WEB_LOGIN_REQUIRED:
+ // Conventional value for counting the states, never used.
+ case GoogleServiceAuthError::NUM_STATES:
+ NOTREACHED() << "Unexpected Auth error ("
+ << sync_service_->GetAuthError().state()
+ << "): " << sync_service_->GetAuthError().error_message();
+ break;
+ }
+ if (sync_service_->HasUnrecoverableError())
+ return kSyncServiceUnrecoverableError;
+ if (sync_service_->IsPassphraseRequiredForDecryption())
+ return kSyncServiceNeedsPassphrase;
+ return kNoSyncServiceError;
+}
+
+bool SyncSetupService::HasFinishedInitialSetup() {
+ // Sync initial setup is considered to finished iff:
+ // 1. User is signed in with sync enabled and the sync setup was completed.
+ // OR
+ // 2. User is not signed in or has disabled sync.
+ return !sync_service_->IsSyncEnabledAndLoggedIn() ||
+ sync_service_->HasSyncSetupCompleted();
+}
+
+void SyncSetupService::PrepareForFirstSyncSetup() {
+ // |PrepareForFirstSyncSetup| should always be called while the user is signed
+ // out. At that time, sync setup is not completed.
+ DCHECK(!sync_service_->HasSyncSetupCompleted());
+ sync_service_->SetSetupInProgress(true);
+}
+
+void SyncSetupService::CommitChanges() {
+ if (sync_service_->FirstSetupInProgress()) {
+ // Turn on the sync setup completed flag only if the user did not turn sync
+ // off.
+ if (sync_service_->IsSyncEnabledAndLoggedIn()) {
+ sync_service_->SetSyncSetupCompleted();
+ }
+ }
+
+ sync_service_->SetSetupInProgress(false);
+}
+
+bool SyncSetupService::HasUncommittedChanges() {
+ return sync_service_->setup_in_progress();
+}
+
+void SyncSetupService::SetSyncEnabledWithoutChangingDatatypes(
+ bool sync_enabled) {
+ sync_service_->SetSetupInProgress(true);
+ if (sync_enabled)
+ sync_service_->UnsuppressAndStart();
+ else
+ sync_service_->StopAndSuppress();
+}
diff --git a/ios/chrome/browser/sync/sync_setup_service.h b/ios/chrome/browser/sync/sync_setup_service.h
new file mode 100644
index 0000000..491a09b
--- /dev/null
+++ b/ios/chrome/browser/sync/sync_setup_service.h
@@ -0,0 +1,111 @@
+// Copyright 2012 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 IOS_CHROME_BROWSER_SYNC_SYNC_SETUP_SERVICE_H_
+#define IOS_CHROME_BROWSER_SYNC_SYNC_SETUP_SERVICE_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "sync/internal_api/public/base/model_type.h"
+#include "sync/internal_api/public/util/syncer_error.h"
+
+namespace sync_driver {
+class SyncService;
+}
+
+class PrefService;
+
+// Class that allows configuring sync. It handles enabling and disabling it, as
+// well as choosing datatypes. Most actions are delayed until a commit is done,
+// to allow the complex sync setup flow on iOS.
+class SyncSetupService : public KeyedService {
+ public:
+ typedef enum {
+ kNoSyncServiceError,
+ kSyncServiceSignInNeedsUpdate,
+ kSyncServiceCouldNotConnect,
+ kSyncServiceServiceUnavailable,
+ kSyncServiceNeedsPassphrase,
+ kSyncServiceUnrecoverableError,
+ kLastSyncServiceError = kSyncServiceUnrecoverableError
+ } SyncServiceState;
+
+ // The set of user-selectable datatypes handled by Chrome for iOS.
+ typedef enum {
+ kSyncBookmarks,
+ kSyncOmniboxHistory,
+ kSyncPasswords,
+ kSyncOpenTabs,
+ kSyncAutofill,
+ kNumberOfSyncableDatatypes
+ } SyncableDatatype;
+
+ SyncSetupService(sync_driver::SyncService* sync_service, PrefService* prefs);
+ ~SyncSetupService() override;
+
+ // Returns the |syncer::ModelType| associated to the given
+ // |SyncableDatatypes|.
+ syncer::ModelType GetModelType(SyncableDatatype datatype);
+
+ // Returns whether sync is enabled.
+ virtual bool IsSyncEnabled() const;
+ // Enables or disables sync. Changes won't take effect in the sync backend
+ // before the next call to |CommitChanges|.
+ virtual void SetSyncEnabled(bool sync_enabled);
+
+ // Returns all currently enabled datatypes.
+ syncer::ModelTypeSet GetDataTypes() const;
+ // Returns whether the given datatype is enabled.
+ virtual bool IsDataTypeEnabled(syncer::ModelType datatype) const;
+ // Enables or disables the given datatype. To be noted: this can be called at
+ // any time, but will only be meaningful if |IsSyncEnabled| is true and
+ // |IsSyncingAllDataTypes| is false. Changes won't take effect in the sync
+ // backend before the next call to |CommitChanges|.
+ void SetDataTypeEnabled(syncer::ModelType datatype, bool enabled);
+
+ // Returns whether the user needs to enter a passphrase or enable sync to make
+ // sync work.
+ bool UserActionIsRequiredToHaveSyncWork();
+
+ // Returns whether all datatypes are being synced.
+ virtual bool IsSyncingAllDataTypes() const;
+ // Sets whether all datatypes should be synced or not. Changes won't take
+ // effect before the next call to |CommitChanges|.
+ virtual void SetSyncingAllDataTypes(bool sync_all);
+
+ // Returns the current sync service state.
+ virtual SyncServiceState GetSyncServiceState();
+
+ // Returns true if the user has gone through the initial sync configuration.
+ // This method is guaranteed not to start the sync backend so it can be
+ // called at start-up.
+ bool HasFinishedInitialSetup();
+
+ // Pauses sync allowing the user to configure what data to sync before
+ // actually starting to sync data with the server.
+ void PrepareForFirstSyncSetup();
+
+ // Commit the current state of the configuration to the sync backend.
+ void CommitChanges();
+
+ // Returns true if there are uncommitted sync changes;
+ bool HasUncommittedChanges();
+
+ private:
+ // Enables or disables sync. Changes won't take effect in the sync backend
+ // before the next call to |CommitChanges|. No changes are made to the
+ // currently selected datatypes.
+ void SetSyncEnabledWithoutChangingDatatypes(bool sync_enabled);
+
+ sync_driver::SyncService* const sync_service_;
+ PrefService* const prefs_;
+ syncer::ModelTypeSet user_selectable_types_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncSetupService);
+};
+
+#endif // IOS_CHROME_BROWSER_SYNC_SYNC_SETUP_SERVICE_H_
diff --git a/ios/chrome/browser/sync/sync_setup_service_mock.cc b/ios/chrome/browser/sync/sync_setup_service_mock.cc
new file mode 100644
index 0000000..39be8b7
--- /dev/null
+++ b/ios/chrome/browser/sync/sync_setup_service_mock.cc
@@ -0,0 +1,14 @@
+// Copyright 2013 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 "ios/chrome/browser/sync/sync_setup_service_mock.h"
+
+SyncSetupServiceMock::SyncSetupServiceMock(
+ sync_driver::SyncService* sync_service,
+ PrefService* prefs)
+ : SyncSetupService(sync_service, prefs) {
+}
+
+SyncSetupServiceMock::~SyncSetupServiceMock() {
+}
diff --git a/ios/chrome/browser/sync/sync_setup_service_mock.h b/ios/chrome/browser/sync/sync_setup_service_mock.h
new file mode 100644
index 0000000..aa2f8ea
--- /dev/null
+++ b/ios/chrome/browser/sync/sync_setup_service_mock.h
@@ -0,0 +1,28 @@
+// Copyright 2013 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 IOS_CHROME_BROWSER_SYNC_SYNC_SETUP_SERVICE_MOCK_H_
+#define IOS_CHROME_BROWSER_SYNC_SYNC_SETUP_SERVICE_MOCK_H_
+
+#include "ios/chrome/browser/sync/sync_setup_service.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+
+// Mock for the class that allows configuring sync on iOS.
+class SyncSetupServiceMock : public SyncSetupService {
+ public:
+ SyncSetupServiceMock(sync_driver::SyncService* sync_service,
+ PrefService* prefs);
+ ~SyncSetupServiceMock();
+
+ MOCK_CONST_METHOD0(IsSyncEnabled, bool());
+
+ MOCK_CONST_METHOD0(IsSyncingAllDataTypes, bool());
+
+ MOCK_METHOD0(GetSyncServiceState, SyncServiceState());
+
+ MOCK_CONST_METHOD1(IsDataTypeEnabled, bool(syncer::ModelType));
+};
+
+#endif // IOS_CHROME_BROWSER_SYNC_SYNC_SETUP_SERVICE_MOCK_H_