[iOS][Unity] Adding wallet toggle in Manage sync settings

Adding "Payment Methods and Addresses Using Google Pay" in Manage sync
settings.
Screenshot:
https://drive.google.com/open?id=1a5BV3iALFCqRszA73Nn4s4dGMiWtx4dj

Bug: 936460
Change-Id: Ia70d4202b00f5778384d3ef5980c5a8c4bcb4302
Reviewed-on: https://chromium-review.googlesource.com/c/1495534
Commit-Queue: Jérôme Lebel <jlebel@chromium.org>
Reviewed-by: Gauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#637117}
diff --git a/ios/chrome/browser/ui/settings/google_services/BUILD.gn b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
index a199afa..e0551e7 100644
--- a/ios/chrome/browser/ui/settings/google_services/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
@@ -33,6 +33,7 @@
   deps = [
     "resources:google_services_sync_error",
     "//base",
+    "//components/autofill/core/common",
     "//components/browser_sync",
     "//components/google/core/common",
     "//components/metrics",
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm
index 3ca1b2f..0a8aaba 100644
--- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm
@@ -10,6 +10,7 @@
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/google/core/common/google_util.h"
 #include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
 #import "ios/chrome/browser/signin/authentication_service.h"
 #import "ios/chrome/browser/signin/authentication_service_factory.h"
@@ -60,8 +61,9 @@
 - (void)start {
   syncer::SyncService* syncService =
       ProfileSyncServiceFactory::GetForBrowserState(self.browserState);
-  self.mediator =
-      [[ManageSyncSettingsMediator alloc] initWithSyncService:syncService];
+  self.mediator = [[ManageSyncSettingsMediator alloc]
+      initWithSyncService:syncService
+          userPrefService:self.browserState->GetPrefs()];
   self.mediator.syncSetupService =
       SyncSetupServiceFactory::GetForBrowserState(self.browserState);
   self.mediator.commandHandler = self;
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.h b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.h
index 1240dc5..fe34aa6e 100644
--- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.h
+++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.h
@@ -12,6 +12,7 @@
 
 @protocol ManageSyncSettingsCommandHandler;
 @protocol ManageSyncSettingsConsumer;
+class PrefService;
 class SyncSetupService;
 namespace syncer {
 class SyncService;
@@ -34,6 +35,7 @@
 // Designated initializer.
 // |syncService|: Sync service. Should not be null.
 - (instancetype)initWithSyncService:(syncer::SyncService*)syncService
+                    userPrefService:(PrefService*)userPrefService
     NS_DESIGNATED_INITIALIZER;
 - (instancetype)init NS_UNAVAILABLE;
 
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
index ea2fa799..2a7f854 100644
--- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
+++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
@@ -6,6 +6,7 @@
 
 #include "base/auto_reset.h"
 #include "base/logging.h"
+#include "components/autofill/core/common/autofill_prefs.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/sync/driver/sync_service.h"
 #include "ios/chrome/browser/sync/profile_sync_service_factory.h"
@@ -16,6 +17,7 @@
 #import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h"
 #import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_command_handler.h"
 #import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_consumer.h"
+#import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_image_item.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
@@ -63,6 +65,8 @@
   ReadingListDataTypeItemType,
   // kSyncPreferences.
   SettingsDataTypeItemType,
+  // Item for kAutofillWalletImportEnabled.
+  AutocompleteWalletItemType,
   // AdvancedSettingsSectionIdentifier section.
   // Encryption item.
   EncryptionItemType,
@@ -76,21 +80,29 @@
 
 }  // namespace
 
-@interface ManageSyncSettingsMediator () <SyncObserverModelBridge> {
+@interface ManageSyncSettingsMediator () <BooleanObserver,
+                                          SyncObserverModelBridge> {
   // Sync observer.
   std::unique_ptr<SyncObserverBridge> _syncObserver;
   // Whether Sync State changes should be currently ignored.
   BOOL _ignoreSyncStateChanges;
 }
 
+// Preference value for kAutofillWalletImportEnabled.
+@property(nonatomic, strong, readonly)
+    PrefBackedBoolean* autocompleteWalletPreference;
 // Sync service.
 @property(nonatomic, assign) syncer::SyncService* syncService;
 // Model item for sync everything.
 @property(nonatomic, strong) SyncSwitchItem* syncEverythingItem;
 // Model item for each data types.
 @property(nonatomic, strong) NSArray<SyncSwitchItem*>* syncSwitchItems;
+// Autocomplete wallet item.
+@property(nonatomic, strong) SyncSwitchItem* autocompleteWalletItem;
 // Encryption item.
 @property(nonatomic, strong) TableViewImageItem* encryptionItem;
+// Returns YES if the sync data items should be enabled.
+@property(nonatomic, assign, readonly) BOOL shouldSyncDataItemEnabled;
 // Returns whether the Sync settings should be disabled because of a Sync error.
 @property(nonatomic, assign, readonly) BOOL disabledBecauseOfSyncError;
 
@@ -98,12 +110,17 @@
 
 @implementation ManageSyncSettingsMediator
 
-- (instancetype)initWithSyncService:(syncer::SyncService*)syncService {
+- (instancetype)initWithSyncService:(syncer::SyncService*)syncService
+                    userPrefService:(PrefService*)userPrefService {
   self = [super init];
   if (self) {
     DCHECK(syncService);
     self.syncService = syncService;
     _syncObserver.reset(new SyncObserverBridge(self, syncService));
+    _autocompleteWalletPreference = [[PrefBackedBoolean alloc]
+        initWithPrefService:userPrefService
+                   prefName:autofill::prefs::kAutofillWalletImportEnabled];
+    _autocompleteWalletPreference.observer = self;
   }
   return self;
 }
@@ -129,11 +146,17 @@
     [self switchItemWithDataType:SyncSetupService::kSyncReadingList],
     [self switchItemWithDataType:SyncSetupService::kSyncPreferences]
   ];
-  [self updateSyncDataItemsNotifyConsumer:NO];
   for (SyncSwitchItem* switchItem in self.syncSwitchItems) {
     [model addItem:switchItem
         toSectionWithIdentifier:SyncDataTypeSectionIdentifier];
   }
+  self.autocompleteWalletItem =
+      [[SyncSwitchItem alloc] initWithType:AutocompleteWalletItemType];
+  self.autocompleteWalletItem.text =
+      GetNSString(IDS_AUTOFILL_ENABLE_PAYMENTS_INTEGRATION_CHECKBOX_LABEL);
+  [model addItem:self.autocompleteWalletItem
+      toSectionWithIdentifier:SyncDataTypeSectionIdentifier];
+  [self updateSyncItemsNotifyConsumer:NO];
 }
 
 // Updates the sync everything item, and notify the consumer if |notifyConsumer|
@@ -155,13 +178,16 @@
   }
 }
 
+// Updates all the items related to sync (sync data items and autocomplete
+// wallet item). The consumer is notified if |notifyConsumer| is set to YES.
+- (void)updateSyncItemsNotifyConsumer:(BOOL)notifyConsumer {
+  [self updateSyncDataItemsNotifyConsumer:notifyConsumer];
+  [self updateAutocompleteWalletItemNotifyConsumer:notifyConsumer];
+}
+
 // Updates all the sync data type items, and notify the consumer if
 // |notifyConsumer| is set to YES.
 - (void)updateSyncDataItemsNotifyConsumer:(BOOL)notifyConsumer {
-  BOOL isSyncDataTypeItemEnabled =
-      (!self.syncSetupService->IsSyncingAllDataTypes() &&
-       self.syncSetupService->IsSyncEnabled() &&
-       !self.disabledBecauseOfSyncError);
   for (SyncSwitchItem* syncSwitchItem in self.syncSwitchItems) {
     SyncSetupService::SyncableDatatype dataType =
         static_cast<SyncSetupService::SyncableDatatype>(
@@ -169,16 +195,37 @@
     syncer::ModelType modelType = self.syncSetupService->GetModelType(dataType);
     BOOL isDataTypeSynced =
         self.syncSetupService->IsDataTypePreferred(modelType);
-    BOOL needsUpdate = (syncSwitchItem.on != isDataTypeSynced) ||
-                       (syncSwitchItem.isEnabled != isSyncDataTypeItemEnabled);
+    BOOL needsUpdate =
+        (syncSwitchItem.on != isDataTypeSynced) ||
+        (syncSwitchItem.isEnabled != self.shouldSyncDataItemEnabled);
     syncSwitchItem.on = isDataTypeSynced;
-    syncSwitchItem.enabled = isSyncDataTypeItemEnabled;
+    syncSwitchItem.enabled = self.shouldSyncDataItemEnabled;
     if (needsUpdate && notifyConsumer) {
       [self.consumer reloadItem:syncSwitchItem];
     }
   }
 }
 
+// Updates the autocomplete wallet item. The consumer is notified if
+// |notifyConsumer| is set to YES.
+- (void)updateAutocompleteWalletItemNotifyConsumer:(BOOL)notifyConsumer {
+  syncer::ModelType autofillModelType =
+      self.syncSetupService->GetModelType(SyncSetupService::kSyncAutofill);
+  BOOL isAutofillOn =
+      self.syncSetupService->IsDataTypePreferred(autofillModelType);
+  BOOL autocompleteWalletEnabled =
+      isAutofillOn && self.shouldSyncDataItemEnabled;
+  BOOL autocompleteWalletOn = self.autocompleteWalletPreference.value;
+  BOOL needsUpdate =
+      (self.autocompleteWalletItem.enabled != autocompleteWalletEnabled) ||
+      (self.autocompleteWalletItem.on != autocompleteWalletOn);
+  self.autocompleteWalletItem.enabled = autocompleteWalletEnabled;
+  self.autocompleteWalletItem.on = autocompleteWalletOn;
+  if (needsUpdate && notifyConsumer) {
+    [self.consumer reloadItem:self.autocompleteWalletItem];
+  }
+}
+
 #pragma mark - Loads the advanced settings section
 
 // Loads the advanced settings section.
@@ -305,6 +352,12 @@
          state != SyncSetupService::kSyncServiceNeedsPassphrase;
 }
 
