[ios] Remove use of rootViewController from autofill

[UIApplication sharedApplication].keyWindow.rootViewController was
used to present UI. Now, the appropriate view controller is
plumbed into autofill to present UI.

Bug: 791793, 692525
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: If82b5a5ee37d2ea9778d0332dd6686949d6bbfab
Reviewed-on: https://chromium-review.googlesource.com/882400
Reviewed-by: Mark Cogan <[email protected]>
Reviewed-by: Moe Ahmadi <[email protected]>
Reviewed-by: edchin <[email protected]>
Cr-Commit-Position: refs/heads/master@{#531991}
diff --git a/ios/chrome/browser/autofill/autofill_controller.h b/ios/chrome/browser/autofill/autofill_controller.h
index e70f5d8..0b25ed8e 100644
--- a/ios/chrome/browser/autofill/autofill_controller.h
+++ b/ios/chrome/browser/autofill/autofill_controller.h
@@ -63,6 +63,9 @@
 - (void)sendAutofillTypePredictionsToRenderer:
     (const std::vector<autofill::FormStructure*>&)forms;
 
+// Sets a weak reference to the view controller used to present UI.
+- (void)setBaseViewController:(UIViewController*)baseViewController;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_AUTOFILL_AUTOFILL_CONTROLLER_H_
diff --git a/ios/chrome/browser/autofill/autofill_controller.mm b/ios/chrome/browser/autofill/autofill_controller.mm
index 14935d7..f256f09 100644
--- a/ios/chrome/browser/autofill/autofill_controller.mm
+++ b/ios/chrome/browser/autofill/autofill_controller.mm
@@ -43,7 +43,7 @@
 @interface AutofillController ()<AutofillClientIOSBridge,
                                  AutofillDriverIOSBridge> {
   AutofillAgent* _autofillAgent;
-  std::unique_ptr<autofill::AutofillClient> _autofillClient;
+  std::unique_ptr<autofill::ChromeAutofillClientIOS> _autofillClient;
   autofill::AutofillManager* _autofillManager;  // weak
 }
 
@@ -125,6 +125,10 @@
   _autofillAgent = nil;
 }
 
+- (void)setBaseViewController:(UIViewController*)baseViewController {
+  _autofillClient->SetBaseViewController(baseViewController);
+}
+
 #pragma mark - AutofillClientIOSBridge
 
 - (void)
diff --git a/ios/chrome/browser/autofill/autofill_tab_helper.h b/ios/chrome/browser/autofill/autofill_tab_helper.h
index 120eea2..35b65c0f 100644
--- a/ios/chrome/browser/autofill/autofill_tab_helper.h
+++ b/ios/chrome/browser/autofill/autofill_tab_helper.h
@@ -11,6 +11,7 @@
 
 @class AutofillController;
 @protocol FormSuggestionProvider;
+@class UIViewController;
 
 namespace password_manager {
 class PasswordGenerationManager;
@@ -27,6 +28,9 @@
       web::WebState* web_state,
       password_manager::PasswordGenerationManager* password_generation_manager);
 
+  // Sets a weak reference to the view controller used to present UI.
+  void SetBaseViewController(UIViewController* base_view_controller);
+
   // Returns an object that can provide suggestions from the PasswordController.
   // May return nil.
   id<FormSuggestionProvider> GetSuggestionProvider();
diff --git a/ios/chrome/browser/autofill/autofill_tab_helper.mm b/ios/chrome/browser/autofill/autofill_tab_helper.mm
index a6d9c4a..b93ee3fe8 100644
--- a/ios/chrome/browser/autofill/autofill_tab_helper.mm
+++ b/ios/chrome/browser/autofill/autofill_tab_helper.mm
@@ -29,6 +29,11 @@
   }
 }
 
+void AutofillTabHelper::SetBaseViewController(
+    UIViewController* base_view_controller) {
+  [controller_ setBaseViewController:base_view_controller];
+}
+
 id<FormSuggestionProvider> AutofillTabHelper::GetSuggestionProvider() {
   return controller_.suggestionProvider;
 }
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index 67b5473f6..898d139a 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -295,6 +295,7 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
     "//ios/chrome/browser/app_launcher",
