Autofill Elements WKWebView

Viewed 1367

I was wondering if it would be possible to autofill elements in the WKWebView? Or like auto click on them or something like that.

I want to make a script that autofill's info in a webbrowser.

(Maybe with javascript or something.)

2 Answers

iOS 11.0 had introduced username and password autofill in apps and it is possible to use it also in WKWebView.

Please refer to Enabling Password AutoFill on an HTML Input Element from Apple's docs.

In short:

<input id="password-text-field" type="password" autocomplete="current-password"/>
<input id="user-text-field" type="email" autocomplete="username"/>

I did custom implement that auto-fill feature, would like to share

use it with

let data = AutoFillData(fName: "Jhon")
webView.evaluateJavaScript(data.createJSString(), completionHandler: nil)

It searches dom elements with name and id

struct AutoFillData {
    var fName: String?
    var lName: String?
    var email: String?
    var phone: String?
    var shipAddress: String?
    var shipCity: String?
    var shipState: String?
    var shipCountry: String?
    var zip: String?

    enum KeyNames: String, CaseIterable {
        case first_name, customerFirstName,
             last_name, customerLastName,
             name,
             email, customerEmail,
             phone, alternatePhone, phoneNumber, phoneNumber2 = "phone-number",
             shipAddress = "ship-address", addressLine1, addressLine2,
             shipCity = "ship-city", city,
             shipState = "ship-state", state,
             shipZip = "ship-zip", zip, pincode,
             shipCountry = "ship-country", country
    }

    func getData(keyName: KeyNames) -> String? {
        switch keyName {
        case .first_name, .customerFirstName: return fName
        case .last_name, .customerLastName: return lName
        case .name: return [fName, lName].compactMap { $0 }.joined(separator: " ")
        case .email, .customerEmail: return email
        case .phone, .alternatePhone, .phoneNumber, .phoneNumber2: return phone
        case .shipAddress, .addressLine1, .addressLine2: return shipAddress
        case .shipCity, .city: return shipCity
        case .shipState, .state: return shipState
        case .shipCountry, .country: return shipCountry
        case .zip, .shipZip, .pincode: return zip
        }
    }

    func createJSString() -> String {
        var str = ""
        KeyNames.allCases.forEach {
            let value = getData(keyName: $0)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
            if !value.isEmpty {
                str.append("""
                var e = document.getElementsByName('\($0.rawValue)')[0];
                if (e == null) {
                    e = document.getElementById('\($0.rawValue)');
                }
                if (e != null) {
                    e.value = '\(value)';
                }
                """)
            }
        }
        return str
    }
}
Related