[Dice] Avoid showing the sync confirmation dialog before sync engine starts.

In pre-DICE, the sync confirmation dialog was always shown after the
accounts were added to the Gaia cookies. This took several seconds
allowing the sync engine to initialize and check whether sync was
allowed for the given account.

When DICE enabled, the sync confirmation dialog should only be shown
after sync has been initialized or failed to be initialized. This allows
us to make sure that the policy to enable or disable sync for the given
account is checked before displaying the sync confirmation dialog.

BUG = 812546
TBR=msarda@chromium.org

(cherry picked from commit 859bc0e66cd10599ce7a96517474fe22f57935cf)

Change-Id: Ic414cd8eb5a810a1ff0827526361b10f8e76210b
Reviewed-on: https://chromium-review.googlesource.com/921741
Reviewed-by: David Roger <droger@chromium.org>
Reviewed-by: Nicolas Zea <zea@chromium.org>
Commit-Queue: Mihai Sardarescu <msarda@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#537348}
Reviewed-on: https://chromium-review.googlesource.com/928404
Reviewed-by: Mihai Sardarescu <msarda@chromium.org>
Cr-Commit-Position: refs/branch-heads/3325@{#530}
Cr-Branched-From: bc084a8b5afa3744a74927344e304c02ae54189f-refs/heads/master@{#530369}
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
index 6b171c7..a1962a5 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
@@ -376,10 +376,41 @@
   signin_metrics::LogSigninReason(signin_reason_);
   base::RecordAction(base::UserMetricsAction("Signin_Signin_Succeed"));
 
-  // Show Sync confirmation.
   browser_sync::ProfileSyncService* sync_service = GetProfileSyncService();
-  if (sync_service)
+  if (sync_service) {
+    // Take a SyncSetupInProgressHandle, so that the UI code can use
+    // IsFirstSyncSetupInProgress() as a way to know if there is a signin in
+    // progress.
+    // TODO(https://crbug.com/811211): Remove this handle.
     sync_blocker_ = sync_service->GetSetupInProgressHandle();
+    if (SyncStartupTracker::GetSyncServiceState(profile_) ==
+        SyncStartupTracker::SYNC_STARTUP_PENDING) {
+      // Wait until sync is initialized so that the confirmation UI can be
+      // aware of startup errors. This is needed to make sure that the sync
+      // confirmation dialog is shown only after the sync service had a chance
+      // to check whether sync was disabled by admin.
+      // See http://crbug.com/812546
+      sync_startup_tracker_.reset(new SyncStartupTracker(profile_, this));
+      return;
+    }
+  }
+
+  ShowSyncConfirmationUI();
+}
+
+void DiceTurnSyncOnHelper::SyncStartupCompleted() {
+  DCHECK(sync_startup_tracker_);
+  sync_startup_tracker_.reset();
+  ShowSyncConfirmationUI();
+}
+
+void DiceTurnSyncOnHelper::SyncStartupFailed() {
+  DCHECK(sync_startup_tracker_);
+  sync_startup_tracker_.reset();
+  ShowSyncConfirmationUI();
+}
+
+void DiceTurnSyncOnHelper::ShowSyncConfirmationUI() {
   scoped_login_ui_service_observer_.Add(
       LoginUIServiceFactory::GetForProfile(profile_));
   browser_ = EnsureBrowser(browser_, profile_);
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
index d1ef87b..85ef34e 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
@@ -10,6 +10,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/sync_startup_tracker.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
@@ -33,7 +34,8 @@
 // Handles details of signing the user in with SigninManager and turning on
 // sync for an account that is already present in the token service.
 class DiceTurnSyncOnHelper : public BrowserListObserver,
-                             public LoginUIService::Observer {
+                             public LoginUIService::Observer,
+                             public SyncStartupTracker::Observer {
  public:
   // Behavior when the signin is aborted (by an error or cancelled by the user).
   enum class SigninAbortedMode {
@@ -52,6 +54,10 @@
                        const std::string& account_id,
                        SigninAbortedMode signin_aborted_mode);
 
+  // SyncStartupTracker::Observer:
+  void SyncStartupCompleted() override;
+  void SyncStartupFailed() override;
+
  private:
   enum class ProfileMode {
     // Attempts to sign the user in |profile_|. Note that if the account to be
@@ -121,6 +127,11 @@
   // UI.
   void SigninAndShowSyncConfirmationUI();
 
+  // Displays the Sync confirmation UI.
+  // Note: If sync fails to start (e.g. sync is disabled by admin), the sync
+  // confirmation dialog will be updated accordingly.
+  void ShowSyncConfirmationUI();
+
   // LoginUIService::Observer override. Deletes this object.
   void OnSyncConfirmationUIClosed(
       LoginUIService::SyncConfirmationUIClosedResult result) override;
@@ -156,6 +167,7 @@
       scoped_browser_list_observer_;
   ScopedObserver<LoginUIService, LoginUIService::Observer>
       scoped_login_ui_service_observer_;
+  std::unique_ptr<SyncStartupTracker> sync_startup_tracker_;
 
   base::WeakPtrFactory<DiceTurnSyncOnHelper> weak_pointer_factory_;
   DISALLOW_COPY_AND_ASSIGN(DiceTurnSyncOnHelper);