diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2022-09-25 16:34:23 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2022-09-26 16:35:38 +0200 |
| commit | f389956c2cd884df142adbf00ff2ac7e2f69c2b2 (patch) | |
| tree | 5f7d4869324760eb4ba0107c0356edc89efd1457 /ios | |
| parent | 2e83b1ca27ff243a615ff10c94c20840b38dfd45 (diff) | |
| download | mullvadvpn-f389956c2cd884df142adbf00ff2ac7e2f69c2b2.tar.xz mullvadvpn-f389956c2cd884df142adbf00ff2ac7e2f69c2b2.zip | |
Move AsyncOperation into Operations static library and add separate tests
Diffstat (limited to 'ios')
62 files changed, 832 insertions, 362 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index e86d8aab37..a76f70fbd1 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -7,9 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 58059DDC28465E8F002B1049 /* TransformOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDB28465E8F002B1049 /* TransformOperation.swift */; }; - 58059DDE28468158002B1049 /* OutputOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDD28468158002B1049 /* OutputOperation.swift */; }; - 58059DE02846823E002B1049 /* ResultOperation+Output.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDF2846823E002B1049 /* ResultOperation+Output.swift */; }; 5806767C27048E9B00C858CB /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CE5E7B224146470008646E /* PacketTunnelProvider.swift */; }; 5807483B27DB8A980020ECBF /* WireGuardKitTypes in Frameworks */ = {isa = PBXBuildFile; productRef = 5807483A27DB8A980020ECBF /* WireGuardKitTypes */; }; 5807E2C02432038B00F5FF30 /* String+Split.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5807E2BF2432038B00F5FF30 /* String+Split.swift */; }; @@ -21,8 +18,6 @@ 58095C532760EEC700890776 /* RESTNetworkOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58095C522760EEC700890776 /* RESTNetworkOperation.swift */; }; 58095C572760F47900890776 /* api-ip-address.json in Resources */ = {isa = PBXBuildFile; fileRef = 58095C562760F47900890776 /* api-ip-address.json */; }; 58095C592762155700890776 /* RESTRetryStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58095C582762155700890776 /* RESTRetryStrategy.swift */; }; - 580CBFB82848D503007878F0 /* OperationConditionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580CBFB72848D503007878F0 /* OperationConditionTests.swift */; }; - 580EE22424B3243100F9D8A1 /* AsyncBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */; }; 580F8B8328197881002E0998 /* TunnelSettingsV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8228197881002E0998 /* TunnelSettingsV2.swift */; }; 580F8B8428197884002E0998 /* TunnelSettingsV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8228197881002E0998 /* TunnelSettingsV2.swift */; }; 580F8B8628197958002E0998 /* DNSSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8528197958002E0998 /* DNSSettings.swift */; }; @@ -39,6 +34,11 @@ 581503A624D6F4AE00C9C50E /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581503A524D6F4AE00C9C50E /* Logging.swift */; }; 581503A724D6F4AE00C9C50E /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581503A524D6F4AE00C9C50E /* Logging.swift */; }; 58161C9C28352F850028ECFD /* MigrateSettingsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58161C9B28352F850028ECFD /* MigrateSettingsOperation.swift */; }; + 5818139F28E09BD8002817DE /* libOperations.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58E5126528DDF04200B0BCDE /* libOperations.a */; }; + 581813A128E09DBB002817DE /* NoCancelledDependenciesCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581813A028E09DBB002817DE /* NoCancelledDependenciesCondition.swift */; }; + 581813A328E09DCD002817DE /* NoFailedDependenciesCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581813A228E09DCD002817DE /* NoFailedDependenciesCondition.swift */; }; + 581813A528E09DE2002817DE /* BlockCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581813A428E09DE2002817DE /* BlockCondition.swift */; }; + 581813A728E09DF2002817DE /* MutuallyExclusive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581813A628E09DF2002817DE /* MutuallyExclusive.swift */; }; 5819C2142726CC8D00D6EC38 /* DataSourceSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5819C2132726CC8D00D6EC38 /* DataSourceSnapshotTests.swift */; }; 5819C2152726CC9400D6EC38 /* DataSourceSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587EB66F27143B6500123C75 /* DataSourceSnapshot.swift */; }; 5819C2172729595500D6EC38 /* SettingsAddDNSEntryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5819C2162729595500D6EC38 /* SettingsAddDNSEntryCell.swift */; }; @@ -50,7 +50,6 @@ 5820675926E652BE00655B05 /* RESTCoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA88926B027A300B8C587 /* RESTCoding.swift */; }; 5820675B26E6576800655B05 /* RelayCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820675A26E6576800655B05 /* RelayCache.swift */; }; 5820675C26E6576800655B05 /* RelayCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820675A26E6576800655B05 /* RelayCache.swift */; }; - 5820675E26E6839900655B05 /* PresentAlertOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820675D26E6839900655B05 /* PresentAlertOperation.swift */; }; 5820676226E75D8500655B05 /* REST.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820674D26E6510200655B05 /* REST.swift */; }; 5820676426E771DB00655B05 /* TunnelManagerErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820676326E771DB00655B05 /* TunnelManagerErrors.swift */; }; 5820EDA9288FE064006BF4E4 /* DeviceManagementInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820EDA8288FE064006BF4E4 /* DeviceManagementInteractor.swift */; }; @@ -71,27 +70,15 @@ 5835B7CC233B76CB0096D79F /* TunnelManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5835B7CB233B76CB0096D79F /* TunnelManager.swift */; }; 5838318B27C40A3900000571 /* Pinger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5838318A27C40A3900000571 /* Pinger.swift */; }; 583DA21425FA4B5C00318683 /* LocationDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 583DA21325FA4B5C00318683 /* LocationDataSource.swift */; }; - 583E1E1C2848DE1C004838B3 /* AsyncOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28782846250500F9A7B3 /* AsyncOperationQueue.swift */; }; - 583E1E1E2848DE1C004838B3 /* OperationCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28772846250500F9A7B3 /* OperationCondition.swift */; }; - 583E1E202848DE1C004838B3 /* OperationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28792846250500F9A7B3 /* OperationObserver.swift */; }; - 583E1E222848DE1C004838B3 /* GroupOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28812846306C00F9A7B3 /* GroupOperation.swift */; }; - 583E1E232848DE1C004838B3 /* OperationCompletion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840BE34279EDB16002836BA /* OperationCompletion.swift */; }; - 583E1E252848DE1C004838B3 /* ResultOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7D26427EB50A300E4D821 /* ResultOperation.swift */; }; - 583E1E262848DE1C004838B3 /* ResultBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5842102D282D3FC200F24E46 /* ResultBlockOperation.swift */; }; - 583E1E282848DE1C004838B3 /* BackgroundObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D287F28462CB000F9A7B3 /* BackgroundObserver.swift */; }; - 583E1E2A2848DF67004838B3 /* OperationObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 583E1E292848DF67004838B3 /* OperationObserverTests.swift */; }; 583E1E2C2848E1A1004838B3 /* WireGuardKitTypes in Frameworks */ = {isa = PBXBuildFile; productRef = 583E1E2B2848E1A1004838B3 /* WireGuardKitTypes */; }; 5840250122B1124600E4CFEC /* IPAddress+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250022B1124600E4CFEC /* IPAddress+Codable.swift */; }; 5840250222B1124600E4CFEC /* IPAddress+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250022B1124600E4CFEC /* IPAddress+Codable.swift */; }; 5840250422B11AB700E4CFEC /* MullvadEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250322B11AB700E4CFEC /* MullvadEndpoint.swift */; }; 5840250522B11AB700E4CFEC /* MullvadEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250322B11AB700E4CFEC /* MullvadEndpoint.swift */; }; - 5840BE35279EDB16002836BA /* OperationCompletion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840BE34279EDB16002836BA /* OperationCompletion.swift */; }; - 5842102E282D3FC200F24E46 /* ResultBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5842102D282D3FC200F24E46 /* ResultBlockOperation.swift */; }; 58421030282D8A3C00F24E46 /* UpdateAccountDataOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5842102F282D8A3C00F24E46 /* UpdateAccountDataOperation.swift */; }; 58421032282E42B000F24E46 /* UpdateDeviceDataOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58421031282E42B000F24E46 /* UpdateDeviceDataOperation.swift */; }; 58421034282E4B1500F24E46 /* TunnelSettingsV2+REST.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58421033282E4B1500F24E46 /* TunnelSettingsV2+REST.swift */; }; 584592612639B4A200EF967F /* TermsOfServiceContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584592602639B4A200EF967F /* TermsOfServiceContentView.swift */; }; - 5846226526E0D9630035F7C2 /* ProductsRequestOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846226426E0D9630035F7C2 /* ProductsRequestOperation.swift */; }; 5846227126E229F20035F7C2 /* AppStoreSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227026E229F20035F7C2 /* AppStoreSubscription.swift */; }; 5846227326E22A160035F7C2 /* AppStorePaymentObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227226E22A160035F7C2 /* AppStorePaymentObserver.swift */; }; 5846227726E22A7C0035F7C2 /* AppStorePaymentManagerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227626E22A7C0035F7C2 /* AppStorePaymentManagerDelegate.swift */; }; @@ -117,8 +104,6 @@ 58554F7D280D6FE000013055 /* RESTURLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58554F7C280D6FE000013055 /* RESTURLSession.swift */; }; 58561C99239A5D1500BD6B5E /* IPEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58561C98239A5D1500BD6B5E /* IPEndpoint.swift */; }; 58561C9A239A5D1500BD6B5E /* IPEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58561C98239A5D1500BD6B5E /* IPEndpoint.swift */; }; - 5857F23424C8443700CF6F47 /* AsyncOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E973DD24850EB600096F90 /* AsyncOperation.swift */; }; - 5857F23824C8446700CF6F47 /* AsyncBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */; }; 5857F24324C8662600CF6F47 /* SelectLocationHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5857F24224C8662600CF6F47 /* SelectLocationHeaderView.swift */; }; 5857F24724C882D700CF6F47 /* SelectLocationNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5857F24624C882D700CF6F47 /* SelectLocationNavigationController.swift */; }; 585834F824D2BC1F00A8AF56 /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 585834F724D2BC1F00A8AF56 /* Logging */; }; @@ -143,7 +128,6 @@ 5868585524054096000B8131 /* AppButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5868585424054096000B8131 /* AppButton.swift */; }; 5868BD33261DCD2600E6027F /* CustomSplitViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5868BD32261DCD2600E6027F /* CustomSplitViewController.swift */; }; 586E54FB27A2DF6D0029B88B /* SendTunnelProviderMessageOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 586E54FA27A2DF6D0029B88B /* SendTunnelProviderMessageOperation.swift */; }; - 5871FB8325498CA20051A0A4 /* Swizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5871FB8225498CA20051A0A4 /* Swizzle.swift */; }; 5871FB96254ADE4E0051A0A4 /* ConsolidatedApplicationLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5871FB95254ADE4E0051A0A4 /* ConsolidatedApplicationLog.swift */; }; 5871FBA0254C26C00051A0A4 /* NSRegularExpression+IPAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5871FB9F254C26BF0051A0A4 /* NSRegularExpression+IPAddress.swift */; }; 5872631B283F6EAB00E14ADF /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 5872631A283F6EAB00E14ADF /* Intents.intentdefinition */; }; @@ -185,7 +169,6 @@ 588BCF24280FE43D009ADCEC /* RESTDevicesProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 588BCF23280FE43D009ADCEC /* RESTDevicesProxy.swift */; }; 588BCF26280FE79A009ADCEC /* RESTProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 588BCF25280FE79A009ADCEC /* RESTProxy.swift */; }; 588BCF282816D664009ADCEC /* RESTResponseHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 588BCF272816D664009ADCEC /* RESTResponseHandler.swift */; }; - 588D2FE3248AC27F00E313F7 /* AsyncOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E973DD24850EB600096F90 /* AsyncOperation.swift */; }; 58900D0328BBDCC70094E4F0 /* FixedWidthInteger+Arithmetics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58900D0228BBDCC70094E4F0 /* FixedWidthInteger+Arithmetics.swift */; }; 58906DE02445C7A5002F0673 /* NEProviderStopReason+Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58906DDF2445C7A5002F0673 /* NEProviderStopReason+Debug.swift */; }; 58907D9524D17B4E00CFC3F5 /* DisconnectSplitButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58907D9424D17B4E00CFC3F5 /* DisconnectSplitButton.swift */; }; @@ -198,11 +181,13 @@ 5896AE86246D6AD8005B36CB /* CustomDateComponentsFormattingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5896AE85246D6AD8005B36CB /* CustomDateComponentsFormattingTests.swift */; }; 5896AE88246D7FAF005B36CB /* CustomDateComponentsFormatting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5896AE83246D5889005B36CB /* CustomDateComponentsFormatting.swift */; }; 5896CEF226972DEB00B0FAE8 /* AccountContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5896CEF126972DEB00B0FAE8 /* AccountContentView.swift */; }; - 589D287A2846250500F9A7B3 /* OperationCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28772846250500F9A7B3 /* OperationCondition.swift */; }; - 589D287B2846250500F9A7B3 /* AsyncOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28782846250500F9A7B3 /* AsyncOperationQueue.swift */; }; - 589D287C2846250500F9A7B3 /* OperationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28792846250500F9A7B3 /* OperationObserver.swift */; }; - 589D288028462CB000F9A7B3 /* BackgroundObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D287F28462CB000F9A7B3 /* BackgroundObserver.swift */; }; - 589D28822846306C00F9A7B3 /* GroupOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28812846306C00F9A7B3 /* GroupOperation.swift */; }; + 589A454C28DDF5E100565204 /* Swizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589A454B28DDF5E100565204 /* Swizzle.swift */; }; + 589A454D28DDF5E500565204 /* Swizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589A454B28DDF5E100565204 /* Swizzle.swift */; }; + 589A455628E094B300565204 /* libOperations.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58E5126528DDF04200B0BCDE /* libOperations.a */; }; + 589A455C28E094BF00565204 /* OperationSmokeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B7E2852778600E92647 /* OperationSmokeTests.swift */; }; + 589A455D28E094BF00565204 /* OperationObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 583E1E292848DF67004838B3 /* OperationObserverTests.swift */; }; + 589A455E28E094BF00565204 /* OperationInputInjectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B772852178600E92647 /* OperationInputInjectionTests.swift */; }; + 589A455F28E094BF00565204 /* OperationConditionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580CBFB72848D503007878F0 /* OperationConditionTests.swift */; }; 58A1AA8C23F5584C009F7EA6 /* ConnectionPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A1AA8B23F5584B009F7EA6 /* ConnectionPanelView.swift */; }; 58A3BDB028A1821A00C8C2C6 /* WgStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A3BDAF28A1821A00C8C2C6 /* WgStats.swift */; }; 58A8055E2716EA6700681642 /* AnyIPAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26BE270C550B004EA533 /* AnyIPAddress.swift */; }; @@ -227,7 +212,6 @@ 58B67B482602079E008EF58E /* RelaySelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58781CD422AFBA39009B9D8E /* RelaySelector.swift */; }; 58B93A1326C3F13600A55733 /* TunnelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58B93A1226C3F13600A55733 /* TunnelState.swift */; }; 58B993B12608A34500BA7811 /* LoginContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58B993B02608A34500BA7811 /* LoginContentView.swift */; }; - 58B9EB132488ED2100095626 /* AlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58B9EB122488ED2100095626 /* AlertPresenter.swift */; }; 58B9EB152489139B00095626 /* DisplayChainedError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58B9EB142489139B00095626 /* DisplayChainedError.swift */; }; 58BA693123EADA6A009DC256 /* SimulatorTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BA693023EADA6A009DC256 /* SimulatorTunnelProvider.swift */; }; 58BA791B2578F092006FAEA0 /* WireGuardKit in Frameworks */ = {isa = PBXBuildFile; productRef = 58BA791A2578F092006FAEA0 /* WireGuardKit */; }; @@ -252,16 +236,26 @@ 58D0C79E23F1CEBA00FE9BA7 /* SnapshotHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D0C79D23F1CEBA00FE9BA7 /* SnapshotHelper.swift */; }; 58D0C7A223F1CECF00FE9BA7 /* MullvadVPNScreenshots.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D0C7A023F1CECF00FE9BA7 /* MullvadVPNScreenshots.swift */; }; 58D67A0A26D7AE3300557C3C /* OSLogHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5823FA4F26CA690600283BF8 /* OSLogHandler.swift */; }; + 58D889B328DDF4B400583FA8 /* libOperations.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58E5126528DDF04200B0BCDE /* libOperations.a */; }; + 58D889B928DDF53500583FA8 /* BackgroundObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D287F28462CB000F9A7B3 /* BackgroundObserver.swift */; }; + 58D889BA28DDF53500583FA8 /* OutputOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDD28468158002B1049 /* OutputOperation.swift */; }; + 58D889BB28DDF53500583FA8 /* AsyncOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28782846250500F9A7B3 /* AsyncOperationQueue.swift */; }; + 58D889BC28DDF53500583FA8 /* OperationCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28772846250500F9A7B3 /* OperationCondition.swift */; }; + 58D889BD28DDF53500583FA8 /* ProductsRequestOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846226426E0D9630035F7C2 /* ProductsRequestOperation.swift */; }; + 58D889BE28DDF53500583FA8 /* AsyncBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */; }; + 58D889BF28DDF53500583FA8 /* OperationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28792846250500F9A7B3 /* OperationObserver.swift */; }; + 58D889C028DDF53500583FA8 /* AlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58B9EB122488ED2100095626 /* AlertPresenter.swift */; }; + 58D889C128DDF53500583FA8 /* InputInjectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B752852108E00E92647 /* InputInjectionBuilder.swift */; }; + 58D889C228DDF53500583FA8 /* OperationCompletion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840BE34279EDB16002836BA /* OperationCompletion.swift */; }; + 58D889C328DDF53500583FA8 /* PresentAlertOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820675D26E6839900655B05 /* PresentAlertOperation.swift */; }; + 58D889C428DDF53500583FA8 /* ResultBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5842102D282D3FC200F24E46 /* ResultBlockOperation.swift */; }; + 58D889C528DDF53500583FA8 /* TransformOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDB28465E8F002B1049 /* TransformOperation.swift */; }; + 58D889C628DDF53500583FA8 /* GroupOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28812846306C00F9A7B3 /* GroupOperation.swift */; }; + 58D889C728DDF53500583FA8 /* AsyncOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E973DD24850EB600096F90 /* AsyncOperation.swift */; }; + 58D889C828DDF53500583FA8 /* ResultOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7D26427EB50A300E4D821 /* ResultOperation.swift */; }; + 58D889C928DDF53500583FA8 /* InputOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B732851FF3F00E92647 /* InputOperation.swift */; }; + 58D889CA28DDF53500583FA8 /* ResultOperation+Output.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDF2846823E002B1049 /* ResultOperation+Output.swift */; }; 58DF28A52417CB4B00E836B0 /* AppStorePaymentManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF28A42417CB4B00E836B0 /* AppStorePaymentManager.swift */; }; - 58DF5B742851FF3F00E92647 /* InputOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B732851FF3F00E92647 /* InputOperation.swift */; }; - 58DF5B762852108E00E92647 /* InputInjectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B752852108E00E92647 /* InputInjectionBuilder.swift */; }; - 58DF5B782852178600E92647 /* OperationInputInjectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B772852178600E92647 /* OperationInputInjectionTests.swift */; }; - 58DF5B79285217F300E92647 /* TransformOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDB28465E8F002B1049 /* TransformOperation.swift */; }; - 58DF5B7A285217FA00E92647 /* InputInjectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B752852108E00E92647 /* InputInjectionBuilder.swift */; }; - 58DF5B7B285217FE00E92647 /* InputOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B732851FF3F00E92647 /* InputOperation.swift */; }; - 58DF5B7C28521A9F00E92647 /* ResultOperation+Output.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDF2846823E002B1049 /* ResultOperation+Output.swift */; }; - 58DF5B7D28521AAC00E92647 /* OutputOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDD28468158002B1049 /* OutputOperation.swift */; }; - 58DF5B7F2852778600E92647 /* OperationSmokeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B7E2852778600E92647 /* OperationSmokeTests.swift */; }; 58E0729D28814AAE008902F8 /* PacketTunnelConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E0729C28814AAE008902F8 /* PacketTunnelConfiguration.swift */; }; 58E0729F28814ACC008902F8 /* WireGuardLogLevel+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E0729E28814ACC008902F8 /* WireGuardLogLevel+Logging.swift */; }; 58E072A128814B0E008902F8 /* MullvadEndpoint+WgEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E072A028814B0E008902F8 /* MullvadEndpoint+WgEndpoint.swift */; }; @@ -292,7 +286,6 @@ 58F3C0A624A50157003E76BE /* relays.json in Resources */ = {isa = PBXBuildFile; fileRef = 58F3C0A524A50155003E76BE /* relays.json */; }; 58F3C0A724A50C02003E76BE /* relays.json in Resources */ = {isa = PBXBuildFile; fileRef = 58F3C0A524A50155003E76BE /* relays.json */; }; 58F7CA882692E34000FC59FD /* WireguardKeysContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7CA872692E34000FC59FD /* WireguardKeysContentView.swift */; }; - 58F7D26527EB50A300E4D821 /* ResultOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7D26427EB50A300E4D821 /* ResultOperation.swift */; }; 58F8AC0E25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F8AC0D25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift */; }; 58F97A1B280EEBC00050C2FC /* RESTProxyFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F97A1A280EEBC00050C2FC /* RESTProxyFactory.swift */; }; 58F97A1E280FDE230050C2FC /* RESTRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F97A1D280FDE230050C2FC /* RESTRequestHandler.swift */; }; @@ -328,6 +321,13 @@ remoteGlobalIDString = 58FBDA9722A519BC00EB69A3; remoteInfo = WireGuardGoBridge; }; + 589A455728E094B300565204 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 58CE5E58224146200008646E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 58E5126428DDF04200B0BCDE; + remoteInfo = Operations; + }; 58CE5E7F224146470008646E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 58CE5E58224146200008646E /* Project object */; @@ -342,6 +342,20 @@ remoteGlobalIDString = 58CE5E5F224146200008646E; remoteInfo = MullvadVPN; }; + 58D889B428DDF4DD00583FA8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 58CE5E58224146200008646E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 58E5126428DDF04200B0BCDE; + remoteInfo = Operations; + }; + 58E5126D28DDF09F00B0BCDE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 58CE5E58224146200008646E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 58E5126428DDF04200B0BCDE; + remoteInfo = Operations; + }; 58FBDAA122A52A6800EB69A3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 58CE5E58224146200008646E /* Project object */; @@ -363,6 +377,15 @@ name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; }; + 58E5126328DDF04200B0BCDE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -391,6 +414,10 @@ 581503A224D6F1EC00C9C50E /* Logger+Errors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logger+Errors.swift"; sourceTree = "<group>"; }; 581503A524D6F4AE00C9C50E /* Logging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = "<group>"; }; 58161C9B28352F850028ECFD /* MigrateSettingsOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrateSettingsOperation.swift; sourceTree = "<group>"; }; + 581813A028E09DBB002817DE /* NoCancelledDependenciesCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoCancelledDependenciesCondition.swift; sourceTree = "<group>"; }; + 581813A228E09DCD002817DE /* NoFailedDependenciesCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoFailedDependenciesCondition.swift; sourceTree = "<group>"; }; + 581813A428E09DE2002817DE /* BlockCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockCondition.swift; sourceTree = "<group>"; }; + 581813A628E09DF2002817DE /* MutuallyExclusive.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutuallyExclusive.swift; sourceTree = "<group>"; }; 5819C2132726CC8D00D6EC38 /* DataSourceSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataSourceSnapshotTests.swift; sourceTree = "<group>"; }; 5819C2162729595500D6EC38 /* SettingsAddDNSEntryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAddDNSEntryCell.swift; sourceTree = "<group>"; }; 5820674D26E6510200655B05 /* REST.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = REST.swift; sourceTree = "<group>"; }; @@ -463,7 +490,6 @@ 5868585424054096000B8131 /* AppButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppButton.swift; sourceTree = "<group>"; }; 5868BD32261DCD2600E6027F /* CustomSplitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomSplitViewController.swift; sourceTree = "<group>"; }; 586E54FA27A2DF6D0029B88B /* SendTunnelProviderMessageOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendTunnelProviderMessageOperation.swift; sourceTree = "<group>"; }; - 5871FB8225498CA20051A0A4 /* Swizzle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Swizzle.swift; sourceTree = "<group>"; }; 5871FB95254ADE4E0051A0A4 /* ConsolidatedApplicationLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsolidatedApplicationLog.swift; sourceTree = "<group>"; }; 5871FB9F254C26BF0051A0A4 /* NSRegularExpression+IPAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSRegularExpression+IPAddress.swift"; sourceTree = "<group>"; }; 5872631A283F6EAB00E14ADF /* Intents.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = Intents.intentdefinition; sourceTree = "<group>"; }; @@ -510,6 +536,8 @@ 5896AE83246D5889005B36CB /* CustomDateComponentsFormatting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDateComponentsFormatting.swift; sourceTree = "<group>"; }; 5896AE85246D6AD8005B36CB /* CustomDateComponentsFormattingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDateComponentsFormattingTests.swift; sourceTree = "<group>"; }; 5896CEF126972DEB00B0FAE8 /* AccountContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountContentView.swift; sourceTree = "<group>"; }; + 589A454B28DDF5E100565204 /* Swizzle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Swizzle.swift; sourceTree = "<group>"; }; + 589A455228E094B300565204 /* OperationsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OperationsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 589D28772846250500F9A7B3 /* OperationCondition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperationCondition.swift; sourceTree = "<group>"; }; 589D28782846250500F9A7B3 /* AsyncOperationQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncOperationQueue.swift; sourceTree = "<group>"; }; 589D28792846250500F9A7B3 /* OperationObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperationObserver.swift; sourceTree = "<group>"; }; @@ -576,6 +604,7 @@ 58E511E328DDDE8900B0BCDE /* CustomErrorDescriptionProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomErrorDescriptionProtocol.swift; sourceTree = "<group>"; }; 58E511E528DDDEAC00B0BCDE /* CodingErrors+CustomErrorDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CodingErrors+CustomErrorDescription.swift"; sourceTree = "<group>"; }; 58E511EA28DDE18400B0BCDE /* Error+Chain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Error+Chain.swift"; sourceTree = "<group>"; }; + 58E5126528DDF04200B0BCDE /* libOperations.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libOperations.a; sourceTree = BUILT_PRODUCTS_DIR; }; 58E6771E24ADFE7800AA26E7 /* SettingsNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsNavigationController.swift; sourceTree = "<group>"; }; 58E973DD24850EB600096F90 /* AsyncOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncOperation.swift; sourceTree = "<group>"; }; 58ECD29123F178FD004298B6 /* Screenshots.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Screenshots.xcconfig; sourceTree = "<group>"; }; @@ -620,10 +649,19 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 589A454F28E094B300565204 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 589A455628E094B300565204 /* libOperations.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 58B0A29D238EE67E00BC001D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 58D889B328DDF4B400583FA8 /* libOperations.a in Frameworks */, 583E1E2C2848E1A1004838B3 /* WireGuardKitTypes in Frameworks */, 584789EC2652A1A2000E45FB /* Logging in Frameworks */, ); @@ -633,6 +671,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 5818139F28E09BD8002817DE /* libOperations.a in Frameworks */, 5807483B27DB8A980020ECBF /* WireGuardKitTypes in Frameworks */, 585834F824D2BC1F00A8AF56 /* Logging in Frameworks */, ); @@ -654,6 +693,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 58E5126228DDF04200B0BCDE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -674,30 +720,6 @@ path = AddressCache; sourceTree = "<group>"; }; - 580EE1FF24B3218800F9D8A1 /* Operations */ = { - isa = PBXGroup; - children = ( - 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */, - 58E973DD24850EB600096F90 /* AsyncOperation.swift */, - 589D28782846250500F9A7B3 /* AsyncOperationQueue.swift */, - 589D287F28462CB000F9A7B3 /* BackgroundObserver.swift */, - 589D28812846306C00F9A7B3 /* GroupOperation.swift */, - 58DF5B752852108E00E92647 /* InputInjectionBuilder.swift */, - 58DF5B732851FF3F00E92647 /* InputOperation.swift */, - 5840BE34279EDB16002836BA /* OperationCompletion.swift */, - 589D28772846250500F9A7B3 /* OperationCondition.swift */, - 589D28792846250500F9A7B3 /* OperationObserver.swift */, - 58059DDD28468158002B1049 /* OutputOperation.swift */, - 5820675D26E6839900655B05 /* PresentAlertOperation.swift */, - 5846226426E0D9630035F7C2 /* ProductsRequestOperation.swift */, - 5842102D282D3FC200F24E46 /* ResultBlockOperation.swift */, - 58F7D26427EB50A300E4D821 /* ResultOperation.swift */, - 58059DDF2846823E002B1049 /* ResultOperation+Output.swift */, - 58059DDB28465E8F002B1049 /* TransformOperation.swift */, - ); - path = Operations; - sourceTree = "<group>"; - }; 580F8B88281A79A7002E0998 /* SettingsManager */ = { isa = PBXGroup; children = ( @@ -823,13 +845,28 @@ path = Notifications; sourceTree = "<group>"; }; - 58B0A2A1238EE67E00BC001D /* MullvadVPNTests */ = { + 589A454A28DDF59B00565204 /* Shared */ = { + isa = PBXGroup; + children = ( + 589A454B28DDF5E100565204 /* Swizzle.swift */, + ); + path = Shared; + sourceTree = "<group>"; + }; + 589A455328E094B300565204 /* OperationsTests */ = { isa = PBXGroup; children = ( 58DF5B7E2852778600E92647 /* OperationSmokeTests.swift */, 58DF5B772852178600E92647 /* OperationInputInjectionTests.swift */, 583E1E292848DF67004838B3 /* OperationObserverTests.swift */, 580CBFB72848D503007878F0 /* OperationConditionTests.swift */, + ); + path = OperationsTests; + sourceTree = "<group>"; + }; + 58B0A2A1238EE67E00BC001D /* MullvadVPNTests */ = { + isa = PBXGroup; + children = ( 582AE3112440CA0D00E6733A /* AccountTokenInputTests.swift */, 5896AE85246D6AD8005B36CB /* CustomDateComponentsFormattingTests.swift */, 58B0A2A4238EE67E00BC001D /* Info.plist */, @@ -848,9 +885,12 @@ 58ECD29023F178FD004298B6 /* Configurations */, 0E15C74FDCF763609B367486 /* Frameworks */, 582CFEE1269448160072883A /* Localizations */, + 589A454A28DDF59B00565204 /* Shared */, 58CE5E62224146200008646E /* MullvadVPN */, 58D0C79423F1CE7000FE9BA7 /* MullvadVPNScreenshots */, 58B0A2A1238EE67E00BC001D /* MullvadVPNTests */, + 58E5126628DDF04200B0BCDE /* Operations */, + 589A455328E094B300565204 /* OperationsTests */, 58CE5E7A224146470008646E /* PacketTunnel */, 58CE5E61224146200008646E /* Products */, ); @@ -863,6 +903,8 @@ 58CE5E79224146470008646E /* PacketTunnel.appex */, 58B0A2A0238EE67E00BC001D /* MullvadVPNTests.xctest */, 58D0C79323F1CE7000FE9BA7 /* MullvadVPNScreenshots.xctest */, + 58E5126528DDF04200B0BCDE /* libOperations.a */, + 589A455228E094B300565204 /* OperationsTests.xctest */, ); name = Products; sourceTree = "<group>"; @@ -877,7 +919,6 @@ 582AE30F2440A6CA00E6733A /* AccountTokenInput.swift */, 58CCA01722426713004F3011 /* AccountViewController.swift */, 58095C49275FA24800890776 /* AddressCache */, - 58B9EB122488ED2100095626 /* AlertPresenter.swift */, 584D26BE270C550B004EA533 /* AnyIPAddress.swift */, 5868585424054096000B8131 /* AppButton.swift */, 58CE5E63224146200008646E /* AppDelegate.swift */, @@ -944,7 +985,6 @@ 587D9675288989DB00CD8F1C /* NSLayoutConstraint+Helpers.swift */, 5871FB9F254C26BF0051A0A4 /* NSRegularExpression+IPAddress.swift */, 58CC40EE24A601900019D96E /* ObserverList.swift */, - 580EE1FF24B3218800F9D8A1 /* Operations */, E1187ABB289BBB850024E748 /* OutOfTimeContentView.swift */, E1187ABA289BBB850024E748 /* OutOfTimeViewController.swift */, 584D26C3270C855A004EA533 /* PreferencesDataSource.swift */, @@ -989,7 +1029,6 @@ 58EF581025D69DB400AEBA94 /* StatusImageView.swift */, 5807E2BF2432038B00F5FF30 /* String+Split.swift */, E158B35F285381C60002F069 /* StringFormatter.swift */, - 5871FB8225498CA20051A0A4 /* Swizzle.swift */, 5872D6E7286304DE00DB5F4E /* TermsOfService.swift */, 584592602639B4A200EF967F /* TermsOfServiceContentView.swift */, 58A99ED2240014A0006599E9 /* TermsOfServiceViewController.swift */, @@ -1045,6 +1084,35 @@ path = TunnelMonitor; sourceTree = "<group>"; }; + 58E5126628DDF04200B0BCDE /* Operations */ = { + isa = PBXGroup; + children = ( + 58B9EB122488ED2100095626 /* AlertPresenter.swift */, + 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */, + 58E973DD24850EB600096F90 /* AsyncOperation.swift */, + 589D28782846250500F9A7B3 /* AsyncOperationQueue.swift */, + 589D287F28462CB000F9A7B3 /* BackgroundObserver.swift */, + 581813A428E09DE2002817DE /* BlockCondition.swift */, + 589D28812846306C00F9A7B3 /* GroupOperation.swift */, + 58DF5B752852108E00E92647 /* InputInjectionBuilder.swift */, + 58DF5B732851FF3F00E92647 /* InputOperation.swift */, + 581813A628E09DF2002817DE /* MutuallyExclusive.swift */, + 581813A028E09DBB002817DE /* NoCancelledDependenciesCondition.swift */, + 581813A228E09DCD002817DE /* NoFailedDependenciesCondition.swift */, + 5840BE34279EDB16002836BA /* OperationCompletion.swift */, + 589D28772846250500F9A7B3 /* OperationCondition.swift */, + 589D28792846250500F9A7B3 /* OperationObserver.swift */, + 58059DDD28468158002B1049 /* OutputOperation.swift */, + 5820675D26E6839900655B05 /* PresentAlertOperation.swift */, + 5846226426E0D9630035F7C2 /* ProductsRequestOperation.swift */, + 5842102D282D3FC200F24E46 /* ResultBlockOperation.swift */, + 58F7D26427EB50A300E4D821 /* ResultOperation.swift */, + 58059DDF2846823E002B1049 /* ResultOperation+Output.swift */, + 58059DDB28465E8F002B1049 /* TransformOperation.swift */, + ); + path = Operations; + sourceTree = "<group>"; + }; 58ECD29023F178FD004298B6 /* Configurations */ = { isa = PBXGroup; children = ( @@ -1087,6 +1155,24 @@ /* End PBXLegacyTarget section */ /* Begin PBXNativeTarget section */ + 589A455128E094B300565204 /* OperationsTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 589A455928E094B300565204 /* Build configuration list for PBXNativeTarget "OperationsTests" */; + buildPhases = ( + 589A454E28E094B300565204 /* Sources */, + 589A454F28E094B300565204 /* Frameworks */, + 589A455028E094B300565204 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 589A455828E094B300565204 /* PBXTargetDependency */, + ); + name = OperationsTests; + productName = OperationsTests; + productReference = 589A455228E094B300565204 /* OperationsTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 58B0A29F238EE67E00BC001D /* MullvadVPNTests */ = { isa = PBXNativeTarget; buildConfigurationList = 58B0A2A5238EE67E00BC001D /* Build configuration list for PBXNativeTarget "MullvadVPNTests" */; @@ -1098,6 +1184,7 @@ buildRules = ( ); dependencies = ( + 58D889B528DDF4DD00583FA8 /* PBXTargetDependency */, 5841E04325D53BCC00D989F7 /* PBXTargetDependency */, ); name = MullvadVPNTests; @@ -1122,6 +1209,7 @@ ); dependencies = ( 58CE5E80224146470008646E /* PBXTargetDependency */, + 58E5126E28DDF09F00B0BCDE /* PBXTargetDependency */, ); name = MullvadVPN; packageProductDependencies = ( @@ -1172,16 +1260,36 @@ productReference = 58D0C79323F1CE7000FE9BA7 /* MullvadVPNScreenshots.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; }; + 58E5126428DDF04200B0BCDE /* Operations */ = { + isa = PBXNativeTarget; + buildConfigurationList = 58E5126B28DDF04200B0BCDE /* Build configuration list for PBXNativeTarget "Operations" */; + buildPhases = ( + 58E5126128DDF04200B0BCDE /* Sources */, + 58E5126228DDF04200B0BCDE /* Frameworks */, + 58E5126328DDF04200B0BCDE /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Operations; + productName = Operations; + productReference = 58E5126528DDF04200B0BCDE /* libOperations.a */; + productType = "com.apple.product-type.library.static"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 58CE5E58224146200008646E /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1130; + LastSwiftUpdateCheck = 1400; LastUpgradeCheck = 1400; ORGANIZATIONNAME = "Mullvad VPN AB"; TargetAttributes = { + 589A455128E094B300565204 = { + CreatedOnToolsVersion = 14.0.1; + }; 58B0A29F238EE67E00BC001D = { CreatedOnToolsVersion = 11.2.1; }; @@ -1210,6 +1318,9 @@ CreatedOnToolsVersion = 11.3; TestTargetID = 58CE5E5F224146200008646E; }; + 58E5126428DDF04200B0BCDE = { + CreatedOnToolsVersion = 14.0.1; + }; 58FBDA9722A519BC00EB69A3 = { CreatedOnToolsVersion = 10.2.1; }; @@ -1237,11 +1348,20 @@ 58CE5E78224146470008646E /* PacketTunnel */, 58B0A29F238EE67E00BC001D /* MullvadVPNTests */, 58D0C79223F1CE7000FE9BA7 /* MullvadVPNScreenshots */, + 58E5126428DDF04200B0BCDE /* Operations */, + 589A455128E094B300565204 /* OperationsTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 589A455028E094B300565204 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 58B0A29E238EE67E00BC001D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1281,54 +1401,46 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 589A454E28E094B300565204 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 589A455F28E094BF00565204 /* OperationConditionTests.swift in Sources */, + 589A455E28E094BF00565204 /* OperationInputInjectionTests.swift in Sources */, + 589A455C28E094BF00565204 /* OperationSmokeTests.swift in Sources */, + 589A455D28E094BF00565204 /* OperationObserverTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 58B0A29C238EE67E00BC001D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 58DF5B7A285217FA00E92647 /* InputInjectionBuilder.swift in Sources */, 582AE3132440CA2700E6733A /* AccountTokenInput.swift in Sources */, 58CAF4EF26025954007C5886 /* SimulatorTunnelProvider.swift in Sources */, - 583E1E232848DE1C004838B3 /* OperationCompletion.swift in Sources */, - 583E1E222848DE1C004838B3 /* GroupOperation.swift in Sources */, 58B0A2AA238EE6A900BC001D /* RelaySelector.swift in Sources */, 5896AE86246D6AD8005B36CB /* CustomDateComponentsFormattingTests.swift in Sources */, 5807E2C3243203E700F5FF30 /* String+Split.swift in Sources */, 58B0A2A8238EE68200BC001D /* RelaySelectorTests.swift in Sources */, 5819C2152726CC9400D6EC38 /* DataSourceSnapshot.swift in Sources */, 584E96BE240FD4DB00D3334F /* Location.swift in Sources */, - 5857F23424C8443700CF6F47 /* AsyncOperation.swift in Sources */, 585DA8A626B14F5100B8C587 /* SSLPinningURLSessionDelegate.swift in Sources */, 582A8A3B28BCE1AB00D0F9FB /* FixedWidthInteger+Arithmetics.swift in Sources */, 58B0A2AC238EE6D500BC001D /* IPAddress+Codable.swift in Sources */, 58B0A2AD238EE6EC00BC001D /* MullvadEndpoint.swift in Sources */, - 58DF5B7F2852778600E92647 /* OperationSmokeTests.swift in Sources */, 58FAEDF4245088B300CB0F5B /* KeychainError.swift in Sources */, - 583E1E252848DE1C004838B3 /* ResultOperation.swift in Sources */, - 583E1E262848DE1C004838B3 /* ResultBlockOperation.swift in Sources */, - 583E1E2A2848DF67004838B3 /* OperationObserverTests.swift in Sources */, 5896AE88246D7FAF005B36CB /* CustomDateComponentsFormatting.swift in Sources */, - 5857F23824C8446700CF6F47 /* AsyncBlockOperation.swift in Sources */, 582AE3122440CA0D00E6733A /* AccountTokenInputTests.swift in Sources */, - 58DF5B782852178600E92647 /* OperationInputInjectionTests.swift in Sources */, 582A8A3A28BCE19B00D0F9FB /* FixedWidthIntegerArithmeticsTests.swift in Sources */, 58B0A2A9238EE6A100BC001D /* RelayConstraints.swift in Sources */, - 583E1E282848DE1C004838B3 /* BackgroundObserver.swift in Sources */, 5807E2C2243203D000F5FF30 /* StringTests.swift in Sources */, - 58DF5B7B285217FE00E92647 /* InputOperation.swift in Sources */, 5819C2142726CC8D00D6EC38 /* DataSourceSnapshotTests.swift in Sources */, 585DA8A326B14E0D00B8C587 /* ServerRelaysResponse.swift in Sources */, 58A8D1D72892D3D60065405D /* PacketTunnelStatus.swift in Sources */, - 583E1E1E2848DE1C004838B3 /* OperationCondition.swift in Sources */, - 583E1E1C2848DE1C004838B3 /* AsyncOperationQueue.swift in Sources */, 5820676226E75D8500655B05 /* REST.swift in Sources */, 58A8055E2716EA6700681642 /* AnyIPAddress.swift in Sources */, - 58DF5B7D28521AAC00E92647 /* OutputOperation.swift in Sources */, - 58DF5B79285217F300E92647 /* TransformOperation.swift in Sources */, 58A8BE81239FBE62006B74AC /* IPEndpoint.swift in Sources */, 58871D2325D535D2002297FA /* IPAddressRange+Codable.swift in Sources */, - 580CBFB82848D503007878F0 /* OperationConditionTests.swift in Sources */, - 583E1E202848DE1C004838B3 /* OperationObserver.swift in Sources */, - 58DF5B7C28521A9F00E92647 /* ResultOperation+Output.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1344,24 +1456,21 @@ 587988C728A2A01F00E3DF54 /* AccountDataThrottling.swift in Sources */, 5896CEF226972DEB00B0FAE8 /* AccountContentView.swift in Sources */, 5840250122B1124600E4CFEC /* IPAddress+Codable.swift in Sources */, - 5842102E282D3FC200F24E46 /* ResultBlockOperation.swift in Sources */, 587D96742886D87C00CD8F1C /* DeviceManagementContentView.swift in Sources */, + 589A454C28DDF5E100565204 /* Swizzle.swift in Sources */, 5857F24724C882D700CF6F47 /* SelectLocationNavigationController.swift in Sources */, 5846227126E229F20035F7C2 /* AppStoreSubscription.swift in Sources */, 58421030282D8A3C00F24E46 /* UpdateAccountDataOperation.swift in Sources */, 5820675B26E6576800655B05 /* RelayCache.swift in Sources */, - 5846226526E0D9630035F7C2 /* ProductsRequestOperation.swift in Sources */, 58FF2C03281BDE02009EF542 /* SettingsManager.swift in Sources */, 587EB672271451E300123C75 /* PreferencesViewModel.swift in Sources */, 58095C512760BBB500890776 /* AddressCacheTracker.swift in Sources */, 584D26C6270C8741004EA533 /* SettingsDNSTextCell.swift in Sources */, 585DA87D26B0254000B8C587 /* RelayCacheIO.swift in Sources */, 58F2E148276A307400A79513 /* MapConnectionStatusOperation.swift in Sources */, - 58F7D26527EB50A300E4D821 /* ResultOperation.swift in Sources */, 58BA693123EADA6A009DC256 /* SimulatorTunnelProvider.swift in Sources */, 58F1311327E09B00007AC5BC /* Cancellable.swift in Sources */, 587C575326D2615F005EF767 /* PacketTunnelOptions.swift in Sources */, - 589D287C2846250500F9A7B3 /* OperationObserver.swift in Sources */, 587B753B2666467500DEF7E9 /* NotificationBannerView.swift in Sources */, 58B993B12608A34500BA7811 /* LoginContentView.swift in Sources */, 58E6771F24ADFE7800AA26E7 /* SettingsNavigationController.swift in Sources */, @@ -1371,11 +1480,9 @@ 58F1311527E0B2AB007AC5BC /* Result+Extensions.swift in Sources */, 5872631B283F6EAB00E14ADF /* Intents.intentdefinition in Sources */, 585DA88426B0270700B8C587 /* ServerRelaysResponse.swift in Sources */, - 58DF5B742851FF3F00E92647 /* InputOperation.swift in Sources */, 58F8AC0E25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift in Sources */, 58CCA010224249A1004F3011 /* ConnectViewController.swift in Sources */, 5893716A28817A45004EE76C /* DeviceManagementViewController.swift in Sources */, - 58059DE02846823E002B1049 /* ResultOperation+Output.swift in Sources */, 588BCF282816D664009ADCEC /* RESTResponseHandler.swift in Sources */, 58554F77280AFD5C00013055 /* RESTTaskIdentifier.swift in Sources */, 58BFA5C622A7C97F00A6173D /* RelayCacheTracker.swift in Sources */, @@ -1389,7 +1496,6 @@ 58ACF6492655365700ACE4B7 /* PreferencesViewController.swift in Sources */, E1FD0DF528AA7CE400299DB4 /* StatusActivityView.swift in Sources */, 58968FAE28743E2000B799DC /* TunnelInteractor.swift in Sources */, - 588D2FE3248AC27F00E313F7 /* AsyncOperation.swift in Sources */, 5820675026E6514100655B05 /* HTTP.swift in Sources */, 584D26C2270C8542004EA533 /* SettingsStaticTextFooterView.swift in Sources */, 587B7536266528A200DEF7E9 /* NotificationManager.swift in Sources */, @@ -1398,14 +1504,11 @@ 58ACF64D26567A5000ACE4B7 /* CustomSwitch.swift in Sources */, 5850367F25A481D800A43E93 /* IPAddressRange+Codable.swift in Sources */, 58F2E14C276A61C000A79513 /* RotateKeyOperation.swift in Sources */, - 589D287A2846250500F9A7B3 /* OperationCondition.swift in Sources */, - 589D288028462CB000F9A7B3 /* BackgroundObserver.swift in Sources */, 5871FB96254ADE4E0051A0A4 /* ConsolidatedApplicationLog.swift in Sources */, 58FEEB58260B662E00A621A8 /* AutomaticKeyboardResponder.swift in Sources */, 5846227326E22A160035F7C2 /* AppStorePaymentObserver.swift in Sources */, 58F2E146276A2C9900A79513 /* StopTunnelOperation.swift in Sources */, E1187ABC289BBB850024E748 /* OutOfTimeViewController.swift in Sources */, - 58DF5B762852108E00E92647 /* InputInjectionBuilder.swift in Sources */, 58CB0EE024B86751001EF0D8 /* RESTAPIProxy.swift in Sources */, 58095C532760EEC700890776 /* RESTNetworkOperation.swift in Sources */, 58293FB125124117005D0BB5 /* CustomTextField.swift in Sources */, @@ -1413,9 +1516,7 @@ 58554F7D280D6FE000013055 /* RESTURLSession.swift in Sources */, 5820EDAB288FF0D2006BF4E4 /* DeviceRowView.swift in Sources */, 75FD0C2128B108570021E33E /* ShortcutsDataSource.swift in Sources */, - 589D28822846306C00F9A7B3 /* GroupOperation.swift in Sources */, 5846227726E22A7C0035F7C2 /* AppStorePaymentManagerDelegate.swift in Sources */, - 5871FB8325498CA20051A0A4 /* Swizzle.swift in Sources */, 58EF581125D69DB400AEBA94 /* StatusImageView.swift in Sources */, 58907D9524D17B4E00CFC3F5 /* DisconnectSplitButton.swift in Sources */, 58EE2E3B272FF814003BFF93 /* SettingsDataSourceDelegate.swift in Sources */, @@ -1459,7 +1560,6 @@ 5878BA1426DD0B01004147D7 /* OSLogHandler.swift in Sources */, 582BB1AF229566420055B6EF /* SettingsCell.swift in Sources */, 58F3C0A4249CB069003E76BE /* HeaderBarView.swift in Sources */, - 58B9EB132488ED2100095626 /* AlertPresenter.swift in Sources */, 587A01FC23F1F0BE00B68763 /* SimulatorTunnelProviderHost.swift in Sources */, 5819C2172729595500D6EC38 /* SettingsAddDNSEntryCell.swift in Sources */, 584D26BF270C550B004EA533 /* AnyIPAddress.swift in Sources */, @@ -1479,7 +1579,6 @@ 58B93A1326C3F13600A55733 /* TunnelState.swift in Sources */, 58FEEB46260A028D00A621A8 /* GeoJSON.swift in Sources */, 5815039724D6ECAE00C9C50E /* CustomFormatLogHandler.swift in Sources */, - 5820675E26E6839900655B05 /* PresentAlertOperation.swift in Sources */, 5815039D24D6ECE600C9C50E /* TextFileOutputStream.swift in Sources */, 753D6C0C28B4BF3E0052D9E1 /* ShortcutsManager.swift in Sources */, 58CE5E64224146200008646E /* AppDelegate.swift in Sources */, @@ -1487,7 +1586,6 @@ 58E0A98827C8F46300FE6BDD /* Tunnel.swift in Sources */, 58ACF64F26567A7100ACE4B7 /* CustomSwitchContainer.swift in Sources */, 5857F24324C8662600CF6F47 /* SelectLocationHeaderView.swift in Sources */, - 5840BE35279EDB16002836BA /* OperationCompletion.swift in Sources */, 58EE2E3A272FF814003BFF93 /* SettingsDataSource.swift in Sources */, 58421032282E42B000F24E46 /* UpdateDeviceDataOperation.swift in Sources */, 58AEEF652344A36000C9BBD5 /* KeychainError.swift in Sources */, @@ -1498,7 +1596,6 @@ 58FB865526E8BF3100F188BC /* AppStorePaymentManagerError.swift in Sources */, 58FD5BF42428C67600112C88 /* InAppPurchaseButton.swift in Sources */, 587D9676288989DB00CD8F1C /* NSLayoutConstraint+Helpers.swift in Sources */, - 580EE22424B3243100F9D8A1 /* AsyncBlockOperation.swift in Sources */, 58293FAE2510CA58005D0BB5 /* ProblemReportViewController.swift in Sources */, 58B9EB152489139B00095626 /* DisplayChainedError.swift in Sources */, 587B753F2668E5A700DEF7E9 /* NotificationContainerView.swift in Sources */, @@ -1513,7 +1610,6 @@ 584592612639B4A200EF967F /* TermsOfServiceContentView.swift in Sources */, 58B5A895280AACC4009FDE99 /* RESTRequestFactory.swift in Sources */, 584EBDBD2747C98F00A0C9FD /* NSAttributedString+Markdown.swift in Sources */, - 58059DDC28465E8F002B1049 /* TransformOperation.swift in Sources */, 5875960A26F371FC00BF6711 /* Tunnel+Messaging.swift in Sources */, 58FB865E26EA284E00F188BC /* LogFormatting.swift in Sources */, 585DA88726B0277200B8C587 /* RESTError.swift in Sources */, @@ -1532,8 +1628,6 @@ 58F97A1E280FDE230050C2FC /* RESTRequestHandler.swift in Sources */, 5811DE50239014550011EB53 /* NEVPNStatus+Debug.swift in Sources */, 58C3A4B222456F1B00340BDB /* AccountInputGroupView.swift in Sources */, - 58059DDE28468158002B1049 /* OutputOperation.swift in Sources */, - 589D287B2846250500F9A7B3 /* AsyncOperationQueue.swift in Sources */, 588BCF24280FE43D009ADCEC /* RESTDevicesProxy.swift in Sources */, 58ACF64B26553C3F00ACE4B7 /* SettingsSwitchCell.swift in Sources */, 587EB67027143B6500123C75 /* DataSourceSnapshot.swift in Sources */, @@ -1605,6 +1699,36 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 58E5126128DDF04200B0BCDE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 58D889C828DDF53500583FA8 /* ResultOperation.swift in Sources */, + 58D889BB28DDF53500583FA8 /* AsyncOperationQueue.swift in Sources */, + 58D889C128DDF53500583FA8 /* InputInjectionBuilder.swift in Sources */, + 58D889BD28DDF53500583FA8 /* ProductsRequestOperation.swift in Sources */, + 58D889C228DDF53500583FA8 /* OperationCompletion.swift in Sources */, + 58D889CA28DDF53500583FA8 /* ResultOperation+Output.swift in Sources */, + 58D889C428DDF53500583FA8 /* ResultBlockOperation.swift in Sources */, + 589A454D28DDF5E500565204 /* Swizzle.swift in Sources */, + 58D889BF28DDF53500583FA8 /* OperationObserver.swift in Sources */, + 581813A328E09DCD002817DE /* NoFailedDependenciesCondition.swift in Sources */, + 58D889C328DDF53500583FA8 /* PresentAlertOperation.swift in Sources */, + 58D889C528DDF53500583FA8 /* TransformOperation.swift in Sources */, + 58D889BA28DDF53500583FA8 /* OutputOperation.swift in Sources */, + 581813A528E09DE2002817DE /* BlockCondition.swift in Sources */, + 58D889B928DDF53500583FA8 /* BackgroundObserver.swift in Sources */, + 581813A728E09DF2002817DE /* MutuallyExclusive.swift in Sources */, + 58D889BE28DDF53500583FA8 /* AsyncBlockOperation.swift in Sources */, + 58D889C628DDF53500583FA8 /* GroupOperation.swift in Sources */, + 58D889BC28DDF53500583FA8 /* OperationCondition.swift in Sources */, + 58D889C728DDF53500583FA8 /* AsyncOperation.swift in Sources */, + 58D889C928DDF53500583FA8 /* InputOperation.swift in Sources */, + 58D889C028DDF53500583FA8 /* AlertPresenter.swift in Sources */, + 581813A128E09DBB002817DE /* NoCancelledDependenciesCondition.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -1613,6 +1737,11 @@ target = 58FBDA9722A519BC00EB69A3 /* WireGuardGoBridge */; targetProxy = 5841E04225D53BCC00D989F7 /* PBXContainerItemProxy */; }; + 589A455828E094B300565204 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 58E5126428DDF04200B0BCDE /* Operations */; + targetProxy = 589A455728E094B300565204 /* PBXContainerItemProxy */; + }; 58CE5E80224146470008646E /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 58CE5E78224146470008646E /* PacketTunnel */; @@ -1623,6 +1752,16 @@ target = 58CE5E5F224146200008646E /* MullvadVPN */; targetProxy = 58D0C79823F1CE7000FE9BA7 /* PBXContainerItemProxy */; }; + 58D889B528DDF4DD00583FA8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 58E5126428DDF04200B0BCDE /* Operations */; + targetProxy = 58D889B428DDF4DD00583FA8 /* PBXContainerItemProxy */; + }; + 58E5126E28DDF09F00B0BCDE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 58E5126428DDF04200B0BCDE /* Operations */; + targetProxy = 58E5126D28DDF09F00B0BCDE /* PBXContainerItemProxy */; + }; 58FBDAA222A52A6800EB69A3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 58FBDA9722A519BC00EB69A3 /* WireGuardGoBridge */; @@ -1642,10 +1781,47 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 589A455A28E094B300565204 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = CKG9MXH72F; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = net.mullvad.MullvadVPN.OperationsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 589A455B28E094B300565204 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = CKG9MXH72F; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = net.mullvad.MullvadVPN.OperationsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; 58B0A2A6238EE67E00BC001D /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5808273928487E3E006B77A4 /* Base.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; INFOPLIST_FILE = MullvadVPNTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1662,6 +1838,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 5808273928487E3E006B77A4 /* Base.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; INFOPLIST_FILE = MullvadVPNTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1920,6 +2097,36 @@ }; name = Release; }; + 58E5126928DDF04200B0BCDE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = CKG9MXH72F; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 58E5126A28DDF04200B0BCDE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = CKG9MXH72F; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; 58FBDA9822A519BC00EB69A3 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5808273928487E3E006B77A4 /* Base.xcconfig */; @@ -1948,6 +2155,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 589A455928E094B300565204 /* Build configuration list for PBXNativeTarget "OperationsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 589A455A28E094B300565204 /* Debug */, + 589A455B28E094B300565204 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 58B0A2A5238EE67E00BC001D /* Build configuration list for PBXNativeTarget "MullvadVPNTests" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1993,6 +2209,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 58E5126B28DDF04200B0BCDE /* Build configuration list for PBXNativeTarget "Operations" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 58E5126928DDF04200B0BCDE /* Debug */, + 58E5126A28DDF04200B0BCDE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 58FBDA9A22A519BC00EB69A3 /* Build configuration list for PBXLegacyTarget "WireGuardGoBridge" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme index cf71390c14..69c2ec895d 100644 --- a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme +++ b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme @@ -66,6 +66,16 @@ ReferencedContainer = "container:MullvadVPN.xcodeproj"> </BuildableReference> </TestableReference> + <TestableReference + skipped = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "589A455128E094B300565204" + BuildableName = "OperationsTests.xctest" + BlueprintName = "OperationsTests" + ReferencedContainer = "container:MullvadVPN.xcodeproj"> + </BuildableReference> + </TestableReference> </Testables> </TestAction> <LaunchAction diff --git a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/Operations.xcscheme b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/Operations.xcscheme new file mode 100644 index 0000000000..8de7be338d --- /dev/null +++ b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/Operations.xcscheme @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "1400" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "58E5126428DDF04200B0BCDE" + BuildableName = "libOperations.a" + BlueprintName = "Operations" + ReferencedContainer = "container:MullvadVPN.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + <TestableReference + skipped = "NO" + parallelizable = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "589A455128E094B300565204" + BuildableName = "OperationsTests.xctest" + BlueprintName = "OperationsTests" + ReferencedContainer = "container:MullvadVPN.xcodeproj"> + </BuildableReference> + </TestableReference> + </Testables> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + </LaunchAction> + <ProfileAction + buildConfiguration = "Release" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "58E5126428DDF04200B0BCDE" + BuildableName = "libOperations.a" + BlueprintName = "Operations" + ReferencedContainer = "container:MullvadVPN.xcodeproj"> + </BuildableReference> + </MacroExpansion> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/OperationsTests.xcscheme b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/OperationsTests.xcscheme new file mode 100644 index 0000000000..99be15817e --- /dev/null +++ b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/OperationsTests.xcscheme @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "1400" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + <TestableReference + skipped = "NO" + parallelizable = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "589A455128E094B300565204" + BuildableName = "OperationsTests.xctest" + BlueprintName = "OperationsTests" + ReferencedContainer = "container:MullvadVPN.xcodeproj"> + </BuildableReference> + </TestableReference> + </Testables> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + </LaunchAction> + <ProfileAction + buildConfiguration = "Release" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/ios/MullvadVPN/AccountViewController.swift b/ios/MullvadVPN/AccountViewController.swift index 88b8654fc8..c55d503619 100644 --- a/ios/MullvadVPN/AccountViewController.swift +++ b/ios/MullvadVPN/AccountViewController.swift @@ -7,6 +7,7 @@ // import Logging +import Operations import StoreKit import UIKit diff --git a/ios/MullvadVPN/AddressCache/AddressCacheTracker.swift b/ios/MullvadVPN/AddressCache/AddressCacheTracker.swift index 00d118de75..e88b14dfe6 100644 --- a/ios/MullvadVPN/AddressCache/AddressCacheTracker.swift +++ b/ios/MullvadVPN/AddressCache/AddressCacheTracker.swift @@ -7,6 +7,7 @@ // import Logging +import Operations import UIKit extension AddressCache { diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift index 66a99cc302..e08d84f025 100644 --- a/ios/MullvadVPN/AppDelegate.swift +++ b/ios/MullvadVPN/AppDelegate.swift @@ -9,6 +9,7 @@ import BackgroundTasks import Intents import Logging +import Operations import StoreKit import UIKit import UserNotifications diff --git a/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift b/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift index ffeba9c84c..ed5f829fa3 100644 --- a/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift +++ b/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations import StoreKit class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver { diff --git a/ios/MullvadVPN/AppStorePaymentManager/SendAppStoreReceiptOperation.swift b/ios/MullvadVPN/AppStorePaymentManager/SendAppStoreReceiptOperation.swift index b99c542c5a..0711817c6e 100644 --- a/ios/MullvadVPN/AppStorePaymentManager/SendAppStoreReceiptOperation.swift +++ b/ios/MullvadVPN/AppStorePaymentManager/SendAppStoreReceiptOperation.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations class SendAppStoreReceiptOperation: ResultOperation< REST.CreateApplePaymentResponse, diff --git a/ios/MullvadVPN/AppStoreReceipt.swift b/ios/MullvadVPN/AppStoreReceipt.swift index ee1186b9b9..579c6bf303 100644 --- a/ios/MullvadVPN/AppStoreReceipt.swift +++ b/ios/MullvadVPN/AppStoreReceipt.swift @@ -7,6 +7,7 @@ // import Foundation +import Operations import StoreKit struct AppStoreReceiptNotFound: LocalizedError { diff --git a/ios/MullvadVPN/DeviceManagementInteractor.swift b/ios/MullvadVPN/DeviceManagementInteractor.swift index 1890799221..6dc84e76ba 100644 --- a/ios/MullvadVPN/DeviceManagementInteractor.swift +++ b/ios/MullvadVPN/DeviceManagementInteractor.swift @@ -7,6 +7,7 @@ // import Foundation +import Operations class DeviceManagementInteractor { private let devicesProxy = REST.ProxyFactory.shared.createDevicesProxy() diff --git a/ios/MullvadVPN/DeviceManagementViewController.swift b/ios/MullvadVPN/DeviceManagementViewController.swift index 383b7ca822..3a2915fae4 100644 --- a/ios/MullvadVPN/DeviceManagementViewController.swift +++ b/ios/MullvadVPN/DeviceManagementViewController.swift @@ -7,6 +7,7 @@ // import Logging +import Operations import UIKit protocol DeviceManagementViewControllerDelegate: AnyObject { diff --git a/ios/MullvadVPN/LoginViewController.swift b/ios/MullvadVPN/LoginViewController.swift index b0587e9543..15ec69535d 100644 --- a/ios/MullvadVPN/LoginViewController.swift +++ b/ios/MullvadVPN/LoginViewController.swift @@ -7,6 +7,7 @@ // import Logging +import Operations import UIKit enum LoginAction { diff --git a/ios/MullvadVPN/Operations/OperationCondition.swift b/ios/MullvadVPN/Operations/OperationCondition.swift deleted file mode 100644 index 024ca52013..0000000000 --- a/ios/MullvadVPN/Operations/OperationCondition.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// OperationCondition.swift -// MullvadVPN -// -// Created by pronebird on 30/05/2022. -// Copyright © 2022 Mullvad VPN AB. All rights reserved. -// - -import Foundation - -protocol OperationCondition { - var name: String { get } - var isMutuallyExclusive: Bool { get } - - func evaluate(for operation: Operation, completion: @escaping (Bool) -> Void) -} - -final class NoCancelledDependenciesCondition: OperationCondition { - var name: String { - return "NoCancelledDependenciesCondition" - } - - var isMutuallyExclusive: Bool { - return false - } - - func evaluate(for operation: Operation, completion: @escaping (Bool) -> Void) { - let satisfy = operation.dependencies.allSatisfy { operation in - return !operation.isCancelled - } - - completion(satisfy) - } -} - -final class NoFailedDependenciesCondition: OperationCondition { - var name: String { - return "NoFailedDependenciesCondition" - } - - var isMutuallyExclusive: Bool { - return false - } - - let ignoreCancellations: Bool - init(ignoreCancellations: Bool) { - self.ignoreCancellations = ignoreCancellations - } - - func evaluate(for operation: Operation, completion: @escaping (Bool) -> Void) { - let satisfy = operation.dependencies.allSatisfy { operation in - if let operation = operation as? AsyncOperation, operation.error != nil { - return false - } - - if operation.isCancelled, !self.ignoreCancellations { - return false - } - - return true - } - - completion(satisfy) - } -} - -final class BlockCondition: OperationCondition { - typealias HandlerBlock = (Operation, @escaping (Bool) -> Void) -> Void - - var name: String { - return "BlockCondition" - } - - var isMutuallyExclusive: Bool { - return false - } - - let block: HandlerBlock - init(block: @escaping HandlerBlock) { - self.block = block - } - - func evaluate(for operation: Operation, completion: @escaping (Bool) -> Void) { - block(operation, completion) - } -} - -final class MutuallyExclusive: OperationCondition { - let name: String - - var isMutuallyExclusive: Bool { - return true - } - - init(category: String) { - name = "MutuallyExclusive<\(category)>" - } - - func evaluate(for operation: Operation, completion: @escaping (Bool) -> Void) { - completion(true) - } -} diff --git a/ios/MullvadVPN/OutOfTimeViewController.swift b/ios/MullvadVPN/OutOfTimeViewController.swift index 6c7700a6f2..5691f38905 100644 --- a/ios/MullvadVPN/OutOfTimeViewController.swift +++ b/ios/MullvadVPN/OutOfTimeViewController.swift @@ -7,6 +7,7 @@ // import Foundation +import Operations import StoreKit import UIKit diff --git a/ios/MullvadVPN/ProblemReportViewController.swift b/ios/MullvadVPN/ProblemReportViewController.swift index c2e4958004..823cd450fc 100644 --- a/ios/MullvadVPN/ProblemReportViewController.swift +++ b/ios/MullvadVPN/ProblemReportViewController.swift @@ -6,6 +6,7 @@ // Copyright © 2020 Mullvad VPN AB. All rights reserved. // +import Operations import UIKit class ProblemReportViewController: UIViewController, UITextFieldDelegate, ConditionalNavigation { diff --git a/ios/MullvadVPN/REST/RESTAccessTokenManager.swift b/ios/MullvadVPN/REST/RESTAccessTokenManager.swift index 79e5096fb5..b3f91083a4 100644 --- a/ios/MullvadVPN/REST/RESTAccessTokenManager.swift +++ b/ios/MullvadVPN/REST/RESTAccessTokenManager.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations extension REST { final class AccessTokenManager { diff --git a/ios/MullvadVPN/REST/RESTAuthorization.swift b/ios/MullvadVPN/REST/RESTAuthorization.swift index e97c42e732..81a0f96dff 100644 --- a/ios/MullvadVPN/REST/RESTAuthorization.swift +++ b/ios/MullvadVPN/REST/RESTAuthorization.swift @@ -7,6 +7,7 @@ // import Foundation +import Operations protocol RESTAuthorizationProvider { typealias Completion = OperationCompletion<REST.Authorization, REST.Error> diff --git a/ios/MullvadVPN/REST/RESTNetworkOperation.swift b/ios/MullvadVPN/REST/RESTNetworkOperation.swift index f1ffe472da..26ab4cf220 100644 --- a/ios/MullvadVPN/REST/RESTNetworkOperation.swift +++ b/ios/MullvadVPN/REST/RESTNetworkOperation.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations extension REST { class NetworkOperation<Success>: ResultOperation<Success, REST.Error> { diff --git a/ios/MullvadVPN/REST/RESTProxy.swift b/ios/MullvadVPN/REST/RESTProxy.swift index 1030133354..6dc2c08a33 100644 --- a/ios/MullvadVPN/REST/RESTProxy.swift +++ b/ios/MullvadVPN/REST/RESTProxy.swift @@ -7,6 +7,7 @@ // import Foundation +import Operations extension REST { class Proxy<ConfigurationType: ProxyConfiguration> { diff --git a/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift b/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift index 9698322559..c997ac7cd4 100644 --- a/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift +++ b/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations import UIKit extension RelayCache { diff --git a/ios/MullvadVPN/SceneDelegate.swift b/ios/MullvadVPN/SceneDelegate.swift index a12513d6b8..3297e66d6b 100644 --- a/ios/MullvadVPN/SceneDelegate.swift +++ b/ios/MullvadVPN/SceneDelegate.swift @@ -7,6 +7,7 @@ // import Logging +import Operations import UIKit class SceneDelegate: UIResponder { diff --git a/ios/MullvadVPN/TunnelManager/LoadTunnelConfigurationOperation.swift b/ios/MullvadVPN/TunnelManager/LoadTunnelConfigurationOperation.swift index 70a3d95d25..91920e9643 100644 --- a/ios/MullvadVPN/TunnelManager/LoadTunnelConfigurationOperation.swift +++ b/ios/MullvadVPN/TunnelManager/LoadTunnelConfigurationOperation.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations class LoadTunnelConfigurationOperation: ResultOperation<Void, Error> { private let logger = Logger(label: "LoadTunnelConfigurationOperation") diff --git a/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift b/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift index 4adc15e0ef..14aacf3c7d 100644 --- a/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift +++ b/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift @@ -9,6 +9,7 @@ import Foundation import Logging import NetworkExtension +import Operations class MapConnectionStatusOperation: AsyncOperation { private let interactor: TunnelInteractor diff --git a/ios/MullvadVPN/TunnelManager/MigrateSettingsOperation.swift b/ios/MullvadVPN/TunnelManager/MigrateSettingsOperation.swift index adf3735f14..b22f4a988f 100644 --- a/ios/MullvadVPN/TunnelManager/MigrateSettingsOperation.swift +++ b/ios/MullvadVPN/TunnelManager/MigrateSettingsOperation.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations import class WireGuardKitTypes.PrivateKey class MigrateSettingsOperation: AsyncOperation { diff --git a/ios/MullvadVPN/TunnelManager/ReconnectTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/ReconnectTunnelOperation.swift index 495e5f0479..3b0ce5b7a3 100644 --- a/ios/MullvadVPN/TunnelManager/ReconnectTunnelOperation.swift +++ b/ios/MullvadVPN/TunnelManager/ReconnectTunnelOperation.swift @@ -7,6 +7,7 @@ // import Foundation +import Operations class ReconnectTunnelOperation: ResultOperation<Void, Error> { private let interactor: TunnelInteractor diff --git a/ios/MullvadVPN/TunnelManager/RotateKeyOperation.swift b/ios/MullvadVPN/TunnelManager/RotateKeyOperation.swift index 0029373af7..78cdc89e31 100644 --- a/ios/MullvadVPN/TunnelManager/RotateKeyOperation.swift +++ b/ios/MullvadVPN/TunnelManager/RotateKeyOperation.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations import class WireGuardKitTypes.PrivateKey class RotateKeyOperation: ResultOperation<Bool, Error> { diff --git a/ios/MullvadVPN/TunnelManager/SendTunnelProviderMessageOperation.swift b/ios/MullvadVPN/TunnelManager/SendTunnelProviderMessageOperation.swift index 9fb72e03d9..04febe26a8 100644 --- a/ios/MullvadVPN/TunnelManager/SendTunnelProviderMessageOperation.swift +++ b/ios/MullvadVPN/TunnelManager/SendTunnelProviderMessageOperation.swift @@ -8,6 +8,7 @@ import Foundation import NetworkExtension +import Operations private enum MessagingConfiguration { /// Delay for sending tunnel provider messages to the tunnel when in connecting state. diff --git a/ios/MullvadVPN/TunnelManager/SetAccountOperation.swift b/ios/MullvadVPN/TunnelManager/SetAccountOperation.swift index 5ceb8cdfda..8231eee9fe 100644 --- a/ios/MullvadVPN/TunnelManager/SetAccountOperation.swift +++ b/ios/MullvadVPN/TunnelManager/SetAccountOperation.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations import class WireGuardKitTypes.PrivateKey import class WireGuardKitTypes.PublicKey diff --git a/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift index f1eeee4a21..f7ab198463 100644 --- a/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift +++ b/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift @@ -9,6 +9,7 @@ import Foundation import Logging import NetworkExtension +import Operations class StartTunnelOperation: ResultOperation<Void, Error> { typealias EncodeErrorHandler = (Error) -> Void diff --git a/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift index 766626cea3..2c63b1ae2e 100644 --- a/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift +++ b/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift @@ -7,6 +7,7 @@ // import Foundation +import Operations class StopTunnelOperation: ResultOperation<Void, Error> { private let interactor: TunnelInteractor diff --git a/ios/MullvadVPN/TunnelManager/Tunnel+Messaging.swift b/ios/MullvadVPN/TunnelManager/Tunnel+Messaging.swift index ef737466f3..ef2f4de6e2 100644 --- a/ios/MullvadVPN/TunnelManager/Tunnel+Messaging.swift +++ b/ios/MullvadVPN/TunnelManager/Tunnel+Messaging.swift @@ -7,6 +7,7 @@ // import Foundation +import Operations /// Shared operation queue used for IPC requests. private let operationQueue = AsyncOperationQueue() diff --git a/ios/MullvadVPN/TunnelManager/TunnelManager.swift b/ios/MullvadVPN/TunnelManager/TunnelManager.swift index b107491712..dbe10f2056 100644 --- a/ios/MullvadVPN/TunnelManager/TunnelManager.swift +++ b/ios/MullvadVPN/TunnelManager/TunnelManager.swift @@ -9,6 +9,7 @@ import Foundation import Logging import NetworkExtension +import Operations import StoreKit import UIKit import class WireGuardKitTypes.PublicKey diff --git a/ios/MullvadVPN/TunnelManager/UpdateAccountDataOperation.swift b/ios/MullvadVPN/TunnelManager/UpdateAccountDataOperation.swift index b95d629ea5..19543ae469 100644 --- a/ios/MullvadVPN/TunnelManager/UpdateAccountDataOperation.swift +++ b/ios/MullvadVPN/TunnelManager/UpdateAccountDataOperation.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations class UpdateAccountDataOperation: ResultOperation<Void, Error> { private let logger = Logger(label: "UpdateAccountDataOperation") diff --git a/ios/MullvadVPN/TunnelManager/UpdateDeviceDataOperation.swift b/ios/MullvadVPN/TunnelManager/UpdateDeviceDataOperation.swift index da7bc3d7bd..2d8708f795 100644 --- a/ios/MullvadVPN/TunnelManager/UpdateDeviceDataOperation.swift +++ b/ios/MullvadVPN/TunnelManager/UpdateDeviceDataOperation.swift @@ -8,6 +8,7 @@ import Foundation import Logging +import Operations import class WireGuardKitTypes.PublicKey class UpdateDeviceDataOperation: ResultOperation<StoredDeviceData, Error> { diff --git a/ios/MullvadVPN/AlertPresenter.swift b/ios/Operations/AlertPresenter.swift index c260201e05..6bf4470e23 100644 --- a/ios/MullvadVPN/AlertPresenter.swift +++ b/ios/Operations/AlertPresenter.swift @@ -6,10 +6,11 @@ // Copyright © 2020 Mullvad VPN AB. All rights reserved. // -import Foundation +#if canImport(UIKit) + import UIKit -class AlertPresenter { +public final class AlertPresenter { static let alertControllerDidDismissNotification = Notification .Name("UIAlertControllerDidDismiss") @@ -31,11 +32,11 @@ class AlertPresenter { ) }() - init() { + public init() { _ = Self.initClass } - func enqueue( + public func enqueue( _ alertController: UIAlertController, presentingController: UIViewController, presentCompletion: (() -> Void)? = nil @@ -49,7 +50,7 @@ class AlertPresenter { operationQueue.addOperation(operation) } - func cancelAll() { + public func cancelAll() { operationQueue.cancelAllOperations() } } @@ -67,3 +68,5 @@ private extension UIAlertController { } } } + +#endif diff --git a/ios/MullvadVPN/Operations/AsyncBlockOperation.swift b/ios/Operations/AsyncBlockOperation.swift index 03872873f9..72b95c98a3 100644 --- a/ios/MullvadVPN/Operations/AsyncBlockOperation.swift +++ b/ios/Operations/AsyncBlockOperation.swift @@ -9,20 +9,23 @@ import Foundation /// Asynchronous block operation -class AsyncBlockOperation: AsyncOperation { +public class AsyncBlockOperation: AsyncOperation { private var executionBlock: ((AsyncBlockOperation) -> Void)? private var cancellationBlocks: [() -> Void] = [] - override init(dispatchQueue: DispatchQueue? = nil) { + override public init(dispatchQueue: DispatchQueue? = nil) { super.init(dispatchQueue: dispatchQueue) } - init(dispatchQueue: DispatchQueue? = nil, block: @escaping (AsyncBlockOperation) -> Void) { + public init( + dispatchQueue: DispatchQueue? = nil, + block: @escaping (AsyncBlockOperation) -> Void + ) { executionBlock = block super.init(dispatchQueue: dispatchQueue) } - init(dispatchQueue: DispatchQueue? = nil, block: @escaping () -> Void) { + public init(dispatchQueue: DispatchQueue? = nil, block: @escaping () -> Void) { executionBlock = { operation in block() operation.finish() @@ -30,7 +33,7 @@ class AsyncBlockOperation: AsyncOperation { super.init(dispatchQueue: dispatchQueue) } - override func main() { + override public func main() { let block = executionBlock executionBlock = nil @@ -41,7 +44,7 @@ class AsyncBlockOperation: AsyncOperation { } } - override func operationDidCancel() { + override public func operationDidCancel() { let blocks = cancellationBlocks cancellationBlocks.removeAll() @@ -50,26 +53,26 @@ class AsyncBlockOperation: AsyncOperation { } } - override func operationDidFinish() { + override public func operationDidFinish() { cancellationBlocks.removeAll() executionBlock = nil } - func setExecutionBlock(_ block: @escaping (AsyncBlockOperation) -> Void) { + public func setExecutionBlock(_ block: @escaping (AsyncBlockOperation) -> Void) { dispatchQueue.async { assert(!self.isExecuting && !self.isFinished) self.executionBlock = block } } - func setExecutionBlock(_ block: @escaping () -> Void) { + public func setExecutionBlock(_ block: @escaping () -> Void) { setExecutionBlock { operation in block() operation.finish() } } - func addCancellationBlock(_ block: @escaping () -> Void) { + public func addCancellationBlock(_ block: @escaping () -> Void) { dispatchQueue.async { if self.isCancelled { block() diff --git a/ios/MullvadVPN/Operations/AsyncOperation.swift b/ios/Operations/AsyncOperation.swift index b384fd2bee..a8aa4262a8 100644 --- a/ios/MullvadVPN/Operations/AsyncOperation.swift +++ b/ios/Operations/AsyncOperation.swift @@ -8,7 +8,7 @@ import Foundation -@objc enum State: Int, Comparable, CustomStringConvertible { +@objc private enum State: Int, Comparable, CustomStringConvertible { case initialized case pending case evaluatingConditions @@ -39,7 +39,7 @@ import Foundation } /// A base implementation of an asynchronous operation -class AsyncOperation: Operation { +open class AsyncOperation: Operation { /// Mutex lock used for guarding critical sections of operation lifecycle. private let operationLock = NSRecursiveLock() @@ -64,7 +64,7 @@ class AsyncOperation: Operation { /// Backing variable for `error`. /// Access must be guarded with `stateLock`. - private var _error: Error? + private var __error: Error? /// Operation state. @objc private var state: State { @@ -100,20 +100,24 @@ class AsyncOperation: Operation { } } - private(set) var error: Error? { + private var _error: Error? { get { stateLock.lock() defer { stateLock.unlock() } - return _error + return __error } set { stateLock.lock() defer { stateLock.unlock() } - _error = newValue + __error = newValue } } - override final var isReady: Bool { + public var error: Error? { + return _error + } + + override public final var isReady: Bool { stateLock.lock() defer { stateLock.unlock() } @@ -136,19 +140,19 @@ class AsyncOperation: Operation { } } - override final var isExecuting: Bool { + override public final var isExecuting: Bool { return state == .executing } - override final var isFinished: Bool { + override public final var isFinished: Bool { return state == .finished } - override final var isCancelled: Bool { + override public final var isCancelled: Bool { return _isCancelled } - override final var isAsynchronous: Bool { + override public final var isAsynchronous: Bool { return true } @@ -156,14 +160,14 @@ class AsyncOperation: Operation { private var _observers: [OperationObserver] = [] - final var observers: [OperationObserver] { + public final var observers: [OperationObserver] { operationLock.lock() defer { operationLock.unlock() } return _observers } - final func addObserver(_ observer: OperationObserver) { + public final func addObserver(_ observer: OperationObserver) { operationLock.lock() assert(state < .executing) _observers.append(observer) @@ -175,14 +179,14 @@ class AsyncOperation: Operation { private var _conditions: [OperationCondition] = [] - final var conditions: [OperationCondition] { + public final var conditions: [OperationCondition] { operationLock.lock() defer { operationLock.unlock() } return _conditions } - func addCondition(_ condition: OperationCondition) { + public func addCondition(_ condition: OperationCondition) { operationLock.lock() assert(state < .evaluatingConditions) _conditions.append(condition) @@ -231,9 +235,9 @@ class AsyncOperation: Operation { // MARK: - - let dispatchQueue: DispatchQueue + public let dispatchQueue: DispatchQueue - init(dispatchQueue: DispatchQueue? = nil) { + public init(dispatchQueue: DispatchQueue? = nil) { self.dispatchQueue = dispatchQueue ?? DispatchQueue(label: "AsyncOperation.dispatchQueue") super.init() @@ -253,7 +257,7 @@ class AsyncOperation: Operation { private static var observerContext = 0 - override func observeValue( + override public func observeValue( forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, @@ -286,7 +290,7 @@ class AsyncOperation: Operation { // MARK: - Lifecycle - override final func start() { + override public final func start() { let currentQueue = OperationQueue.current let underlyingQueue = currentQueue?.underlyingQueue @@ -316,11 +320,11 @@ class AsyncOperation: Operation { } } - override func main() { + override open func main() { // Override in subclasses } - override final func cancel() { + override public final func cancel() { var notifyDidCancel = false operationLock.lock() @@ -343,11 +347,11 @@ class AsyncOperation: Operation { } } - func finish() { + public func finish() { finish(error: nil) } - func finish(error: Error?) { + public func finish(error: Error?) { guard tryFinish(error: error) else { return } dispatchQueue.async { @@ -362,7 +366,7 @@ class AsyncOperation: Operation { // MARK: - Private - func didEnqueue() { + internal func didEnqueue() { operationLock.lock() defer { operationLock.unlock() } @@ -388,7 +392,7 @@ class AsyncOperation: Operation { guard state < .finished else { return false } - self.error = error + _error = error state = .finished return true @@ -396,16 +400,16 @@ class AsyncOperation: Operation { // MARK: - Subclass overrides - func operationDidCancel() { + open func operationDidCancel() { // Override in subclasses. } - func operationDidFinish() { + open func operationDidFinish() { // Override in subclasses. } } -extension Operation { +public extension Operation { func addDependencies(_ dependencies: [Operation]) { for dependency in dependencies { addDependency(dependency) @@ -413,16 +417,16 @@ extension Operation { } } -extension Operation { +public extension Operation { var operationName: String { return name ?? "\(self)" } } -protocol OperationBlockObserverSupport {} +public protocol OperationBlockObserverSupport {} extension AsyncOperation: OperationBlockObserverSupport {} -extension OperationBlockObserverSupport where Self: AsyncOperation { +public extension OperationBlockObserverSupport where Self: AsyncOperation { func addBlockObserver(_ observer: OperationBlockObserver<Self>) { addObserver(observer) } diff --git a/ios/MullvadVPN/Operations/AsyncOperationQueue.swift b/ios/Operations/AsyncOperationQueue.swift index 86a9cb0891..1c62038671 100644 --- a/ios/MullvadVPN/Operations/AsyncOperationQueue.swift +++ b/ios/Operations/AsyncOperationQueue.swift @@ -8,8 +8,8 @@ import Foundation -class AsyncOperationQueue: OperationQueue { - override func addOperation(_ operation: Operation) { +public class AsyncOperationQueue: OperationQueue { + override public func addOperation(_ operation: Operation) { if let operation = operation as? AsyncOperation { let categories = operation.conditions .filter { condition in @@ -31,7 +31,7 @@ class AsyncOperationQueue: OperationQueue { } } - override func addOperations(_ operations: [Operation], waitUntilFinished wait: Bool) { + override public func addOperations(_ operations: [Operation], waitUntilFinished wait: Bool) { for operation in operations { addOperation(operation) } diff --git a/ios/MullvadVPN/Operations/BackgroundObserver.swift b/ios/Operations/BackgroundObserver.swift index ba924140f2..1de842f766 100644 --- a/ios/MullvadVPN/Operations/BackgroundObserver.swift +++ b/ios/Operations/BackgroundObserver.swift @@ -3,20 +3,21 @@ // MullvadVPN // // Created by pronebird on 31/05/2022. +// Copyright © 2022 Mullvad VPN AB. All rights reserved. // #if canImport(UIKit) import UIKit -class BackgroundObserver: OperationObserver { - let name: String - let application: UIApplication - let cancelUponExpiration: Bool +public final class BackgroundObserver: OperationObserver { + public let name: String + public let application: UIApplication + public let cancelUponExpiration: Bool private var taskIdentifier: UIBackgroundTaskIdentifier? - init( + public init( application: UIApplication = .shared, name: String, cancelUponExpiration: Bool @@ -26,7 +27,7 @@ class BackgroundObserver: OperationObserver { self.cancelUponExpiration = cancelUponExpiration } - func didAttach(to operation: Operation) { + public func didAttach(to operation: Operation) { let expirationHandler = cancelUponExpiration ? { operation.cancel() } : nil taskIdentifier = application.beginBackgroundTask( @@ -35,15 +36,15 @@ class BackgroundObserver: OperationObserver { ) } - func operationDidStart(_ operation: Operation) { + public func operationDidStart(_ operation: Operation) { // no-op } - func operationDidCancel(_ operation: Operation) { + public func operationDidCancel(_ operation: Operation) { // no-op } - func operationDidFinish(_ operation: Operation, error: Error?) { + public func operationDidFinish(_ operation: Operation, error: Error?) { if let taskIdentifier = taskIdentifier { application.endBackgroundTask(taskIdentifier) } diff --git a/ios/Operations/BlockCondition.swift b/ios/Operations/BlockCondition.swift new file mode 100644 index 0000000000..e6aafa1e2d --- /dev/null +++ b/ios/Operations/BlockCondition.swift @@ -0,0 +1,30 @@ +// +// BlockCondition.swift +// Operations +// +// Created by pronebird on 25/09/2022. +// Copyright © 2022 Mullvad VPN AB. All rights reserved. +// + +import Foundation + +public final class BlockCondition: OperationCondition { + public typealias HandlerBlock = (Operation, @escaping (Bool) -> Void) -> Void + + public var name: String { + return "BlockCondition" + } + + public var isMutuallyExclusive: Bool { + return false + } + + public let block: HandlerBlock + public init(block: @escaping HandlerBlock) { + self.block = block + } + + public func evaluate(for operation: Operation, completion: @escaping (Bool) -> Void) { + block(operation, completion) + } +} diff --git a/ios/MullvadVPN/Operations/GroupOperation.swift b/ios/Operations/GroupOperation.swift index 5a6ca9902d..0d83d732fe 100644 --- a/ios/MullvadVPN/Operations/GroupOperation.swift +++ b/ios/Operations/GroupOperation.swift @@ -8,17 +8,17 @@ import Foundation -class GroupOperation: AsyncOperation { +public final class GroupOperation: AsyncOperation { private let operationQueue = AsyncOperationQueue() private let children: [Operation] - init(operations: [Operation]) { + public init(operations: [Operation]) { children = operations super.init(dispatchQueue: nil) } - override func main() { + override public func main() { let finishingOperation = BlockOperation() finishingOperation.completionBlock = { [weak self] in self?.finish() @@ -29,7 +29,7 @@ class GroupOperation: AsyncOperation { operationQueue.addOperation(finishingOperation) } - override func operationDidCancel() { + override public func operationDidCancel() { operationQueue.cancelAllOperations() } } diff --git a/ios/MullvadVPN/Operations/InputInjectionBuilder.swift b/ios/Operations/InputInjectionBuilder.swift index ba4c0ea968..ad2f329024 100644 --- a/ios/MullvadVPN/Operations/InputInjectionBuilder.swift +++ b/ios/Operations/InputInjectionBuilder.swift @@ -8,25 +8,27 @@ import Foundation -protocol OperationInputContext { +public protocol OperationInputContext { associatedtype Input func reduce() -> Input? } -class InputInjectionBuilder<OperationType, Context> where OperationType: InputOperation { - typealias InputBlock = (inout Context) -> Void +public final class InputInjectionBuilder<OperationType, Context> + where OperationType: InputOperation +{ + public typealias InputBlock = (inout Context) -> Void private let operation: OperationType private var context: Context private var inputBlocks: [InputBlock] = [] - init(operation: OperationType, context: Context) { + public init(operation: OperationType, context: Context) { self.operation = operation self.context = context } - func inject<T>( + public func inject<T>( from dependency: T, assignOutputTo keyPath: WritableKeyPath<Context, T.Output?> ) -> Self @@ -37,7 +39,7 @@ class InputInjectionBuilder<OperationType, Context> where OperationType: InputOp } } - func inject<T>( + public func inject<T>( from dependency: T, via block: @escaping (inout Context, T.Output) -> Void ) -> Self @@ -54,7 +56,7 @@ class InputInjectionBuilder<OperationType, Context> where OperationType: InputOp return self } - func injectCompletion<T, Success, Failure>( + public func injectCompletion<T, Success, Failure>( from dependency: T, via block: @escaping (inout Context, T.Completion) -> Void ) -> Self @@ -71,7 +73,7 @@ class InputInjectionBuilder<OperationType, Context> where OperationType: InputOp return self } - func reduce(_ reduceBlock: @escaping (Context) -> OperationType.Input?) { + public func reduce(_ reduceBlock: @escaping (Context) -> OperationType.Input?) { operation.setInputBlock { for inputBlock in self.inputBlocks { inputBlock(&self.context) @@ -82,7 +84,7 @@ class InputInjectionBuilder<OperationType, Context> where OperationType: InputOp } } -extension InputInjectionBuilder +public extension InputInjectionBuilder where Context: OperationInputContext, Context.Input == OperationType.Input { diff --git a/ios/MullvadVPN/Operations/InputOperation.swift b/ios/Operations/InputOperation.swift index 7f351d5ba4..9d88861f4d 100644 --- a/ios/MullvadVPN/Operations/InputOperation.swift +++ b/ios/Operations/InputOperation.swift @@ -8,7 +8,7 @@ import Foundation -protocol InputOperation: Operation { +public protocol InputOperation: Operation { associatedtype Input var input: Input? { get } @@ -22,7 +22,7 @@ protocol InputOperation: Operation { where T: OutputOperation } -extension InputOperation { +public extension InputOperation { func inject<T>(from dependency: T) where T: OutputOperation, T.Output == Input { inject(from: dependency, via: { $0 }) } diff --git a/ios/Operations/MutuallyExclusive.swift b/ios/Operations/MutuallyExclusive.swift new file mode 100644 index 0000000000..b9097d3420 --- /dev/null +++ b/ios/Operations/MutuallyExclusive.swift @@ -0,0 +1,25 @@ +// +// MutuallyExclusive.swift +// Operations +// +// Created by pronebird on 25/09/2022. +// Copyright © 2022 Mullvad VPN AB. All rights reserved. +// + +import Foundation + +public final class MutuallyExclusive: OperationCondition { + public let name: String + + public var isMutuallyExclusive: Bool { + return true + } + + public init(category: String) { + name = "MutuallyExclusive<\(category)>" + } + + public func evaluate(for operation: Operation, completion: @escaping (Bool) -> Void) { + completion(true) + } +} diff --git a/ios/Operations/NoCancelledDependenciesCondition.swift b/ios/Operations/NoCancelledDependenciesCondition.swift new file mode 100644 index 0000000000..da562153ce --- /dev/null +++ b/ios/Operations/NoCancelledDependenciesCondition.swift @@ -0,0 +1,29 @@ +// +// NoCancelledDependenciesCondition.swift +// Operations +// +// Created by pronebird on 25/09/2022. +// Copyright © 2022 Mullvad VPN AB. All rights reserved. +// + +import Foundation + +public final class NoCancelledDependenciesCondition: OperationCondition { + public var name: String { + return "NoCancelledDependenciesCondition" + } + + public var isMutuallyExclusive: Bool { + return false + } + + public init() {} + + public func evaluate(for operation: Operation, completion: @escaping (Bool) -> Void) { + let satisfy = operation.dependencies.allSatisfy { operation in + return !operation.isCancelled + } + + completion(satisfy) + } +} diff --git a/ios/Operations/NoFailedDependenciesCondition.swift b/ios/Operations/NoFailedDependenciesCondition.swift new file mode 100644 index 0000000000..2e96a12593 --- /dev/null +++ b/ios/Operations/NoFailedDependenciesCondition.swift @@ -0,0 +1,40 @@ +// +// NoFailedDependenciesCondition.swift +// Operations +// +// Created by pronebird on 25/09/2022. +// Copyright © 2022 Mullvad VPN AB. All rights reserved. +// + +import Foundation + +public final class NoFailedDependenciesCondition: OperationCondition { + public var name: String { + return "NoFailedDependenciesCondition" + } + + public var isMutuallyExclusive: Bool { + return false + } + + public let ignoreCancellations: Bool + public init(ignoreCancellations: Bool) { + self.ignoreCancellations = ignoreCancellations + } + + public func evaluate(for operation: Operation, completion: @escaping (Bool) -> Void) { + let satisfy = operation.dependencies.allSatisfy { operation in + if let operation = operation as? AsyncOperation, operation.error != nil { + return false + } + + if operation.isCancelled, !self.ignoreCancellations { + return false + } + + return true + } + + completion(satisfy) + } +} diff --git a/ios/MullvadVPN/Operations/OperationCompletion.swift b/ios/Operations/OperationCompletion.swift index c4a9f90a88..ffb8f54ce8 100644 --- a/ios/MullvadVPN/Operations/OperationCompletion.swift +++ b/ios/Operations/OperationCompletion.swift @@ -8,12 +8,12 @@ import Foundation -enum OperationCompletion<Success, Failure: Error> { +public enum OperationCompletion<Success, Failure: Error> { case cancelled case success(Success) case failure(Failure) - var isSuccess: Bool { + public var isSuccess: Bool { if case .success = self { return true } else { @@ -21,7 +21,7 @@ enum OperationCompletion<Success, Failure: Error> { } } - var value: Success? { + public var value: Success? { if case let .success(value) = self { return value } else { @@ -29,7 +29,7 @@ enum OperationCompletion<Success, Failure: Error> { } } - var error: Failure? { + public var error: Failure? { if case let .failure(error) = self { return error } else { @@ -37,7 +37,7 @@ enum OperationCompletion<Success, Failure: Error> { } } - var result: Result<Success, Failure>? { + public var result: Result<Success, Failure>? { switch self { case let .success(value): return .success(value) @@ -48,7 +48,7 @@ enum OperationCompletion<Success, Failure: Error> { } } - init(result: Result<Success, Failure>) { + public init(result: Result<Success, Failure>) { switch result { case let .success(value): self = .success(value) @@ -57,7 +57,7 @@ enum OperationCompletion<Success, Failure: Error> { } } - init(error: Failure?) where Success == Void { + public init(error: Failure?) where Success == Void { if let error = error { self = .failure(error) } else { @@ -65,7 +65,7 @@ enum OperationCompletion<Success, Failure: Error> { } } - func map<NewSuccess>(_ block: (Success) -> NewSuccess) + public func map<NewSuccess>(_ block: (Success) -> NewSuccess) -> OperationCompletion<NewSuccess, Failure> { switch self { @@ -78,7 +78,7 @@ enum OperationCompletion<Success, Failure: Error> { } } - func mapError<NewFailure: Error>(_ block: (Failure) -> NewFailure) + public func mapError<NewFailure: Error>(_ block: (Failure) -> NewFailure) -> OperationCompletion<Success, NewFailure> { switch self { @@ -91,7 +91,7 @@ enum OperationCompletion<Success, Failure: Error> { } } - func flatMap<NewSuccess>(_ block: (Success) -> OperationCompletion<NewSuccess, Failure>) + public func flatMap<NewSuccess>(_ block: (Success) -> OperationCompletion<NewSuccess, Failure>) -> OperationCompletion<NewSuccess, Failure> { switch self { @@ -104,7 +104,7 @@ enum OperationCompletion<Success, Failure: Error> { } } - func flatMapError<NewFailure: Error>( + public func flatMapError<NewFailure: Error>( _ block: (Failure) -> OperationCompletion<Success, NewFailure> ) -> OperationCompletion<Success, NewFailure> { @@ -118,7 +118,7 @@ enum OperationCompletion<Success, Failure: Error> { } } - func tryMap<NewSuccess>(_ block: (Success) throws -> NewSuccess) + public func tryMap<NewSuccess>(_ block: (Success) throws -> NewSuccess) -> OperationCompletion<NewSuccess, Error> { switch self { @@ -135,11 +135,11 @@ enum OperationCompletion<Success, Failure: Error> { } } - func ignoreOutput() -> OperationCompletion<Void, Failure> { + public func ignoreOutput() -> OperationCompletion<Void, Failure> { return map { _ in () } } - func eraseFailureType() -> OperationCompletion<Success, Error> { + public func eraseFailureType() -> OperationCompletion<Success, Error> { return mapError { $0 } } } diff --git a/ios/Operations/OperationCondition.swift b/ios/Operations/OperationCondition.swift new file mode 100644 index 0000000000..7a30744c2d --- /dev/null +++ b/ios/Operations/OperationCondition.swift @@ -0,0 +1,16 @@ +// +// OperationCondition.swift +// MullvadVPN +// +// Created by pronebird on 30/05/2022. +// Copyright © 2022 Mullvad VPN AB. All rights reserved. +// + +import Foundation + +public protocol OperationCondition { + var name: String { get } + var isMutuallyExclusive: Bool { get } + + func evaluate(for operation: Operation, completion: @escaping (Bool) -> Void) +} diff --git a/ios/MullvadVPN/Operations/OperationObserver.swift b/ios/Operations/OperationObserver.swift index fd9fb61bfa..db6264d2ba 100644 --- a/ios/MullvadVPN/Operations/OperationObserver.swift +++ b/ios/Operations/OperationObserver.swift @@ -8,7 +8,7 @@ import Foundation -protocol OperationObserver { +public protocol OperationObserver { func didAttach(to operation: Operation) func operationDidStart(_ operation: Operation) func operationDidCancel(_ operation: Operation) @@ -16,16 +16,16 @@ protocol OperationObserver { } /// Block based operation observer. -class OperationBlockObserver<OperationType: Operation>: OperationObserver { - typealias VoidBlock = (OperationType) -> Void - typealias FinishBlock = (OperationType, Error?) -> Void +public class OperationBlockObserver<OperationType: Operation>: OperationObserver { + public typealias VoidBlock = (OperationType) -> Void + public typealias FinishBlock = (OperationType, Error?) -> Void private let _didAttach: VoidBlock? private let _didStart: VoidBlock? private let _didCancel: VoidBlock? private let _didFinish: FinishBlock? - init( + public init( didAttach: VoidBlock? = nil, didStart: VoidBlock? = nil, didCancel: VoidBlock? = nil, @@ -37,25 +37,25 @@ class OperationBlockObserver<OperationType: Operation>: OperationObserver { _didFinish = didFinish } - func didAttach(to operation: Operation) { + public func didAttach(to operation: Operation) { if let operation = operation as? OperationType { _didAttach?(operation) } } - func operationDidStart(_ operation: Operation) { + public func operationDidStart(_ operation: Operation) { if let operation = operation as? OperationType { _didStart?(operation) } } - func operationDidCancel(_ operation: Operation) { + public func operationDidCancel(_ operation: Operation) { if let operation = operation as? OperationType { _didCancel?(operation) } } - func operationDidFinish(_ operation: Operation, error: Error?) { + public func operationDidFinish(_ operation: Operation, error: Error?) { if let operation = operation as? OperationType { _didFinish?(operation, error) } diff --git a/ios/MullvadVPN/Operations/OutputOperation.swift b/ios/Operations/OutputOperation.swift index 0a7f50df5b..0e2e44525f 100644 --- a/ios/MullvadVPN/Operations/OutputOperation.swift +++ b/ios/Operations/OutputOperation.swift @@ -8,7 +8,7 @@ import Foundation -protocol OutputOperation: Operation { +public protocol OutputOperation: Operation { associatedtype Output var output: Output? { get } diff --git a/ios/MullvadVPN/Operations/PresentAlertOperation.swift b/ios/Operations/PresentAlertOperation.swift index 3a3976de7a..f9fae07e0c 100644 --- a/ios/MullvadVPN/Operations/PresentAlertOperation.swift +++ b/ios/Operations/PresentAlertOperation.swift @@ -6,14 +6,16 @@ // Copyright © 2021 Mullvad VPN AB. All rights reserved. // +#if canImport(UIKit) + import UIKit -class PresentAlertOperation: AsyncOperation { +public final class PresentAlertOperation: AsyncOperation { private let alertController: UIAlertController private let presentingController: UIViewController private let presentCompletion: (() -> Void)? - init( + public init( alertController: UIAlertController, presentingController: UIViewController, presentCompletion: (() -> Void)? = nil @@ -25,7 +27,7 @@ class PresentAlertOperation: AsyncOperation { super.init(dispatchQueue: .main) } - override func operationDidCancel() { + override public func operationDidCancel() { // Guard against trying to dismiss the alert when operation hasn't started yet. guard isExecuting else { return } @@ -35,7 +37,7 @@ class PresentAlertOperation: AsyncOperation { } } - override func main() { + override public func main() { NotificationCenter.default.addObserver( self, selector: #selector(alertControllerDidDismiss(_:)), @@ -69,3 +71,5 @@ class PresentAlertOperation: AsyncOperation { finish() } } + +#endif diff --git a/ios/MullvadVPN/Operations/ProductsRequestOperation.swift b/ios/Operations/ProductsRequestOperation.swift index cc80b9e3f4..91635b3cd6 100644 --- a/ios/MullvadVPN/Operations/ProductsRequestOperation.swift +++ b/ios/Operations/ProductsRequestOperation.swift @@ -6,10 +6,11 @@ // Copyright © 2021 Mullvad VPN AB. All rights reserved. // -import Foundation +#if canImport(StoreKit) + import StoreKit -class ProductsRequestOperation: ResultOperation<SKProductsResponse, Error>, +public final class ProductsRequestOperation: ResultOperation<SKProductsResponse, Error>, SKProductsRequestDelegate { private let productIdentifiers: Set<String> @@ -21,7 +22,7 @@ class ProductsRequestOperation: ResultOperation<SKProductsResponse, Error>, private var retryTimer: DispatchSourceTimer? private var request: SKProductsRequest? - init(productIdentifiers: Set<String>, completionHandler: @escaping CompletionHandler) { + public init(productIdentifiers: Set<String>, completionHandler: @escaping CompletionHandler) { self.productIdentifiers = productIdentifiers super.init( @@ -31,22 +32,22 @@ class ProductsRequestOperation: ResultOperation<SKProductsResponse, Error>, ) } - override func main() { + override public func main() { startRequest() } - override func operationDidCancel() { + override public func operationDidCancel() { request?.cancel() retryTimer?.cancel() } // - MARK: SKProductsRequestDelegate - func requestDidFinish(_ request: SKRequest) { + public func requestDidFinish(_ request: SKRequest) { // no-op } - func request(_ request: SKRequest, didFailWithError error: Error) { + public func request(_ request: SKRequest, didFailWithError error: Error) { dispatchQueue.async { if self.retryCount < self.maxRetryCount, !self.isCancelled { self.retryCount += 1 @@ -57,7 +58,10 @@ class ProductsRequestOperation: ResultOperation<SKProductsResponse, Error>, } } - func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { + public func productsRequest( + _ request: SKProductsRequest, + didReceive response: SKProductsResponse + ) { finish(completion: .success(response)) } @@ -84,3 +88,5 @@ class ProductsRequestOperation: ResultOperation<SKProductsResponse, Error>, retryTimer?.activate() } } + +#endif diff --git a/ios/MullvadVPN/Operations/ResultBlockOperation.swift b/ios/Operations/ResultBlockOperation.swift index c9616d958d..483731360a 100644 --- a/ios/MullvadVPN/Operations/ResultBlockOperation.swift +++ b/ios/Operations/ResultBlockOperation.swift @@ -8,14 +8,17 @@ import Foundation -class ResultBlockOperation<Success, Failure: Error>: ResultOperation<Success, Failure> { - typealias ExecutionBlock = (ResultBlockOperation<Success, Failure>) -> Void - typealias ThrowingExecutionBlock = () throws -> Success +public final class ResultBlockOperation<Success, Failure: Error>: ResultOperation< + Success, + Failure +> { + public typealias ExecutionBlock = (ResultBlockOperation<Success, Failure>) -> Void + public typealias ThrowingExecutionBlock = () throws -> Success private var executionBlock: ExecutionBlock? private var cancellationBlocks: [() -> Void] = [] - convenience init( + public convenience init( dispatchQueue: DispatchQueue? = nil, executionBlock: ExecutionBlock? = nil ) { @@ -27,7 +30,7 @@ class ResultBlockOperation<Success, Failure: Error>: ResultOperation<Success, Fa ) } - convenience init( + public convenience init( dispatchQueue: DispatchQueue? = nil, executionBlock: @escaping ThrowingExecutionBlock ) { @@ -39,7 +42,7 @@ class ResultBlockOperation<Success, Failure: Error>: ResultOperation<Success, Fa ) } - init( + public init( dispatchQueue: DispatchQueue?, executionBlock: ExecutionBlock?, completionQueue: DispatchQueue?, @@ -54,14 +57,14 @@ class ResultBlockOperation<Success, Failure: Error>: ResultOperation<Success, Fa ) } - override func main() { + override public func main() { let block = executionBlock executionBlock = nil block?(self) } - override func operationDidCancel() { + override public func operationDidCancel() { let blocks = cancellationBlocks cancellationBlocks.removeAll() @@ -70,23 +73,26 @@ class ResultBlockOperation<Success, Failure: Error>: ResultOperation<Success, Fa } } - override func operationDidFinish() { + override public func operationDidFinish() { cancellationBlocks.removeAll() executionBlock = nil } - func setExecutionBlock(_ block: @escaping (ResultBlockOperation<Success, Failure>) -> Void) { + public func setExecutionBlock( + _ block: @escaping (ResultBlockOperation<Success, Failure>) + -> Void + ) { dispatchQueue.async { assert(!self.isExecuting && !self.isFinished) self.executionBlock = block } } - func setExecutionBlock(_ block: @escaping ThrowingExecutionBlock) { + public func setExecutionBlock(_ block: @escaping ThrowingExecutionBlock) { setExecutionBlock(Self.wrapThrowingBlock(block)) } - func addCancellationBlock(_ block: @escaping () -> Void) { + public func addCancellationBlock(_ block: @escaping () -> Void) { dispatchQueue.async { if self.isCancelled { block() diff --git a/ios/MullvadVPN/Operations/ResultOperation+Output.swift b/ios/Operations/ResultOperation+Output.swift index db5cd2a6e7..56b13a0524 100644 --- a/ios/MullvadVPN/Operations/ResultOperation+Output.swift +++ b/ios/Operations/ResultOperation+Output.swift @@ -9,7 +9,7 @@ import Foundation extension ResultOperation: OutputOperation { - var output: Success? { + public var output: Success? { return completion?.value } } diff --git a/ios/MullvadVPN/Operations/ResultOperation.swift b/ios/Operations/ResultOperation.swift index 4d7ec4b7ce..4f88ce769b 100644 --- a/ios/MullvadVPN/Operations/ResultOperation.swift +++ b/ios/Operations/ResultOperation.swift @@ -9,9 +9,9 @@ import Foundation /// Base class for operations producing result. -class ResultOperation<Success, Failure: Error>: AsyncOperation { - typealias Completion = OperationCompletion<Success, Failure> - typealias CompletionHandler = (Completion) -> Void +open class ResultOperation<Success, Failure: Error>: AsyncOperation { + public typealias Completion = OperationCompletion<Success, Failure> + public typealias CompletionHandler = (Completion) -> Void private let nslock = NSLock() private var completionValue: Completion? @@ -19,13 +19,13 @@ class ResultOperation<Success, Failure: Error>: AsyncOperation { private var _completionHandler: CompletionHandler? private var pendingFinish = false - var completion: Completion? { + public var completion: Completion? { nslock.lock() defer { nslock.unlock() } return completionValue } - var completionQueue: DispatchQueue? { + public var completionQueue: DispatchQueue? { get { nslock.lock() defer { nslock.unlock() } @@ -39,7 +39,7 @@ class ResultOperation<Success, Failure: Error>: AsyncOperation { } } - var completionHandler: CompletionHandler? { + public var completionHandler: CompletionHandler? { get { nslock.lock() defer { nslock.unlock() } @@ -55,11 +55,11 @@ class ResultOperation<Success, Failure: Error>: AsyncOperation { } } - override init(dispatchQueue: DispatchQueue?) { + override public init(dispatchQueue: DispatchQueue?) { super.init(dispatchQueue: dispatchQueue) } - init( + public init( dispatchQueue: DispatchQueue?, completionQueue: DispatchQueue?, completionHandler: CompletionHandler? @@ -71,16 +71,16 @@ class ResultOperation<Success, Failure: Error>: AsyncOperation { } @available(*, unavailable) - override func finish() { + override public func finish() { _finish(error: nil) } @available(*, unavailable) - override func finish(error: Error?) { + override public func finish(error: Error?) { _finish(error: error) } - func finish(completion: Completion) { + open func finish(completion: Completion) { nslock.lock() if completionValue == nil { completionValue = completion diff --git a/ios/MullvadVPN/Operations/TransformOperation.swift b/ios/Operations/TransformOperation.swift index abca23077a..71cac93f4b 100644 --- a/ios/MullvadVPN/Operations/TransformOperation.swift +++ b/ios/Operations/TransformOperation.swift @@ -7,62 +7,65 @@ import Foundation -final class TransformOperation<Input, Output, Failure: Error>: +public final class TransformOperation<Input, Output, Failure: Error>: ResultOperation<Output, Failure>, InputOperation { - typealias ExecutionBlock = (Input, TransformOperation<Input, Output, Failure>) -> Void - typealias ThrowingExecutionBlock = (Input) throws -> Output - - typealias InputBlock = () -> Input? + public typealias ExecutionBlock = (Input, TransformOperation<Input, Output, Failure>) -> Void + public typealias ThrowingExecutionBlock = (Input) throws -> Output + public typealias InputBlock = () -> Input? private let nslock = NSLock() - private(set) var input: Input? { + public var input: Input? { + return _input + } + + private var __input: Input? + private var _input: Input? { get { nslock.lock() defer { nslock.unlock() } - return _input + return __input } set { nslock.lock() - _input = newValue + __input = newValue nslock.unlock() } } - private var _input: Input? private var inputBlock: InputBlock? private var executionBlock: ExecutionBlock? private var cancellationBlocks: [() -> Void] = [] - init( + public init( dispatchQueue: DispatchQueue? = nil, input: Input? = nil, block: ExecutionBlock? = nil ) { - _input = input + __input = input executionBlock = block super.init(dispatchQueue: dispatchQueue) } - init( + public init( dispatchQueue: DispatchQueue? = nil, input: Input? = nil, throwingBlock: @escaping ThrowingExecutionBlock ) { - _input = input + __input = input executionBlock = Self.wrapThrowingBlock(throwingBlock) super.init(dispatchQueue: dispatchQueue) } - override func main() { + override public func main() { let inputValue = inputBlock?() - input = inputValue + _input = inputValue guard let inputValue = inputValue, let executionBlock = executionBlock else { finish(completion: .cancelled) @@ -72,7 +75,7 @@ final class TransformOperation<Input, Output, Failure: Error>: executionBlock(inputValue, self) } - override func operationDidCancel() { + override public func operationDidCancel() { let blocks = cancellationBlocks cancellationBlocks.removeAll() @@ -81,25 +84,25 @@ final class TransformOperation<Input, Output, Failure: Error>: } } - override func operationDidFinish() { + override public func operationDidFinish() { cancellationBlocks.removeAll() executionBlock = nil } // MARK: - Block handlers - func setExecutionBlock(_ block: @escaping ExecutionBlock) { + public func setExecutionBlock(_ block: @escaping ExecutionBlock) { dispatchQueue.async { assert(!self.isExecuting && !self.isFinished) self.executionBlock = block } } - func setExecutionBlock(_ block: @escaping ThrowingExecutionBlock) { + public func setExecutionBlock(_ block: @escaping ThrowingExecutionBlock) { setExecutionBlock(Self.wrapThrowingBlock(block)) } - func addCancellationBlock(_ block: @escaping () -> Void) { + public func addCancellationBlock(_ block: @escaping () -> Void) { dispatchQueue.async { if self.isCancelled { block() @@ -111,7 +114,7 @@ final class TransformOperation<Input, Output, Failure: Error>: // MARK: - Input injection - func setInputBlock(_ block: @escaping () -> Input?) { + public func setInputBlock(_ block: @escaping () -> Input?) { dispatchQueue.async { self.inputBlock = block } diff --git a/ios/MullvadVPNTests/OperationConditionTests.swift b/ios/OperationsTests/OperationConditionTests.swift index 80bf13b2da..ca4a15f20a 100644 --- a/ios/MullvadVPNTests/OperationConditionTests.swift +++ b/ios/OperationsTests/OperationConditionTests.swift @@ -6,6 +6,7 @@ // Copyright © 2022 Mullvad VPN AB. All rights reserved. // +import Operations import XCTest class OperationConditionTests: XCTestCase { diff --git a/ios/MullvadVPNTests/OperationInputInjectionTests.swift b/ios/OperationsTests/OperationInputInjectionTests.swift index 52394f89f1..828afd2643 100644 --- a/ios/MullvadVPNTests/OperationInputInjectionTests.swift +++ b/ios/OperationsTests/OperationInputInjectionTests.swift @@ -6,6 +6,7 @@ // Copyright © 2022 Mullvad VPN AB. All rights reserved. // +import Operations import XCTest class OperationInputInjectionTests: XCTestCase { diff --git a/ios/MullvadVPNTests/OperationObserverTests.swift b/ios/OperationsTests/OperationObserverTests.swift index 5c9d257fdc..c246cdc526 100644 --- a/ios/MullvadVPNTests/OperationObserverTests.swift +++ b/ios/OperationsTests/OperationObserverTests.swift @@ -6,6 +6,7 @@ // Copyright © 2022 Mullvad VPN AB. All rights reserved. // +import Operations import XCTest class OperationObserverTests: XCTestCase { diff --git a/ios/MullvadVPNTests/OperationSmokeTests.swift b/ios/OperationsTests/OperationSmokeTests.swift index c739e4e3c9..7d8b17e784 100644 --- a/ios/MullvadVPNTests/OperationSmokeTests.swift +++ b/ios/OperationsTests/OperationSmokeTests.swift @@ -6,6 +6,7 @@ // Copyright © 2022 Mullvad VPN AB. All rights reserved. // +import Operations import XCTest class OperationSmokeTests: XCTestCase { diff --git a/ios/MullvadVPN/Swizzle.swift b/ios/Shared/Swizzle.swift index 6073384cf4..6073384cf4 100644 --- a/ios/MullvadVPN/Swizzle.swift +++ b/ios/Shared/Swizzle.swift |