+    "//ios/chrome/browser/autofill:autofill_internal",
     "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/download",
diff --git a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h
index 2268307..e8c040e 100644
--- a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h
+++ b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h
@@ -13,6 +13,7 @@
 extern NSString* const kCardUnmaskPromptCollectionViewAccessibilityID;
 
 @class CardUnmaskPromptViewController;
+@class UIViewController;
 
 namespace autofill {
 
@@ -21,7 +22,10 @@
 // iOS implementation of the unmask prompt UI.
 class CardUnmaskPromptViewBridge : public CardUnmaskPromptView {
  public:
-  explicit CardUnmaskPromptViewBridge(CardUnmaskPromptController* controller);
+  // |base_view_controller| is a weak reference to the view controller used to
+  // present UI.
+  CardUnmaskPromptViewBridge(CardUnmaskPromptController* controller,
+                             UIViewController* base_view_controller);
   ~CardUnmaskPromptViewBridge() override;
 
   // CardUnmaskPromptView:
@@ -47,6 +51,9 @@
   // The controller |this| queries for logic and state.
   CardUnmaskPromptController* controller_;  // weak
 
+  // Weak reference to the view controller used to present UI.
+  __weak UIViewController* base_view_controller_;
+
   base::WeakPtrFactory<CardUnmaskPromptViewBridge> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(CardUnmaskPromptViewBridge);
diff --git a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
index e7cecd9..b0da0f9 100644
--- a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
+++ b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
@@ -53,8 +53,11 @@
 #pragma mark CardUnmaskPromptViewBridge
 
 CardUnmaskPromptViewBridge::CardUnmaskPromptViewBridge(
-    CardUnmaskPromptController* controller)
-    : controller_(controller), weak_ptr_factory_(this) {
+    CardUnmaskPromptController* controller,
+    UIViewController* base_view_controller)
+    : controller_(controller),
+      base_view_controller_(base_view_controller),
+      weak_ptr_factory_(this) {
   DCHECK(controller_);
 }
 
@@ -69,14 +72,9 @@
   [view_controller_ setModalPresentationStyle:UIModalPresentationFormSheet];
   [view_controller_
       setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
-  // Present the view controller.
-  // TODO(crbug.com/692525): Find an alternative to presenting the view
-  // controller on the root view controller.
-  UIViewController* rootController =
-      [UIApplication sharedApplication].keyWindow.rootViewController;
-  [rootController presentViewController:view_controller_
-                               animated:YES
-                             completion:nil];
+  [base_view_controller_ presentViewController:view_controller_
+                                      animated:YES
+                                    completion:nil];
 }
 
 void CardUnmaskPromptViewBridge::ControllerGone() {
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
index 2ec49e9..8d9638af 100644
--- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
+++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
@@ -25,6 +25,8 @@
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/web/public/web_state/web_state.h"
 
+@class UIViewController;
+
 namespace autofill {
 
 // Chrome iOS implementation of AutofillClient.
@@ -39,6 +41,9 @@
       std::unique_ptr<IdentityProvider> identity_provider);
   ~ChromeAutofillClientIOS() override;
 
+  // Sets a weak reference to the view controller used to present UI.
+  void SetBaseViewController(UIViewController* base_view_controller);
+
   // AutofillClientIOS implementation.
   PersonalDataManager* GetPersonalDataManager() override;
   PrefService* GetPrefs() override;
@@ -98,6 +103,9 @@
   password_manager::PasswordGenerationManager* password_generation_manager_;
   CardUnmaskPromptControllerImpl unmask_controller_;
 
+  // A weak reference to the view controller used to present UI.
+  __weak UIViewController* base_view_controller_;
+
   DISALLOW_COPY_AND_ASSIGN(ChromeAutofillClientIOS);
 };
 
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
index 330c120..a1fb3aa 100644
--- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
+++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
@@ -60,6 +60,11 @@
   HideAutofillPopup();
 }
 
+void ChromeAutofillClientIOS::SetBaseViewController(
+    UIViewController* base_view_controller) {
+  base_view_controller_ = base_view_controller;
+}
+
 PersonalDataManager* ChromeAutofillClientIOS::GetPersonalDataManager() {
   return personal_data_manager_;
 }
@@ -103,8 +108,9 @@
   unmask_controller_.ShowPrompt(
       // autofill::CardUnmaskPromptViewBridge manages its own lifetime, so
       // do not use std::unique_ptr<> here.
-      new autofill::CardUnmaskPromptViewBridge(&unmask_controller_), card,
-      reason, delegate);
+      new autofill::CardUnmaskPromptViewBridge(&unmask_controller_,
+                                               base_view_controller_),
+      card, reason, delegate);
 }
 
 void ChromeAutofillClientIOS::OnUnmaskVerificationResult(
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 0f110ff..33d43f6e5 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -55,6 +55,7 @@
 #include "components/toolbar/toolbar_model_impl.h"
 #include "ios/chrome/app/tests_hook.h"
 #import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h"
+#import "ios/chrome/browser/autofill/autofill_tab_helper.h"
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
@@ -2844,6 +2845,11 @@
     passwordTabHelper->SetPasswordControllerDelegate(self);
   }
 
