-
Notifications
You must be signed in to change notification settings - Fork 423
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Malicious site protection - extract special error page navigation log…
…ic (#3624) Task/Issue URL: https://app.asana.com/0/1206329551987282/1208836682251611/f Tech Design URL: https://app.asana.com/0/1206329551987282/1207273224076495/f **Description**: This PR extracts the navigation logic for special error pages in its own class. This PR focuses on creating the the entites used to encapsulate the logic for SSL and Malicious site protection
- Loading branch information
1 parent
c8bf749
commit 8f39f6b
Showing
21 changed files
with
1,616 additions
and
77 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
56 changes: 56 additions & 0 deletions
56
DuckDuckGo/MaliciousSiteProtection/MaliciousSiteProtectionManager.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// | ||
// MaliciousSiteProtectionManager.swift | ||
// DuckDuckGo | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
import Foundation | ||
|
||
final class MaliciousSiteProtectionManager: MaliciousSiteDetecting { | ||
|
||
func evaluate(_ url: URL) async -> ThreatKind? { | ||
try? await Task.sleep(interval: 0.3) | ||
return .none | ||
} | ||
|
||
} | ||
|
||
// MARK: - To Remove | ||
|
||
// These entities are copied from BSK and they will be used to mock the library | ||
import SpecialErrorPages | ||
|
||
protocol MaliciousSiteDetecting { | ||
func evaluate(_ url: URL) async -> ThreatKind? | ||
} | ||
|
||
public enum ThreatKind: String, CaseIterable, CustomStringConvertible { | ||
public var description: String { rawValue } | ||
|
||
case phishing | ||
case malware | ||
} | ||
|
||
public extension ThreatKind { | ||
|
||
var errorPageType: SpecialErrorKind { | ||
switch self { | ||
case .malware: .phishing // WIP in BSK | ||
case .phishing: .phishing | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// | ||
// SpecialErrorModel.swift | ||
// DuckDuckGo | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
import Foundation | ||
import SpecialErrorPages | ||
|
||
struct SpecialErrorModel: Equatable { | ||
let url: URL | ||
let errorData: SpecialErrorData | ||
} | ||
|
||
struct SSLSpecialError { | ||
let type: SSLErrorType | ||
let error: SpecialErrorModel | ||
} |
36 changes: 36 additions & 0 deletions
36
DuckDuckGo/SpecialErrorPage/SpecialErrorPageInterfaces/SpecialErrorPageActionHandler.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// | ||
// SpecialErrorPageActionHandler.swift | ||
// DuckDuckGo | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
import Foundation | ||
|
||
/// A type that defines actions for handling special error pages. | ||
/// | ||
/// This protocol is intended to be adopted by types that need to manage user interactions | ||
/// with special error pages, such as navigating to a site, leaving a site, or presenting | ||
/// advanced information related to the error. | ||
protocol SpecialErrorPageActionHandler { | ||
/// Handles the action of navigating to the site associated with the error page | ||
func visitSite() | ||
|
||
/// Handles the action of leaving the site associated with the error page | ||
func leaveSite() | ||
|
||
/// Handles the action of requesting more detailed information about the error | ||
func advancedInfoPresented() | ||
} |
40 changes: 40 additions & 0 deletions
40
DuckDuckGo/SpecialErrorPage/SpecialErrorPageInterfaces/SpecialErrorPageContextHandling.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// | ||
// SpecialErrorPageContextHandling.swift | ||
// DuckDuckGo | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
import Foundation | ||
import WebKit | ||
import SpecialErrorPages | ||
|
||
/// A type that defines the base functionality for handling navigation related to special error pages. | ||
protocol SpecialErrorPageContextHandling: AnyObject { | ||
/// The delegate that handles navigation actions for special error pages. | ||
var delegate: SpecialErrorPageNavigationDelegate? { get set } | ||
|
||
/// A Boolean value indicating whether the special error page is currently visible. | ||
var isSpecialErrorPageVisible: Bool { get } | ||
|
||
/// The URL that failed to load, if any. | ||
var failedURL: URL? { get } | ||
|
||
/// Attaches a web view to the special error page handling. | ||
func attachWebView(_ webView: WKWebView) | ||
|
||
/// Sets the user script for the special error page. | ||
func setUserScript(_ userScript: SpecialErrorPageUserScript?) | ||
} |
26 changes: 26 additions & 0 deletions
26
...ckGo/SpecialErrorPage/SpecialErrorPageInterfaces/SpecialErrorPageNavigationDelegate.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// | ||
// SpecialErrorPageNavigationDelegate.swift | ||
// DuckDuckGo | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
import Foundation | ||
|
||
/// A delegate for handling navigation actions related to special error pages. | ||
protocol SpecialErrorPageNavigationDelegate: AnyObject { | ||
/// Asks the delegate to close the special error page tab when the web view can't navigate back. | ||
func closeSpecialErrorPageTab() | ||
} |
69 changes: 69 additions & 0 deletions
69
DuckDuckGo/SpecialErrorPage/SpecialErrorPageInterfaces/WebViewNavigationHandling.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// | ||
// WebViewNavigationHandling.swift | ||
// DuckDuckGo | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
import Foundation | ||
import WebKit | ||
|
||
// MARK: - WebViewNavigation | ||
|
||
/// For testing purposes. | ||
protocol WebViewNavigation {} | ||
|
||
// Used in tests. WKNavigation() crashes on deinit when initialising it manually. | ||
// As workaround we used to Swizzle the implementation of deinit in tests. | ||
// The problem with that approach is that when running different test suites it is possible that unrelated tests re-set the original implementation of deinit while other tests are running. | ||
// This cause the app to crash as the original implementation is executed. | ||
// Defining a protocol for WKNavigation and using mocks such as DummyWKNavigation in tests resolves the problem. | ||
extension WKNavigation: WebViewNavigation {} | ||
|
||
// MARK: - WebViewNavigationHandling | ||
|
||
/// A protocol that defines methods for handling navigation events of `WKWebView`. | ||
protocol WebViewNavigationHandling: AnyObject { | ||
/// Decides whether to cancel navigation to prevent opening a site and show a special error page based on the specified action information. | ||
/// | ||
/// - Parameters: | ||
/// - navigationAction: Details about the action that triggered the navigation request. | ||
/// - webView: The web view from which the navigation request began. | ||
/// - Returns: A Boolean value that indicates whether the navigation action was handled. | ||
func handleSpecialErrorNavigation(navigationAction: WKNavigationAction, webView: WKWebView) async -> Bool | ||
|
||
/// Handles authentication challenges received by the web view. | ||
/// | ||
/// - Parameters: | ||
/// - webView: The web view that receives the authentication challenge. | ||
/// - challenge: The authentication challenge. | ||
/// - completionHandler: A completion handler block to execute with the response. | ||
func handleWebView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) | ||
|
||
/// Handles failures during provisional navigation. | ||
/// | ||
/// - Parameters: | ||
/// - webView: The `WKWebView` instance that failed the navigation. | ||
/// - navigation: The navigation object for the operation. | ||
/// - error: The error that occurred. | ||
func handleWebView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WebViewNavigation, withError error: NSError) | ||
|
||
/// Handles the successful completion of a navigation in the web view. | ||
/// | ||
/// - Parameters: | ||
/// - webView: The web view that loaded the content. | ||
/// - navigation: The navigation object that finished. | ||
func handleWebView(_ webView: WKWebView, didFinish navigation: WebViewNavigation) | ||
} |
83 changes: 83 additions & 0 deletions
83
DuckDuckGo/SpecialErrorPage/SpecialErrorPageNavigationHandler+MaliciousSite.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// | ||
// SpecialErrorPageNavigationHandler+MaliciousSite.swift | ||
// DuckDuckGo | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
import Foundation | ||
import BrowserServicesKit | ||
import Core | ||
import SpecialErrorPages | ||
import WebKit | ||
|
||
enum MaliciousSiteProtectionNavigationResult: Equatable { | ||
case navigationHandled(SpecialErrorModel) | ||
case navigationNotHandled | ||
} | ||
|
||
protocol MaliciousSiteProtectionNavigationHandling: AnyObject { | ||
/// Decides whether to cancel navigation to prevent opening the YouTube app from the web view. | ||
/// | ||
/// - Parameters: | ||
/// - navigationAction: The navigation action to evaluate. | ||
/// - webView: The web view where navigation is occurring. | ||
/// - Returns: `true` if the navigation should be canceled, `false` otherwise. | ||
func handleMaliciousSiteProtectionNavigation(for navigationAction: WKNavigationAction, webView: WKWebView) async -> MaliciousSiteProtectionNavigationResult | ||
} | ||
|
||
final class MaliciousSiteProtectionNavigationHandler { | ||
private let maliciousSiteProtectionManager: MaliciousSiteDetecting | ||
private let storageCache: StorageCache | ||
|
||
init( | ||
maliciousSiteProtectionManager: MaliciousSiteDetecting = MaliciousSiteProtectionManager(), | ||
storageCache: StorageCache = AppDependencyProvider.shared.storageCache | ||
) { | ||
self.maliciousSiteProtectionManager = maliciousSiteProtectionManager | ||
self.storageCache = storageCache | ||
} | ||
} | ||
|
||
// MARK: - MaliciousSiteProtectionNavigationHandling | ||
|
||
extension MaliciousSiteProtectionNavigationHandler: MaliciousSiteProtectionNavigationHandling { | ||
|
||
@MainActor | ||
func handleMaliciousSiteProtectionNavigation(for navigationAction: WKNavigationAction, webView: WKWebView) async -> MaliciousSiteProtectionNavigationResult { | ||
// Implement logic to use `maliciousSiteProtectionManager.evaluate(url)` | ||
// Return navigationNotHandled for the time being | ||
return .navigationNotHandled | ||
} | ||
|
||
} | ||
|
||
// MARK: - SpecialErrorPageActionHandler | ||
|
||
extension MaliciousSiteProtectionNavigationHandler: SpecialErrorPageActionHandler { | ||
|
||
func visitSite() { | ||
// Fire Pixel | ||
} | ||
|
||
func leaveSite() { | ||
// Fire Pixel | ||
} | ||
|
||
func advancedInfoPresented() { | ||
// Fire Pixel | ||
} | ||
|
||
} |
Oops, something went wrong.