+- (BOOL)shouldSyncDataItemEnabled {
+  return (!self.syncSetupService->IsSyncingAllDataTypes() &&
+          self.syncSetupService->IsSyncEnabled() &&
+          !self.disabledBecauseOfSyncError);
+}
+
 - (BOOL)shouldEncryptionItemBeEnabled {
   return self.syncService->IsEngineInitialized() &&
          self.syncSetupService->IsSyncEnabled() &&
@@ -320,6 +373,12 @@
   [self loadAdvancedSettingsSection];
 }
 
+#pragma mark - BooleanObserver
+
+- (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
+  [self updateAutocompleteWalletItemNotifyConsumer:YES];
+}
+
 #pragma mark - SyncObserverModelBridge
 
 - (void)onSyncStateChanged {
@@ -328,7 +387,7 @@
     return;
   }
   [self updateSyncEverythingItemNotifyConsumer:YES];
-  [self updateSyncDataItemsNotifyConsumer:YES];
+  [self updateSyncItemsNotifyConsumer:YES];
   [self updateEncryptionItem:YES];
 }
 
@@ -341,18 +400,46 @@
     // settings.
     base::AutoReset<BOOL> autoReset(&_ignoreSyncStateChanges, YES);
     switchItem.on = value;
-    if (switchItem.type == SyncEverythingItemType) {
-      self.syncSetupService->SetSyncingAllDataTypes(value);
-    } else {
-      SyncSetupService::SyncableDatatype dataType =
-          static_cast<SyncSetupService::SyncableDatatype>(switchItem.dataType);
-      syncer::ModelType modelType =
-          self.syncSetupService->GetModelType(dataType);
-      self.syncSetupService->SetDataTypeEnabled(modelType, value);
+    ItemType itemType = static_cast<ItemType>(switchItem.type);
+    switch (itemType) {
+      case SyncEverythingItemType:
+        self.syncSetupService->SetSyncingAllDataTypes(value);
+        break;
+      case AutofillDataTypeItemType:
+      case BookmarksDataTypeItemType:
+      case HistoryDataTypeItemType:
+      case OpenTabsDataTypeItemType:
+      case PasswordsDataTypeItemType:
+      case ReadingListDataTypeItemType:
+      case SettingsDataTypeItemType: {
+        SyncSetupService::SyncableDatatype dataType =
+            static_cast<SyncSetupService::SyncableDatatype>(
+                switchItem.dataType);
+        syncer::ModelType modelType =
+            self.syncSetupService->GetModelType(dataType);
+        self.syncSetupService->SetDataTypeEnabled(modelType, value);
+        if (dataType == SyncSetupService::kSyncAutofill) {
+          // When the auto fill data type is updated, the autocomplete wallet
+          // should be updated too. Autocomplete wallet should not be enabled
+          // when auto fill data type disabled. This behaviour not be
+          // implemented in the UI code. This code can be removed once
+          // crbug.com/937234 is fixed.
+          self.autocompleteWalletPreference.value = value;
+        }
+        break;
+      }
+      case AutocompleteWalletItemType:
+        self.autocompleteWalletPreference.value = value;
+        break;
+      case EncryptionItemType:
+      case GoogleActivityControlsItemType:
+      case DataFromChromeSync:
+        NOTREACHED();
+        break;
     }
   }
   [self updateSyncEverythingItemNotifyConsumer:YES];
-  [self updateSyncDataItemsNotifyConsumer:YES];
+  [self updateSyncItemsNotifyConsumer:YES];
 }
 
 - (void)didSelectItem:(TableViewItem*)item {
@@ -375,6 +462,7 @@
     case PasswordsDataTypeItemType:
     case ReadingListDataTypeItemType:
     case SettingsDataTypeItemType:
+    case AutocompleteWalletItemType:
       // Nothing to do.
       break;
   }