如何在iOS上注入用户脚本?

[英]How can I inject a user script on iOS?


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.

我正在研究Fahrii,它本质上是一个支持用户脚本的移动浏览器。目前,我在加载到UIWebView的网页上调用脚本时遇到问题。如果可能的话,我想保留这些公共API。如果没有,概念证明至少会很好,所以我可以更好地理解它是如何工作的。我正在尝试在webViewDidFinishLoad:方法中执行此操作。

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".)

我尝试通过读取webView的内容(使用JavaScript)然后使用loadHTML:baseURL:将其加载回来进行注入,但这会导致无限递归。 (完成的加载会导致脚本被注入,这反过来导致完成“加载”。)

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.

我使用它的唯一方法是使用ASIHTTPRequest库来发出实际请求,但最后我遇到了登录表单的问题,除此之外,我必须在这种情况下每次请求两次。

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?

我可能正在做一些不可能的事情,或者我只是做错了。那么,如何在现有的UIWebView上调用带有从Web加载的内容的用户脚本?

Edit:

编辑:

Here's some more code, including the changes proposed by @rich:

这里有一些代码,包括@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);

2 个解决方案

#1


4  

An example of doing just this is below. I had the same problem until I realized that the js needed to be injected into the page. To properly inject the js you need to write it into the head of the dom as shown below.

这样做的一个例子如下。我遇到了同样的问题,直到我意识到需要将js注入页面。要正确注入js,您需要将其写入dom的头部,如下所示。

- (void)webViewDidFinishLoad:(UIWebView *)webView {
 [webView stringByEvaluatingJavaScriptFromString:@"var script = document.createElement('script');"  
 "script.type = 'text/javascript';"  
 "script.text = \"function myFunction() { "  
 "window.scrollTo(100,100)"
 "}\";"  
 "document.getElementsByTagName('head')[0].appendChild(script);"];  

 [webView stringByEvaluatingJavaScriptFromString:@"myFunction();"];
}    

#2


1  

You should directly pass the string to the stringByEvaluatingJavaScriptFromString: method, like this:

您应该直接将字符串传递给stringByEvaluatingJavaScriptFromString:方法,如下所示:

NSString *result = [webView stringByEvaluatingJavaScriptFromString:@"Script To Be Run"];

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.itdaan.com/blog/2011/08/05/1851f5cd94c7102376b794ef13e44736.html



 
© 2014-2018 ITdaan.com 粤ICP备14056181号