blob: 7345178564c128437d7491f5563b9d39551c828d [file] [log] [blame]
// Copyright 2018 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/store_kit/store_kit_coordinator.h"
#import <StoreKit/StoreKit.h>
#import <UIKit/UIKit.h>
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface StoreKitCoordinator () <SKStoreProductViewControllerDelegate>
// StoreKitViewController to present. Set as a weak reference so it only exists
// while its being presented by baseViewController.
@property(nonatomic, weak) SKStoreProductViewController* viewController;
@end
@implementation StoreKitCoordinator
@synthesize iTunesProductParameters = _iTunesProductParameters;
#pragma mark - Public
- (void)start {
DCHECK(self.iTunesProductParameters
[SKStoreProductParameterITunesItemIdentifier]);
// StoreKit shouldn't be launched, if there is one already presented.
if (self.viewController)
return;
SKStoreProductViewController* viewController =
[[SKStoreProductViewController alloc] init];
viewController.delegate = self;
[viewController
loadProductWithParameters:self.iTunesProductParameters
completionBlock:^(BOOL result, NSError* _Nullable error) {
UMA_HISTOGRAM_BOOLEAN("IOS.StoreKitLoadedSuccessfully",
result);
}];
[self.baseViewController presentViewController:viewController
animated:YES
completion:nil];
self.viewController = viewController;
}
- (void)stop {
// Do not call -dismissViewControllerAnimated:completion: on
// |self.baseViewController|, since the receiver of the method can be
// dismissed if there is no presented view controller. On iOS 12
// SKStoreProductViewControllerDelegate is responsible for dismissing
// SKStoreProductViewController. On iOS 13.0 OS dismisses
// SKStoreProductViewController after calling -productViewControllerDidFinish:
// On iOS 13.2 OS dismisses SKStoreProductViewController before calling
// -productViewControllerDidFinish: Calling
// -dismissViewControllerAnimated:completion: on |self.baseViewController| on
// iOS 13.2 will dismiss base view controller and break the application UI.
// According to SKStoreProductViewController documentation the delegate is
// responsible for calling deprecated dismissModalViewControllerAnimated: so
// the documentation is clearly outdated and this code should be resilient to
// different SKStoreProductViewController behavior without relying on iOS
// version check (see crbug.com/1027058).
[self.viewController dismissViewControllerAnimated:YES completion:nil];
self.viewController = nil;
}
#pragma mark - StoreKitLauncher
- (void)openAppStore:(NSString*)iTunesItemIdentifier {
[self openAppStoreWithParameters:@{
SKStoreProductParameterITunesItemIdentifier : iTunesItemIdentifier
}];
}
- (void)openAppStoreWithParameters:(NSDictionary*)productParameters {
self.iTunesProductParameters = productParameters;
[self start];
}
#pragma mark - SKStoreProductViewControllerDelegate
- (void)productViewControllerDidFinish:
(SKStoreProductViewController*)viewController {
[self stop];
}
@end