OSDN Git Service

am 07b3e39f: am d6f0aa4a: Merge "Fix crash in WebCore::GlyphPageTreeNode::getChild...
[android-x86/external-webkit.git] / WebKit / android / jni / WebCoreFrameBridge.cpp
1 /*
2  * Copyright 2006, The Android Open Source Project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #define LOG_TAG "webcoreglue"
27
28 #include "config.h"
29 #include "WebCoreFrameBridge.h"
30
31 #include "Arena.h"
32 #include "BackForwardList.h"
33 #include "MemoryCache.h"
34 #include "Chrome.h"
35 #include "ChromeClientAndroid.h"
36 #include "ChromiumInit.h"
37 #include "ContextMenuClientAndroid.h"
38 #include "DeviceMotionClientAndroid.h"
39 #include "DeviceOrientationClientAndroid.h"
40 #include "Document.h"
41 #include "DocumentLoader.h"
42 #include "DragClientAndroid.h"
43 #include "EditorClientAndroid.h"
44 #include "Element.h"
45 #include "FocusController.h"
46 #include "Font.h"
47 #include "Frame.h"
48 #include "FrameLoader.h"
49 #include "FrameLoaderClientAndroid.h"
50 #include "FrameLoadRequest.h"
51 #include "FrameTree.h"
52 #include "FrameView.h"
53 #include "GraphicsContext.h"
54 #include "HistoryItem.h"
55 #include "HTMLCollection.h"
56 #include "HTMLElement.h"
57 #include "HTMLFormElement.h"
58 #include "HTMLInputElement.h"
59 #include "HTMLNames.h"
60 #include "IconDatabase.h"
61 #include "Image.h"
62 #include "InspectorClientAndroid.h"
63 #include "KURL.h"
64 #include "Page.h"
65 #include "PageCache.h"
66 #include "PlatformString.h"
67 #include "RenderPart.h"
68 #include "RenderSkinAndroid.h"
69 #include "RenderTreeAsText.h"
70 #include "RenderView.h"
71 #include "ResourceHandle.h"
72 #include "ResourceHandleInternal.h"
73 #include "ScriptController.h"
74 #include "ScriptValue.h"
75 #include "SecurityOrigin.h"
76 #include "SelectionController.h"
77 #include "Settings.h"
78 #include "SubstituteData.h"
79 #include "UrlInterceptResponse.h"
80 #include "UserGestureIndicator.h"
81 #include "WebCache.h"
82 #include "WebCoreJni.h"
83 #include "WebCoreResourceLoader.h"
84 #include "WebHistory.h"
85 #include "WebIconDatabase.h"
86 #include "WebFrameView.h"
87 #include "WebUrlLoaderClient.h"
88 #include "WebViewCore.h"
89 #include "android_graphics.h"
90 #include "jni.h"
91 #include "wds/DebugServer.h"
92
93 #include <JNIUtility.h>
94 #include <JNIHelp.h>
95 #include <SkGraphics.h>
96 #include <android_runtime/android_util_AssetManager.h>
97 #include <utils/misc.h>
98 #include <utils/AssetManager.h>
99 #include <wtf/CurrentTime.h>
100 #include <wtf/Platform.h>
101 #include <wtf/text/AtomicString.h>
102 #include <wtf/text/CString.h>
103 #include <wtf/text/StringBuilder.h>
104
105 #if USE(JSC)
106 #include "GCController.h"
107 #include "JSDOMWindow.h"
108 #include "JavaInstanceJSC.h"
109 #include <runtime_object.h>
110 #include <runtime_root.h>
111 #include <runtime/JSLock.h>
112 #elif USE(V8)
113 #include "JavaNPObjectV8.h"
114 #include "JavaInstanceV8.h"
115 #include "V8Counters.h"
116 #endif  // USE(JSC)
117
118 #ifdef ANDROID_INSTRUMENT
119 #include "TimeCounter.h"
120 #endif
121
122 #if ENABLE(ARCHIVE)
123 #include "WebArchiveAndroid.h"
124 #endif
125
126 #if ENABLE(WEB_AUTOFILL)
127 #include "autofill/WebAutoFill.h"
128 #endif
129
130 using namespace JSC::Bindings;
131
132 static String* gUploadFileLabel;
133 static String* gResetLabel;
134 static String* gSubmitLabel;
135 static String* gNoFileChosenLabel;
136
137 String* WebCore::PlatformBridge::globalLocalizedName(
138         WebCore::PlatformBridge::rawResId resId)
139 {
140     switch (resId) {
141     case WebCore::PlatformBridge::FileUploadLabel:
142         return gUploadFileLabel;
143     case WebCore::PlatformBridge::ResetLabel:
144         return gResetLabel;
145     case WebCore::PlatformBridge::SubmitLabel:
146         return gSubmitLabel;
147     case WebCore::PlatformBridge::FileUploadNoFileChosenLabel:
148         return gNoFileChosenLabel;
149
150     default:
151         return 0;
152     }
153 }
154 /**
155  * Instantiate the localized name desired.
156  */
157 void initGlobalLocalizedName(WebCore::PlatformBridge::rawResId resId,
158         android::WebFrame* webFrame)
159 {
160     String** pointer;
161     switch (resId) {
162     case WebCore::PlatformBridge::FileUploadLabel:
163         pointer = &gUploadFileLabel;
164         break;
165     case WebCore::PlatformBridge::ResetLabel:
166         pointer = &gResetLabel;
167         break;
168     case WebCore::PlatformBridge::SubmitLabel:
169         pointer = &gSubmitLabel;
170         break;
171     case WebCore::PlatformBridge::FileUploadNoFileChosenLabel:
172         pointer = &gNoFileChosenLabel;
173         break;
174     default:
175         return;
176     }
177     if (!(*pointer) && webFrame) {
178         (*pointer) = new String(webFrame->getRawResourceFilename(resId).impl());
179     }
180 }
181
182 namespace android {
183
184 // ----------------------------------------------------------------------------
185
186 #define WEBCORE_MEMORY_CAP 15 * 1024 * 1024
187
188 // ----------------------------------------------------------------------------
189
190 struct WebFrame::JavaBrowserFrame
191 {
192     jweak       mObj;
193     jweak       mHistoryList; // WebBackForwardList object
194     jmethodID   mStartLoadingResource;
195     jmethodID   mMaybeSavePassword;
196     jmethodID   mShouldInterceptRequest;
197     jmethodID   mLoadStarted;
198     jmethodID   mTransitionToCommitted;
199     jmethodID   mLoadFinished;
200     jmethodID   mReportError;
201     jmethodID   mSetTitle;
202     jmethodID   mWindowObjectCleared;
203     jmethodID   mSetProgress;
204     jmethodID   mDidReceiveIcon;
205     jmethodID   mDidReceiveTouchIconUrl;
206     jmethodID   mUpdateVisitedHistory;
207     jmethodID   mHandleUrl;
208     jmethodID   mCreateWindow;
209     jmethodID   mCloseWindow;
210     jmethodID   mDecidePolicyForFormResubmission;
211     jmethodID   mRequestFocus;
212     jmethodID   mGetRawResFilename;
213     jmethodID   mDensity;
214     jmethodID   mGetFileSize;
215     jmethodID   mGetFile;
216     jmethodID   mDidReceiveAuthenticationChallenge;
217     jmethodID   mReportSslCertError;
218     jmethodID   mDownloadStart;
219     jmethodID   mDidReceiveData;
220     jmethodID   mDidFinishLoading;
221     jmethodID   mSetCertificate;
222     jmethodID   mShouldSaveFormData;
223     jmethodID   mSaveFormData;
224     jmethodID   mAutoLogin;
225     AutoJObject frame(JNIEnv* env) {
226         return getRealObject(env, mObj);
227     }
228     AutoJObject history(JNIEnv* env) {
229         return getRealObject(env, mHistoryList);
230     }
231 };
232
233 static jfieldID gFrameField;
234 #define GET_NATIVE_FRAME(env, obj) ((WebCore::Frame*)env->GetIntField(obj, gFrameField))
235 #define SET_NATIVE_FRAME(env, obj, frame) (env->SetIntField(obj, gFrameField, frame))
236
237 // ----------------------------------------------------------------------------
238
239 WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* page)
240     : mPage(page)
241 {
242     jclass clazz = env->GetObjectClass(obj);
243     mJavaFrame = new JavaBrowserFrame;
244     mJavaFrame->mObj = env->NewWeakGlobalRef(obj);
245     mJavaFrame->mHistoryList = env->NewWeakGlobalRef(historyList);
246     mJavaFrame->mStartLoadingResource = env->GetMethodID(clazz, "startLoadingResource",
247             "(ILjava/lang/String;Ljava/lang/String;Ljava/util/HashMap;[BJIZZZLjava/lang/String;Ljava/lang/String;)Landroid/webkit/LoadListener;");
248     mJavaFrame->mMaybeSavePassword = env->GetMethodID(clazz, "maybeSavePassword",
249             "([BLjava/lang/String;Ljava/lang/String;)V");
250     mJavaFrame->mShouldInterceptRequest =
251             env->GetMethodID(clazz, "shouldInterceptRequest",
252             "(Ljava/lang/String;)Landroid/webkit/WebResourceResponse;");
253     mJavaFrame->mLoadStarted = env->GetMethodID(clazz, "loadStarted",
254             "(Ljava/lang/String;Landroid/graphics/Bitmap;IZ)V");
255     mJavaFrame->mTransitionToCommitted = env->GetMethodID(clazz, "transitionToCommitted",
256             "(IZ)V");
257     mJavaFrame->mLoadFinished = env->GetMethodID(clazz, "loadFinished",
258             "(Ljava/lang/String;IZ)V");
259     mJavaFrame->mReportError = env->GetMethodID(clazz, "reportError",
260             "(ILjava/lang/String;Ljava/lang/String;)V");
261     mJavaFrame->mSetTitle = env->GetMethodID(clazz, "setTitle",
262             "(Ljava/lang/String;)V");
263     mJavaFrame->mWindowObjectCleared = env->GetMethodID(clazz, "windowObjectCleared",
264             "(I)V");
265     mJavaFrame->mSetProgress = env->GetMethodID(clazz, "setProgress",
266             "(I)V");
267     mJavaFrame->mDidReceiveIcon = env->GetMethodID(clazz, "didReceiveIcon",
268             "(Landroid/graphics/Bitmap;)V");
269     mJavaFrame->mDidReceiveTouchIconUrl = env->GetMethodID(clazz, "didReceiveTouchIconUrl",
270             "(Ljava/lang/String;Z)V");
271     mJavaFrame->mUpdateVisitedHistory = env->GetMethodID(clazz, "updateVisitedHistory",
272             "(Ljava/lang/String;Z)V");
273     mJavaFrame->mHandleUrl = env->GetMethodID(clazz, "handleUrl",
274             "(Ljava/lang/String;)Z");
275     mJavaFrame->mCreateWindow = env->GetMethodID(clazz, "createWindow",
276             "(ZZ)Landroid/webkit/BrowserFrame;");
277     mJavaFrame->mCloseWindow = env->GetMethodID(clazz, "closeWindow",
278             "(Landroid/webkit/WebViewCore;)V");
279     mJavaFrame->mDecidePolicyForFormResubmission = env->GetMethodID(clazz,
280             "decidePolicyForFormResubmission", "(I)V");
281     mJavaFrame->mRequestFocus = env->GetMethodID(clazz, "requestFocus",
282             "()V");
283     mJavaFrame->mGetRawResFilename = env->GetMethodID(clazz, "getRawResFilename",
284             "(I)Ljava/lang/String;");
285     mJavaFrame->mDensity = env->GetMethodID(clazz, "density","()F");
286     mJavaFrame->mGetFileSize = env->GetMethodID(clazz, "getFileSize", "(Ljava/lang/String;)I");
287     mJavaFrame->mGetFile = env->GetMethodID(clazz, "getFile", "(Ljava/lang/String;[BII)I");
288     mJavaFrame->mDidReceiveAuthenticationChallenge = env->GetMethodID(clazz, "didReceiveAuthenticationChallenge",
289             "(ILjava/lang/String;Ljava/lang/String;Z)V");
290     mJavaFrame->mReportSslCertError = env->GetMethodID(clazz, "reportSslCertError", "(II[B)V");
291     mJavaFrame->mDownloadStart = env->GetMethodID(clazz, "downloadStart",
292             "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V");
293     mJavaFrame->mDidReceiveData = env->GetMethodID(clazz, "didReceiveData", "([BI)V");
294     mJavaFrame->mDidFinishLoading = env->GetMethodID(clazz, "didFinishLoading", "()V");
295     mJavaFrame->mSetCertificate = env->GetMethodID(clazz, "setCertificate", "([B)V");
296     mJavaFrame->mShouldSaveFormData = env->GetMethodID(clazz, "shouldSaveFormData", "()Z");
297     mJavaFrame->mSaveFormData = env->GetMethodID(clazz, "saveFormData", "(Ljava/util/HashMap;)V");
298     mJavaFrame->mAutoLogin = env->GetMethodID(clazz, "autoLogin",
299             "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
300     env->DeleteLocalRef(clazz);
301
302     LOG_ASSERT(mJavaFrame->mStartLoadingResource, "Could not find method startLoadingResource");
303     LOG_ASSERT(mJavaFrame->mMaybeSavePassword, "Could not find method maybeSavePassword");
304     LOG_ASSERT(mJavaFrame->mShouldInterceptRequest, "Could not find method shouldInterceptRequest");
305     LOG_ASSERT(mJavaFrame->mLoadStarted, "Could not find method loadStarted");
306     LOG_ASSERT(mJavaFrame->mTransitionToCommitted, "Could not find method transitionToCommitted");
307     LOG_ASSERT(mJavaFrame->mLoadFinished, "Could not find method loadFinished");
308     LOG_ASSERT(mJavaFrame->mReportError, "Could not find method reportError");
309     LOG_ASSERT(mJavaFrame->mSetTitle, "Could not find method setTitle");
310     LOG_ASSERT(mJavaFrame->mWindowObjectCleared, "Could not find method windowObjectCleared");
311     LOG_ASSERT(mJavaFrame->mSetProgress, "Could not find method setProgress");
312     LOG_ASSERT(mJavaFrame->mDidReceiveIcon, "Could not find method didReceiveIcon");
313     LOG_ASSERT(mJavaFrame->mDidReceiveTouchIconUrl, "Could not find method didReceiveTouchIconUrl");
314     LOG_ASSERT(mJavaFrame->mUpdateVisitedHistory, "Could not find method updateVisitedHistory");
315     LOG_ASSERT(mJavaFrame->mHandleUrl, "Could not find method handleUrl");
316     LOG_ASSERT(mJavaFrame->mCreateWindow, "Could not find method createWindow");
317     LOG_ASSERT(mJavaFrame->mCloseWindow, "Could not find method closeWindow");
318     LOG_ASSERT(mJavaFrame->mDecidePolicyForFormResubmission, "Could not find method decidePolicyForFormResubmission");
319     LOG_ASSERT(mJavaFrame->mRequestFocus, "Could not find method requestFocus");
320     LOG_ASSERT(mJavaFrame->mGetRawResFilename, "Could not find method getRawResFilename");
321     LOG_ASSERT(mJavaFrame->mDensity, "Could not find method density");
322     LOG_ASSERT(mJavaFrame->mGetFileSize, "Could not find method getFileSize");
323     LOG_ASSERT(mJavaFrame->mGetFile, "Could not find method getFile");
324     LOG_ASSERT(mJavaFrame->mDidReceiveAuthenticationChallenge, "Could not find method didReceiveAuthenticationChallenge");
325     LOG_ASSERT(mJavaFrame->mReportSslCertError, "Could not find method reportSslCertError");
326     LOG_ASSERT(mJavaFrame->mDownloadStart, "Could not find method downloadStart");
327     LOG_ASSERT(mJavaFrame->mDidReceiveData, "Could not find method didReceiveData");
328     LOG_ASSERT(mJavaFrame->mDidFinishLoading, "Could not find method didFinishLoading");
329     LOG_ASSERT(mJavaFrame->mSetCertificate, "Could not find method setCertificate");
330     LOG_ASSERT(mJavaFrame->mShouldSaveFormData, "Could not find method shouldSaveFormData");
331     LOG_ASSERT(mJavaFrame->mSaveFormData, "Could not find method saveFormData");
332     LOG_ASSERT(mJavaFrame->mAutoLogin, "Could not find method autoLogin");
333
334     mUserAgent = WTF::String();
335     mUserInitiatedAction = false;
336     mBlockNetworkLoads = false;
337     m_renderSkins = 0;
338 }
339
340 WebFrame::~WebFrame()
341 {
342     if (mJavaFrame->mObj) {
343         JNIEnv* env = getJNIEnv();
344         env->DeleteWeakGlobalRef(mJavaFrame->mObj);
345         env->DeleteWeakGlobalRef(mJavaFrame->mHistoryList);
346         mJavaFrame->mObj = 0;
347     }
348     delete mJavaFrame;
349     delete m_renderSkins;
350 }
351
352 WebFrame* WebFrame::getWebFrame(const WebCore::Frame* frame)
353 {
354     FrameLoaderClientAndroid* client =
355             static_cast<FrameLoaderClientAndroid*> (frame->loader()->client());
356     return client->webFrame();
357 }
358
359 static jobject createJavaMapFromHTTPHeaders(JNIEnv* env, const WebCore::HTTPHeaderMap& map)
360 {
361     jclass mapClass = env->FindClass("java/util/HashMap");
362     LOG_ASSERT(mapClass, "Could not find HashMap class!");
363     jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V");
364     LOG_ASSERT(init, "Could not find constructor for HashMap");
365     jobject hashMap = env->NewObject(mapClass, init, map.size());
366     LOG_ASSERT(hashMap, "Could not create a new HashMap");
367     jmethodID put = env->GetMethodID(mapClass, "put",
368             "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
369     LOG_ASSERT(put, "Could not find put method on HashMap");
370
371     WebCore::HTTPHeaderMap::const_iterator end = map.end();
372     for (WebCore::HTTPHeaderMap::const_iterator i = map.begin(); i != end; ++i) {
373         if (i->first.length() == 0 || i->second.length() == 0)
374             continue;
375         jstring key = wtfStringToJstring(env, i->first);
376         jstring val = wtfStringToJstring(env, i->second);
377         if (key && val) {
378             env->CallObjectMethod(hashMap, put, key, val);
379         }
380         env->DeleteLocalRef(key);
381         env->DeleteLocalRef(val);
382     }
383
384     env->DeleteLocalRef(mapClass);
385
386     return hashMap;
387 }
388
389 // This class stores the URI and the size of each file for upload.  The URI is
390 // stored so we do not have to create it again.  The size is stored so we can
391 // compare the actual size of the file with the stated size.  If the actual size
392 // is larger, we will not copy it, since we will not have enough space in our
393 // buffer.
394 class FileInfo {
395 public:
396     FileInfo(JNIEnv* env, const WTF::String& name) {
397         m_uri = wtfStringToJstring(env, name);
398         checkException(env);
399         m_size = 0;
400         m_env = env;
401     }
402     ~FileInfo() {
403         m_env->DeleteLocalRef(m_uri);
404     }
405     int getSize() { return m_size; }
406     jstring getUri() { return m_uri; }
407     void setSize(int size) { m_size = size; }
408 private:
409     // This is only a pointer to the JNIEnv* returned by
410     // JSC::Bindings::getJNIEnv().  Used to delete the jstring when finished.
411     JNIEnv* m_env;
412     jstring m_uri;
413     int m_size;
414 };
415
416 PassRefPtr<WebCore::ResourceLoaderAndroid>
417 WebFrame::startLoadingResource(WebCore::ResourceHandle* loader,
418                                   const WebCore::ResourceRequest& request,
419                                   bool mainResource,
420                                   bool synchronous)
421 {
422 #ifdef ANDROID_INSTRUMENT
423     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
424 #endif
425     LOGV("::WebCore:: startLoadingResource(%p, %s)",
426             loader, request.url().string().latin1().data());
427
428     WTF::String method = request.httpMethod();
429     WebCore::HTTPHeaderMap headers = request.httpHeaderFields();
430
431     JNIEnv* env = getJNIEnv();
432     WTF::String urlStr = request.url().string();
433     int colon = urlStr.find(':');
434     bool allLower = true;
435     for (int index = 0; index < colon; index++) {
436         UChar ch = urlStr[index];
437         if (!WTF::isASCIIAlpha(ch))
438             break;
439         allLower &= WTF::isASCIILower(ch);
440         if (index == colon - 1 && !allLower) {
441             urlStr = urlStr.substring(0, colon).lower()
442                     + urlStr.substring(colon);
443         }
444     }
445     LOGV("%s lower=%s", __FUNCTION__, urlStr.latin1().data());
446     jstring jUrlStr = wtfStringToJstring(env, urlStr);
447     jstring jMethodStr = NULL;
448     if (!method.isEmpty())
449         jMethodStr = wtfStringToJstring(env, method);
450     WebCore::FormData* formdata = request.httpBody();
451     jbyteArray jPostDataStr = getPostData(request);
452     jobject jHeaderMap = createJavaMapFromHTTPHeaders(env, headers);
453
454     // Convert the WebCore Cache Policy to a WebView Cache Policy.
455     int cacheMode = 0;  // WebSettings.LOAD_NORMAL
456     switch (request.cachePolicy()) {
457         case WebCore::ReloadIgnoringCacheData:
458             cacheMode = 2; // WebSettings.LOAD_NO_CACHE
459             break;
460         case WebCore::ReturnCacheDataDontLoad:
461             cacheMode = 3; // WebSettings.LOAD_CACHE_ONLY
462             break;
463         case WebCore::ReturnCacheDataElseLoad:
464             cacheMode = 1;   // WebSettings.LOAD_CACHE_ELSE_NETWORK
465             break;
466         case WebCore::UseProtocolCachePolicy:
467         default:
468             break;
469     }
470
471     LOGV("::WebCore:: startLoadingResource %s with cacheMode %d", urlStr.ascii().data(), cacheMode);
472
473     ResourceHandleInternal* loaderInternal = loader->getInternal();
474     jstring jUsernameString = loaderInternal->m_user.isEmpty() ?
475             NULL : wtfStringToJstring(env, loaderInternal->m_user);
476     jstring jPasswordString = loaderInternal->m_pass.isEmpty() ?
477             NULL : wtfStringToJstring(env, loaderInternal->m_pass);
478
479     bool isUserGesture = UserGestureIndicator::processingUserGesture();
480     jobject jLoadListener =
481         env->CallObjectMethod(mJavaFrame->frame(env).get(), mJavaFrame->mStartLoadingResource,
482                 (int)loader, jUrlStr, jMethodStr, jHeaderMap,
483                 jPostDataStr, formdata ? formdata->identifier(): 0,
484                 cacheMode, mainResource, isUserGesture,
485                 synchronous, jUsernameString, jPasswordString);
486
487     env->DeleteLocalRef(jUrlStr);
488     env->DeleteLocalRef(jMethodStr);
489     env->DeleteLocalRef(jPostDataStr);
490     env->DeleteLocalRef(jHeaderMap);
491     env->DeleteLocalRef(jUsernameString);
492     env->DeleteLocalRef(jPasswordString);
493     if (checkException(env))
494         return NULL;
495
496     PassRefPtr<WebCore::ResourceLoaderAndroid> h;
497     if (jLoadListener)
498         h = WebCoreResourceLoader::create(env, jLoadListener);
499     env->DeleteLocalRef(jLoadListener);
500     return h;
501 }
502
503 UrlInterceptResponse*
504 WebFrame::shouldInterceptRequest(const WTF::String& url)
505 {
506 #ifdef ANDROID_INSTRUMENT
507     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
508 #endif
509     LOGV("::WebCore:: shouldInterceptRequest(%s)", url.latin1().data());
510
511     JNIEnv* env = getJNIEnv();
512     jstring urlStr = wtfStringToJstring(env, url);
513     jobject response = env->CallObjectMethod(mJavaFrame->frame(env).get(), mJavaFrame->mShouldInterceptRequest, urlStr);
514     env->DeleteLocalRef(urlStr);
515     if (response == 0)
516         return 0;
517     return new UrlInterceptResponse(env, response);
518 }
519
520 void
521 WebFrame::reportError(int errorCode, const WTF::String& description,
522         const WTF::String& failingUrl)
523 {
524 #ifdef ANDROID_INSTRUMENT
525     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
526 #endif
527     LOGV("::WebCore:: reportError(%d, %s)", errorCode, description.ascii().data());
528     JNIEnv* env = getJNIEnv();
529
530     jstring descStr = wtfStringToJstring(env, description);
531     jstring failUrl = wtfStringToJstring(env, failingUrl);
532     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mReportError,
533             errorCode, descStr, failUrl);
534     env->DeleteLocalRef(descStr);
535     env->DeleteLocalRef(failUrl);
536 }
537
538 void
539 WebFrame::loadStarted(WebCore::Frame* frame)
540 {
541 #ifdef ANDROID_INSTRUMENT
542     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
543 #endif
544     // activeDocumentLoader() can return null.
545     DocumentLoader* documentLoader = frame->loader()->activeDocumentLoader();
546     if (documentLoader == NULL)
547         return;
548
549     const WebCore::KURL& url = documentLoader->url();
550     if (url.isEmpty())
551         return;
552     LOGV("::WebCore:: loadStarted %s", url.string().ascii().data());
553
554     bool isMainFrame = (!frame->tree() || !frame->tree()->parent());
555     WebCore::FrameLoadType loadType = frame->loader()->loadType();
556
557     if (loadType == WebCore::FrameLoadTypeReplace ||
558             (loadType == WebCore::FrameLoadTypeRedirectWithLockedBackForwardList &&
559              !isMainFrame))
560         return;
561
562     JNIEnv* env = getJNIEnv();
563     const WTF::String& urlString = url.string();
564     // If this is the main frame and we already have a favicon in the database,
565     // send it along with the page started notification.
566     jobject favicon = NULL;
567     if (isMainFrame) {
568         WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL(urlString, WebCore::IntSize(16, 16));
569         if (icon)
570             favicon = webcoreImageToJavaBitmap(env, icon);
571         LOGV("favicons", "Starting load with icon %p for %s", icon, url.string().utf8().data());
572     }
573     jstring urlStr = wtfStringToJstring(env, urlString);
574
575     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mLoadStarted, urlStr, favicon,
576             (int)loadType, isMainFrame);
577     checkException(env);
578     env->DeleteLocalRef(urlStr);
579     if (favicon)
580         env->DeleteLocalRef(favicon);
581
582     // Inform the client that the main frame has started a new load.
583     if (isMainFrame && mPage) {
584         Chrome* chrome = mPage->chrome();
585         if (chrome) {
586             ChromeClientAndroid* client = static_cast<ChromeClientAndroid*>(chrome->client());
587             if (client)
588                 client->onMainFrameLoadStarted();
589         }
590     }
591 }
592
593 void
594 WebFrame::transitionToCommitted(WebCore::Frame* frame)
595 {
596 #ifdef ANDROID_INSTRUMENT
597     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
598 #endif
599     JNIEnv* env = getJNIEnv();
600     WebCore::FrameLoadType loadType = frame->loader()->loadType();
601     bool isMainFrame = (!frame->tree() || !frame->tree()->parent());
602     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mTransitionToCommitted,
603             (int)loadType, isMainFrame);
604     checkException(env);
605 }
606
607 void
608 WebFrame::didFinishLoad(WebCore::Frame* frame)
609 {
610 #ifdef ANDROID_INSTRUMENT
611     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
612 #endif
613     JNIEnv* env = getJNIEnv();
614
615     // activeDocumentLoader() can return null.
616     WebCore::FrameLoader* loader = frame->loader();
617     DocumentLoader* documentLoader = loader->activeDocumentLoader();
618     if (documentLoader == NULL)
619       return;
620
621     const WebCore::KURL& url = documentLoader->url();
622     if (url.isEmpty())
623         return;
624     LOGV("::WebCore:: didFinishLoad %s", url.string().ascii().data());
625
626     bool isMainFrame = (!frame->tree() || !frame->tree()->parent());
627     WebCore::FrameLoadType loadType = loader->loadType();
628     const WTF::String& urlString = url.string();
629     jstring urlStr = wtfStringToJstring(env, urlString);
630     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mLoadFinished, urlStr,
631             (int)loadType, isMainFrame);
632     checkException(env);
633     env->DeleteLocalRef(urlStr);
634 }
635
636 void
637 WebFrame::addHistoryItem(WebCore::HistoryItem* item)
638 {
639 #ifdef ANDROID_INSTRUMENT
640     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
641 #endif
642     LOGV("::WebCore:: addHistoryItem");
643     JNIEnv* env = getJNIEnv();
644     WebHistory::AddItem(mJavaFrame->history(env), item);
645 }
646
647 void
648 WebFrame::removeHistoryItem(int index)
649 {
650 #ifdef ANDROID_INSTRUMENT
651     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
652 #endif
653     LOGV("::WebCore:: removeHistoryItem at %d", index);
654     JNIEnv* env = getJNIEnv();
655     WebHistory::RemoveItem(mJavaFrame->history(env), index);
656 }
657
658 void
659 WebFrame::updateHistoryIndex(int newIndex)
660 {
661 #ifdef ANDROID_INSTRUMENT
662     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
663 #endif
664     LOGV("::WebCore:: updateHistoryIndex to %d", newIndex);
665     JNIEnv* env = getJNIEnv();
666     WebHistory::UpdateHistoryIndex(mJavaFrame->history(env), newIndex);
667 }
668
669 void
670 WebFrame::setTitle(const WTF::String& title)
671 {
672 #ifdef ANDROID_INSTRUMENT
673     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
674 #endif
675 #ifndef NDEBUG
676     LOGV("setTitle(%s)", title.ascii().data());
677 #endif
678     JNIEnv* env = getJNIEnv();
679     jstring jTitleStr = wtfStringToJstring(env, title);
680
681     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSetTitle, jTitleStr);
682     checkException(env);
683     env->DeleteLocalRef(jTitleStr);
684 }
685
686 void
687 WebFrame::windowObjectCleared(WebCore::Frame* frame)
688 {
689 #ifdef ANDROID_INSTRUMENT
690     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
691 #endif
692     LOGV("::WebCore:: windowObjectCleared");
693     JNIEnv* env = getJNIEnv();
694
695     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mWindowObjectCleared, (int)frame);
696     checkException(env);
697 }
698
699 void
700 WebFrame::setProgress(float newProgress)
701 {
702 #ifdef ANDROID_INSTRUMENT
703     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
704 #endif
705     JNIEnv* env = getJNIEnv();
706     int progress = (int) (100 * newProgress);
707     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSetProgress, progress);
708     checkException(env);
709 }
710
711 const WTF::String
712 WebFrame::userAgentForURL(const WebCore::KURL* url)
713 {
714     return mUserAgent;
715 }
716
717 void
718 WebFrame::didReceiveIcon(WebCore::Image* icon)
719 {
720 #ifdef ANDROID_INSTRUMENT
721     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
722 #endif
723     LOG_ASSERT(icon, "DidReceiveIcon called without an image!");
724     JNIEnv* env = getJNIEnv();
725     jobject bitmap = webcoreImageToJavaBitmap(env, icon);
726     if (!bitmap)
727         return;
728
729     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDidReceiveIcon, bitmap);
730     env->DeleteLocalRef(bitmap);
731     checkException(env);
732 }
733
734 void
735 WebFrame::didReceiveTouchIconURL(const WTF::String& url, bool precomposed)
736 {
737 #ifdef ANDROID_INSTRUMENT
738     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
739 #endif
740     JNIEnv* env = getJNIEnv();
741     jstring jUrlStr = wtfStringToJstring(env, url);
742
743     env->CallVoidMethod(mJavaFrame->frame(env).get(),
744             mJavaFrame->mDidReceiveTouchIconUrl, jUrlStr, precomposed);
745     env->DeleteLocalRef(jUrlStr);
746     checkException(env);
747 }
748
749 void
750 WebFrame::updateVisitedHistory(const WebCore::KURL& url, bool reload)
751 {
752 #ifdef ANDROID_INSTRUMENT
753     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
754 #endif
755     const WTF::String& urlStr = url.string();
756     JNIEnv* env = getJNIEnv();
757     jstring jUrlStr = wtfStringToJstring(env, urlStr);
758
759     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mUpdateVisitedHistory, jUrlStr, reload);
760     env->DeleteLocalRef(jUrlStr);
761     checkException(env);
762 }
763
764 bool
765 WebFrame::canHandleRequest(const WebCore::ResourceRequest& request)
766 {
767 #ifdef ANDROID_INSTRUMENT
768     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
769 #endif
770     // always handle "POST" in place
771     if (equalIgnoringCase(request.httpMethod(), "POST"))
772         return true;
773     const WebCore::KURL& requestUrl = request.url();
774     bool isUserGesture = UserGestureIndicator::processingUserGesture();
775     if (!mUserInitiatedAction && !isUserGesture &&
776             (requestUrl.protocolIs("http") || requestUrl.protocolIs("https") ||
777             requestUrl.protocolIs("file") || requestUrl.protocolIs("about") ||
778             WebCore::protocolIsJavaScript(requestUrl.string())))
779         return true;
780     const WTF::String& url = requestUrl.string();
781     // Empty urls should not be sent to java
782     if (url.isEmpty())
783         return true;
784     JNIEnv* env = getJNIEnv();
785     jstring jUrlStr = wtfStringToJstring(env, url);
786
787     // check to see whether browser app wants to hijack url loading.
788     // if browser app handles the url, we will return false to bail out WebCore loading
789     jboolean ret = env->CallBooleanMethod(mJavaFrame->frame(env).get(), mJavaFrame->mHandleUrl, jUrlStr);
790     checkException(env);
791     env->DeleteLocalRef(jUrlStr);
792     return (ret == 0);
793 }
794
795 bool
796 WebFrame::shouldSaveFormData()
797 {
798     JNIEnv* env = getJNIEnv();
799     jboolean ret = env->CallBooleanMethod(mJavaFrame->frame(env).get(),
800             mJavaFrame->mShouldSaveFormData);
801     checkException(env);
802     return ret;
803 }
804
805 WebCore::Frame*
806 WebFrame::createWindow(bool dialog, bool userGesture)
807 {
808 #ifdef ANDROID_INSTRUMENT
809     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
810 #endif
811     JNIEnv* env = getJNIEnv();
812     jobject obj = env->CallObjectMethod(mJavaFrame->frame(env).get(),
813             mJavaFrame->mCreateWindow, dialog, userGesture);
814     if (obj) {
815         WebCore::Frame* frame = GET_NATIVE_FRAME(env, obj);
816         return frame;
817     }
818     return NULL;
819 }
820
821 void
822 WebFrame::requestFocus() const
823 {
824 #ifdef ANDROID_INSTRUMENT
825     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
826 #endif
827     JNIEnv* env = getJNIEnv();
828     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mRequestFocus);
829     checkException(env);
830 }
831
832 void
833 WebFrame::closeWindow(WebViewCore* webViewCore)
834 {
835 #ifdef ANDROID_INSTRUMENT
836     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
837 #endif
838     assert(webViewCore);
839     JNIEnv* env = getJNIEnv();
840     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mCloseWindow,
841             webViewCore->getJavaObject().get());
842 }
843
844 struct PolicyFunctionWrapper {
845     WebCore::FramePolicyFunction func;
846 };
847
848 void
849 WebFrame::decidePolicyForFormResubmission(WebCore::FramePolicyFunction func)
850 {
851 #ifdef ANDROID_INSTRUMENT
852     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
853 #endif
854     JNIEnv* env = getJNIEnv();
855     PolicyFunctionWrapper* p = new PolicyFunctionWrapper;
856     p->func = func;
857     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDecidePolicyForFormResubmission, p);
858 }
859
860 WTF::String
861 WebFrame::getRawResourceFilename(WebCore::PlatformBridge::rawResId id) const
862 {
863     JNIEnv* env = getJNIEnv();
864     jstring ret = (jstring) env->CallObjectMethod(mJavaFrame->frame(env).get(),
865             mJavaFrame->mGetRawResFilename, (int)id);
866
867     return jstringToWtfString(env, ret);
868 }
869
870 float
871 WebFrame::density() const
872 {
873     JNIEnv* env = getJNIEnv();
874     jfloat dpi = env->CallFloatMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDensity);
875     checkException(env);
876     return dpi;
877 }
878
879 #if USE(CHROME_NETWORK_STACK)
880 void
881 WebFrame::didReceiveAuthenticationChallenge(WebUrlLoaderClient* client, const std::string& host, const std::string& realm, bool useCachedCredentials)
882 {
883 #ifdef ANDROID_INSTRUMENT
884     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
885 #endif
886     JNIEnv* env = getJNIEnv();
887     int jHandle = reinterpret_cast<int>(client);
888     jstring jHost = stdStringToJstring(env, host, true);
889     jstring jRealm = stdStringToJstring(env, realm, true);
890
891     env->CallVoidMethod(mJavaFrame->frame(env).get(),
892             mJavaFrame->mDidReceiveAuthenticationChallenge, jHandle, jHost, jRealm, useCachedCredentials);
893     env->DeleteLocalRef(jHost);
894     env->DeleteLocalRef(jRealm);
895     checkException(env);
896 }
897 #endif
898
899 void
900 WebFrame::reportSslCertError(WebUrlLoaderClient* client, int cert_error, const std::string& cert)
901 {
902 #ifdef ANDROID_INSTRUMENT
903     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
904 #endif
905     JNIEnv* env = getJNIEnv();
906     int jHandle = reinterpret_cast<int>(client);
907
908     int len = cert.length();
909     jbyteArray jCert = env->NewByteArray(len);
910     jbyte* bytes = env->GetByteArrayElements(jCert, NULL);
911     cert.copy(reinterpret_cast<char*>(bytes), len);
912
913     env->CallVoidMethod(mJavaFrame->frame(env).get(),
914             mJavaFrame->mReportSslCertError, jHandle, cert_error, jCert);
915     env->DeleteLocalRef(jCert);
916     checkException(env);
917 }
918
919 #if USE(CHROME_NETWORK_STACK)
920 void
921 WebFrame::downloadStart(const std::string& url, const std::string& userAgent, const std::string& contentDisposition, const std::string& mimetype, long long contentLength)
922 {
923 #ifdef ANDROID_INSTRUMENT
924     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
925 #endif
926     JNIEnv* env = getJNIEnv();
927     jstring jUrl = stdStringToJstring(env, url, true);
928     jstring jUserAgent = stdStringToJstring(env, userAgent, true);
929     jstring jContentDisposition = stdStringToJstring(env, contentDisposition, true);
930     jstring jMimetype = stdStringToJstring(env, mimetype, true);
931
932     env->CallVoidMethod(mJavaFrame->frame(env).get(),
933             mJavaFrame->mDownloadStart, jUrl, jUserAgent, jContentDisposition, jMimetype, contentLength);
934
935     env->DeleteLocalRef(jUrl);
936     env->DeleteLocalRef(jUserAgent);
937     env->DeleteLocalRef(jContentDisposition);
938     env->DeleteLocalRef(jMimetype);
939     checkException(env);
940 }
941
942 void
943 WebFrame::didReceiveData(const char* data, int size) {
944 #ifdef ANDROID_INSTRUMENT
945     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
946 #endif
947     JNIEnv* env = getJNIEnv();
948
949     jbyteArray jData = env->NewByteArray(size);
950     jbyte* bytes = env->GetByteArrayElements(jData, NULL);
951     memcpy(reinterpret_cast<char*>(bytes), data, size);
952
953     env->CallVoidMethod(mJavaFrame->frame(env).get(),
954             mJavaFrame->mDidReceiveData, jData, size);
955     env->DeleteLocalRef(jData);
956     checkException(env);
957 }
958
959 void
960 WebFrame::didFinishLoading() {
961 #ifdef ANDROID_INSTRUMENT
962     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
963 #endif
964     JNIEnv* env = getJNIEnv();
965
966     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDidFinishLoading);
967     checkException(env);
968 }
969
970 #endif
971
972 #if USE(CHROME_NETWORK_STACK)
973 void WebFrame::setCertificate(const std::string& cert)
974 {
975 #ifdef ANDROID_INSTRUMENT
976     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
977 #endif
978     JNIEnv* env = getJNIEnv();
979
980     int len = cert.length();
981     jbyteArray jCert = env->NewByteArray(len);
982     jbyte* bytes = env->GetByteArrayElements(jCert, NULL);
983     cert.copy(reinterpret_cast<char*>(bytes), len);
984
985     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSetCertificate, jCert);
986
987     env->DeleteLocalRef(jCert);
988     checkException(env);
989 }
990 #endif
991
992 void WebFrame::autoLogin(const std::string& loginHeader)
993 {
994 #ifdef ANDROID_INSTRUMENT
995     TimeCounterAuto counter(TimerCoutner::JavaCallbackTimeCounter);
996 #endif
997     WTF::String header(loginHeader.c_str(), loginHeader.length());
998     WTF::Vector<WTF::String> split;
999     header.split('&', split);
1000     if (!split.isEmpty()) {
1001         WTF::String realm;
1002         WTF::String account;
1003         WTF::String args;
1004         int len = split.size();
1005         while (len--) {
1006             WTF::String& str = split[len];
1007             size_t equals = str.find('=');
1008             if (equals == WTF::notFound)
1009                 continue;
1010
1011             WTF::String* result = 0;
1012             if (str.startsWith("realm", false))
1013                 result = &realm;
1014             else if (str.startsWith("account", false))
1015                 result = &account;
1016             else if (str.startsWith("args", false))
1017                 result = &args;
1018
1019             if (result)
1020                 // Decode url escape sequences before sending to the app.
1021                 *result = WebCore::decodeURLEscapeSequences(str.substring(equals + 1));
1022         }
1023
1024         // realm and args are required parameters.
1025         if (realm.isEmpty() || args.isEmpty())
1026             return;
1027
1028         // Args is double-encoded as it contains urls.
1029         args = WebCore::decodeURLEscapeSequences(args);
1030
1031         JNIEnv* env = getJNIEnv();
1032         jstring jRealm = wtfStringToJstring(env, realm, true);
1033         jstring jAccount = wtfStringToJstring(env, account);
1034         jstring jArgs = wtfStringToJstring(env, args, true);
1035         env->CallVoidMethod(mJavaFrame->frame(env).get(),
1036                 mJavaFrame->mAutoLogin, jRealm, jAccount, jArgs);
1037     }
1038 }
1039
1040 void WebFrame::maybeSavePassword(WebCore::Frame* frame, const WebCore::ResourceRequest& request)
1041 {
1042     if (request.httpMethod() != "POST")
1043         return;
1044
1045     WTF::String username;
1046     WTF::String password;
1047     if (!getUsernamePasswordFromDom(frame, username, password))
1048         return;
1049
1050     JNIEnv* env = getJNIEnv();
1051     jstring jUsername = wtfStringToJstring(env, username);
1052     jstring jPassword = wtfStringToJstring(env, password);
1053     jbyteArray jPostData = getPostData(request);
1054     if (jPostData) {
1055         env->CallVoidMethod(mJavaFrame->frame(env).get(),
1056                 mJavaFrame->mMaybeSavePassword, jPostData, jUsername, jPassword);
1057     }
1058
1059     env->DeleteLocalRef(jPostData);
1060     env->DeleteLocalRef(jUsername);
1061     env->DeleteLocalRef(jPassword);
1062     checkException(env);
1063 }
1064
1065 bool WebFrame::getUsernamePasswordFromDom(WebCore::Frame* frame, WTF::String& username, WTF::String& password)
1066 {
1067     bool found = false;
1068     WTF::PassRefPtr<WebCore::HTMLCollection> form = frame->document()->forms();
1069     WebCore::Node* node = form->firstItem();
1070     while (node && !found && !node->namespaceURI().isNull() &&
1071            !node->namespaceURI().isEmpty()) {
1072         const WTF::Vector<WebCore::HTMLFormControlElement*>& elements =
1073             ((WebCore::HTMLFormElement*)node)->associatedElements();
1074         size_t size = elements.size();
1075         for (size_t i = 0; i< size && !found; i++) {
1076             WebCore::HTMLFormControlElement* e = elements[i];
1077             if (e->hasLocalName(WebCore::HTMLNames::inputTag)) {
1078                 WebCore::HTMLInputElement* input = (WebCore::HTMLInputElement*)e;
1079                 if (input->autoComplete() == false)
1080                     continue;
1081                 if (input->isPasswordField())
1082                     password = input->value();
1083                 else if (input->isTextField() || input->isEmailField())
1084                     username = input->value();
1085                 if (!username.isNull() && !password.isNull())
1086                     found = true;
1087             }
1088         }
1089         node = form->nextItem();
1090     }
1091     return found;
1092 }
1093
1094 jbyteArray WebFrame::getPostData(const WebCore::ResourceRequest& request)
1095 {
1096     jbyteArray jPostDataStr = NULL;
1097     WebCore::FormData* formdata = request.httpBody();
1098     if (formdata) {
1099         JNIEnv* env = getJNIEnv();
1100         AutoJObject obj = mJavaFrame->frame(env);
1101
1102         // We can use the formdata->flatten() but it will result in two
1103         // memcpys, first through loading up the vector with the form data
1104         // then another to copy it out of the vector and into the java byte
1105         // array. Instead, we copy the form data ourselves below saving a
1106         // memcpy.
1107         const WTF::Vector<WebCore::FormDataElement>& elements =
1108                 formdata->elements();
1109
1110         // Sizing pass
1111         int size = 0;
1112         size_t n = elements.size();
1113         FileInfo** fileinfos = new FileInfo*[n];
1114         for (size_t i = 0; i < n; ++i) {
1115             fileinfos[i] = 0;
1116             const WebCore::FormDataElement& e = elements[i];
1117             if (e.m_type == WebCore::FormDataElement::data) {
1118                 size += e.m_data.size();
1119             } else if (e.m_type == WebCore::FormDataElement::encodedFile) {
1120                 fileinfos[i] = new FileInfo(env, e.m_filename);
1121                 int delta = env->CallIntMethod(obj.get(),
1122                     mJavaFrame->mGetFileSize, fileinfos[i]->getUri());
1123                 checkException(env);
1124                 fileinfos[i]->setSize(delta);
1125                 size += delta;
1126             }
1127         }
1128
1129         // Only create the byte array if there is POST data to pass up.
1130         // The Java code is expecting null if there is no data.
1131         if (size > 0) {
1132             // Copy the actual form data.
1133             jPostDataStr = env->NewByteArray(size);
1134             if (jPostDataStr) {
1135                 // Write  the form data to the java array.
1136                 jbyte* bytes = env->GetByteArrayElements(jPostDataStr, NULL);
1137                 int offset = 0;
1138                 for (size_t i = 0; i < n; ++i) {
1139                     const WebCore::FormDataElement& e = elements[i];
1140                     if (e.m_type == WebCore::FormDataElement::data) {
1141                         int delta = e.m_data.size();
1142                         memcpy(bytes + offset, e.m_data.data(), delta);
1143                         offset += delta;
1144                     } else if (e.m_type
1145                             == WebCore::FormDataElement::encodedFile) {
1146                         int delta = env->CallIntMethod(obj.get(),
1147                             mJavaFrame->mGetFile, fileinfos[i]->getUri(),
1148                             jPostDataStr, offset, fileinfos[i]->getSize());
1149                         checkException(env);
1150                         offset += delta;
1151                     }
1152                 }
1153                 env->ReleaseByteArrayElements(jPostDataStr, bytes, 0);
1154             }
1155         }
1156         delete[] fileinfos;
1157     }
1158     return jPostDataStr;
1159 }
1160
1161 // ----------------------------------------------------------------------------
1162
1163 static void CallPolicyFunction(JNIEnv* env, jobject obj, jint func, jint decision)
1164 {
1165 #ifdef ANDROID_INSTRUMENT
1166     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1167 #endif
1168     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1169     LOG_ASSERT(pFrame, "nativeCallPolicyFunction must take a valid frame pointer!");
1170     PolicyFunctionWrapper* pFunc = (PolicyFunctionWrapper*)func;
1171     LOG_ASSERT(pFunc, "nativeCallPolicyFunction must take a valid function pointer!");
1172
1173     // If we are resending the form then we should reset the multiple submission protection.
1174     if (decision == WebCore::PolicyUse)
1175         pFrame->loader()->resetMultipleFormSubmissionProtection();
1176
1177     (pFrame->loader()->policyChecker()->*(pFunc->func))((WebCore::PolicyAction)decision);
1178 }
1179
1180 static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAssetManager, jobject historyList)
1181 {
1182     ScriptController::initializeThreading();
1183
1184 #if USE(CHROME_NETWORK_STACK)
1185     // needs to be called before any other chromium code
1186     initChromium();
1187 #endif
1188
1189 #ifdef ANDROID_INSTRUMENT
1190 #if USE(V8)
1191     V8Counters::initCounters();
1192 #endif
1193     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1194 #endif
1195     // Create a new page
1196     ChromeClientAndroid* chromeC = new ChromeClientAndroid;
1197     EditorClientAndroid* editorC = new EditorClientAndroid;
1198     DeviceMotionClientAndroid* deviceMotionC = new DeviceMotionClientAndroid;
1199     DeviceOrientationClientAndroid* deviceOrientationC = new DeviceOrientationClientAndroid;
1200
1201     WebCore::Page::PageClients pageClients;
1202     pageClients.chromeClient = chromeC;
1203     pageClients.contextMenuClient = new ContextMenuClientAndroid;
1204     pageClients.editorClient = editorC;
1205     pageClients.dragClient = new DragClientAndroid;
1206     pageClients.inspectorClient = new InspectorClientAndroid;
1207     pageClients.deviceMotionClient = deviceMotionC;
1208     pageClients.deviceOrientationClient = deviceOrientationC;
1209     WebCore::Page* page = new WebCore::Page(pageClients);
1210
1211     editorC->setPage(page);
1212     page->setGroupName("android.webkit");
1213
1214     // Create a WebFrame to access the Java BrowserFrame associated with this page
1215     WebFrame* webFrame = new WebFrame(env, obj, historyList, page);
1216     // Attach webFrame to pageClients.chromeClient and release our ownership
1217     chromeC->setWebFrame(webFrame);
1218     Release(webFrame);
1219
1220     FrameLoaderClientAndroid* loaderC = new FrameLoaderClientAndroid(webFrame);
1221     // Create a Frame and the page holds its reference
1222     WebCore::Frame* frame = WebCore::Frame::create(page, NULL, loaderC).get();
1223     loaderC->setFrame(frame);
1224 #if ENABLE(WDS)
1225     WDS::server()->addFrame(frame);
1226 #endif
1227
1228     // Create a WebViewCore to access the Java WebViewCore associated with this page
1229     WebViewCore* webViewCore = new WebViewCore(env, javaview, frame);
1230
1231 #if ENABLE(WEB_AUTOFILL)
1232     editorC->getAutoFill()->setWebViewCore(webViewCore);
1233 #endif
1234
1235     // Create a FrameView
1236     RefPtr<WebCore::FrameView> frameView = WebCore::FrameView::create(frame);
1237     // Create a WebFrameView
1238     WebFrameView* webFrameView = new WebFrameView(frameView.get(), webViewCore);
1239     // As webFrameView Retains webViewCore, release our ownership
1240     Release(webViewCore);
1241     // As frameView Retains webFrameView, release our ownership
1242     Release(webFrameView);
1243     // Attach the frameView to the frame and release our ownership
1244     frame->setView(frameView);
1245     // Set the frame to active to turn on keyboard focus.
1246     frame->init();
1247     frame->selection()->setFocused(true);
1248     frame->page()->focusController()->setFocused(true);
1249     deviceMotionC->setWebViewCore(webViewCore);
1250     deviceOrientationC->setWebViewCore(webViewCore);
1251
1252     // Allow local access to file:/// and substitute data
1253     WebCore::SecurityOrigin::setLocalLoadPolicy(
1254             WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
1255
1256     LOGV("::WebCore:: createFrame %p", frame);
1257
1258     // Set the mNativeFrame field in Frame
1259     SET_NATIVE_FRAME(env, obj, (int)frame);
1260
1261     String directory = webFrame->getRawResourceFilename(
1262             WebCore::PlatformBridge::DrawableDir);
1263     if (directory.isEmpty())
1264         LOGE("Can't find the drawable directory");
1265     else {
1266         // Setup the asset manager.
1267         AssetManager* am = assetManagerForJavaObject(env, jAssetManager);
1268         // Initialize our skinning classes
1269         webFrame->setRenderSkins(new WebCore::RenderSkinAndroid(am, directory));
1270     }
1271     for (int i = WebCore::PlatformBridge::FileUploadLabel;
1272             i <= WebCore::PlatformBridge::FileUploadNoFileChosenLabel; i++)
1273         initGlobalLocalizedName(
1274                 static_cast<WebCore::PlatformBridge::rawResId>(i), webFrame);
1275 }
1276
1277 static void DestroyFrame(JNIEnv* env, jobject obj)
1278 {
1279 #ifdef ANDROID_INSTRUMENT
1280     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1281 #endif
1282     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1283     LOG_ASSERT(pFrame, "nativeDestroyFrame must take a valid frame pointer!");
1284
1285     LOGV("::WebCore:: deleting frame %p", pFrame);
1286
1287     WebCore::FrameView* view = pFrame->view();
1288     view->ref();
1289     // detachFromParent will cause the page to be closed.
1290     WebCore::FrameLoader* fl = pFrame->loader();
1291     // retain a pointer because detachFromParent will set the page to null.
1292     WebCore::Page* page = pFrame->page();
1293     if (fl)
1294         fl->detachFromParent();
1295     delete page;
1296     view->deref();
1297
1298     SET_NATIVE_FRAME(env, obj, 0);
1299 #if ENABLE(WDS)
1300     WDS::server()->removeFrame(pFrame);
1301 #endif
1302 }
1303
1304 static void LoadUrl(JNIEnv *env, jobject obj, jstring url, jobject headers)
1305 {
1306 #ifdef ANDROID_INSTRUMENT
1307     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1308 #endif
1309     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1310     LOG_ASSERT(pFrame, "nativeLoadUrl must take a valid frame pointer!");
1311
1312     WTF::String webcoreUrl = jstringToWtfString(env, url);
1313     WebCore::KURL kurl(WebCore::KURL(), webcoreUrl);
1314     WebCore::ResourceRequest request(kurl);
1315     if (headers) {
1316         // dalvikvm will raise exception if any of these fail
1317         jclass mapClass = env->FindClass("java/util/Map");
1318         jmethodID entrySet = env->GetMethodID(mapClass, "entrySet",
1319                 "()Ljava/util/Set;");
1320         jobject set = env->CallObjectMethod(headers, entrySet);
1321
1322         jclass setClass = env->FindClass("java/util/Set");
1323         jmethodID iterator = env->GetMethodID(setClass, "iterator",
1324                 "()Ljava/util/Iterator;");
1325         jobject iter = env->CallObjectMethod(set, iterator);
1326
1327         jclass iteratorClass = env->FindClass("java/util/Iterator");
1328         jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z");
1329         jmethodID next = env->GetMethodID(iteratorClass, "next",
1330                 "()Ljava/lang/Object;");
1331         jclass entryClass = env->FindClass("java/util/Map$Entry");
1332         jmethodID getKey = env->GetMethodID(entryClass, "getKey",
1333                 "()Ljava/lang/Object;");
1334         jmethodID getValue = env->GetMethodID(entryClass, "getValue",
1335                 "()Ljava/lang/Object;");
1336
1337         while (env->CallBooleanMethod(iter, hasNext)) {
1338             jobject entry = env->CallObjectMethod(iter, next);
1339             jstring key = (jstring) env->CallObjectMethod(entry, getKey);
1340             jstring value = (jstring) env->CallObjectMethod(entry, getValue);
1341             request.setHTTPHeaderField(jstringToWtfString(env, key), jstringToWtfString(env, value));
1342             env->DeleteLocalRef(entry);
1343             env->DeleteLocalRef(key);
1344             env->DeleteLocalRef(value);
1345         }
1346
1347         env->DeleteLocalRef(entryClass);
1348         env->DeleteLocalRef(iteratorClass);
1349         env->DeleteLocalRef(iter);
1350         env->DeleteLocalRef(setClass);
1351         env->DeleteLocalRef(set);
1352         env->DeleteLocalRef(mapClass);
1353     }
1354     LOGV("LoadUrl %s", kurl.string().latin1().data());
1355     pFrame->loader()->load(request, false);
1356 }
1357
1358 static void PostUrl(JNIEnv *env, jobject obj, jstring url, jbyteArray postData)
1359 {
1360 #ifdef ANDROID_INSTRUMENT
1361     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1362 #endif
1363     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1364     LOG_ASSERT(pFrame, "nativePostUrl must take a valid frame pointer!");
1365
1366     WebCore::KURL kurl(WebCore::KURL(), jstringToWtfString(env, url));
1367     WebCore::ResourceRequest request(kurl);
1368     request.setHTTPMethod("POST");
1369     request.setHTTPContentType("application/x-www-form-urlencoded");
1370
1371     if (postData) {
1372         jsize size = env->GetArrayLength(postData);
1373         jbyte* bytes = env->GetByteArrayElements(postData, NULL);
1374         RefPtr<FormData> formData = FormData::create((const void*)bytes, size);
1375         // the identifier uses the same logic as generateFormDataIdentifier() in
1376         // HTMLFormElement.cpp
1377         formData->setIdentifier(static_cast<int64_t>(WTF::currentTime() * 1000000.0));
1378         request.setHTTPBody(formData);
1379         env->ReleaseByteArrayElements(postData, bytes, 0);
1380     }
1381
1382     LOGV("PostUrl %s", kurl.string().latin1().data());
1383     WebCore::FrameLoadRequest frameRequest(request);
1384     pFrame->loader()->loadFrameRequest(frameRequest, false, false, 0, 0, WebCore::SendReferrer);
1385 }
1386
1387 static void LoadData(JNIEnv *env, jobject obj, jstring baseUrl, jstring data,
1388         jstring mimeType, jstring encoding, jstring failUrl)
1389 {
1390 #ifdef ANDROID_INSTRUMENT
1391     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1392 #endif
1393     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1394     LOG_ASSERT(pFrame, "nativeLoadData must take a valid frame pointer!");
1395
1396     // Setup the resource request
1397     WebCore::ResourceRequest request(jstringToWtfString(env, baseUrl));
1398
1399     // Setup the substituteData
1400     const char* dataStr = env->GetStringUTFChars(data, NULL);
1401     WTF::PassRefPtr<WebCore::SharedBuffer> sharedBuffer =
1402         WebCore::SharedBuffer::create();
1403     LOG_ASSERT(dataStr, "nativeLoadData has a null data string.");
1404     sharedBuffer->append(dataStr, strlen(dataStr));
1405     env->ReleaseStringUTFChars(data, dataStr);
1406
1407     WebCore::SubstituteData substituteData(sharedBuffer,
1408             jstringToWtfString(env, mimeType), jstringToWtfString(env, encoding),
1409             WebCore::KURL(ParsedURLString, jstringToWtfString(env, failUrl)));
1410
1411     // Perform the load
1412     pFrame->loader()->load(request, substituteData, false);
1413 }
1414
1415 static void StopLoading(JNIEnv *env, jobject obj)
1416 {
1417 #ifdef ANDROID_INSTRUMENT
1418     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1419 #endif
1420     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1421     LOG_ASSERT(pFrame, "nativeStopLoading must take a valid frame pointer!");
1422     LOGV("::WebCore:: stopLoading %p", pFrame);
1423
1424     // Stop loading the page and do not send an unload event
1425     pFrame->loader()->stopForUserCancel();
1426 }
1427
1428 #if ENABLE(ARCHIVE)
1429 static String saveArchiveAutoname(String basename, String name, String extension) {
1430     if (name.isNull() || name.isEmpty()) {
1431         name = String("index");
1432     }
1433
1434     String testname = basename;
1435     testname.append(name);
1436     testname.append(extension);
1437
1438     errno = 0;
1439     struct stat permissions;
1440     if (stat(testname.utf8().data(), &permissions) < 0) {
1441         if (errno == ENOENT)
1442             return testname;
1443         return String();
1444     }
1445
1446     const int maxAttempts = 100;
1447     for (int i = 1; i < maxAttempts; i++) {
1448         String testname = basename;
1449         testname.append(name);
1450         testname.append("-");
1451         testname.append(String::number(i));
1452         testname.append(extension);
1453
1454         errno = 0;
1455         if (stat(testname.utf8().data(), &permissions) < 0) {
1456             if (errno == ENOENT)
1457                 return testname;
1458             return String();
1459         }
1460     }
1461
1462     return String();
1463 }
1464 #endif
1465
1466 static jstring SaveWebArchive(JNIEnv *env, jobject obj, jstring basename, jboolean autoname)
1467 {
1468 #if ENABLE(ARCHIVE)
1469     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1470     LOG_ASSERT(pFrame, "nativeSaveWebArchive must take a valid frame pointer!");
1471     String mimeType = pFrame->loader()->documentLoader()->mainResource()->mimeType();
1472     if ((mimeType != "text/html") && (mimeType != "application/xhtml+xml"))
1473         return NULL;
1474
1475     const char* basenameNative = getCharactersFromJStringInEnv(env, basename);
1476     String basenameString = String::fromUTF8(basenameNative);
1477     String filename;
1478
1479     if (autoname) {
1480         String name = pFrame->loader()->documentLoader()->originalURL().lastPathComponent();
1481         String extension = String(".webarchivexml");
1482         filename = saveArchiveAutoname(basenameString, name, extension);
1483     } else {
1484         filename = basenameString;
1485     }
1486
1487     if (filename.isNull() || filename.isEmpty()) {
1488         LOGD("saveWebArchive: Failed to select a filename to save.");
1489         releaseCharactersForJStringInEnv(env, basename, basenameNative);
1490         return NULL;
1491     }
1492
1493     const int noCompression = 0;
1494     xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.utf8().data(), noCompression);
1495     if (writer == NULL) {
1496         LOGD("saveWebArchive: Failed to initialize xml writer.");
1497         releaseCharactersForJStringInEnv(env, basename, basenameNative);
1498         return NULL;
1499     }
1500
1501     RefPtr<WebArchiveAndroid> archive = WebCore::WebArchiveAndroid::create(pFrame);
1502
1503     bool result = archive->saveWebArchive(writer);
1504
1505     releaseCharactersForJStringInEnv(env, basename, basenameNative);
1506     xmlFreeTextWriter(writer);
1507
1508     if (result)
1509         return wtfStringToJstring(env, filename);
1510
1511     return NULL;
1512 #endif
1513 }
1514
1515 static jstring ExternalRepresentation(JNIEnv *env, jobject obj)
1516 {
1517 #ifdef ANDROID_INSTRUMENT
1518     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1519 #endif
1520     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1521     LOG_ASSERT(pFrame, "android_webcore_nativeExternalRepresentation must take a valid frame pointer!");
1522
1523     // Request external representation of the render tree
1524     WTF::String renderDump = WebCore::externalRepresentation(pFrame);
1525     return wtfStringToJstring(env, renderDump);
1526 }
1527
1528 static StringBuilder FrameAsText(WebCore::Frame *pFrame, jboolean dumpChildFrames) {
1529     StringBuilder renderDump;
1530     if (!pFrame)
1531         return renderDump;
1532     WebCore::Element *documentElement = pFrame->document()->documentElement();
1533     if (!documentElement)
1534         return renderDump;
1535     if (pFrame->tree()->parent()) {
1536         renderDump.append("\n--------\nFrame: '");
1537         renderDump.append(pFrame->tree()->name());
1538         renderDump.append("'\n--------\n");
1539     }
1540     renderDump.append(((WebCore::HTMLElement*)documentElement)->innerText());
1541     renderDump.append("\n");
1542     if (dumpChildFrames) {
1543         for (unsigned i = 0; i < pFrame->tree()->childCount(); ++i) {
1544             renderDump.append(FrameAsText(pFrame->tree()->child(i), dumpChildFrames).toString());
1545         }
1546     }
1547     return renderDump;
1548 }
1549
1550 static jstring DocumentAsText(JNIEnv *env, jobject obj)
1551 {
1552 #ifdef ANDROID_INSTRUMENT
1553     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1554 #endif
1555     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1556     LOG_ASSERT(pFrame, "android_webcore_nativeDocumentAsText must take a valid frame pointer!");
1557
1558     WTF::String renderDump = FrameAsText(pFrame, false /* dumpChildFrames */).toString();
1559     return wtfStringToJstring(env, renderDump);
1560 }
1561
1562 static jstring ChildFramesAsText(JNIEnv *env, jobject obj)
1563 {
1564 #ifdef ANDROID_INSTRUMENT
1565     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1566 #endif
1567     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1568     LOG_ASSERT(pFrame, "android_webcore_nativeDocumentAsText must take a valid frame pointer!");
1569
1570     StringBuilder renderDumpBuilder;
1571     for (unsigned i = 0; i < pFrame->tree()->childCount(); ++i) {
1572         renderDumpBuilder.append(FrameAsText(pFrame->tree()->child(i), true /* dumpChildFrames */).toString());
1573     }
1574     WTF::String renderDump = renderDumpBuilder.toString();
1575     return wtfStringToJstring(env, renderDump);
1576 }
1577
1578 static void Reload(JNIEnv *env, jobject obj, jboolean allowStale)
1579 {
1580 #ifdef ANDROID_INSTRUMENT
1581     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1582 #endif
1583     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1584     LOG_ASSERT(pFrame, "nativeReload must take a valid frame pointer!");
1585
1586     WebCore::FrameLoader* loader = pFrame->loader();
1587     if (allowStale) {
1588         // load the current page with FrameLoadTypeIndexedBackForward so that it
1589         // will use cache when it is possible
1590         WebCore::Page* page = pFrame->page();
1591         WebCore::HistoryItem* item = page->backForwardList()->currentItem();
1592         if (item)
1593             page->goToItem(item, FrameLoadTypeIndexedBackForward);
1594     } else
1595         loader->reload(true);
1596 }
1597
1598 static void GoBackOrForward(JNIEnv *env, jobject obj, jint pos)
1599 {
1600 #ifdef ANDROID_INSTRUMENT
1601     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1602 #endif
1603     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1604     LOG_ASSERT(pFrame, "nativeGoBackOrForward must take a valid frame pointer!");
1605
1606     if (pos == 1)
1607         pFrame->page()->goForward();
1608     else if (pos == -1)
1609         pFrame->page()->goBack();
1610     else
1611         pFrame->page()->goBackOrForward(pos);
1612 }
1613
1614 static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj, jstring script)
1615 {
1616 #ifdef ANDROID_INSTRUMENT
1617     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1618 #endif
1619     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1620     LOG_ASSERT(pFrame, "stringByEvaluatingJavaScriptFromString must take a valid frame pointer!");
1621
1622     WebCore::ScriptValue value =
1623             pFrame->script()->executeScript(jstringToWtfString(env, script), true);
1624     WTF::String result = WTF::String();
1625     ScriptState* scriptState = mainWorldScriptState(pFrame);
1626     if (!value.getString(scriptState, result))
1627         return NULL;
1628     return wtfStringToJstring(env, result);
1629 }
1630
1631 // Wrap the JavaInstance used when binding custom javascript interfaces. Use a
1632 // weak reference so that the gc can collect the WebView. Override virtualBegin
1633 // and virtualEnd and swap the weak reference for the real object.
1634 class WeakJavaInstance : public JavaInstance {
1635 public:
1636 #if USE(JSC)
1637     static PassRefPtr<WeakJavaInstance> create(jobject obj, PassRefPtr<RootObject> root)
1638     {
1639         return adoptRef(new WeakJavaInstance(obj, root));
1640     }
1641 #elif USE(V8)
1642     static PassRefPtr<WeakJavaInstance> create(jobject obj)
1643     {
1644         return adoptRef(new WeakJavaInstance(obj));
1645     }
1646 #endif
1647
1648 private:
1649 #if USE(JSC)
1650     WeakJavaInstance(jobject instance, PassRefPtr<RootObject> rootObject)
1651         : JavaInstance(instance, rootObject)
1652 #elif USE(V8)
1653     WeakJavaInstance(jobject instance)
1654         : JavaInstance(instance)
1655 #endif
1656         , m_beginEndDepth(0)
1657     {
1658         JNIEnv* env = getJNIEnv();
1659         // JavaInstance creates a global ref to instance in its constructor.
1660         env->DeleteGlobalRef(m_instance->instance());
1661         // Set the object to a weak reference.
1662         m_instance->setInstance(env->NewWeakGlobalRef(instance));
1663     }
1664     ~WeakJavaInstance()
1665     {
1666         JNIEnv* env = getJNIEnv();
1667         // Store the weak reference so we can delete it later.
1668         jweak weak = m_instance->instance();
1669         // The JavaInstance destructor attempts to delete the global ref stored
1670         // in m_instance. Since we replaced it in our constructor with a weak
1671         // reference, restore the global ref here so the vm will not complain.
1672         m_instance->setInstance(env->NewGlobalRef(
1673                 getRealObject(env, m_instance->instance()).get()));
1674         // Delete the weak reference.
1675         env->DeleteWeakGlobalRef(weak);
1676     }
1677
1678     virtual void virtualBegin()
1679     {
1680         if (m_beginEndDepth++ > 0)
1681             return;
1682         m_weakRef = m_instance->instance();
1683         JNIEnv* env = getJNIEnv();
1684         // This is odd. getRealObject returns an AutoJObject which is used to
1685         // cleanly create and delete a local reference. But, here we need to
1686         // maintain the local reference across calls to virtualBegin() and
1687         // virtualEnd(). So, release the local reference from the AutoJObject
1688         // and delete the local reference in virtualEnd().
1689         m_realObject = getRealObject(env, m_weakRef).release();
1690         // Point to the real object
1691         m_instance->setInstance(m_realObject);
1692         // Call the base class method
1693         INHERITED::virtualBegin();
1694     }
1695
1696     virtual void virtualEnd()
1697     {
1698         if (--m_beginEndDepth > 0)
1699             return;
1700         // Call the base class method first to pop the local frame.
1701         INHERITED::virtualEnd();
1702         // Get rid of the local reference to the real object.
1703         getJNIEnv()->DeleteLocalRef(m_realObject);
1704         // Point back to the WeakReference.
1705         m_instance->setInstance(m_weakRef);
1706     }
1707
1708 private:
1709     typedef JavaInstance INHERITED;
1710     jobject m_realObject;
1711     jweak m_weakRef;
1712     // The current depth of nested calls to virtualBegin and virtualEnd.
1713     int m_beginEndDepth;
1714 };
1715
1716 static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePointer,
1717         jobject javascriptObj, jstring interfaceName)
1718 {
1719 #ifdef ANDROID_INSTRUMENT
1720     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1721 #endif
1722     WebCore::Frame* pFrame = 0;
1723     if (nativeFramePointer == 0)
1724         pFrame = GET_NATIVE_FRAME(env, obj);
1725     else
1726         pFrame = (WebCore::Frame*)nativeFramePointer;
1727     LOG_ASSERT(pFrame, "nativeAddJavascriptInterface must take a valid frame pointer!");
1728
1729     JavaVM* vm;
1730     env->GetJavaVM(&vm);
1731     LOGV("::WebCore:: addJSInterface: %p", pFrame);
1732
1733 #if USE(JSC)
1734     // Copied from qwebframe.cpp
1735     JSC::JSLock lock(JSC::SilenceAssertionsOnly);
1736     WebCore::JSDOMWindow *window = WebCore::toJSDOMWindow(pFrame, mainThreadNormalWorld());
1737     if (window) {
1738         RootObject *root = pFrame->script()->bindingRootObject();
1739         setJavaVM(vm);
1740         // Add the binding to JS environment
1741         JSC::ExecState* exec = window->globalExec();
1742         JSC::JSObject* addedObject = WeakJavaInstance::create(javascriptObj,
1743                 root)->createRuntimeObject(exec);
1744         const jchar* s = env->GetStringChars(interfaceName, NULL);
1745         if (s) {
1746             // Add the binding name to the window's table of child objects.
1747             JSC::PutPropertySlot slot;
1748             window->put(exec, JSC::Identifier(exec, (const UChar *)s,
1749                     env->GetStringLength(interfaceName)), addedObject, slot);
1750             env->ReleaseStringChars(interfaceName, s);
1751             checkException(env);
1752         }
1753     }
1754 #elif USE(V8)
1755     if (pFrame) {
1756         RefPtr<JavaInstance> addedObject = WeakJavaInstance::create(javascriptObj);
1757         const char* name = getCharactersFromJStringInEnv(env, interfaceName);
1758         // Pass ownership of the added object to bindToWindowObject.
1759         NPObject* npObject = JavaInstanceToNPObject(addedObject.get());
1760         pFrame->script()->bindToWindowObject(pFrame, name, npObject);
1761         // bindToWindowObject calls NPN_RetainObject on the
1762         // returned one (see createV8ObjectForNPObject in V8NPObject.cpp).
1763         // bindToWindowObject also increases obj's ref count and decreases
1764         // the ref count when the object is not reachable from JavaScript
1765         // side. Code here must release the reference count increased by
1766         // bindToWindowObject.
1767
1768         // Note that while this function is declared in WebCore/bridge/npruntime.h, for V8 builds
1769         // we use WebCore/bindings/v8/npruntime.cpp (rather than
1770         // WebCore/bridge/npruntime.cpp), so the function is implemented there.
1771         // TODO: Combine the two versions of these NPAPI files.
1772         NPN_ReleaseObject(npObject);
1773         releaseCharactersForJString(interfaceName, name);
1774     }
1775 #endif
1776
1777 }
1778
1779 static void SetCacheDisabled(JNIEnv *env, jobject obj, jboolean disabled)
1780 {
1781 #ifdef ANDROID_INSTRUMENT
1782     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1783 #endif
1784     WebCore::cache()->setDisabled(disabled);
1785 }
1786
1787 static jboolean CacheDisabled(JNIEnv *env, jobject obj)
1788 {
1789 #ifdef ANDROID_INSTRUMENT
1790     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1791 #endif
1792     return WebCore::cache()->disabled();
1793 }
1794
1795 static void ClearWebCoreCache()
1796 {
1797     if (!WebCore::cache()->disabled()) {
1798         // Disabling the cache will remove all resources from the cache.  They may
1799         // still live on if they are referenced by some Web page though.
1800         WebCore::cache()->setDisabled(true);
1801         WebCore::cache()->setDisabled(false);
1802     }
1803
1804     // clear page cache
1805     int pageCapacity = WebCore::pageCache()->capacity();
1806     // Setting size to 0, makes all pages be released.
1807     WebCore::pageCache()->setCapacity(0);
1808     WebCore::pageCache()->releaseAutoreleasedPagesNow();
1809     WebCore::pageCache()->setCapacity(pageCapacity);
1810 }
1811
1812 static void ClearWebViewCache()
1813 {
1814 #if USE(CHROME_NETWORK_STACK)
1815     WebCache::get(false /*privateBrowsing*/)->clear();
1816 #else
1817     // The Android network stack provides a WebView cache in CacheManager.java.
1818     // Clearing this is handled entirely Java-side.
1819 #endif
1820 }
1821
1822 static void ClearCache(JNIEnv *env, jobject obj)
1823 {
1824 #ifdef ANDROID_INSTRUMENT
1825     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1826 #if USE(JSC)
1827     JSC::JSLock lock(false);
1828     JSC::Heap::Statistics jsHeapStatistics = WebCore::JSDOMWindow::commonJSGlobalData()->heap.statistics();
1829     LOGD("About to gc and JavaScript heap size is %d and has %d bytes free",
1830             jsHeapStatistics.size, jsHeapStatistics.free);
1831 #endif  // USE(JSC)
1832     LOGD("About to clear cache and current cache has %d bytes live and %d bytes dead",
1833             cache()->getLiveSize(), cache()->getDeadSize());
1834 #endif  // ANDROID_INSTRUMENT
1835     ClearWebCoreCache();
1836     ClearWebViewCache();
1837 #if USE(JSC)
1838     // force JavaScript to GC when clear cache
1839     WebCore::gcController().garbageCollectSoon();
1840 #elif USE(V8)
1841     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1842     pFrame->script()->lowMemoryNotification();
1843 #endif  // USE(JSC)
1844 }
1845
1846 static jboolean DocumentHasImages(JNIEnv *env, jobject obj)
1847 {
1848 #ifdef ANDROID_INSTRUMENT
1849     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1850 #endif
1851     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1852     LOG_ASSERT(pFrame, "DocumentHasImages must take a valid frame pointer!");
1853
1854     return pFrame->document()->images()->length() > 0;
1855 }
1856
1857 static jboolean HasPasswordField(JNIEnv *env, jobject obj)
1858 {
1859 #ifdef ANDROID_INSTRUMENT
1860     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1861 #endif
1862     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1863     LOG_ASSERT(pFrame, "HasPasswordField must take a valid frame pointer!");
1864
1865     bool found = false;
1866     WTF::PassRefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms();
1867     WebCore::Node* node = form->firstItem();
1868     // Null/Empty namespace means that node is not created in HTMLFormElement
1869     // class, but just normal Element class.
1870     while (node && !found && !node->namespaceURI().isNull() &&
1871            !node->namespaceURI().isEmpty()) {
1872         const WTF::Vector<WebCore::HTMLFormControlElement*>& elements =
1873             ((WebCore::HTMLFormElement*)node)->associatedElements();
1874         size_t size = elements.size();
1875         for (size_t i = 0; i< size && !found; i++) {
1876             WebCore::HTMLFormControlElement* e = elements[i];
1877             if (e->hasLocalName(WebCore::HTMLNames::inputTag)) {
1878                 if (static_cast<WebCore::HTMLInputElement*>(e)->isPasswordField())
1879                     found = true;
1880             }
1881         }
1882         node = form->nextItem();
1883     }
1884     return found;
1885 }
1886
1887 static jobjectArray GetUsernamePassword(JNIEnv *env, jobject obj)
1888 {
1889 #ifdef ANDROID_INSTRUMENT
1890     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1891 #endif
1892     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1893     LOG_ASSERT(pFrame, "GetUsernamePassword must take a valid frame pointer!");
1894     jobjectArray strArray = NULL;
1895     WTF::String username;
1896     WTF::String password;
1897     if (WebFrame::getWebFrame(pFrame)->getUsernamePasswordFromDom(pFrame, username, password)) {
1898         jclass stringClass = env->FindClass("java/lang/String");
1899         strArray = env->NewObjectArray(2, stringClass, NULL);
1900         env->DeleteLocalRef(stringClass);
1901         env->SetObjectArrayElement(strArray, 0, wtfStringToJstring(env, username));
1902         env->SetObjectArrayElement(strArray, 1, wtfStringToJstring(env, password));
1903     }
1904     return strArray;
1905 }
1906
1907 static void SetUsernamePassword(JNIEnv *env, jobject obj,
1908     jstring username, jstring password)
1909 {
1910 #ifdef ANDROID_INSTRUMENT
1911     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1912 #endif
1913     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1914     LOG_ASSERT(pFrame, "SetUsernamePassword must take a valid frame pointer!");
1915
1916     WebCore::HTMLInputElement* usernameEle = NULL;
1917     WebCore::HTMLInputElement* passwordEle = NULL;
1918     bool found = false;
1919     WTF::PassRefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms();
1920     WebCore::Node* node = form->firstItem();
1921     while (node && !found && !node->namespaceURI().isNull() &&
1922            !node->namespaceURI().isEmpty()) {
1923         const WTF::Vector<WebCore::HTMLFormControlElement*>& elements =
1924             ((WebCore::HTMLFormElement*)node)->associatedElements();
1925         size_t size = elements.size();
1926         for (size_t i = 0; i< size && !found; i++) {
1927             WebCore::HTMLFormControlElement* e = elements[i];
1928             if (e->hasLocalName(WebCore::HTMLNames::inputTag)) {
1929                 WebCore::HTMLInputElement* input = (WebCore::HTMLInputElement*)e;
1930                 if (input->autoComplete() == false)
1931                     continue;
1932                 if (input->isPasswordField())
1933                     passwordEle = input;
1934                 else if (input->isTextField() || input->isEmailField())
1935                     usernameEle = input;
1936                 if (usernameEle != NULL && passwordEle != NULL)
1937                     found = true;
1938             }
1939         }
1940         node = form->nextItem();
1941     }
1942     if (found) {
1943         usernameEle->setValue(jstringToWtfString(env, username));
1944         passwordEle->setValue(jstringToWtfString(env, password));
1945     }
1946 }
1947
1948 void
1949 WebFrame::saveFormData(HTMLFormElement* form)
1950 {
1951     if (form->autoComplete()) {
1952         JNIEnv* env = getJNIEnv();
1953         jclass mapClass = env->FindClass("java/util/HashMap");
1954         LOG_ASSERT(mapClass, "Could not find HashMap class!");
1955         jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V");
1956         LOG_ASSERT(init, "Could not find constructor for HashMap");
1957         jobject hashMap = env->NewObject(mapClass, init, 1);
1958         LOG_ASSERT(hashMap, "Could not create a new HashMap");
1959         jmethodID put = env->GetMethodID(mapClass, "put",
1960                 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
1961         LOG_ASSERT(put, "Could not find put method on HashMap");
1962         WTF::Vector<WebCore::HTMLFormControlElement*> elements = form->associatedElements();
1963         size_t size = elements.size();
1964         for (size_t i = 0; i < size; i++) {
1965             WebCore::HTMLFormControlElement* e = elements[i];
1966             if (e->hasTagName(WebCore::HTMLNames::inputTag)) {
1967                 WebCore::HTMLInputElement* input = static_cast<WebCore::HTMLInputElement*>(e);
1968                 if (input->isTextField() && !input->isPasswordField()
1969                         && input->autoComplete()) {
1970                     WTF::String value = input->value();
1971                     int len = value.length();
1972                     if (len) {
1973                         const WTF::AtomicString& name = input->name();
1974                         jstring key = wtfStringToJstring(env, name);
1975                         jstring val = wtfStringToJstring(env, value);
1976                         LOG_ASSERT(key && val, "name or value not set");
1977                         env->CallObjectMethod(hashMap, put, key, val);
1978                         env->DeleteLocalRef(key);
1979                         env->DeleteLocalRef(val);
1980                     }
1981                 }
1982             }
1983         }
1984         env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSaveFormData, hashMap);
1985         env->DeleteLocalRef(hashMap);
1986         env->DeleteLocalRef(mapClass);
1987     }
1988 }
1989
1990 static void OrientationChanged(JNIEnv *env, jobject obj, int orientation)
1991 {
1992 #ifdef ANDROID_INSTRUMENT
1993     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1994 #endif
1995     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1996     LOGV("Sending orientation: %d", orientation);
1997     pFrame->sendOrientationChangeEvent(orientation);
1998 }
1999
2000 #if USE(CHROME_NETWORK_STACK)
2001
2002 static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword)
2003 {
2004     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
2005     std::string username = jstringToStdString(env, jUsername);
2006     std::string password = jstringToStdString(env, jPassword);
2007     client->setAuth(username, password);
2008 }
2009
2010 static void AuthenticationCancel(JNIEnv *env, jobject obj, int handle)
2011 {
2012     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
2013     client->cancelAuth();
2014 }
2015
2016 static void SslCertErrorProceed(JNIEnv *env, jobject obj, int handle)
2017 {
2018     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
2019     client->proceedSslCertError();
2020 }
2021
2022 static void SslCertErrorCancel(JNIEnv *env, jobject obj, int handle, int cert_error)
2023 {
2024     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
2025     client->cancelSslCertError(cert_error);
2026 }
2027
2028 #else
2029
2030 static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword)
2031 {
2032     LOGW("Chromium authentication API called, but libchromium is not available");
2033 }
2034
2035 static void AuthenticationCancel(JNIEnv *env, jobject obj, int handle)
2036 {
2037     LOGW("Chromium authentication API called, but libchromium is not available");
2038 }
2039
2040 static void SslCertErrorProceed(JNIEnv *env, jobject obj, int handle)
2041 {
2042     LOGW("Chromium SSL API called, but libchromium is not available");
2043 }
2044
2045 static void SslCertErrorCancel(JNIEnv *env, jobject obj, int handle, int cert_error)
2046 {
2047     LOGW("Chromium SSL API called, but libchromium is not available");
2048 }
2049
2050 #endif // USE(CHROME_NETWORK_STACK)
2051
2052 // ----------------------------------------------------------------------------
2053
2054 /*
2055  * JNI registration.
2056  */
2057 static JNINativeMethod gBrowserFrameNativeMethods[] = {
2058     /* name, signature, funcPtr */
2059     { "nativeCallPolicyFunction", "(II)V",
2060         (void*) CallPolicyFunction },
2061     { "nativeCreateFrame", "(Landroid/webkit/WebViewCore;Landroid/content/res/AssetManager;Landroid/webkit/WebBackForwardList;)V",
2062         (void*) CreateFrame },
2063     { "nativeDestroyFrame", "()V",
2064         (void*) DestroyFrame },
2065     { "nativeStopLoading", "()V",
2066         (void*) StopLoading },
2067     { "nativeLoadUrl", "(Ljava/lang/String;Ljava/util/Map;)V",
2068         (void*) LoadUrl },
2069     { "nativePostUrl", "(Ljava/lang/String;[B)V",
2070         (void*) PostUrl },
2071     { "nativeLoadData", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
2072         (void*) LoadData },
2073     { "nativeSaveWebArchive", "(Ljava/lang/String;Z)Ljava/lang/String;",
2074         (void*) SaveWebArchive },
2075     { "externalRepresentation", "()Ljava/lang/String;",
2076         (void*) ExternalRepresentation },
2077     { "documentAsText", "()Ljava/lang/String;",
2078         (void*) DocumentAsText },
2079     { "childFramesAsText", "()Ljava/lang/String;",
2080         (void*) ChildFramesAsText },
2081     { "reload", "(Z)V",
2082         (void*) Reload },
2083     { "nativeGoBackOrForward", "(I)V",
2084         (void*) GoBackOrForward },
2085     { "nativeAddJavascriptInterface", "(ILjava/lang/Object;Ljava/lang/String;)V",
2086         (void*) AddJavascriptInterface },
2087     { "stringByEvaluatingJavaScriptFromString",
2088             "(Ljava/lang/String;)Ljava/lang/String;",
2089         (void*) StringByEvaluatingJavaScriptFromString },
2090     { "setCacheDisabled", "(Z)V",
2091         (void*) SetCacheDisabled },
2092     { "cacheDisabled", "()Z",
2093         (void*) CacheDisabled },
2094     { "clearCache", "()V",
2095         (void*) ClearCache },
2096     { "documentHasImages", "()Z",
2097         (void*) DocumentHasImages },
2098     { "hasPasswordField", "()Z",
2099         (void*) HasPasswordField },
2100     { "getUsernamePassword", "()[Ljava/lang/String;",
2101         (void*) GetUsernamePassword },
2102     { "setUsernamePassword", "(Ljava/lang/String;Ljava/lang/String;)V",
2103         (void*) SetUsernamePassword },
2104     { "nativeOrientationChanged", "(I)V",
2105         (void*) OrientationChanged },
2106     { "nativeAuthenticationProceed", "(ILjava/lang/String;Ljava/lang/String;)V",
2107         (void*) AuthenticationProceed },
2108     { "nativeAuthenticationCancel", "(I)V",
2109         (void*) AuthenticationCancel },
2110     { "nativeSslCertErrorProceed", "(I)V",
2111         (void*) SslCertErrorProceed },
2112     { "nativeSslCertErrorCancel", "(II)V",
2113         (void*) SslCertErrorCancel },
2114 };
2115
2116 int registerWebFrame(JNIEnv* env)
2117 {
2118     jclass clazz = env->FindClass("android/webkit/BrowserFrame");
2119     LOG_ASSERT(clazz, "Cannot find BrowserFrame");
2120     gFrameField = env->GetFieldID(clazz, "mNativeFrame", "I");
2121     LOG_ASSERT(gFrameField, "Cannot find mNativeFrame on BrowserFrame");
2122     env->DeleteLocalRef(clazz);
2123
2124     return jniRegisterNativeMethods(env, "android/webkit/BrowserFrame",
2125             gBrowserFrameNativeMethods, NELEM(gBrowserFrameNativeMethods));
2126 }
2127
2128 } /* namespace android */