I'm working on Fahrii, which is, essentially, a userscript enabled mobile browser. At the moment, I'm having trouble invoking the scripts on a web page that's loaded into a UIWebView. I'd like to keep this public APIs if possible. If not, a proof of concept would at least be nice, so I can get a better understanding of how this works. I'm trying to do it in the webViewDidFinishLoad:
method.
I've tried injecting by reading out the webView's content (using JavaScript) and then loading it back with loadHTML:baseURL:
, but that causes infinite recursion. (A completed load causes a script to be injected, which is in turn causing a completed "load".)
Next, I've tried something like this:
[self.browser stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.body.innerHTML = %@", originalHTMLWithScriptsInjected]];
The script seems to be injected, but not run.
The only way I got this to work was to use the ASIHTTPRequest library to make the actual requests, but then I ended up having trouble with login forms, besides for which, I have to make each request twice in that case.
I might be doing something that's either impossible, or I'm just doing it the wrong away. So, how can I invoke a user script on an existing UIWebView with content loaded from the web?
Edit:
Here's some more code, including the changes proposed by @rich:
//
// Run the remaining scripts
//
NSMutableString *scriptTextToInject = [[NSMutableString alloc]init];
//
// Add each script into the page
//
for (Userscript *script in scriptsToExecute) {
//
// Read the userscript
//
NSString *scriptToLoad = [NSString stringWithContentsOfURL:[NSURL URLWithString:script.pathToScript] encoding:NSUTF8StringEncoding error:&error];
NSLog(@"Script to load: %@", scriptToLoad);
[scriptTextToInject appendFormat:@"%@\n\n",scriptToLoad];
}
NSString *documentHeadBefore = [self.browser stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('head')[0].innerHTML"];
//
// Inject the scripts
//
NSString *scriptWrappedInATag = [NSString stringWithFormat:@"window.onload() = function(){var script = document.createElement('script');\n"
"script.charset = 'UTF-8'"
"script.setAttribute(\"type\",\"text/javascript\");\n"
"text = \"function u(){\n"
"%@"
"}\";\n"
"document.getElementsByTagName('head')[0].appendChild(script);}", scriptTextToInject];
NSLog(@"Scripts wrapped in a tag: %@", scriptWrappedInATag);
NSString *runResults = [self.browser stringByEvaluatingJavaScriptFromString:@"u();"];
NSString *documentHeadAfter = [self.browser stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('head')[0].innerHTML"];
NSLog(@"Before: %@ \n\n\n\n After: %@", documentHeadBefore, documentHeadAfter);