| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- /*! @file OIDExternalUserAgentIOSCustomBrowser.m
- @brief AppAuth iOS SDK
- @copyright
- Copyright 2018 Google LLC
- @copydetails
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- #import <TargetConditionals.h>
- #if TARGET_OS_IOS || TARGET_OS_MACCATALYST
- #import "OIDExternalUserAgentIOSCustomBrowser.h"
- #import <UIKit/UIKit.h>
- #import "OIDAuthorizationRequest.h"
- #import "OIDAuthorizationService.h"
- #import "OIDErrorUtilities.h"
- #import "OIDURLQueryComponent.h"
- #if !TARGET_OS_MACCATALYST
- NS_ASSUME_NONNULL_BEGIN
- @implementation OIDExternalUserAgentIOSCustomBrowser
- + (instancetype)CustomBrowserChrome {
- // Chrome iOS documentation: https://developer.chrome.com/multidevice/ios/links
- OIDCustomBrowserURLTransformation transform = [[self class] URLTransformationSchemeSubstitutionHTTPS:@"googlechromes" HTTP:@"googlechrome"];
- NSURL *appStoreURL =
- [NSURL URLWithString:@"https://itunes.apple.com/us/app/chrome/id535886823"];
- return [[[self class] alloc] initWithURLTransformation:transform
- canOpenURLScheme:@"googlechromes"
- appStoreURL:appStoreURL];
- }
- + (instancetype)CustomBrowserFirefox {
- // Firefox iOS documentation: https://github.com/mozilla-mobile/firefox-ios-open-in-client
- OIDCustomBrowserURLTransformation transform =
- [[self class] URLTransformationSchemeConcatPrefix:@"firefox://open-url?url="];
- NSURL *appStoreURL =
- [NSURL URLWithString:@"https://itunes.apple.com/us/app/firefox-web-browser/id989804926"];
- return [[[self class] alloc] initWithURLTransformation:transform
- canOpenURLScheme:@"firefox"
- appStoreURL:appStoreURL];
- }
- + (instancetype)CustomBrowserOpera {
- OIDCustomBrowserURLTransformation transform =
- [[self class] URLTransformationSchemeSubstitutionHTTPS:@"opera-https" HTTP:@"opera-http"];
- NSURL *appStoreURL =
- [NSURL URLWithString:@"https://itunes.apple.com/us/app/opera-mini-web-browser/id363729560"];
- return [[[self class] alloc] initWithURLTransformation:transform
- canOpenURLScheme:@"opera-https"
- appStoreURL:appStoreURL];
- }
- + (instancetype)CustomBrowserSafari {
- OIDCustomBrowserURLTransformation transformNOP = ^NSURL *(NSURL *requestURL) {
- return requestURL;
- };
- OIDExternalUserAgentIOSCustomBrowser *transform =
- [[[self class] alloc] initWithURLTransformation:transformNOP];
- return transform;
- }
- + (OIDCustomBrowserURLTransformation)
- URLTransformationSchemeSubstitutionHTTPS:(NSString *)browserSchemeHTTPS
- HTTP:(nullable NSString *)browserSchemeHTTP {
- OIDCustomBrowserURLTransformation transform = ^NSURL *(NSURL *requestURL) {
- // Replace the URL Scheme with the Chrome equivalent.
- NSString *newScheme = nil;
- if ([requestURL.scheme isEqualToString:@"https"]) {
- newScheme = browserSchemeHTTPS;
- } else if ([requestURL.scheme isEqualToString:@"http"]) {
- if (!browserSchemeHTTP) {
- NSAssert(false, @"No HTTP scheme registered for browser");
- return nil;
- }
- newScheme = browserSchemeHTTP;
- }
-
- // Replaces the URI scheme with the custom scheme
- NSURLComponents *components = [NSURLComponents componentsWithURL:requestURL
- resolvingAgainstBaseURL:YES];
- components.scheme = newScheme;
- return components.URL;
- };
- return transform;
- }
- + (OIDCustomBrowserURLTransformation)URLTransformationSchemeConcatPrefix:(NSString *)URLprefix {
- OIDCustomBrowserURLTransformation transform = ^NSURL *(NSURL *requestURL) {
- NSString *requestURLString = [requestURL absoluteString];
- NSMutableCharacterSet *allowedParamCharacters =
- [OIDURLQueryComponent URLParamValueAllowedCharacters];
- NSString *encodedUrl = [requestURLString stringByAddingPercentEncodingWithAllowedCharacters:allowedParamCharacters];
- NSString *newURL = [NSString stringWithFormat:@"%@%@", URLprefix, encodedUrl];
- return [NSURL URLWithString:newURL];
- };
- return transform;
- }
- - (nullable instancetype)initWithURLTransformation:
- (OIDCustomBrowserURLTransformation)URLTransformation {
- return [self initWithURLTransformation:URLTransformation canOpenURLScheme:nil appStoreURL:nil];
- }
- - (nullable instancetype)
- initWithURLTransformation:(OIDCustomBrowserURLTransformation)URLTransformation
- canOpenURLScheme:(nullable NSString *)canOpenURLScheme
- appStoreURL:(nullable NSURL *)appStoreURL {
- self = [super init];
- if (self) {
- _URLTransformation = URLTransformation;
- _canOpenURLScheme = canOpenURLScheme;
- _appStoreURL = appStoreURL;
- }
- return self;
- }
- - (BOOL)presentExternalUserAgentRequest:(nonnull id<OIDExternalUserAgentRequest>)request
- session:(nonnull id<OIDExternalUserAgentSession>)session {
- // If the app store URL is set, checks if the app is installed and if not opens the app store.
- if (_appStoreURL && _canOpenURLScheme) {
- // Verifies existence of LSApplicationQueriesSchemes Info.plist key.
- NSArray __unused* canOpenURLs =
- [[NSBundle mainBundle] objectForInfoDictionaryKey:@"LSApplicationQueriesSchemes"];
- NSAssert(canOpenURLs, @"plist missing LSApplicationQueriesSchemes key");
- NSAssert1([canOpenURLs containsObject:_canOpenURLScheme],
- @"plist missing LSApplicationQueriesSchemes entry for '%@'", _canOpenURLScheme);
- // Opens AppStore if app isn't installed
- NSString *testURLString = [NSString stringWithFormat:@"%@://example.com", _canOpenURLScheme];
- NSURL *testURL = [NSURL URLWithString:testURLString];
- if (![[UIApplication sharedApplication] canOpenURL:testURL]) {
- [[UIApplication sharedApplication] openURL:_appStoreURL];
- return NO;
- }
- }
-
- // Transforms the request URL and opens it.
- NSURL *requestURL = [request externalUserAgentRequestURL];
- requestURL = _URLTransformation(requestURL);
- BOOL openedInBrowser = [[UIApplication sharedApplication] openURL:requestURL];
- return openedInBrowser;
- }
- - (void)dismissExternalUserAgentAnimated:(BOOL)animated
- completion:(nonnull void (^)(void))completion {
- completion();
- }
- @end
- NS_ASSUME_NONNULL_END
- #endif // !TARGET_OS_MACCATALYST
- #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST
|