/* MonkeyTalk - a cross-platform functional testing tool
Copyright (C) 2012 Gorilla Logic, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package com.gorillalogic.fonemonkey.web;
import java.lang.reflect.Method;
import org.apache.commons.codec.net.URLCodec;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Message;
import android.view.KeyEvent;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.gorillalogic.fonemonkey.automators.WebViewAutomator;
/*
* Hack alert:
* WebView.addJavaScriptInterface doesn't work if called after a page has already been loaded.
* AndroidWebDriver relies on addJavaScriptInterface to bridge between JS and Java.
* Because we might not find out about a WebView until after its initial page has been loaded,
* we use this mechanism instead whereby we intercept dummy url requests.
*/
public class WebViewClientWrapper extends WebViewClient {
private WebViewClient client;
// private WebViewRecorder recorder;
public WebViewClientWrapper(WebView view) {
Method meth;
try {
// recorder = new WebViewRecorder(webView);
// webView.addJavascriptInterface(recorder, "mtrecorder");
meth = WebView.class.getDeclaredMethod("getWebViewClient", (Class<?>[]) null);
this.client = (WebViewClient) meth.invoke(view, (Object[]) null);
if (client == null) {
client = new WebViewClient();
}
} catch (Exception e) {
throw new IllegalStateException("Error getting WebViewClient: " + e.getMessage(), e);
}
view.setWebViewClient(this);
// view.loadUrl("javascript:window.webdriver = {resultMethod: function(result) {window.location = \"http://mtdummy?monkeytalkresult=\" + result}}");
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
String decoded;
if (url.contains("mtdummy")) {
try {
decoded = new URLCodec().decode(url, "UTF-8");
// We seem to be double-encoded...
decoded = new URLCodec().decode(decoded, "UTF-8");
} catch (Exception e) {
throw new IllegalStateException(e);
}
String[] result = decoded.split("monkeytalkresult=");
if (result.length == 1) {
WebViewAutomator.reportResult(null);
return true;
}
if (result.length > 1) {
WebViewAutomator.reportResult(result[result.length - 1]);
return true;
}
}
return client.shouldOverrideUrlLoading(view, url);
}
public void onTooManyRedirects(WebView view, Message cancelMsg, Message continueMsg) {
client.onTooManyRedirects(view, cancelMsg, continueMsg);
}
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
client.onReceivedError(view, errorCode, description, failingUrl);
}
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
client.doUpdateVisitedHistory(view, url, isReload);
}
public boolean equals(Object arg0) {
return client.equals(arg0);
}
public int hashCode() {
return client.hashCode();
}
public void onPageStarted(WebView view, String url, Bitmap favicon) {
client.onPageStarted(view, url, favicon);
// recorder.setJsAttached(false);
}
public void onPageFinished(WebView view, String url) {
client.onPageFinished(view, url);
// final String lib = WebViewAutomator.fileToString("monkeytalk.js");
// String s = "javascript:" + lib;
// webView.loadUrl(s);
// webView.loadUrl("javascript:( document.onclick = function (event) { alert('works' + event); } ) ()");
// probably where we add record logic
// webView.loadUrl("javascript:( function () { alert('woohoo'); } ) ()");
WebViewRecorder.attachJs(view);
}
public void onLoadResource(WebView view, String url) {
client.onLoadResource(view, url);
// final String lib = WebViewAutomator.fileToString("monkeytalk.js");
// String s = "javascript:" + lib;
// String s =
// "javascript:console.log('count: ' + document.getElementsByTagName('*').length);";
// recorder.webViewDidChange();
}
public void onFormResubmission(WebView view, Message dontResend, Message resend) {
client.onFormResubmission(view, dontResend, resend);
}
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
client.onReceivedSslError(view, handler, error);
}
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,
String realm) {
client.onReceivedHttpAuthRequest(view, handler, host, realm);
}
public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
return client.shouldOverrideKeyEvent(view, event);
}
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
client.onUnhandledKeyEvent(view, event);
}
public void onScaleChanged(WebView view, float oldScale, float newScale) {
client.onScaleChanged(view, oldScale, newScale);
}
public String toString() {
return client.toString();
}
}