Getting Webview to work in Springboard (Patreon)
Content
This will be a long one. I share what I tried to get a webview working on iOS SpringBoard on iOS16. Where I failed and finally where I succeeded.
TLDR; Designer now allows loading local html files on iOS13 - iOS16. In iOS16 webviews were blocked from loading in SpringBoard. I found a way around that.
It all starts here.
History
Over 10 months ago I was able to jailbreak iOS16, much sooner than most because I had a checkm8 supported device. The first thing I realized was I could no longer load a WKWebview.
You can think of WKWebview like a browser window. This lets you load html, css, and run javascript. I will refer to it as webview. I had a very popular tweak named LockPlus. LockPlus utilized this webview to show things users created in a wysiwyg (what you see is what you get) editor. Users could create "websites" using the creator I built and then display them on their iOS lock screen. LockPlus had 10s of thousands of these themes created with it.
You can see why I wanted this to work. After a month or so of researching. I couldn't figure it out how to get a webview to load. Searching through open source webkit files, headers and anything I could find led me to believe Apple really didn't want a webview showing in SpringBoard. Which makes sense I mean some jailbreaks were ran on webkit itself.
I gave up. I couldn't figure it out and it seemed this was an issue only I had. Not many tweak developers even cared to run a webview. So I created Designer. Designer was built just like LockPlus I created an editor which allowed users to create their own themes without the need to code. Instead of using a webview, Designer used native elements. Therefore they were able to be placed on the Springboard.
Extendability
Designer is great, i'm very proud of what i've made. It does have limitations. Users would start to request things like analog clocks, calendars, knockout text, etc. Things that are possible to make with native elements, but are hard to create. Even more so I have to make these items and give the users options to modify them, change colors, sizes, etc.
This made me think about webview again. These things are much easier to make with html, css, and javascript. Also if I gave the ability to load htmls the possibilities are endless. Extending Designer way beyond what it can do.
My Addiction
I will skip most of the things I initially tried, but they were basically trying to patch all the things that didn't allow the webview to load. I could get webviews to load but the web process kill them, just leaving them blank pages. I tried 100s of different ways to allow them, none was successful.
I began looking at it a different way. Instead of patching it to allow it, try to find something that wasn't patched out, something that was missed. Maybe loading the webview without a url, maybe just injecting the html with loadHTMLString or injecting it via javascript using something like stringByEvaluatingJavaScriptFromString. I also was not successful.
One day I woke up and decided to try UIWebView. This is the old way websites were shown in iOS way before WKWebview. Cydia for example used this UIWebView. I was able to get a UIWebview to show html. I did this by reading the html from file, converting it to a string and then injecting it with document.write(). This was the first time on iOS16 I saw html in a webview on iOS16. This got me excited. I though I could then call javascript functions in the injected html and have a self updating html. I was wrong any attempt to refresh or update the webview would cause a crash. Something to the lines of webkit not allowing it. While I did inject html the javascript engine was not active. It simply acted like a text document that rendered css.
Around this time I found out that a semi jailbreak named Serotonin allowed the WKWebviews to load. I was very happy about this, this was before Dopamine 2.0 was released. I believe this works as Serotonin resigns SpringBoard and this was confirmed as Opa334 said the same. Basically it's given entitlements that allow this. Which is well beyond the scope of a tweak. Anyway I added webview support to Designer. This lasted about a week and dopamine came out, when it was released ofc webviews no longer worked. Since Dopamine would be the jailbreak everyone used I removed webview support.
I saw it though. I was able to see webviews running code from a local file in springboard on iOS16. I wanted this to happen and I kept on trying things. I had no idea if I could make this happen I fought with this a long time. Going from "i'm wasting so much time on this" to "there's more than one way to skin a cat"
Breakthrough #1
I had another idea. Apps can launch webviews. You can go to twitter and click a link, it doesn't open in Safari it opens in it's own little thing. I began researching and this is called a SFSafariViewController. This controller has a view on it that is the SFSafarView which is what shows the underlying webview. I implemented this and I was able to load a url from http or https. This was exciting as I found something that got around the restriction. A few things though I couldn't load a local html, the background was solid white, it couldn't be shown while passcode was enabled, and I could not inject info into it.
I began looking into this SFSafariView and it was something i've never seen before. It was a black hole. It initiated something called a UIRemoteView and I could not find the webview at all. This had me puzzled so I began researching it. I did find some posts about it and apparently it was introduced in iOS6. A good way to think about UIRemoteView is it's just an image. So it has no subviews. It loads a service, in this case com.apple.SafariViewService this service is what's making the webview and handling all the "secret" stuff. It then sends and "image" of what it looks like to the UIRemoteView. This makes it pretty secure as no one can inject into the service, they could inject into UIRemoteView but nothing is there. I can see why they use this in apps. As the app will not be able to collect any data from this view.
I'm jailbroke though like a full root jailbreak so that wouldn't stop me. I hooked into com.apple.SafariViewService and also did research on what it actually loads. Come to find out it creates a _SFWebView another thing i've never heard of before. This is the webview it uses. I made a tweak that hooks into com.apple.SafariViewService then hooks _SFWebview didMoveToWindow method. When this view moved to a window I could detect it. When I did I stored a reference to it, and since it is a sub class of WKWebView. I loaded an html string into it using loadHTMLString from before. It worked and it kept updating.
Furthermore I started doing all the things I needed. I removed the background, allowed it to load when passcode was enabled and I injected my own info into it. All was great I finally did it!
I didn't do it.
So that worked on a root jailbreak, but I couldn't get it to work on Dopamine. In the beginning I thought this had to do with Ellekit, but in the end realized it was because of a rootless jailbreak. Many will say rootless jailbreak is the same as a root jailbreak but you don't have root access to files. While this is somewhat true there is more to it. Rootless jailbreaks are not full jailbreaks as I consider a full jailbreak. While I was able to hook com.apple.SafariViewService on a root jailbreak, a rootless jailbreak simply doesn't have access to do this. This frustrated me a lot. I spent a lot of time doing this and finally had it working. Now it doesn't work because of a jailbreak. Small rant. I jailbreak my device to have full access to the device. I own that device and can do as I please. I will always pick a root jailbreak over a rootless as a rootless doesn't give me this access. I'm sure rootless is fine for many people but I would never consider this a full jailbreak. As you are still jailed in some aspects.
Breakthrough #2
Did I give up? No. I should have given up a long time ago. I don't know why I didn't but I carried on. I think this has to do with some personality disorder or determination. What is not explained well here is the shear amount of time I spent doing these things. You would think i'm insane. I think i'm insane.
Anyway. I learned a lot researching this UIRemoteView and the com.apple.SafariViewService I was impressed on how this worked. My next idea is to create my own service that mimicked what SafariViewService did. I never made a service like this before, so back to researching. Eventually I figured it out and created my own service. It acted similar to SafarViewService. I called it, it created me a UIRemoteView and I was able to display a red square that was rendered in my service on the lock screen in Designer. These are two processes not knowing much about each other and completely in a different space communicating. I'm able to give my service entitlements unlike a tweak. I gave it entitlements that allowed it to launch a webview. Gave it a try and I had a webview displaying in Designer on a rootless device.
I finally did it.
Since I own this service I can do whatever I want. Made it show when passcode is locked, removed the background, and even implemented a method that allowed me to inject data I wanted. Everything I needed.
Conclusion
I tested this on many devices
- iPX unc0ver 13.2.2 (substitute)
- 6S+ checkra1n 14.0.1 (substrate)
- 7+ palera1n 15.7.1 (substitue)
- iPX palera1n 16.1.2 (ellekit)
- XSMax dopamine 16.6b1 (ellekit)
This was also tested by many testers in Discord with no one at this point saying it doesn't work. I have released Designer v1.4.4 that has this option.
I did run into some issues. The ellekit devices I couldn't load WKWebView but I could load UIWebviews. Home button devices (not sure this had anything to do with it) I couldn't load UIWebview but could load WKWebview.
So in the service it tries to load WKWebview if this fails then it loads UIWebview. Not a big deal in this context, but something I need to look more into at a later time. I'm so over this html stuff atm. I got it to work and need to take a break from it. I do have other things that need my attention in Designer.
The time spent doing this now equals "Added LS html" in the change log of Designer. One line of text, but now you know what it actually took to put that line of text.
I'm very relieved I got this working. Its been a pain for me for awhile now, but persistence won. Many times in my life i've said things were impossible, but i've lived long enough to see the impossible made possible. I feel like I made the impossible possible.
Thanks to all my supporters. You allow me to spend the time I do on things like this. Without you this wouldn't have been possible.
If anyone else has questions on how I achieved this (other tweak devs) join my discord I can answer any question you have.
thanks for reading