Commit 0ed12bba authored by Carola Nitz's avatar Carola Nitz

VLCURLHandler: Have a designated Class for handling openURL calls

Add first UnitTests for the parts of the URLHandler as well
parent ded60c40
......@@ -29,6 +29,7 @@ target 'VLC-iOS' do
target 'VLC for iOSUITests' do
pod 'SimulatorStatusMagic'
end
target 'VLC for iOSTests'
end
target 'VLC-tvOS' do
......
......@@ -168,6 +168,6 @@ SPEC CHECKSUMS:
XKKeychain: 852ef663c56a7194c73d3c68e8d9d4f07b121d4f
xmlrpc: 109bb21d15ed6d108b2c1ac5973a6a223a50f5f4
PODFILE CHECKSUM: 3dcf0322da92b8ffd75b8fef5df1ef5633b2f3ce
PODFILE CHECKSUM: 0c8231ce51e9fc3523731b5752caab4a1bef5e13
COCOAPODS: 1.5.2
/*****************************************************************************
* URLHandler.swift
* VLC for iOS
*****************************************************************************
* Copyright (c) 2018 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Carola Nitz <caro # videolan.org>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
import Foundation
@objc protocol VLCURLHandler {
func canHandleOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool
func performOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool
}
@objc class URLHandlers: NSObject {
@objc static let googleURLHandler = GoogleURLHandler()
@objc static let handlers =
[
googleURLHandler,
DropBoxURLHandler(),
FileURLHandler(),
XCallbackURLHandler(),
VLCCallbackURLHandler(),
ElseCallbackURLHandler()
]
}
class DropBoxURLHandler: NSObject, VLCURLHandler {
@objc func canHandleOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
return url.scheme == "db-a60fc6qj9zdg7bw"
}
@objc func performOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
let authResult = DBClientsManager.handleRedirectURL(url)
if let authResult = authResult, authResult.isSuccess() == true {
//TODO:update Dropboxcontrollers
return true
}
return false
}
}
class GoogleURLHandler: NSObject, VLCURLHandler {
@objc var currentGoogleAuthorizationFlow: OIDAuthorizationFlowSession?
@objc func canHandleOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
return url.scheme == "com.googleusercontent.apps.CLIENT"
}
@objc func performOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
if currentGoogleAuthorizationFlow?.resumeAuthorizationFlow(with: url) == true {
currentGoogleAuthorizationFlow = nil
return true
}
return false
}
}
class FileURLHandler: NSObject, VLCURLHandler {
@objc func canHandleOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
return url.isFileURL
}
@objc func performOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
let subclass = DocumentClass(fileURL: url)
subclass.open { _ in
play(url: url) { _ in
subclass.close(completionHandler: nil)
}
}
return true
}
}
class XCallbackURLHandler: NSObject, VLCURLHandler {
@objc func canHandleOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
return url.scheme == "vlc-x-callback" || url.scheme == "x-callback-url"
}
@objc func performOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
let action = url.path.replacingOccurrences(of: "/", with: "")
var movieURL: URL?
var successCallback: URL?
var errorCallback: URL?
var fileName: String?
guard let query = url.query else {
assertionFailure("no query")
return false
}
for entry in query.components(separatedBy: "&") {
let components = entry.components(separatedBy: "=")
if components.count < 2 {
continue
}
if let key = components.first, let value = components[1].removingPercentEncoding {
if key == "url"{
movieURL = URL(string: value)
} else if key == "filename" {
fileName = value
} else if key == "x-success" {
successCallback = URL(string: value)
} else if key == "x-error" {
errorCallback = URL(string: value)
}
} else {
assertionFailure("no key or app value")
}
}
if action == "stream", let movieURL = movieURL {
play(url: movieURL) { success in
guard let callback = success ? successCallback : errorCallback else {
assertionFailure("no CallbackURL")
return
}
if #available(iOS 10, *) {
UIApplication.shared.open(callback, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(callback)
}
}
return true
} else if action == "download", let movieURL = movieURL {
downloadMovie(from:movieURL, fileNameOfMedia:fileName)
return true
}
return false
}
}
class VLCCallbackURLHandler: NSObject, VLCURLHandler {
@objc func canHandleOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
return url.scheme == "vlc"
}
// Safari fixes URLs like "vlc://http://example.org" to "vlc://http//example.org"
func transformVLCURL(_ url: URL) -> URL {
var parsedString = url.absoluteString.replacingOccurrences(of: "vlc://", with: "")
if let location = parsedString.range(of: "//"), parsedString[parsedString.index(location.lowerBound, offsetBy: -1)] != ":" {
parsedString = "\(parsedString[parsedString.startIndex..<location.lowerBound])://\(parsedString[location.upperBound...])"
} else if !parsedString.hasPrefix("http://") && !parsedString.hasPrefix("https://") && !parsedString.hasPrefix("ftp://") {
parsedString = "http://\(parsedString)"
}
return URL(string: parsedString)!
}
func performOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
let transformedURL = transformVLCURL(url)
let scheme = transformedURL.scheme
if scheme == "http" || scheme == "https" || scheme == "ftp" {
let alert = UIAlertController(title: NSLocalizedString("OPEN_STREAM_OR_DOWNLOAD", comment:""), message: url.absoluteString, preferredStyle: .alert)
let downloadAction = UIAlertAction(title: NSLocalizedString("BUTTON_DOWNLOAD", comment:""), style: .default) { _ in
downloadMovie(from:transformedURL, fileNameOfMedia:nil)
}
alert.addAction(downloadAction)
let playAction = UIAlertAction(title: NSLocalizedString("PLAY_BUTTON", comment:""), style: .default) { _ in
play(url: transformedURL, completion: nil)
}
alert.addAction(playAction)
alert.show(UIApplication.shared.keyWindow!.rootViewController!, sender: nil)
} else {
play(url: transformedURL, completion: nil)
}
return true
}
}
class ElseCallbackURLHandler: NSObject, VLCURLHandler {
@objc func canHandleOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
return true
}
func performOpen(url: URL, options: [UIApplicationOpenURLOptionsKey: AnyObject]) -> Bool {
play(url: url, completion: nil)
return true
}
}
// TODO: This code should probably not live here
func play(url: URL, completion: ((Bool) -> Void)?) {
let vpc = VLCPlaybackController.sharedInstance()
vpc.fullscreenSessionRequested = true
if let mediaList = VLCMediaList(array: [VLCMedia(url: url)]) {
vpc.playMediaList(mediaList, firstIndex: 0, subtitlesFilePath: nil, completion: completion)
}
}
func downloadMovie(from url: URL, fileNameOfMedia fileName: String?) {
VLCDownloadViewController.sharedInstance().addURL(toDownloadList: url, fileNameOfMedia: fileName)
}
......@@ -14,14 +14,8 @@
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import <AppAuth/AppAuth.h>
extern NSString *const VLCDropboxSessionWasAuthorized;
@interface VLCAppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (atomic, strong) id<OIDAuthorizationFlowSession> currentGoogleAuthorizationFlow;
@end
......@@ -23,21 +23,16 @@
#import "UIDevice+VLC.h"
#import "VLCHTTPUploaderController.h"
#import "VLCMigrationViewController.h"
#import <BoxSDK/BoxSDK.h>
#import "VLCPlaybackController.h"
#import "VLCPlaybackController+MediaLibrary.h"
#import <MediaPlayer/MediaPlayer.h>
#import <HockeySDK/HockeySDK.h>
#import "VLCActivityManager.h"
#import "VLCDropboxConstants.h"
#import "VLCDownloadViewController.h"
#import <ObjectiveDropboxOfficial/ObjectiveDropboxOfficial.h>
#import "VLCPlaybackNavigationController.h"
#import "PAPasscodeViewController.h"
#import "VLC_iOS-Swift.h"
NSString *const VLCDropboxSessionWasAuthorized = @"VLCDropboxSessionWasAuthorized";
#define BETA_DISTRIBUTION 1
@interface VLCAppDelegate () <VLCMediaFileDiscovererDelegate>
......@@ -242,120 +237,13 @@ didFailToContinueUserActivityWithType:(NSString *)userActivityType
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
//Handles Dropbox Authorization flow.
DBOAuthResult *authResult = [DBClientsManager handleRedirectURL:url];
if (authResult != nil) {
if ([authResult isSuccess]) {
return YES;
for (id<VLCURLHandler> handler in URLHandlers.handlers) {
if ([handler canHandleOpenWithUrl:url options:options]) {
if ([handler performOpenWithUrl:url options:options]) {
break;
}
}
}
//Handles Google Authorization flow.
if ([_currentGoogleAuthorizationFlow resumeAuthorizationFlowWithURL:url]) {
_currentGoogleAuthorizationFlow = nil;
return YES;
}
//TODO: we need a model of URLHandlers that registers with the VLCAppdelegate
// then we can go through the list of handlers ask if they can handle the url and the first to say yes handles the call.
// that way internal if elses get encapsulated
/*
protocol VLCURLHandler {
func canHandleOpen(url: URL, options:[UIApplicationOpenURLOptionsKey:AnyObject]=[:]()) -> bool
func performOpen(url: URL, options:[UIApplicationOpenURLOptionsKey:AnyObject]=[:]()) -> bool
} */
// if (_libraryViewController && url != nil) {
// APLog(@"requested %@ to be opened", url);
//
// if (url.isFileURL) {
// VLCDocumentClass *subclass = [[VLCDocumentClass alloc] initWithFileURL:url];
// [subclass openWithCompletionHandler:^(BOOL success) {
// [self playWithURL:url completion:^(BOOL success) {
// [subclass closeWithCompletionHandler:nil];
// }];
// }];
// } else if ([url.scheme isEqualToString:@"vlc-x-callback"] || [url.host isEqualToString:@"x-callback-url"]) {
// // URL confirmes to the x-callback-url specification
// // vlc-x-callback://x-callback-url/action?param=value&x-success=callback
// APLog(@"x-callback-url with host '%@' path '%@' parameters '%@'", url.host, url.path, url.query);
// NSString *action = [url.path stringByReplacingOccurrencesOfString:@"/" withString:@""];
// NSURL *movieURL;
// NSURL *successCallback;
// NSURL *errorCallback;
// NSString *fileName;
// for (NSString *entry in [url.query componentsSeparatedByString:@"&"]) {
// NSArray *keyvalue = [entry componentsSeparatedByString:@"="];
// if (keyvalue.count < 2) continue;
// NSString *key = keyvalue[0];
// NSString *value = [keyvalue[1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//
// if ([key isEqualToString:@"url"])
// movieURL = [NSURL URLWithString:value];
// else if ([key isEqualToString:@"filename"])
// fileName = value;
// else if ([key isEqualToString:@"x-success"])
// successCallback = [NSURL URLWithString:value];
// else if ([key isEqualToString:@"x-error"])
// errorCallback = [NSURL URLWithString:value];
// }
// if ([action isEqualToString:@"stream"] && movieURL) {
// [self playWithURL:movieURL completion:^(BOOL success) {
// NSURL *callback = success ? successCallback : errorCallback;
// if (@available(iOS 10, *)) {
// [[UIApplication sharedApplication] openURL:callback options:@{} completionHandler:nil];
// } else {
//#pragma clang diagnostic push
//#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// /* UIApplication's replacement calls require iOS 10 or later, which we can't enforce as of yet */
// [[UIApplication sharedApplication] openURL:callback];
//#pragma clang diagnostic pop
// }
// }];
// }
// else if ([action isEqualToString:@"download"] && movieURL) {
// [self downloadMovieFromURL:movieURL fileNameOfMedia:fileName];
// }
// } else {
// NSString *receivedUrl = [url absoluteString];
// if ([receivedUrl length] > 6) {
// NSString *verifyVlcUrl = [receivedUrl substringToIndex:6];
// if ([verifyVlcUrl isEqualToString:@"vlc://"]) {
// NSString *parsedString = [receivedUrl substringFromIndex:6];
// NSUInteger location = [parsedString rangeOfString:@"//"].location;
//
// /* Safari & al mangle vlc://http:// so fix this */
// if (location != NSNotFound && [parsedString characterAtIndex:location - 1] != 0x3a) { // :
// parsedString = [NSString stringWithFormat:@"%@://%@", [parsedString substringToIndex:location], [parsedString substringFromIndex:location+2]];
// } else {
// parsedString = [receivedUrl substringFromIndex:6];
// if (![parsedString hasPrefix:@"http://"] && ![parsedString hasPrefix:@"https://"] && ![parsedString hasPrefix:@"ftp://"]) {
// parsedString = [@"http://" stringByAppendingString:[receivedUrl substringFromIndex:6]];
// }
// }
// url = [NSURL URLWithString:parsedString];
// }
// }
// [[VLCSidebarController sharedInstance] selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
// scrollPosition:UITableViewScrollPositionNone];
//
// NSString *scheme = url.scheme;
// if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"] || [scheme isEqualToString:@"ftp"]) {
// VLCAlertView *alert = [[VLCAlertView alloc] initWithTitle:NSLocalizedString(@"OPEN_STREAM_OR_DOWNLOAD", nil) message:url.absoluteString cancelButtonTitle:NSLocalizedString(@"BUTTON_DOWNLOAD", nil) otherButtonTitles:@[NSLocalizedString(@"PLAY_BUTTON", nil)]];
// alert.completion = ^(BOOL cancelled, NSInteger buttonIndex) {
// if (cancelled)
// [self downloadMovieFromURL:url fileNameOfMedia:nil];
// else {
// [self playWithURL:url completion:nil];
// }
// };
// [alert show];
// } else {
// [self playWithURL:url completion:nil];
// }
// }
// return YES;
// }
return NO;
}
......@@ -447,22 +335,4 @@ didFailToContinueUserActivityWithType:(NSString *)userActivityType
}
}
#pragma mark - download handling
- (void)downloadMovieFromURL:(NSURL *)url
fileNameOfMedia:(NSString *)fileName
{
[[VLCDownloadViewController sharedInstance] addURLToDownloadList:url fileNameOfMedia:fileName];
//TODO: open DownloadViewController
}
#pragma mark - playback
- (void)playWithURL:(NSURL *)url completion:(void (^ __nullable)(BOOL success))completion
{
VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
vpc.fullscreenSessionRequested = YES;
VLCMediaList *mediaList = [[VLCMediaList alloc] initWithArray:@[[VLCMedia mediaWithURL:url]]];
[vpc playMediaList:mediaList firstIndex:0 subtitlesFilePath:nil completion:completion];
}
@end
......@@ -50,10 +50,6 @@
self.controller.delegate = self;
#if TARGET_OS_IOS
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(sessionWasUpdated:)
name:VLCDropboxSessionWasAuthorized
object:nil];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"dropbox-white"]];
......
......@@ -166,7 +166,8 @@
additionalParameters:nil];
// Perform the previously built request and saving the current authorization flow.
((VLCAppDelegate *)[UIApplication sharedApplication].delegate).currentGoogleAuthorizationFlow = [OIDAuthState authStateByPresentingAuthorizationRequest:request presentingViewController:self
URLHandlers.googleURLHandler.currentGoogleAuthorizationFlow = [OIDAuthState authStateByPresentingAuthorizationRequest:request presentingViewController:self
callback:^(OIDAuthState *_Nullable authState, NSError *_Nullable error) {
self.authorizationInProgress = NO;
......
#import <AppAuth/AppAuth.h>
#import <MediaLibraryKit/MediaLibraryKit.h>
#import <MobileVLCKit/MobileVLCKit.h>
#import <ObjectiveDropboxOfficial/ObjectiveDropboxOfficial.h>
#import <PAPasscode/PAPasscodeViewController.h>
#import <XKKeychain/XKKeychain.h>
#import "VLCExternalDisplayController.h"
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
/*****************************************************************************
* URLHandlerTests.swift
* VLC for iOS
*****************************************************************************
* Copyright (c) 2018 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Carola Nitz <caro # videolan.org>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
import XCTest
@testable import VLC_iOS
class URLHandlerTests: XCTestCase {
func testVLCHandler() {
let handler = VLCCallbackURLHandler()
let transformURLString = { handler.transformVLCURL(URL(string: $0)!) }
XCTAssertEqual(transformURLString("vlc://http//test"), URL(string: "http://test")!, "strip the custom scheme and re-add the colon")
XCTAssertEqual(transformURLString("vlc://http://test"), URL(string: "http://test")!, "just strip the custom scheme")
XCTAssertEqual(transformURLString("vlc://test"), URL(string: "http://test")!, "strip the custom scheme and add http")
XCTAssertEqual(transformURLString("vlc://ftp//test"), URL(string: "ftp://test")!, "strip the custom scheme and readd :")
XCTAssertEqual(transformURLString("vlc://ftp://test"), URL(string: "ftp://test")!, "strip custom scheme")
XCTAssertEqual(transformURLString("vlc://https//test"), URL(string: "https://test")!, "strip the custom scheme and readd :")
XCTAssertEqual(transformURLString("vlc://https://test"), URL(string: "https://test")!, "strip the custom scheme")
}
}
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "VLC-iOS-Bridging-Header.h"
......@@ -11,6 +11,7 @@
26F1BFD01A770408001DF30C /* libMediaVLC.xml in Resources */ = {isa = PBXBuildFile; fileRef = 26F1BFCF1A770408001DF30C /* libMediaVLC.xml */; };
29125E5617492219003F03E5 /* index.html in Resources */ = {isa = PBXBuildFile; fileRef = 29125E5417492219003F03E5 /* index.html */; };
2915544317490D4A00B86CAD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2915544217490D4A00B86CAD /* Security.framework */; };
2A002188D3D6E76DEF147F08 /* libPods-VLC-iOS-VLC for iOSTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CD92B7DB3994F879C74A70E0 /* libPods-VLC-iOS-VLC for iOSTests.a */; };
411DC0FD20F650B10044305E /* VLCMediaSubcategory+VLCDragAndDrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 412BE7521FC4947400ACCC42 /* VLCMediaSubcategory+VLCDragAndDrop.swift */; };
41251ED01FD0CF7900099110 /* AppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41251ECE1FD0CF7900099110 /* AppCoordinator.swift */; };
41273A3C1A955C4100A2EF77 /* VLCMigrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 41273A3A1A955C4100A2EF77 /* VLCMigrationViewController.m */; };
......@@ -23,6 +24,7 @@
4144156C20ECE6330078EC37 /* VLCFileServerSectionTableHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4144156B20ECE6330078EC37 /* VLCFileServerSectionTableHeaderView.swift */; };
4144C4661A0ED6C700918C89 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D3784E6183A99E1009EE944 /* Reachability.m */; };
4152F1621FEF19BD00F1908B /* KeychainCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4152F1611FEF19BD00F1908B /* KeychainCoordinator.swift */; };
41533C9E2113392F00EC3ABA /* URLHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41533C9D2113392F00EC3ABA /* URLHandlerTests.swift */; };
416443862048419E00CAC646 /* DeviceMotion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 416443852048419E00CAC646 /* DeviceMotion.swift */; };
416DACB720B6DB9A001BC75D /* VLCPlayingExternallyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 416DACB620B6DB9A001BC75D /* VLCPlayingExternallyView.swift */; };
4170152C209A1D3600802E44 /* MediaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4170152B209A1D3600802E44 /* MediaViewController.swift */; };
......@@ -38,6 +40,7 @@
418B144D20179C75000447AA /* VLCTabBarCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 418B144C20179C74000447AA /* VLCTabBarCoordinator.swift */; };
418B145020179CB9000447AA /* LayoutAnchorContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 418B144F20179CB9000447AA /* LayoutAnchorContainer.swift */; };
418B145920179E50000447AA /* VLCDragAndDropManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 418B145820179E50000447AA /* VLCDragAndDropManager.swift */; };
418E88412110E51B00DDA6A7 /* URLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 418E88402110E51B00DDA6A7 /* URLHandler.swift */; };
4195747D206A92ED00393A42 /* RemoteNetworkDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4195747C206A92ED00393A42 /* RemoteNetworkDataSource.swift */; };
419A2C661F37A4B70069D224 /* VLCStringsForLocalization.m in Sources */ = {isa = PBXBuildFile; fileRef = 419A2C651F37A4B70069D224 /* VLCStringsForLocalization.m */; };
419A2C681F37A4B70069D224 /* VLCStringsForLocalization.m in Sources */ = {isa = PBXBuildFile; fileRef = 419A2C651F37A4B70069D224 /* VLCStringsForLocalization.m */; };
......@@ -378,6 +381,13 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
41533C96211338D600EC3ABA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 7D94FCD316DE7D1000F2623B /* Project object */;
proxyType = 1;
remoteGlobalIDString = 7D94FCDA16DE7D1000F2623B;
remoteInfo = "VLC-iOS";
};
41B0BC8B1F73ED7D0063BA26 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 7D94FCD316DE7D1000F2623B /* Project object */;
......@@ -476,16 +486,19 @@
/* Begin PBXFileReference section */
018698905AC809BE4496D84D /* Pods-vlc-ios.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-vlc-ios.debug.xcconfig"; path = "Pods/Target Support Files/Pods-vlc-ios/Pods-vlc-ios.debug.xcconfig"; sourceTree = "<group>"; };
090F2933E962C424E9A80ABB /* Pods-VLC-iOS-no-watch.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-iOS-no-watch.release.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-iOS-no-watch/Pods-VLC-iOS-no-watch.release.xcconfig"; sourceTree = "<group>"; };
1C174528BFB46C3490E773B6 /* Pods-VLC-iOS-VLC for iOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-iOS-VLC for iOSTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-iOS-VLC for iOSTests/Pods-VLC-iOS-VLC for iOSTests.debug.xcconfig"; sourceTree = "<group>"; };
1C7724AABC40B96010E01F65 /* Pods-VLC-iOS-no-watch.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-iOS-no-watch.debug.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-iOS-no-watch/Pods-VLC-iOS-no-watch.debug.xcconfig"; sourceTree = "<group>"; };
260624EB5BF9F1FBE58BF816 /* libPods-VLC for iOSUITests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-VLC for iOSUITests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
268BDA7D1B4FE1E200D622DD /* backArrow_black.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = backArrow_black.png; path = ImportedSources/OneDrive/src/LiveSDK/Library/Internal/Resources/backArrow_black.png; sourceTree = SOURCE_ROOT; };
26F1BFCF1A770408001DF30C /* libMediaVLC.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = libMediaVLC.xml; sourceTree = "<group>"; };
27E1FE5B2995E84315076C45 /* Pods-VLC-iOS-VLC for iOSUITests.distribution.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-iOS-VLC for iOSUITests.distribution.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-iOS-VLC for iOSUITests/Pods-VLC-iOS-VLC for iOSUITests.distribution.xcconfig"; sourceTree = "<group>"; };
27F3CE7A10961E7DA841096D /* Pods-VLC-iOS-VLC for iOSTests.distribution.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-iOS-VLC for iOSTests.distribution.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-iOS-VLC for iOSTests/Pods-VLC-iOS-VLC for iOSTests.distribution.xcconfig"; sourceTree = "<group>"; };
29125E5417492219003F03E5 /* index.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = index.html; sourceTree = "<group>"; };
2915544217490D4A00B86CAD /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
2B1BC34A3BC4BCE7588BD68A /* Pods-VLC-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-tvOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-tvOS/Pods-VLC-tvOS.release.xcconfig"; sourceTree = "<group>"; };
2CD27DA5256F95F3B8594C53 /* Pods-VLC-watchOS-Extension.distribution.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-watchOS-Extension.distribution.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-watchOS-Extension/Pods-VLC-watchOS-Extension.distribution.xcconfig"; sourceTree = "<group>"; };
31BBF816A2507AA02CD551A5 /* Pods-vlc-ios.distribution.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-vlc-ios.distribution.xcconfig"; path = "Pods/Target Support Files/Pods-vlc-ios/Pods-vlc-ios.distribution.xcconfig"; sourceTree = "<group>"; };
31E8A4CF7E65EE1E129A2D21 /* Pods-VLC-iOS-VLC for iOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-iOS-VLC for iOSTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-iOS-VLC for iOSTests/Pods-VLC-iOS-VLC for iOSTests.release.xcconfig"; sourceTree = "<group>"; };
31FB5C5DBFDA9DD74867E2D1 /* libPods-VLC-iOS-VLC for iOSUITests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-VLC-iOS-VLC for iOSUITests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
34DC96A915665AE9EABD30E8 /* Pods-VLC-iOS-Debug.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-iOS-Debug.release.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-iOS-Debug/Pods-VLC-iOS-Debug.release.xcconfig"; sourceTree = "<group>"; };
39DA271F3BEEFE045489B542 /* Pods-VLC-TV.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-TV.release.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-TV/Pods-VLC-TV.release.xcconfig"; sourceTree = "<group>"; };
......@@ -507,6 +520,10 @@
4144156920ECD2620078EC37 /* VLCSectionTableHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = VLCSectionTableHeaderView.swift; path = Sources/VLCSectionTableHeaderView.swift; sourceTree = "<group>"; };
4144156B20ECE6330078EC37 /* VLCFileServerSectionTableHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = VLCFileServerSectionTableHeaderView.swift; path = Sources/VLCFileServerSectionTableHeaderView.swift; sourceTree = "<group>"; };
4152F1611FEF19BD00F1908B /* KeychainCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = KeychainCoordinator.swift; path = Sources/KeychainCoordinator.swift; sourceTree = "<group>"; };
41533C91211338D500EC3ABA /* VLC for iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "VLC for iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
41533C9C2113392E00EC3ABA /* VLC-iOSTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VLC-iOSTests-Bridging-Header.h"; sourceTree = "<group>"; };
41533C9D2113392F00EC3ABA /* URLHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLHandlerTests.swift; sourceTree = "<group>"; };
41533CA1211343D100EC3ABA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "VLC-iOS-Tests/Info.plist"; sourceTree = SOURCE_ROOT; };
416443852048419E00CAC646 /* DeviceMotion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DeviceMotion.swift; path = Sources/DeviceMotion.swift; sourceTree = "<group>"; };
416DACB620B6DB9A001BC75D /* VLCPlayingExternallyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCPlayingExternallyView.swift; sourceTree = "<group>"; };
416DEFF51FEEA76A00F4FC59 /* LayoutAnchorContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LayoutAnchorContainer.swift; path = Sources/LayoutAnchorContainer.swift; sourceTree = "<group>"; };
......@@ -570,6 +587,7 @@
418B144C20179C74000447AA /* VLCTabBarCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = VLCTabBarCoordinator.swift; path = Sources/VLCTabBarCoordinator.swift; sourceTree = SOURCE_ROOT; };
418B144F20179CB9000447AA /* LayoutAnchorContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LayoutAnchorContainer.swift; path = Sources/LayoutAnchorContainer.swift; sourceTree = "<group>"; };
418B145820179E50000447AA /* VLCDragAndDropManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = VLCDragAndDropManager.swift; path = Sources/VLCDragAndDropManager.swift; sourceTree = "<group>"; };
418E88402110E51B00DDA6A7 /* URLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = URLHandler.swift; path = Sources/URLHandler.swift; sourceTree = "<group>"; };
4195747C206A92ED00393A42 /* RemoteNetworkDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteNetworkDataSource.swift; sourceTree = "<group>"; };
419A2C651F37A4B70069D224 /* VLCStringsForLocalization.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCStringsForLocalization.m; sourceTree = "<group>"; };
419D7F041F54176900AF69A2 /* VLCTimeNavigationTitleView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = VLCTimeNavigationTitleView.xib; path = Resources/VLCTimeNavigationTitleView.xib; sourceTree = SOURCE_ROOT; };
......@@ -1007,6 +1025,7 @@
CC87148317A56C85003C7383 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; lineEnding = 0; name = ca; path = ca.lproj/Localizable.strings; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.simpleColoring; };
CCAF837E17DE46D800E3578F /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
CCE2A22D17A5859E00D9EAAD /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
CD92B7DB3994F879C74A70E0 /* libPods-VLC-iOS-VLC for iOSTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-VLC-iOS-VLC for iOSTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
CF79FF6D83030EB30CF91FD1 /* libPods-VLC-iOS-Debug.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-VLC-iOS-Debug.a"; sourceTree = BUILT_PRODUCTS_DIR; };
D0BB9293AAFE75CF15A6C8BC /* Pods-vlc-ios.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-vlc-ios.release.xcconfig"; path = "Pods/Target Support Files/Pods-vlc-ios/Pods-vlc-ios.release.xcconfig"; sourceTree = "<group>"; };
D2711C77E8DF23DB7347ADC9 /* Pods-VLC-watchOS-Extension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-watchOS-Extension.release.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-watchOS-Extension/Pods-VLC-watchOS-Extension.release.xcconfig"; sourceTree = "<group>"; };
......@@ -1171,6 +1190,14 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
41533C8E211338D500EC3ABA /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
2A002188D3D6E76DEF147F08 /* libPods-VLC-iOS-VLC for iOSTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
41B0BC831F73ED7D0063BA26 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
......@@ -1275,6 +1302,16 @@
name = Coordinators;
sourceTree = "<group>";
};
41533C92211338D500EC3ABA /* VLC-iOS-Tests */ = {
isa = PBXGroup;
children = (
41533CA1211343D100EC3ABA /* Info.plist */,
41533C9D2113392F00EC3ABA /* URLHandlerTests.swift */,
41533C9C2113392E00EC3ABA /* VLC-iOSTests-Bridging-Header.h */,
);
path = "VLC-iOS-Tests";
sourceTree = "<group>";
};
41B0948320E6844700DE38AD /* MediaSubcategory */ = {
isa = PBXGroup;
children = (
......@@ -1672,6 +1709,7 @@
DD7110ED1AF38AFD00854776 /* SharedSources */,
7D13293E1BA1F10100BE647E /* VLC-TV */,
41B0BC871F73ED7D0063BA26 /* VLC-iOS-UITests */,
41533C92211338D500EC3ABA /* VLC-iOS-Tests */,
7D94FCDD16DE7D1000F2623B /* Frameworks */,
7D94FCDC16DE7D1000F2623B /* Products */,
A77803FFDA800BD6A3DAED0C /* Pods */,
......@@ -1686,6 +1724,7 @@
7D94FCDB16DE7D1000F2623B /* VLC for iOS.app */,
7D13293D1BA1F10100BE647E /* VLC-tvOS.app */,
41B0BC861F73ED7D0063BA26 /* VLC for iOSUITests.xctest */,
41533C91211338D500EC3ABA /* VLC for iOSTests.xctest */,
);
name = Products;
sourceTree = "<group>";
......@@ -1760,6 +1799,7 @@
FF73F10D7535681155A87975 /* libPods-VLC-watchOS.a */,
260624EB5BF9F1FBE58BF816 /* libPods-VLC for iOSUITests.a */,
31FB5C5DBFDA9DD74867E2D1 /* libPods-VLC-iOS-VLC for iOSUITests.a */,
CD92B7DB3994F879C74A70E0 /* libPods-VLC-iOS-VLC for iOSTests.a */,
);
name = Frameworks;
sourceTree = "<group>";
......@@ -1770,6 +1810,7 @@
415163B01FD0AEC700161354 /* Coordinators */,
41273A391A955C4100A2EF77 /* VLCMigrationViewController.h */,
41273A3A1A955C4100A2EF77 /* VLCMigrationViewController.m */,
418E88402110E51B00DDA6A7 /* URLHandler.swift */,
7D6B08BB174A72A900A05173 /* VLCConstants.h */,
7DBBF180183AB3B80009A339 /* VLCAppDelegate.h */,
7DBBF181183AB3B80009A339 /* VLCAppDelegate.m */,
......@@ -2193,6 +2234,9 @@
A945E02675B76197DEFE0486 /* Pods-VLC-iOS-VLC for iOSUITests.debug.xcconfig */,
E8DB9015F858FF86D1419F2C /* Pods-VLC-iOS-VLC for iOSUITests.release.xcconfig */,
27E1FE5B2995E84315076C45 /* Pods-VLC-iOS-VLC for iOSUITests.distribution.xcconfig */,
1C174528BFB46C3490E773B6 /* Pods-VLC-iOS-VLC for iOSTests.debug.xcconfig */,
31E8A4CF7E65EE1E129A2D21 /* Pods-VLC-iOS-VLC for iOSTests.release.xcconfig */,
27F3CE7A10961E7DA841096D /* Pods-VLC-iOS-VLC for iOSTests.distribution.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
......@@ -2494,6 +2538,26 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
41533C90211338D500EC3ABA /* VLC for iOSTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 41533C98211338D600EC3ABA /* Build configuration list for PBXNativeTarget "VLC for iOSTests" */;
buildPhases = (
16C1AB96786C00EC189F241D /* [CP] Check Pods Manifest.lock */,
41533C8D211338D500EC3ABA /* Sources */,
41533C8E211338D500EC3ABA /* Frameworks */,
41533C8F211338D500EC3ABA /* Resources */,
92EAC000EE54D3264CC62EF8 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
41533C97211338D600EC3ABA /* PBXTargetDependency */,
);
name = "VLC for iOSTests";
productName = "VLC for iOSTests";
productReference = 41533C91211338D500EC3ABA /* VLC for iOSTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
41B0BC851F73ED7D0063BA26 /* VLC for iOSUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 41B0BC901F73ED7D0063BA26 /* Build configuration list for PBXNativeTarget "VLC for iOSUITests" */;
......@@ -2563,10 +2627,17 @@
isa = PBXProject;
attributes = {
CLASSPREFIX = VLC;
LastSwiftUpdateCheck = 0720;