| // Copyright 2021 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. |
| |
| #import "ios/chrome/browser/ui/download/vcard_coordinator.h" |
| |
| #include <ContactsUI/ContactsUI.h> |
| |
| #include "base/scoped_observation.h" |
| #import "ios/chrome/browser/download/vcard_tab_helper.h" |
| #import "ios/chrome/browser/download/vcard_tab_helper_delegate.h" |
| #import "ios/chrome/browser/main/browser.h" |
| #import "ios/chrome/browser/web_state_list/web_state_dependency_installer_bridge.h" |
| #import "ios/web/public/web_state_observer_bridge.h" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| @interface VcardCoordinator () <DependencyInstalling, VcardTabHelperDelegate> { |
| // Bridge which observes WebStateList and alerts this coordinator when this |
| // needs to register the Mediator with a new WebState. |
| std::unique_ptr<WebStateDependencyInstallerBridge> _dependencyInstallerBridge; |
| } |
| |
| // NavigationController that contains a viewController used to display a |
| // contact. |
| @property(nonatomic, strong) UINavigationController* navigationViewController; |
| |
| @end |
| |
| @implementation VcardCoordinator |
| |
| - (instancetype)initWithBaseViewController:(UIViewController*)baseViewController |
| browser:(Browser*)browser { |
| if (self = [super initWithBaseViewController:baseViewController |
| browser:browser]) { |
| _dependencyInstallerBridge = |
| std::make_unique<WebStateDependencyInstallerBridge>( |
| self, browser->GetWebStateList()); |
| } |
| return self; |
| } |
| |
| - (void)stop { |
| // Reset this observer manually. We want this to go out of scope now, to |
| // ensure it detaches before `browser` and its WebStateList get destroyed. |
| _dependencyInstallerBridge.reset(); |
| |
| self.navigationViewController = nil; |
| } |
| |
| #pragma mark - DependencyInstalling methods |
| |
| - (void)installDependencyForWebState:(web::WebState*)webState { |
| if (VcardTabHelper::FromWebState(webState)) { |
| VcardTabHelper::FromWebState(webState)->set_delegate(self); |
| } |
| } |
| |
| - (void)uninstallDependencyForWebState:(web::WebState*)webState { |
| if (VcardTabHelper::FromWebState(webState)) { |
| VcardTabHelper::FromWebState(webState)->set_delegate(nil); |
| } |
| } |
| |
| #pragma mark - Private |
| |
| // Dismisses the the `navigationViewController`. |
| - (void)dismissButtonTapped { |
| [self.baseViewController dismissViewControllerAnimated:true completion:nil]; |
| } |
| |
| // Retreives contact informations from `data` and presents it. |
| - (void)presentContactVCardFromData:(NSData*)vcardData { |
| // TODO(crbug.com/1278657): Vcard download code only support the first |
| // contact. |
| CNContact* contact = |
| [[CNContactVCardSerialization contactsWithData:vcardData |
| error:nil] firstObject]; |
| if (!contact) { |
| return; |
| } |
| |
| CNContactViewController* contactViewController = |
| [CNContactViewController viewControllerForUnknownContact:contact]; |
| |
| contactViewController.allowsEditing = YES; |
| contactViewController.contactStore = [[CNContactStore alloc] init]; |
| |
| UIBarButtonItem* dismissButton = [[UIBarButtonItem alloc] |
| initWithBarButtonSystemItem:UIBarButtonSystemItemDone |
| target:self |
| action:@selector(dismissButtonTapped)]; |
| contactViewController.navigationItem.leftBarButtonItem = dismissButton; |
| |
| self.navigationViewController = [[UINavigationController alloc] |
| initWithRootViewController:contactViewController]; |
| [self.baseViewController presentViewController:self.navigationViewController |
| animated:YES |
| completion:nil]; |
| } |
| |
| #pragma mark - VcardTabHelperDelegate |
| |
| - (void)openVcardFromData:(NSData*)vcardData { |
| DCHECK(vcardData); |
| [self presentContactVCardFromData:vcardData]; |
| } |
| |
| @end |