diff --git a/App/Backend/ResourcePolicyManager.swift b/App/Backend/ResourcePolicyManager.swift index 2f69a23..1429ddf 100644 --- a/App/Backend/ResourcePolicyManager.swift +++ b/App/Backend/ResourcePolicyManager.swift @@ -10,7 +10,7 @@ import Foundation class ResourcePolicyManager: NSObject, SBRResourceOriginPolicyDataSource { static let AllowedOriginsDefaultsKey = "allowedOrigins" - static let EnabledOriginsDefaultsKey = "enabledOrigins" + static let OriginPoliciesDefaultsKey = "originPolicies" private static func stringSetForKey(_ key: String) -> Set { if let set = UserDefaults.standard.array(forKey: key) as? [String] { @@ -30,6 +30,19 @@ class ResourcePolicyManager: NSObject, SBRResourceOriginPolicyDataSource func allowedOriginsForScriptResources() -> Set { allowedOriginSet } + private lazy var scriptPolicies: Dictionary = { + if let existingDict = UserDefaults.standard.dictionary(forKey: Self.OriginPoliciesDefaultsKey) as? Dictionary { + return existingDict.mapValues { ScriptPolicy.PolicyType(rawValue: $0)! } + } + + return Dictionary() + }() { + didSet { + let encodableDictionary = scriptPolicies.mapValues { $0.rawValue } + UserDefaults.standard.set(encodableDictionary, forKey: Self.OriginPoliciesDefaultsKey) + } + } + func allowOriginToLoadScriptResources(_ origin: String) { allowedOriginSet.formUnion([ origin ]) } @@ -37,4 +50,16 @@ class ResourcePolicyManager: NSObject, SBRResourceOriginPolicyDataSource func disallowOriginToLoadScriptResources(_ origin: String) { allowedOriginSet.remove(origin) } + + func scriptPolicy(forOrigin origin: String) -> ScriptPolicy { + if let policyType = scriptPolicies[origin] { + return ScriptPolicy(policyType: policyType, securityOrigin: origin) + } + + return ScriptPolicy(policyType: .alpha, securityOrigin: origin) + } + + func setScriptPolicyType(_ policyType: ScriptPolicy.PolicyType, forOrigin origin: String) { + scriptPolicies[origin] = policyType + } } diff --git a/App/Backend/ScriptPolicy.swift b/App/Backend/ScriptPolicy.swift new file mode 100644 index 0000000..2c4adf4 --- /dev/null +++ b/App/Backend/ScriptPolicy.swift @@ -0,0 +1,84 @@ +// +// ScriptPolicy.swift +// App +// +// Created by James Magahern on 9/29/21. +// + +import UIKit + +struct ScriptPolicy: Hashable { + enum PolicyType: Int, CaseIterable { + case alpha + case bravo + case charlie + case delta + case echo + } + + public let policyType: PolicyType + public let securityOrigin: String + + public static func title(forPolicyType type: PolicyType) -> String { + switch type { + case .alpha: return "Alpha" + case .bravo: return "Bravo" + case .charlie: return "Charlie" + case .delta: return "Delta" + case .echo: return "Echo" + } + } + + public static func localizedDescription(forPolicyType type: PolicyType) -> String { + switch type { + case .alpha: + return "All scripts blocked." + case .bravo: + return "Scripts on page are allowed." + case .charlie: + return "Allow scripts from the same security origin." + case .delta: + return "Allow scripts from common and host CDNs." + case .echo: + return "All scripts are allowed." + } + } + + public static func iconRepresentation(forPolicyType type: PolicyType, size: CGSize) -> UIImage? { + let font = UIFont.boldSystemFont(ofSize: size.height - 2) + let attrs: [NSAttributedString.Key : Any] = [ + .font : font, + .foregroundColor: UIColor.white, + ] + + let rect = CGRect(origin: .zero, size: size) + UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale) + if let _ = UIGraphicsGetCurrentContext() { + let backgroundPath = UIBezierPath.init(roundedRect: rect, cornerRadius: 4.0) + // backgroundPath.usesEvenOddFillRule = true + backgroundPath.fill() + + let character = NSString(string: { () -> String in + switch type { + case .alpha: return "𝝰" + case .bravo: return "𝝱" + case .charlie: return "𝝲" + case .delta: return "𝝳" + case .echo: return "𝝴" + } + }()) + + let charSize = character.size(withAttributes: attrs) + let charRect = CGRect(origin: .init(x: (size.width - charSize.width) / 2 , + y: -(charSize.height - size.height) / 2), + size: charSize) + + character.draw(in: charRect, withAttributes: attrs) + } + + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return image + } +} diff --git a/App/Browser View/BrowserViewController.swift b/App/Browser View/BrowserViewController.swift index fba4283..c67d674 100644 --- a/App/Browser View/BrowserViewController.swift +++ b/App/Browser View/BrowserViewController.swift @@ -523,7 +523,7 @@ class BrowserViewController: UIViewController iconView.someScriptsAllowed = scriptsAllowedForHost iconView.setBlockedScriptsNumber(numBlockedScripts) - iconView.isEnabled = (webView.url != nil) + // iconView.isEnabled = (webView.url != nil) } public func createNewTab(withURL url: URL?) { diff --git a/App/Script Policy UI/ScriptOriginPolicyViewController.swift b/App/Script Policy UI/ScriptOriginPolicyViewController.swift new file mode 100644 index 0000000..45031e6 --- /dev/null +++ b/App/Script Policy UI/ScriptOriginPolicyViewController.swift @@ -0,0 +1,182 @@ +// +// ScriptPolicyViewController.swift +// SBrowser +// +// Created by James Magahern on 7/24/20. +// + +import UIKit + +class ScriptOriginPolicyViewController: UIViewController, UICollectionViewDelegate +{ + var collectionView: UICollectionView? + var allowScriptsForTab = false + weak var delegate: ScriptPolicyViewControllerDelegate? = nil + + private var dataSource: UICollectionViewDiffableDataSource? + private var didChangeScriptPolicy = false + + private enum Section: Int { + case tabOptions + case origins + } + + private static let enableScriptsForTabItem: String = "enableScriptsForTab" + + convenience init(policyManager: ResourcePolicyManager, hostOrigin: String, loadedScripts: Set, scriptsAllowedForTab: Bool) { + self.init(nibName: nil, bundle: nil) + allowScriptsForTab = scriptsAllowedForTab + + let listConfig = UICollectionLayoutListConfiguration(appearance: .insetGrouped) + let listLayout = UICollectionViewCompositionalLayout.list(using: listConfig) + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: listLayout) + + // Make sure host origin goes first in the list. + let otherOriginScripts = loadedScripts.subtracting([ hostOrigin ]) + let allowedScripts = otherOriginScripts.filter { policyManager.allowedOriginsForScriptResources().contains($0) } + + let originItems = [ hostOrigin ] + allowedScripts + otherOriginScripts.subtracting(allowedScripts) + + let switchCellRegistry = UICollectionView.CellRegistration { [unowned self] (listCell, indexPath, item) in + var config = listCell.defaultContentConfiguration() + if item == Self.enableScriptsForTabItem { + if allowScriptsForTab { + config.text = "Shields Up" + config.image = UIImage(systemName: "shield.fill") + } else { + config.text = "Allow for Tab" + config.image = UIImage(systemName: "shield.slash") + } + + config.textProperties.color = UIColor.systemBlue + } + + listCell.contentConfiguration = config + } + + let scriptPolicyRegistry = UICollectionView.CellRegistration { [unowned self] (listCell, indexPath, item) in + var config = listCell.defaultContentConfiguration() + config.text = item + + listCell.contentConfiguration = config + + let segmentedControl = UISegmentedControl(items: [ + UIImage(systemName: "xmark.seal")!, // Disabled + UIImage(systemName: "checkmark.seal.fill")! // Enabled + ]) + + segmentedControl.setTitleTextAttributes([ .foregroundColor: UIColor.init(dynamicProvider: { traits in + if traits.userInterfaceStyle == .dark { + return UIColor.systemTeal + } else { + return UIColor.systemBlue + } + }) ], for: .selected) + + segmentedControl.addAction(UIAction(handler: { [unowned segmentedControl] _ in + let allowed: Bool = (segmentedControl.selectedSegmentIndex == 1) + + if allowed { + policyManager.allowOriginToLoadScriptResources(item) + } else { + policyManager.disallowOriginToLoadScriptResources(item) + } + + if item == hostOrigin { + if var snapshot = self.dataSource?.snapshot() { + snapshot.reloadItems(Array(otherOriginScripts)) + self.dataSource?.apply(snapshot, animatingDifferences: true) + } + } + + self.didChangeScriptPolicy = true + + }), for: .valueChanged) + + if policyManager.allowedOriginsForScriptResources().contains(item) { + segmentedControl.selectedSegmentIndex = 1 + } else { + segmentedControl.selectedSegmentIndex = 0 + } + + let customViewConfiguration = UICellAccessory.CustomViewConfiguration( + customView: segmentedControl, + placement: .trailing(displayed: .always, at: { _ in return 0 }), + isHidden: false, + reservedLayoutWidth: .actual, + tintColor: nil, + maintainsFixedSize: true + ) + + listCell.accessories = [ + .customView(configuration: customViewConfiguration) + ] + } + + let dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { (collectionView, indexPath, item) -> UICollectionViewCell? in + if item == Self.enableScriptsForTabItem { + return collectionView.dequeueConfiguredReusableCell(using: switchCellRegistry, for: indexPath, item: item) + } + + return collectionView.dequeueConfiguredReusableCell(using: scriptPolicyRegistry, for: indexPath, item: item) + } + + collectionView.dataSource = dataSource + collectionView.delegate = self + + var snapshot = dataSource.snapshot() + snapshot.appendSections([ .tabOptions ]) + snapshot.appendItems([ Self.enableScriptsForTabItem ], toSection: .tabOptions) + + if !allowScriptsForTab { + snapshot.appendSections([ .origins ]) + snapshot.appendItems(originItems, toSection: .origins) + } + + dataSource.apply(snapshot) + + self.dataSource = dataSource + self.collectionView = collectionView + + title = "Script Origin Policy" + navigationItem.rightBarButtonItem = UIBarButtonItem(systemItem: .done, primaryAction: UIAction(handler: { [unowned self] action in + if self.didChangeScriptPolicy { + self.delegate?.didChangeScriptPolicy() + self.delegate?.setScriptsEnabledForTab(self.allowScriptsForTab) + } + + self.dismiss(animated: true, completion: nil) + }), menu: nil) + } + + override func loadView() { + self.view = collectionView + self.view.backgroundColor = .systemGroupedBackground + } + + // MARK: UICollectionViewDelegate + + func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool { + indexPath.section != Section.origins.rawValue + } + + func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { + indexPath.section != Section.origins.rawValue + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + guard let dataSource = dataSource else { return } + + if indexPath.section == Section.tabOptions.rawValue { + let identifier = dataSource.itemIdentifier(for: indexPath) + if identifier == Self.enableScriptsForTabItem { + self.allowScriptsForTab = !self.allowScriptsForTab + + // Immediately notify and dismiss + self.delegate?.didChangeScriptPolicy() + self.delegate?.setScriptsEnabledForTab(self.allowScriptsForTab) + self.dismiss(animated: true, completion: nil) + } + } + } +} diff --git a/App/Script Policy UI/ScriptPolicyViewController.swift b/App/Script Policy UI/ScriptPolicyViewController.swift index 21d25d2..8e1dacf 100644 --- a/App/Script Policy UI/ScriptPolicyViewController.swift +++ b/App/Script Policy UI/ScriptPolicyViewController.swift @@ -7,44 +7,57 @@ import UIKit -protocol ScriptPolicyViewControllerDelegate: AnyObject { - func didChangeScriptPolicy() - func setScriptsEnabledForTab(_ enabled: Bool) -} - class ScriptPolicyViewController: UIViewController, UICollectionViewDelegate { var collectionView: UICollectionView? var allowScriptsForTab = false weak var delegate: ScriptPolicyViewControllerDelegate? = nil - private var dataSource: UICollectionViewDiffableDataSource? - private var didChangeScriptPolicy = false - private enum Section: Int { case tabOptions - case origins + case policies + } + + private enum Item: Hashable { + case allowScriptsForTab + case policy(ScriptPolicy.PolicyType) } - private static let enableScriptsForTabItem: String = "enableScriptsForTab" + private var dataSource: UICollectionViewDiffableDataSource? + private var didChangeScriptPolicy = false + private var policyManager: ResourcePolicyManager! + private var hostOrigin: String! convenience init(policyManager: ResourcePolicyManager, hostOrigin: String, loadedScripts: Set, scriptsAllowedForTab: Bool) { self.init(nibName: nil, bundle: nil) - allowScriptsForTab = scriptsAllowedForTab + self.allowScriptsForTab = scriptsAllowedForTab + self.policyManager = policyManager + self.hostOrigin = hostOrigin let listConfig = UICollectionLayoutListConfiguration(appearance: .insetGrouped) let listLayout = UICollectionViewCompositionalLayout.list(using: listConfig) let collectionView = UICollectionView(frame: .zero, collectionViewLayout: listLayout) - // Make sure host origin goes first in the list. - let otherOriginScripts = loadedScripts.subtracting([ hostOrigin ]) - let allowedScripts = otherOriginScripts.filter { policyManager.allowedOriginsForScriptResources().contains($0) } - - let originItems = [ hostOrigin ] + allowedScripts + otherOriginScripts.subtracting(allowedScripts) - - let switchCellRegistry = UICollectionView.CellRegistration { [unowned self] (listCell, indexPath, item) in + let scriptPolicyRegistry = UICollectionView.CellRegistration { (listCell, indexPath, item) in + guard case let Item.policy(policyType) = item else { return } + var config = listCell.defaultContentConfiguration() - if item == Self.enableScriptsForTabItem { + config.text = ScriptPolicy.title(forPolicyType: policyType) + config.secondaryText = ScriptPolicy.localizedDescription(forPolicyType: policyType) + config.image = ScriptPolicy.iconRepresentation(forPolicyType: policyType, size: CGSize(width: 24.0, height: 24.0)) + + config.textProperties.font = UIFont.boldSystemFont(ofSize: 14.0) + + if policyManager.scriptPolicy(forOrigin: hostOrigin).policyType == policyType { + listCell.accessories = [ .checkmark() ] + } + + listCell.contentConfiguration = config + } + + let enableButtonRegistry = UICollectionView.CellRegistration { [unowned self] (listCell, indexPath, item) in + var config = listCell.defaultContentConfiguration() + if indexPath.section == Section.tabOptions.rawValue { if allowScriptsForTab { config.text = "Shields Up" config.image = UIImage(systemName: "shield.fill") @@ -59,68 +72,9 @@ class ScriptPolicyViewController: UIViewController, UICollectionViewDelegate listCell.contentConfiguration = config } - let scriptPolicyRegistry = UICollectionView.CellRegistration { [unowned self] (listCell, indexPath, item) in - var config = listCell.defaultContentConfiguration() - config.text = item - - listCell.contentConfiguration = config - - let segmentedControl = UISegmentedControl(items: [ - UIImage(systemName: "xmark.seal")!, // Disabled - UIImage(systemName: "checkmark.seal.fill")! // Enabled - ]) - - segmentedControl.setTitleTextAttributes([ .foregroundColor: UIColor.init(dynamicProvider: { traits in - if traits.userInterfaceStyle == .dark { - return UIColor.systemTeal - } else { - return UIColor.systemBlue - } - }) ], for: .selected) - - segmentedControl.addAction(UIAction(handler: { [unowned segmentedControl] _ in - let allowed: Bool = (segmentedControl.selectedSegmentIndex == 1) - - if allowed { - policyManager.allowOriginToLoadScriptResources(item) - } else { - policyManager.disallowOriginToLoadScriptResources(item) - } - - if item == hostOrigin { - if var snapshot = self.dataSource?.snapshot() { - snapshot.reloadItems(Array(otherOriginScripts)) - self.dataSource?.apply(snapshot, animatingDifferences: true) - } - } - - self.didChangeScriptPolicy = true - - }), for: .valueChanged) - - if policyManager.allowedOriginsForScriptResources().contains(item) { - segmentedControl.selectedSegmentIndex = 1 - } else { - segmentedControl.selectedSegmentIndex = 0 - } - - let customViewConfiguration = UICellAccessory.CustomViewConfiguration( - customView: segmentedControl, - placement: .trailing(displayed: .always, at: { _ in return 0 }), - isHidden: false, - reservedLayoutWidth: .actual, - tintColor: nil, - maintainsFixedSize: true - ) - - listCell.accessories = [ - .customView(configuration: customViewConfiguration) - ] - } - - let dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { (collectionView, indexPath, item) -> UICollectionViewCell? in - if item == Self.enableScriptsForTabItem { - return collectionView.dequeueConfiguredReusableCell(using: switchCellRegistry, for: indexPath, item: item) + let dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { (collectionView, indexPath, item) -> UICollectionViewCell? in + if indexPath.section == Section.tabOptions.rawValue { + return collectionView.dequeueConfiguredReusableCell(using: enableButtonRegistry, for: indexPath, item: item) } return collectionView.dequeueConfiguredReusableCell(using: scriptPolicyRegistry, for: indexPath, item: item) @@ -131,11 +85,11 @@ class ScriptPolicyViewController: UIViewController, UICollectionViewDelegate var snapshot = dataSource.snapshot() snapshot.appendSections([ .tabOptions ]) - snapshot.appendItems([ Self.enableScriptsForTabItem ], toSection: .tabOptions) + snapshot.appendItems([ .allowScriptsForTab ], toSection: .tabOptions) if !allowScriptsForTab { - snapshot.appendSections([ .origins ]) - snapshot.appendItems(originItems, toSection: .origins) + snapshot.appendSections([ .policies ]) + snapshot.appendItems(ScriptPolicy.PolicyType.allCases.map { .policy($0) }, toSection: .policies) } dataSource.apply(snapshot) @@ -143,7 +97,7 @@ class ScriptPolicyViewController: UIViewController, UICollectionViewDelegate self.dataSource = dataSource self.collectionView = collectionView - title = "Script Origin Policy" + title = "Script Security Policy" navigationItem.rightBarButtonItem = UIBarButtonItem(systemItem: .done, primaryAction: UIAction(handler: { [unowned self] action in if self.didChangeScriptPolicy { self.delegate?.didChangeScriptPolicy() @@ -161,20 +115,12 @@ class ScriptPolicyViewController: UIViewController, UICollectionViewDelegate // MARK: UICollectionViewDelegate - func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool { - indexPath.section != Section.origins.rawValue - } - - func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { - indexPath.section != Section.origins.rawValue - } - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let dataSource = dataSource else { return } if indexPath.section == Section.tabOptions.rawValue { let identifier = dataSource.itemIdentifier(for: indexPath) - if identifier == Self.enableScriptsForTabItem { + if identifier == .allowScriptsForTab { self.allowScriptsForTab = !self.allowScriptsForTab // Immediately notify and dismiss @@ -182,6 +128,21 @@ class ScriptPolicyViewController: UIViewController, UICollectionViewDelegate self.delegate?.setScriptsEnabledForTab(self.allowScriptsForTab) self.dismiss(animated: true, completion: nil) } + } else if indexPath.section == Section.policies.rawValue { + guard let identifier = dataSource.itemIdentifier(for: indexPath) else { return } + guard case let Item.policy(policyType) = identifier else { return } + + var snapshot = dataSource.snapshot() + snapshot.reloadItems([ identifier ]) + let selectedItem = Item.policy(policyManager.scriptPolicy(forOrigin: hostOrigin).policyType) + snapshot.reloadItems([ selectedItem ]) + + policyManager.setScriptPolicyType(policyType, forOrigin: hostOrigin) + dataSource.apply(snapshot) + + delegate?.didChangeScriptPolicy() + collectionView.deselectItem(at: indexPath, animated: true) + dismiss(animated: true, completion: nil) } } } diff --git a/App/Script Policy UI/ScriptPolicyViewControllerDelegate.swift b/App/Script Policy UI/ScriptPolicyViewControllerDelegate.swift new file mode 100644 index 0000000..be04883 --- /dev/null +++ b/App/Script Policy UI/ScriptPolicyViewControllerDelegate.swift @@ -0,0 +1,13 @@ +// +// ScriptPolicyViewControllerDelegate.swift +// App +// +// Created by James Magahern on 9/29/21. +// + +import Foundation + +protocol ScriptPolicyViewControllerDelegate: AnyObject { + func didChangeScriptPolicy() + func setScriptsEnabledForTab(_ enabled: Bool) +} diff --git a/SBrowser.xcodeproj/project.pbxproj b/SBrowser.xcodeproj/project.pbxproj index db3ecd3..4f9f5ee 100644 --- a/SBrowser.xcodeproj/project.pbxproj +++ b/SBrowser.xcodeproj/project.pbxproj @@ -38,13 +38,16 @@ 1ADFF4C724CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4C624CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift */; }; 1ADFF4C924CA793E006DC7AE /* ToolbarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4C824CA793E006DC7AE /* ToolbarViewController.swift */; }; 1ADFF4CB24CB8278006DC7AE /* ScriptControllerIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4CA24CB8278006DC7AE /* ScriptControllerIconView.swift */; }; - 1ADFF4CD24CBB0C8006DC7AE /* ScriptPolicyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4CC24CBB0C8006DC7AE /* ScriptPolicyViewController.swift */; }; + 1ADFF4CD24CBB0C8006DC7AE /* ScriptOriginPolicyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4CC24CBB0C8006DC7AE /* ScriptOriginPolicyViewController.swift */; }; CD01D5A5254A10BB00189CDC /* TabBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD01D5A4254A10BB00189CDC /* TabBarView.swift */; }; CD01D5AB254A206D00189CDC /* TabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD01D5AA254A206D00189CDC /* TabBarViewController.swift */; }; CD16844D269E709400B8F8A5 /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD16844C269E709400B8F8A5 /* Box.swift */; }; CD19576D268BE95900E8089B /* GenericContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD19576C268BE95900E8089B /* GenericContentView.swift */; }; CD470C4225DE056600AFBE0E /* BrowserViewController+WebKitDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD470C4125DE056600AFBE0E /* BrowserViewController+WebKitDelegate.swift */; }; CD470C4425DE070400AFBE0E /* BrowserViewController+Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD470C4325DE070400AFBE0E /* BrowserViewController+Keyboard.swift */; }; + CD7313E22705349700053347 /* ScriptPolicyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7313E12705349700053347 /* ScriptPolicyViewController.swift */; }; + CD7313E4270534B800053347 /* ScriptPolicyViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7313E3270534B800053347 /* ScriptPolicyViewControllerDelegate.swift */; }; + CD7313E62705353500053347 /* ScriptPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7313E52705353500053347 /* ScriptPolicy.swift */; }; CD7A7E9D2686A9A500E20BA3 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7A7E9C2686A9A500E20BA3 /* SettingsViewController.swift */; }; CD7A7E9F2686B29100E20BA3 /* GeneralSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7A7E9E2686B29100E20BA3 /* GeneralSettingsViewController.swift */; }; CD7A7EA12686B2E600E20BA3 /* RedirectRulesSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7A7EA02686B2E600E20BA3 /* RedirectRulesSettingsViewController.swift */; }; @@ -137,13 +140,16 @@ 1ADFF4C624CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIEdgeInsets+Layout.swift"; sourceTree = ""; }; 1ADFF4C824CA793E006DC7AE /* ToolbarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarViewController.swift; sourceTree = ""; }; 1ADFF4CA24CB8278006DC7AE /* ScriptControllerIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptControllerIconView.swift; sourceTree = ""; }; - 1ADFF4CC24CBB0C8006DC7AE /* ScriptPolicyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptPolicyViewController.swift; sourceTree = ""; }; + 1ADFF4CC24CBB0C8006DC7AE /* ScriptOriginPolicyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptOriginPolicyViewController.swift; sourceTree = ""; }; CD01D5A4254A10BB00189CDC /* TabBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarView.swift; sourceTree = ""; }; CD01D5AA254A206D00189CDC /* TabBarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarViewController.swift; sourceTree = ""; }; CD16844C269E709400B8F8A5 /* Box.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Box.swift; sourceTree = ""; }; CD19576C268BE95900E8089B /* GenericContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericContentView.swift; sourceTree = ""; }; CD470C4125DE056600AFBE0E /* BrowserViewController+WebKitDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+WebKitDelegate.swift"; sourceTree = ""; }; CD470C4325DE070400AFBE0E /* BrowserViewController+Keyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+Keyboard.swift"; sourceTree = ""; }; + CD7313E12705349700053347 /* ScriptPolicyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptPolicyViewController.swift; sourceTree = ""; }; + CD7313E3270534B800053347 /* ScriptPolicyViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptPolicyViewControllerDelegate.swift; sourceTree = ""; }; + CD7313E52705353500053347 /* ScriptPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptPolicy.swift; sourceTree = ""; }; CD7A7E9C2686A9A500E20BA3 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; CD7A7E9E2686B29100E20BA3 /* GeneralSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsViewController.swift; sourceTree = ""; }; CD7A7EA02686B2E600E20BA3 /* RedirectRulesSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedirectRulesSettingsViewController.swift; sourceTree = ""; }; @@ -321,6 +327,7 @@ CD853BD224E77BEF00D2BDCC /* History */, 1ADFF4AD24C8ED32006DC7AE /* ResourcePolicyManager.swift */, 1AD3103C252541E600A4A952 /* PersonalRedirectRules.swift */, + CD7313E52705353500053347 /* ScriptPolicy.swift */, ); path = Backend; sourceTree = ""; @@ -371,7 +378,9 @@ isa = PBXGroup; children = ( 1ADFF4CA24CB8278006DC7AE /* ScriptControllerIconView.swift */, - 1ADFF4CC24CBB0C8006DC7AE /* ScriptPolicyViewController.swift */, + CD7313E3270534B800053347 /* ScriptPolicyViewControllerDelegate.swift */, + CD7313E12705349700053347 /* ScriptPolicyViewController.swift */, + 1ADFF4CC24CBB0C8006DC7AE /* ScriptOriginPolicyViewController.swift */, ); path = "Script Policy UI"; sourceTree = ""; @@ -568,6 +577,7 @@ CDD0522125F8023700DD1771 /* Settings.swift in Sources */, 1AD31040252545BF00A4A952 /* FindOnPageView.swift in Sources */, CD470C4225DE056600AFBE0E /* BrowserViewController+WebKitDelegate.swift in Sources */, + CD7313E62705353500053347 /* ScriptPolicy.swift in Sources */, CDEDD8AA25D62ADB00862605 /* UITraitCollection+MacLike.swift in Sources */, CD7A8919251989C90075991E /* UIKeyCommand+ConvInit.swift in Sources */, 1ADFF4C724CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift in Sources */, @@ -582,6 +592,7 @@ 1ADFF48D24C8C176006DC7AE /* SBRProcessBundleBridge.m in Sources */, 1AD3103D252541E600A4A952 /* PersonalRedirectRules.swift in Sources */, 1AB88F0624D4D3A90006F850 /* UIGestureRecognizer+Actions.swift in Sources */, + CD7313E4270534B800053347 /* ScriptPolicyViewControllerDelegate.swift in Sources */, 1ADFF46224C7DE53006DC7AE /* SceneDelegate.swift in Sources */, CD16844D269E709400B8F8A5 /* Box.swift in Sources */, CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */, @@ -598,10 +609,11 @@ CDAD9CE8263A2DF200FF7199 /* DocumentControlsView.swift in Sources */, 1ADFF4C924CA793E006DC7AE /* ToolbarViewController.swift in Sources */, CD7A89172519872D0075991E /* KeyboardShortcuts.swift in Sources */, - 1ADFF4CD24CBB0C8006DC7AE /* ScriptPolicyViewController.swift in Sources */, + 1ADFF4CD24CBB0C8006DC7AE /* ScriptOriginPolicyViewController.swift in Sources */, CDE6A30425F023BC00E912A4 /* AmberSettingsViewController.swift in Sources */, 1A14FC2824D26749009B3F83 /* Tab.swift in Sources */, CD7A7E9F2686B29100E20BA3 /* GeneralSettingsViewController.swift in Sources */, + CD7313E22705349700053347 /* ScriptPolicyViewController.swift in Sources */, CD01D5AB254A206D00189CDC /* TabBarViewController.swift in Sources */, 1ADFF47924C7DFF8006DC7AE /* BrowserView.swift in Sources */, CDCE2664251AA80F007FE92A /* DocumentControlViewController.swift in Sources */,