+  if (AutofillTabHelper* autofillTabHelper =
+          AutofillTabHelper::FromWebState(tab.webState)) {
+    autofillTabHelper->SetBaseViewController(self);
+  }
+
   tab.dialogDelegate = self;
   tab.passKitDialogProvider = self;
   if (!base::FeatureList::IsEnabled(fullscreen::features::kNewFullscreen)) {
diff --git a/ios/chrome/browser/ui/payments/full_card_requester.mm b/ios/chrome/browser/ui/payments/full_card_requester.mm
index e2c0a33..528c6b8 100644
--- a/ios/chrome/browser/ui/payments/full_card_requester.mm
+++ b/ios/chrome/browser/ui/payments/full_card_requester.mm
@@ -12,36 +12,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-
-// The unmask prompt UI for Payment Request.
-class PRCardUnmaskPromptViewBridge
-    : public autofill::CardUnmaskPromptViewBridge {
- public:
-  PRCardUnmaskPromptViewBridge(autofill::CardUnmaskPromptController* controller,
-                               UIViewController* base_view_controller)
-      : autofill::CardUnmaskPromptViewBridge(controller),
-        base_view_controller_(base_view_controller) {}
-
-  // autofill::CardUnmaskPromptView:
-  void Show() override {
-    view_controller_ =
-        [[CardUnmaskPromptViewController alloc] initWithBridge:this];
-    [view_controller_ setModalPresentationStyle:UIModalPresentationFormSheet];
-    [view_controller_
-        setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
-    [base_view_controller_ presentViewController:view_controller_
-                                        animated:YES
-                                      completion:nil];
-  };
-
- private:
-  __weak UIViewController* base_view_controller_;
-  DISALLOW_COPY_AND_ASSIGN(PRCardUnmaskPromptViewBridge);
-};
-
-}  // namespace
-
 FullCardRequester::FullCardRequester(UIViewController* base_view_controller,
                                      ios::ChromeBrowserState* browser_state)
     : base_view_controller_(base_view_controller),
@@ -64,11 +34,9 @@
     const autofill::CreditCard& card,
     autofill::AutofillClient::UnmaskCardReason reason,
     base::WeakPtr<autofill::CardUnmaskDelegate> delegate) {
-  unmask_controller_.ShowPrompt(
-      // PRCardUnmaskPromptViewBridge manages its own lifetime.
-      new PRCardUnmaskPromptViewBridge(&unmask_controller_,
-                                       base_view_controller_),
-      card, reason, delegate);
+  unmask_controller_.ShowPrompt(new autofill::CardUnmaskPromptViewBridge(
+                                    &unmask_controller_, base_view_controller_),
+                                card, reason, delegate);
 }
 
 void FullCardRequester::OnUnmaskVerificationResult(