Skip to content

Instantly share code, notes, and snippets.

@funkydevil
Last active February 15, 2022 13:54
Show Gist options
  • Save funkydevil/fc03f05ff921d6b5daac8f93d91319f6 to your computer and use it in GitHub Desktop.
Save funkydevil/fc03f05ff921d6b5daac8f93d91319f6 to your computer and use it in GitHub Desktop.
JS injections, SWIFT->JS, JS->SWIFT
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.block {
display: block;
width: 100%;
border: none;
background-color: #04AA6D;
color: white;
padding: 14px 28px;
font-size: 16px;
cursor: pointer;
text-align: center;
}
.block:hover {
background-color: #ddd;
color: black;
}
</style>
</head>
<body>
<button onclick="showAlert()" class="block">Show alert</button>
<button onclick="createTextField()" class="block">createTextField</button>
<button onclick="swiftFunction()" class="block">call swiftFunction</button>
<button onclick="injectedFunction()" class="block">call injectedFunction</button>
<script>
function showAlert() {
alert( 'hello world!' );
}
function createTextField() {
var x = document.createElement("INPUT");
x.setAttribute("type", "text");
x.setAttribute("value", "Hello World!");
document.body.appendChild(x);
}
function getValueFromJS() {
return "hello";
}
function swiftFunction() {
window.webkit.messageHandlers.testFunc.postMessage({param1: "111", param2: "222"});
}
</script>
</body>
</html>
//
// ViewController.swift
// JSCallExample
//
// Created by Kirill Pyulzyu on 15.02.2022.
//
import UIKit
import WebKit
class ViewController: UIViewController {
var webview: WKWebView!
let jsHandler = "testFunc"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
addWKWebView()
loadHTML()
}
func addWKWebView() {
let width = self.view.frame.width
let height = self.view.frame.height
let webviewFrame = CGRect(x: 0, y: height/2, width: width, height: height/2)
let contentController = WKUserContentController()
let scriptSource = "function injectedFunction() { alert('testtest') }"
let script = WKUserScript(source: scriptSource, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
contentController.addUserScript(script)
let configuration = WKWebViewConfiguration()
configuration.userContentController = contentController
configuration.userContentController.add(self, name: jsHandler)
webview = WKWebView(frame: webviewFrame, configuration: configuration)
webview.uiDelegate = self
view.addSubview(webview)
}
func loadHTML() {
guard let webview = webview else {
return
}
let url = Bundle.main.url(forResource: "index.html", withExtension: nil)!
webview.loadFileURL(url, allowingReadAccessTo: url)
}
@IBAction func onCallJSTapped(_ sender: Any) {
webview?.evaluateJavaScript("createTextField()", completionHandler: { result, error in
})
}
@IBAction func getValueFromJS(_ sender: Any) {
webview?.evaluateJavaScript("getValueFromJS()", completionHandler: { result, error in
print(result!)
})
}
}
extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == jsHandler {
guard let params = message.body as? [String: String] else {
return
}
for (key, value) in params {
print(key + " = " + value)
}
}
}
}
extension ViewController: WKUIDelegate {
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
completionHandler: @escaping () -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
completionHandler()
}))
present(alertController, animated: true, completion: nil)
}
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
completionHandler: @escaping (Bool) -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
completionHandler(true)
}))
alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
completionHandler(false)
}))
present(alertController, animated: true, completion: nil)
}
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo,
completionHandler: @escaping (String?) -> Void) {
let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .actionSheet)
alertController.addTextField { (textField) in
textField.text = defaultText
}
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
if let text = alertController.textFields?.first?.text {
completionHandler(text)
} else {
completionHandler(defaultText)
}
}))
alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
completionHandler(nil)
}))
present(alertController, animated: true, completion: nil)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment