session-ios/Session/Signal/OnboardingCaptchaViewContro...

202 lines
7.4 KiB
Swift
Raw Normal View History

2019-02-14 15:38:46 +01:00
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
2020-07-23 02:01:49 +02:00
/*
2019-02-14 15:38:46 +01:00
import UIKit
2019-02-14 17:16:50 +01:00
import WebKit
2019-02-14 15:38:46 +01:00
@objc
public class OnboardingCaptchaViewController: OnboardingBaseViewController {
2019-02-14 17:16:50 +01:00
private var webView: WKWebView?
2019-02-14 15:38:46 +01:00
override public func loadView() {
super.loadView()
view.backgroundColor = Theme.backgroundColor
view.layoutMargins = .zero
let titleLabel = self.createTitleLabel(text: NSLocalizedString("ONBOARDING_CAPTCHA_TITLE", comment: "Title of the 'onboarding Captcha' view."))
titleLabel.accessibilityIdentifier = "onboarding.captcha." + "titleLabel"
2019-02-14 15:38:46 +01:00
2019-02-14 17:16:50 +01:00
let titleRow = UIStackView(arrangedSubviews: [
titleLabel
2019-02-14 15:38:46 +01:00
])
2019-02-14 17:16:50 +01:00
titleRow.axis = .vertical
titleRow.alignment = .fill
2019-02-21 00:07:08 +01:00
titleRow.layoutMargins = UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0)
2019-02-14 17:16:50 +01:00
titleRow.isLayoutMarginsRelativeArrangement = true
// We want the CAPTCHA web content to "fill the screen (honoring margins)".
// The way to do this with WKWebView is to inject a javascript snippet that
// manipulates the viewport.
let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
let userScript = WKUserScript(source: jscript, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
let wkUController = WKUserContentController()
wkUController.addUserScript(userScript)
let wkWebConfig = WKWebViewConfiguration()
wkWebConfig.userContentController = wkUController
let webView = WKWebView(frame: self.view.bounds, configuration: wkWebConfig)
self.webView = webView
webView.navigationDelegate = self
webView.allowsBackForwardNavigationGestures = false
webView.customUserAgent = "Signal iOS (+https://signal.org/download)"
webView.allowsLinkPreview = false
2019-02-14 18:41:48 +01:00
webView.scrollView.contentInset = .zero
webView.layoutMargins = .zero
webView.accessibilityIdentifier = "onboarding.captcha." + "webView"
2019-02-14 15:38:46 +01:00
let stackView = UIStackView(arrangedSubviews: [
2019-02-14 17:16:50 +01:00
titleRow,
webView
2019-02-14 15:38:46 +01:00
])
stackView.axis = .vertical
stackView.alignment = .fill
2019-02-14 17:16:50 +01:00
stackView.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
2019-02-14 15:38:46 +01:00
stackView.isLayoutMarginsRelativeArrangement = true
view.addSubview(stackView)
stackView.autoPinWidthToSuperviewMargins()
2020-06-05 05:43:06 +02:00
stackView.autoPinEdge(.top, to: .top, of: view)
2019-02-14 15:38:46 +01:00
autoPinView(toBottomOfViewControllerOrKeyboard: stackView, avoidNotch: true)
2019-02-14 17:16:50 +01:00
NotificationCenter.default.addObserver(self,
selector: #selector(didBecomeActive),
name: NSNotification.Name.OWSApplicationDidBecomeActive,
object: nil)
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
deinit {
NotificationCenter.default.removeObserver(self)
2019-02-14 15:38:46 +01:00
}
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
2019-02-14 17:16:50 +01:00
loadContent()
2019-02-21 00:07:08 +01:00
webView?.scrollView.contentOffset = .zero
}
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
webView?.scrollView.contentOffset = .zero
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
fileprivate let contentUrl = "https://signalcaptchas.org/registration/generate.html"
private func loadContent() {
guard let webView = webView else {
owsFailDebug("Missing webView.")
2019-02-14 15:38:46 +01:00
return
}
2019-02-14 17:16:50 +01:00
guard let url = URL(string: contentUrl) else {
owsFailDebug("Invalid URL.")
2019-02-14 15:38:46 +01:00
return
}
2019-02-14 17:16:50 +01:00
webView.load(URLRequest(url: url))
webView.scrollView.contentOffset = .zero
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
// MARK: - Notifications
2019-02-14 15:38:46 +01:00
2019-02-14 17:16:50 +01:00
@objc func didBecomeActive() {
2019-02-14 15:38:46 +01:00
AssertIsOnMainThread()
2019-02-14 17:16:50 +01:00
loadContent()
2019-02-14 15:38:46 +01:00
}
2019-02-14 18:41:48 +01:00
// MARK: -
2019-02-14 15:38:46 +01:00
2019-02-14 18:41:48 +01:00
private func parseCaptchaAndTryToRegister(url: URL) {
Logger.info("")
guard let captchaToken = parseCaptcha(url: url) else {
owsFailDebug("Could not parse captcha token: \(url)")
// TODO: Alert?
//
// Reload content so user can try again.
loadContent()
return
}
onboardingController.update(captchaToken: captchaToken)
onboardingController.tryToRegister(fromViewController: self, smsVerification: true)
2019-02-14 18:41:48 +01:00
}
private func parseCaptcha(url: URL) -> String? {
2019-02-14 17:16:50 +01:00
Logger.info("")
2019-02-14 15:38:46 +01:00
2019-02-14 21:23:34 +01:00
// Example URL:
2019-02-14 17:16:50 +01:00
// signalcaptcha://03AF6jDqXgf1PocNNrWRJEENZ9l6RAMIsUoESi2dFKkxTgE2qjdZGVjEW6SZNFQqeRRTgGqOii6zHGG--uLyC1HnhSmRt8wHeKxHcg1hsK4ucTusANIeFXVB8wPPiV7U_0w2jUFVak5clMCvW9_JBfbfzj51_e9sou8DYfwc_R6THuTBTdpSV8Nh0yJalgget-nSukCxh6FPA6hRVbw7lP3r-me1QCykHOfh-V29UVaQ4Fs5upHvwB5rtiViqT_HN8WuGmdIdGcaWxaqy1lQTgFSs2Shdj593wZiXfhJnCWAw9rMn3jSgIZhkFxdXwKOmslQ2E_I8iWkm6
guard let host = url.host,
host.count > 0 else {
owsFailDebug("Missing host.")
2019-02-14 18:41:48 +01:00
return nil
2019-02-14 15:38:46 +01:00
}
2019-02-14 18:41:48 +01:00
return host
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
}
// MARK: -
2019-02-14 15:38:46 +01:00
2019-02-14 17:16:50 +01:00
extension OnboardingCaptchaViewController: WKNavigationDelegate {
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
Logger.verbose("navigationAction: \(String(describing: navigationAction.request.url))")
2019-02-14 15:38:46 +01:00
2019-02-14 17:16:50 +01:00
guard let url: URL = navigationAction.request.url else {
owsFailDebug("Missing URL.")
decisionHandler(.cancel)
return
}
if url.scheme == "signalcaptcha" {
decisionHandler(.cancel)
DispatchQueue.main.async {
2019-02-14 18:41:48 +01:00
self.parseCaptchaAndTryToRegister(url: url)
2019-02-14 17:16:50 +01:00
}
2019-02-14 15:38:46 +01:00
return
}
2019-02-14 21:23:34 +01:00
// Loading the Captcha content involves a series of actions.
2019-02-14 17:16:50 +01:00
decisionHandler(.allow)
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
public func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
Logger.verbose("navigationResponse: \(String(describing: navigationResponse))")
2019-02-14 15:38:46 +01:00
2019-02-14 17:16:50 +01:00
decisionHandler(.allow)
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
Logger.verbose("navigation: \(String(describing: navigation))")
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
public func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
Logger.verbose("navigation: \(String(describing: navigation))")
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
Logger.verbose("navigation: \(String(describing: navigation)), error: \(error)")
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
public func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
Logger.verbose("navigation: \(String(describing: navigation))")
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
Logger.verbose("navigation: \(String(describing: navigation))")
2019-02-14 15:38:46 +01:00
}
2019-02-14 17:16:50 +01:00
public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
Logger.verbose("navigation: \(String(describing: navigation)), error: \(error)")
}
2019-02-14 15:38:46 +01:00
2019-02-14 17:16:50 +01:00
public func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
Logger.verbose("")
2019-02-14 15:38:46 +01:00
}
}
2020-07-23 02:01:49 +02:00
*/