• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "AtomicString.h"
33 #include "BackForwardList.h"
34 #include "Cache.h"
35 #include "CString.h"
36 #include "Chrome.h"
37 #include "ChromeClientAndroid.h"
38 #include "ContextMenuClientAndroid.h"
39 #include "Document.h"
40 #include "DocumentLoader.h"
41 #include "DragClientAndroid.h"
42 #include "EditorClientAndroid.h"
43 #include "Element.h"
44 #include "Font.h"
45 #include "FormState.h"
46 #include "Frame.h"
47 #include "FrameLoader.h"
48 #include "FrameLoaderClientAndroid.h"
49 #include "FrameLoadRequest.h"
50 #include "FrameTree.h"
51 #include "FrameView.h"
52 #include "GraphicsContext.h"
53 #include "HistoryItem.h"
54 #include "HTMLCollection.h"
55 #include "HTMLElement.h"
56 #include "HTMLFormElement.h"
57 #include "HTMLInputElement.h"
58 #include "HTMLNames.h"
59 #include "IconDatabase.h"
60 #include "Image.h"
61 #include "InspectorClientAndroid.h"
62 #include "KURL.h"
63 #include "Page.h"
64 #include "PageCache.h"
65 #include "PlatformString.h"
66 #include "RenderPart.h"
67 #include "RenderSkinAndroid.h"
68 #include "RenderTreeAsText.h"
69 #include "RenderView.h"
70 #include "ResourceHandle.h"
71 #include "ResourceHandleInternal.h"
72 #include "ScriptController.h"
73 #include "ScriptValue.h"
74 #include "SecurityOrigin.h"
75 #include "SelectionController.h"
76 #include "Settings.h"
77 #include "SubstituteData.h"
78 #include "WebCoreJni.h"
79 #include "WebCoreResourceLoader.h"
80 #include "WebHistory.h"
81 #include "WebIconDatabase.h"
82 #include "WebFrameView.h"
83 #include "WebViewCore.h"
84 #include "android_graphics.h"
85 #include "jni.h"
86 #include "wds/DebugServer.h"
87 
88 #include <JNIUtility.h>
89 #include <JNIHelp.h>
90 #include <SkGraphics.h>
91 #include <android_runtime/android_util_AssetManager.h>
92 #include <utils/misc.h>
93 #include <utils/AssetManager.h>
94 #include <wtf/CurrentTime.h>
95 #include <wtf/Platform.h>
96 
97 #if USE(JSC)
98 #include "GCController.h"
99 #include "JSDOMWindow.h"
100 #include "JavaInstanceJSC.h"
101 #include <runtime_object.h>
102 #include <runtime_root.h>
103 #include <runtime/JSLock.h>
104 #elif USE(V8)
105 #include "JavaNPObjectV8.h"
106 #include "JavaInstanceV8.h"
107 #include "V8Counters.h"
108 #endif  // USE(JSC)
109 
110 #ifdef ANDROID_INSTRUMENT
111 #include "TimeCounter.h"
112 #endif
113 
114 using namespace JSC::Bindings;
115 
116 static String* gUploadFileLabel;
117 static String* gResetLabel;
118 static String* gSubmitLabel;
119 
globalLocalizedName(WebCore::PlatformBridge::rawResId resId)120 String* WebCore::PlatformBridge::globalLocalizedName(
121         WebCore::PlatformBridge::rawResId resId)
122 {
123     switch (resId) {
124     case WebCore::PlatformBridge::FileUploadLabel:
125         return gUploadFileLabel;
126     case WebCore::PlatformBridge::ResetLabel:
127         return gResetLabel;
128     case WebCore::PlatformBridge::SubmitLabel:
129         return gSubmitLabel;
130     default:
131         return 0;
132     }
133 }
134 /**
135  * Instantiate the localized name desired.
136  */
initGlobalLocalizedName(WebCore::PlatformBridge::rawResId resId,android::WebFrame * webFrame)137 void initGlobalLocalizedName(WebCore::PlatformBridge::rawResId resId,
138         android::WebFrame* webFrame)
139 {
140     String** pointer;
141     switch (resId) {
142     case WebCore::PlatformBridge::FileUploadLabel:
143         pointer = &gUploadFileLabel;
144         break;
145     case WebCore::PlatformBridge::ResetLabel:
146         pointer = &gResetLabel;
147         break;
148     case WebCore::PlatformBridge::SubmitLabel:
149         pointer = &gSubmitLabel;
150         break;
151     default:
152         return;
153     }
154     if (!(*pointer) && webFrame) {
155         (*pointer) = new String(webFrame->getRawResourceFilename(resId).impl());
156     }
157 }
158 
159 namespace android {
160 
161 // ----------------------------------------------------------------------------
162 
163 #define WEBCORE_MEMORY_CAP 15 * 1024 * 1024
164 
165 // ----------------------------------------------------------------------------
166 
167 struct WebFrame::JavaBrowserFrame
168 {
169     jweak       mObj;
170     jweak       mHistoryList; // WebBackForwardList object
171     jmethodID   mStartLoadingResource;
172     jmethodID   mLoadStarted;
173     jmethodID   mTransitionToCommitted;
174     jmethodID   mLoadFinished;
175     jmethodID   mReportError;
176     jmethodID   mSetTitle;
177     jmethodID   mWindowObjectCleared;
178     jmethodID   mSetProgress;
179     jmethodID   mDidReceiveIcon;
180     jmethodID   mDidReceiveTouchIconUrl;
181     jmethodID   mUpdateVisitedHistory;
182     jmethodID   mHandleUrl;
183     jmethodID   mCreateWindow;
184     jmethodID   mCloseWindow;
185     jmethodID   mDecidePolicyForFormResubmission;
186     jmethodID   mRequestFocus;
187     jmethodID   mGetRawResFilename;
188     jmethodID   mDensity;
189     jmethodID   mGetFileSize;
190     jmethodID   mGetFile;
frameandroid::WebFrame::JavaBrowserFrame191     AutoJObject frame(JNIEnv* env) {
192         return getRealObject(env, mObj);
193     }
historyandroid::WebFrame::JavaBrowserFrame194     AutoJObject history(JNIEnv* env) {
195         return getRealObject(env, mHistoryList);
196     }
197 };
198 
199 static jfieldID gFrameField;
200 #define GET_NATIVE_FRAME(env, obj) ((WebCore::Frame*)env->GetIntField(obj, gFrameField))
201 #define SET_NATIVE_FRAME(env, obj, frame) (env->SetIntField(obj, gFrameField, frame))
202 
203 // ----------------------------------------------------------------------------
204 
WebFrame(JNIEnv * env,jobject obj,jobject historyList,WebCore::Page * page)205 WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* page)
206     : mPage(page)
207 {
208     jclass clazz = env->GetObjectClass(obj);
209     mJavaFrame = new JavaBrowserFrame;
210     mJavaFrame->mObj = env->NewWeakGlobalRef(obj);
211     mJavaFrame->mHistoryList = env->NewWeakGlobalRef(historyList);
212     mJavaFrame->mStartLoadingResource = env->GetMethodID(clazz, "startLoadingResource",
213             "(ILjava/lang/String;Ljava/lang/String;Ljava/util/HashMap;[BJIZZZLjava/lang/String;Ljava/lang/String;)Landroid/webkit/LoadListener;");
214     mJavaFrame->mLoadStarted = env->GetMethodID(clazz, "loadStarted",
215             "(Ljava/lang/String;Landroid/graphics/Bitmap;IZ)V");
216     mJavaFrame->mTransitionToCommitted = env->GetMethodID(clazz, "transitionToCommitted",
217             "(IZ)V");
218     mJavaFrame->mLoadFinished = env->GetMethodID(clazz, "loadFinished",
219             "(Ljava/lang/String;IZ)V");
220     mJavaFrame->mReportError = env->GetMethodID(clazz, "reportError",
221             "(ILjava/lang/String;Ljava/lang/String;)V");
222     mJavaFrame->mSetTitle = env->GetMethodID(clazz, "setTitle",
223             "(Ljava/lang/String;)V");
224     mJavaFrame->mWindowObjectCleared = env->GetMethodID(clazz, "windowObjectCleared",
225             "(I)V");
226     mJavaFrame->mSetProgress = env->GetMethodID(clazz, "setProgress",
227             "(I)V");
228     mJavaFrame->mDidReceiveIcon = env->GetMethodID(clazz, "didReceiveIcon",
229             "(Landroid/graphics/Bitmap;)V");
230     mJavaFrame->mDidReceiveTouchIconUrl = env->GetMethodID(clazz, "didReceiveTouchIconUrl",
231             "(Ljava/lang/String;Z)V");
232     mJavaFrame->mUpdateVisitedHistory = env->GetMethodID(clazz, "updateVisitedHistory",
233             "(Ljava/lang/String;Z)V");
234     mJavaFrame->mHandleUrl = env->GetMethodID(clazz, "handleUrl",
235             "(Ljava/lang/String;)Z");
236     mJavaFrame->mCreateWindow = env->GetMethodID(clazz, "createWindow",
237             "(ZZ)Landroid/webkit/BrowserFrame;");
238     mJavaFrame->mCloseWindow = env->GetMethodID(clazz, "closeWindow",
239             "(Landroid/webkit/WebViewCore;)V");
240     mJavaFrame->mDecidePolicyForFormResubmission = env->GetMethodID(clazz,
241             "decidePolicyForFormResubmission", "(I)V");
242     mJavaFrame->mRequestFocus = env->GetMethodID(clazz, "requestFocus",
243             "()V");
244     mJavaFrame->mGetRawResFilename = env->GetMethodID(clazz, "getRawResFilename",
245             "(I)Ljava/lang/String;");
246     mJavaFrame->mDensity = env->GetMethodID(clazz, "density","()F");
247     mJavaFrame->mGetFileSize = env->GetMethodID(clazz, "getFileSize", "(Ljava/lang/String;)I");
248     mJavaFrame->mGetFile = env->GetMethodID(clazz, "getFile", "(Ljava/lang/String;[BII)I");
249 
250     LOG_ASSERT(mJavaFrame->mStartLoadingResource, "Could not find method startLoadingResource");
251     LOG_ASSERT(mJavaFrame->mLoadStarted, "Could not find method loadStarted");
252     LOG_ASSERT(mJavaFrame->mTransitionToCommitted, "Could not find method transitionToCommitted");
253     LOG_ASSERT(mJavaFrame->mLoadFinished, "Could not find method loadFinished");
254     LOG_ASSERT(mJavaFrame->mReportError, "Could not find method reportError");
255     LOG_ASSERT(mJavaFrame->mSetTitle, "Could not find method setTitle");
256     LOG_ASSERT(mJavaFrame->mWindowObjectCleared, "Could not find method windowObjectCleared");
257     LOG_ASSERT(mJavaFrame->mSetProgress, "Could not find method setProgress");
258     LOG_ASSERT(mJavaFrame->mDidReceiveIcon, "Could not find method didReceiveIcon");
259     LOG_ASSERT(mJavaFrame->mDidReceiveTouchIconUrl, "Could not find method didReceiveTouchIconUrl");
260     LOG_ASSERT(mJavaFrame->mUpdateVisitedHistory, "Could not find method updateVisitedHistory");
261     LOG_ASSERT(mJavaFrame->mHandleUrl, "Could not find method handleUrl");
262     LOG_ASSERT(mJavaFrame->mCreateWindow, "Could not find method createWindow");
263     LOG_ASSERT(mJavaFrame->mCloseWindow, "Could not find method closeWindow");
264     LOG_ASSERT(mJavaFrame->mDecidePolicyForFormResubmission, "Could not find method decidePolicyForFormResubmission");
265     LOG_ASSERT(mJavaFrame->mRequestFocus, "Could not find method requestFocus");
266     LOG_ASSERT(mJavaFrame->mGetRawResFilename, "Could not find method getRawResFilename");
267     LOG_ASSERT(mJavaFrame->mDensity, "Could not find method density");
268     LOG_ASSERT(mJavaFrame->mGetFileSize, "Could not find method getFileSize");
269     LOG_ASSERT(mJavaFrame->mGetFile, "Could not find method getFile");
270 
271     mUserAgent = WebCore::String();
272     mUserInitiatedClick = false;
273 }
274 
~WebFrame()275 WebFrame::~WebFrame()
276 {
277     if (mJavaFrame->mObj) {
278         JNIEnv* env = getJNIEnv();
279         env->DeleteWeakGlobalRef(mJavaFrame->mObj);
280         env->DeleteWeakGlobalRef(mJavaFrame->mHistoryList);
281         mJavaFrame->mObj = 0;
282     }
283     delete mJavaFrame;
284 }
285 
getWebFrame(const WebCore::Frame * frame)286 WebFrame* WebFrame::getWebFrame(const WebCore::Frame* frame)
287 {
288     FrameLoaderClientAndroid* client =
289             static_cast<FrameLoaderClientAndroid*> (frame->loader()->client());
290     return client->webFrame();
291 }
292 
createJavaMapFromHTTPHeaders(JNIEnv * env,const WebCore::HTTPHeaderMap & map)293 static jobject createJavaMapFromHTTPHeaders(JNIEnv* env, const WebCore::HTTPHeaderMap& map)
294 {
295     jclass mapClass = env->FindClass("java/util/HashMap");
296     LOG_ASSERT(mapClass, "Could not find HashMap class!");
297     jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V");
298     LOG_ASSERT(init, "Could not find constructor for HashMap");
299     jobject hashMap = env->NewObject(mapClass, init, map.size());
300     LOG_ASSERT(hashMap, "Could not create a new HashMap");
301     jmethodID put = env->GetMethodID(mapClass, "put",
302             "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
303     LOG_ASSERT(put, "Could not find put method on HashMap");
304 
305     WebCore::HTTPHeaderMap::const_iterator end = map.end();
306     for (WebCore::HTTPHeaderMap::const_iterator i = map.begin(); i != end; ++i) {
307         if (i->first.length() == 0 || i->second.length() == 0)
308             continue;
309         jstring key = env->NewString((unsigned short *)i->first.characters(), i->first.length());
310         jstring val = env->NewString((unsigned short *)i->second.characters(), i->second.length());
311         if (key && val) {
312             env->CallObjectMethod(hashMap, put, key, val);
313             env->DeleteLocalRef(key);
314             env->DeleteLocalRef(val);
315         }
316     }
317 
318     env->DeleteLocalRef(mapClass);
319 
320     return hashMap;
321 }
322 
323 // In WebViewCore.java, we artificially append the filename to the URI so that
324 // webkit treats the actual display name of the file as the filename, rather
325 // than the last segment of the URI (which will simply be a number).  When we
326 // pass the URI up to BrowserFrame, we no longer need the appended name (in fact
327 // it causes problems), so remove it here.
328 // FIXME: If we rewrite pathGetFileName (the current version is in
329 // FileSystemPOSIX), we can get the filename that way rather than appending it.
uriFromUriFileName(JNIEnv * env,const WebCore::String & name)330 static jstring uriFromUriFileName(JNIEnv* env, const WebCore::String& name)
331 {
332     const WebCore::String fileName = name.left(name.reverseFind('/'));
333     return env->NewString(fileName.characters(), fileName.length());
334 }
335 
336 // This class stores the URI and the size of each file for upload.  The URI is
337 // stored so we do not have to create it again.  The size is stored so we can
338 // compare the actual size of the file with the stated size.  If the actual size
339 // is larger, we will not copy it, since we will not have enough space in our
340 // buffer.
341 class FileInfo {
342 public:
FileInfo(JNIEnv * env,const WebCore::String & name)343     FileInfo(JNIEnv* env, const WebCore::String& name) {
344         m_uri = uriFromUriFileName(env, name);
345         checkException(env);
346         m_size = 0;
347         m_env = env;
348     }
~FileInfo()349     ~FileInfo() {
350         m_env->DeleteLocalRef(m_uri);
351     }
getSize()352     int getSize() { return m_size; }
getUri()353     jstring getUri() { return m_uri; }
setSize(int size)354     void setSize(int size) { m_size = size; }
355 private:
356     // This is only a pointer to the JNIEnv* returned by
357     // JSC::Bindings::getJNIEnv().  Used to delete the jstring when finished.
358     JNIEnv* m_env;
359     jstring m_uri;
360     int m_size;
361 };
362 
363 PassRefPtr<WebCore::ResourceLoaderAndroid>
startLoadingResource(WebCore::ResourceHandle * loader,const WebCore::ResourceRequest & request,bool mainResource,bool synchronous)364 WebFrame::startLoadingResource(WebCore::ResourceHandle* loader,
365                                   const WebCore::ResourceRequest& request,
366                                   bool mainResource,
367                                   bool synchronous)
368 {
369 #ifdef ANDROID_INSTRUMENT
370     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
371 #endif
372     LOGV("::WebCore:: startLoadingResource(%p, %s)",
373             loader, request.url().string().latin1().data());
374 
375     WebCore::String method = request.httpMethod();
376     WebCore::HTTPHeaderMap headers = request.httpHeaderFields();
377 
378     JNIEnv* env = getJNIEnv();
379     WebCore::String urlStr = request.url().string();
380     int colon = urlStr.find(':');
381     bool allLower = true;
382     for (int index = 0; index < colon; index++) {
383         UChar ch = urlStr[index];
384         if (!WTF::isASCIIAlpha(ch))
385             break;
386         allLower &= WTF::isASCIILower(ch);
387         if (index == colon - 1 && !allLower) {
388             urlStr = urlStr.substring(0, colon).lower()
389                     + urlStr.substring(colon);
390         }
391     }
392     LOGV("%s lower=%s", __FUNCTION__, urlStr.latin1().data());
393     jstring jUrlStr = env->NewString(urlStr.characters(), urlStr.length());
394     jstring jMethodStr = NULL;
395     if (!method.isEmpty())
396         jMethodStr = env->NewString(method.characters(), method.length());
397     jbyteArray jPostDataStr = NULL;
398     WebCore::FormData* formdata = request.httpBody();
399     AutoJObject obj = mJavaFrame->frame(env);
400     if (formdata) {
401         // We can use the formdata->flatten() but it will result in two
402         // memcpys, first through loading up the vector with the form data
403         // then another to copy it out of the vector and into the java byte
404         // array. Instead, we copy the form data ourselves below saving a
405         // memcpy.
406         const WTF::Vector<WebCore::FormDataElement>& elements =
407                 formdata->elements();
408 
409         // Sizing pass
410         int size = 0;
411         size_t n = elements.size();
412         FileInfo** fileinfos = new FileInfo*[n];
413         for (size_t i = 0; i < n; ++i) {
414             fileinfos[i] = 0;
415             const WebCore::FormDataElement& e = elements[i];
416             if (e.m_type == WebCore::FormDataElement::data) {
417                 size += e.m_data.size();
418             } else if (e.m_type == WebCore::FormDataElement::encodedFile) {
419                 fileinfos[i] = new FileInfo(env, e.m_filename);
420                 int delta = env->CallIntMethod(obj.get(),
421                     mJavaFrame->mGetFileSize, fileinfos[i]->getUri());
422                 checkException(env);
423                 fileinfos[i]->setSize(delta);
424                 size += delta;
425             }
426         }
427 
428         // Only create the byte array if there is POST data to pass up.
429         // The Java code is expecting null if there is no data.
430         if (size > 0) {
431             // Copy the actual form data.
432             jPostDataStr = env->NewByteArray(size);
433             if (jPostDataStr) {
434                 // Write  the form data to the java array.
435                 jbyte* bytes = env->GetByteArrayElements(jPostDataStr, NULL);
436                 int offset = 0;
437                 for (size_t i = 0; i < n; ++i) {
438                     const WebCore::FormDataElement& e = elements[i];
439                     if (e.m_type == WebCore::FormDataElement::data) {
440                         int delta = e.m_data.size();
441                         memcpy(bytes + offset, e.m_data.data(), delta);
442                         offset += delta;
443                     } else if (e.m_type
444                             == WebCore::FormDataElement::encodedFile) {
445                         int delta = env->CallIntMethod(obj.get(),
446                             mJavaFrame->mGetFile, fileinfos[i]->getUri(),
447                             jPostDataStr, offset, fileinfos[i]->getSize());
448                         checkException(env);
449                         offset += delta;
450                     }
451                 }
452                 env->ReleaseByteArrayElements(jPostDataStr, bytes, 0);
453             }
454         }
455         delete[] fileinfos;
456     }
457 
458     jobject jHeaderMap = createJavaMapFromHTTPHeaders(env, headers);
459 
460     // Convert the WebCore Cache Policy to a WebView Cache Policy.
461     int cacheMode = 0;  // WebSettings.LOAD_NORMAL
462     switch (request.cachePolicy()) {
463         case WebCore::ReloadIgnoringCacheData:
464             cacheMode = 2; // WebSettings.LOAD_NO_CACHE
465             break;
466         case WebCore::ReturnCacheDataDontLoad:
467             cacheMode = 3; // WebSettings.LOAD_CACHE_ONLY
468             break;
469         case WebCore::ReturnCacheDataElseLoad:
470             cacheMode = 1;   // WebSettings.LOAD_CACHE_ELSE_NETWORK
471             break;
472         case WebCore::UseProtocolCachePolicy:
473         default:
474             break;
475     }
476 
477     LOGV("::WebCore:: startLoadingResource %s with cacheMode %d", urlStr.ascii().data(), cacheMode);
478 
479     ResourceHandleInternal* loaderInternal = loader->getInternal();
480     jstring jUsernameString = loaderInternal->m_user.isEmpty() ?
481             NULL : env->NewString(loaderInternal->m_user.characters(), loaderInternal->m_user.length());
482     jstring jPasswordString = loaderInternal->m_pass.isEmpty() ?
483             NULL : env->NewString(loaderInternal->m_pass.characters(), loaderInternal->m_pass.length());
484 
485     jobject jLoadListener =
486         env->CallObjectMethod(obj.get(), mJavaFrame->mStartLoadingResource,
487                 (int)loader, jUrlStr, jMethodStr, jHeaderMap,
488                 jPostDataStr, formdata ? formdata->identifier(): 0,
489                 cacheMode, mainResource, request.getUserGesture(),
490                 synchronous, jUsernameString, jPasswordString);
491 
492     env->DeleteLocalRef(jUrlStr);
493     env->DeleteLocalRef(jMethodStr);
494     env->DeleteLocalRef(jPostDataStr);
495     env->DeleteLocalRef(jHeaderMap);
496     env->DeleteLocalRef(jUsernameString);
497     env->DeleteLocalRef(jPasswordString);
498     if (checkException(env))
499         return NULL;
500 
501     PassRefPtr<WebCore::ResourceLoaderAndroid> h;
502     if (jLoadListener)
503         h = WebCoreResourceLoader::create(env, jLoadListener);
504     env->DeleteLocalRef(jLoadListener);
505     return h;
506 }
507 
508 void
reportError(int errorCode,const WebCore::String & description,const WebCore::String & failingUrl)509 WebFrame::reportError(int errorCode, const WebCore::String& description,
510         const WebCore::String& failingUrl)
511 {
512 #ifdef ANDROID_INSTRUMENT
513     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
514 #endif
515     LOGV("::WebCore:: reportError(%d, %s)", errorCode, description.ascii().data());
516     JNIEnv* env = getJNIEnv();
517 
518     jstring descStr = env->NewString((unsigned short*)description.characters(), description.length());
519     jstring failUrl = env->NewString((unsigned short*)failingUrl.characters(), failingUrl.length());
520     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mReportError,
521             errorCode, descStr, failUrl);
522     env->DeleteLocalRef(descStr);
523     env->DeleteLocalRef(failUrl);
524 }
525 
526 void
loadStarted(WebCore::Frame * frame)527 WebFrame::loadStarted(WebCore::Frame* frame)
528 {
529 #ifdef ANDROID_INSTRUMENT
530     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
531 #endif
532     const WebCore::KURL& url = frame->loader()->activeDocumentLoader()->url();
533     if (url.isEmpty())
534         return;
535     LOGV("::WebCore:: loadStarted %s", url.string().ascii().data());
536 
537     bool isMainFrame = (!frame->tree() || !frame->tree()->parent());
538     WebCore::FrameLoadType loadType = frame->loader()->loadType();
539 
540     if (loadType == WebCore::FrameLoadTypeReplace ||
541             loadType == WebCore::FrameLoadTypeSame ||
542             (loadType == WebCore::FrameLoadTypeRedirectWithLockedBackForwardList &&
543              !isMainFrame))
544         return;
545 
546     JNIEnv* env = getJNIEnv();
547     WebCore::String urlString(url.string());
548     // If this is the main frame and we already have a favicon in the database,
549     // send it along with the page started notification.
550     jobject favicon = NULL;
551     if (isMainFrame) {
552         WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL(urlString, WebCore::IntSize(16, 16));
553         if (icon)
554             favicon = webcoreImageToJavaBitmap(env, icon);
555         LOGV("favicons", "Starting load with icon %p for %s", icon, url.string().utf8().data());
556     }
557     jstring urlStr = env->NewString((unsigned short*)urlString.characters(), urlString.length());
558 
559     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mLoadStarted, urlStr, favicon,
560             (int)loadType, isMainFrame);
561     checkException(env);
562     env->DeleteLocalRef(urlStr);
563     if (favicon)
564         env->DeleteLocalRef(favicon);
565 
566     // Inform the client that the main frame has started a new load.
567     if (isMainFrame && mPage) {
568         Chrome* chrome = mPage->chrome();
569         if (chrome) {
570             ChromeClientAndroid* client = static_cast<ChromeClientAndroid*>(chrome->client());
571             if (client)
572                 client->onMainFrameLoadStarted();
573         }
574     }
575 }
576 
577 void
transitionToCommitted(WebCore::Frame * frame)578 WebFrame::transitionToCommitted(WebCore::Frame* frame)
579 {
580 #ifdef ANDROID_INSTRUMENT
581     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
582 #endif
583     JNIEnv* env = getJNIEnv();
584     WebCore::FrameLoadType loadType = frame->loader()->loadType();
585     bool isMainFrame = (!frame->tree() || !frame->tree()->parent());
586     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mTransitionToCommitted,
587             (int)loadType, isMainFrame);
588     checkException(env);
589 }
590 
591 void
didFinishLoad(WebCore::Frame * frame)592 WebFrame::didFinishLoad(WebCore::Frame* frame)
593 {
594 #ifdef ANDROID_INSTRUMENT
595     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
596 #endif
597     JNIEnv* env = getJNIEnv();
598     WebCore::FrameLoader* loader = frame->loader();
599     const WebCore::KURL& url = loader->activeDocumentLoader()->url();
600     if (url.isEmpty())
601         return;
602     LOGV("::WebCore:: didFinishLoad %s", url.string().ascii().data());
603 
604     bool isMainFrame = (!frame->tree() || !frame->tree()->parent());
605     WebCore::FrameLoadType loadType = loader->loadType();
606     WebCore::String urlString(url.string());
607     jstring urlStr = env->NewString((unsigned short*)urlString.characters(), urlString.length());
608     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mLoadFinished, urlStr,
609             (int)loadType, isMainFrame);
610     checkException(env);
611     env->DeleteLocalRef(urlStr);
612 }
613 
614 void
addHistoryItem(WebCore::HistoryItem * item)615 WebFrame::addHistoryItem(WebCore::HistoryItem* item)
616 {
617 #ifdef ANDROID_INSTRUMENT
618     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
619 #endif
620     LOGV("::WebCore:: addHistoryItem");
621     JNIEnv* env = getJNIEnv();
622     WebHistory::AddItem(mJavaFrame->history(env), item);
623 }
624 
625 void
removeHistoryItem(int index)626 WebFrame::removeHistoryItem(int index)
627 {
628 #ifdef ANDROID_INSTRUMENT
629     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
630 #endif
631     LOGV("::WebCore:: removeHistoryItem at %d", index);
632     JNIEnv* env = getJNIEnv();
633     WebHistory::RemoveItem(mJavaFrame->history(env), index);
634 }
635 
636 void
updateHistoryIndex(int newIndex)637 WebFrame::updateHistoryIndex(int newIndex)
638 {
639 #ifdef ANDROID_INSTRUMENT
640     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
641 #endif
642     LOGV("::WebCore:: updateHistoryIndex to %d", newIndex);
643     JNIEnv* env = getJNIEnv();
644     WebHistory::UpdateHistoryIndex(mJavaFrame->history(env), newIndex);
645 }
646 
647 void
setTitle(const WebCore::String & title)648 WebFrame::setTitle(const WebCore::String& title)
649 {
650 #ifdef ANDROID_INSTRUMENT
651     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
652 #endif
653 #ifndef NDEBUG
654     LOGV("setTitle(%s)", title.ascii().data());
655 #endif
656     JNIEnv* env = getJNIEnv();
657     jstring jTitleStr = env->NewString((unsigned short *)title.characters(), title.length());
658 
659     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSetTitle,
660                                         jTitleStr);
661     checkException(env);
662     env->DeleteLocalRef(jTitleStr);
663 }
664 
665 void
windowObjectCleared(WebCore::Frame * frame)666 WebFrame::windowObjectCleared(WebCore::Frame* frame)
667 {
668 #ifdef ANDROID_INSTRUMENT
669     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
670 #endif
671     LOGV("::WebCore:: windowObjectCleared");
672     JNIEnv* env = getJNIEnv();
673 
674     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mWindowObjectCleared, (int)frame);
675     checkException(env);
676 }
677 
678 void
setProgress(float newProgress)679 WebFrame::setProgress(float newProgress)
680 {
681 #ifdef ANDROID_INSTRUMENT
682     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
683 #endif
684     JNIEnv* env = getJNIEnv();
685     int progress = (int) (100 * newProgress);
686     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSetProgress, progress);
687     checkException(env);
688 }
689 
690 const WebCore::String
userAgentForURL(const WebCore::KURL * url)691 WebFrame::userAgentForURL(const WebCore::KURL* url)
692 {
693     return mUserAgent;
694 }
695 
696 void
didReceiveIcon(WebCore::Image * icon)697 WebFrame::didReceiveIcon(WebCore::Image* icon)
698 {
699 #ifdef ANDROID_INSTRUMENT
700     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
701 #endif
702     LOG_ASSERT(icon, "DidReceiveIcon called without an image!");
703     JNIEnv* env = getJNIEnv();
704     jobject bitmap = webcoreImageToJavaBitmap(env, icon);
705     if (!bitmap)
706         return;
707 
708     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDidReceiveIcon, bitmap);
709     env->DeleteLocalRef(bitmap);
710     checkException(env);
711 }
712 
713 void
didReceiveTouchIconURL(const WebCore::String & url,bool precomposed)714 WebFrame::didReceiveTouchIconURL(const WebCore::String& url, bool precomposed)
715 {
716 #ifdef ANDROID_INSTRUMENT
717     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
718 #endif
719     JNIEnv* env = getJNIEnv();
720     jstring jUrlStr = env->NewString((unsigned short*)url.characters(),
721             url.length());
722 
723     env->CallVoidMethod(mJavaFrame->frame(env).get(),
724             mJavaFrame->mDidReceiveTouchIconUrl, jUrlStr, precomposed);
725     checkException(env);
726 }
727 
728 void
updateVisitedHistory(const WebCore::KURL & url,bool reload)729 WebFrame::updateVisitedHistory(const WebCore::KURL& url, bool reload)
730 {
731 #ifdef ANDROID_INSTRUMENT
732     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
733 #endif
734     WebCore::String urlStr(url.string());
735     JNIEnv* env = getJNIEnv();
736     jstring jUrlStr = env->NewString((unsigned short*)urlStr.characters(), urlStr.length());
737 
738     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mUpdateVisitedHistory, jUrlStr, reload);
739     checkException(env);
740 }
741 
742 bool
canHandleRequest(const WebCore::ResourceRequest & request)743 WebFrame::canHandleRequest(const WebCore::ResourceRequest& request)
744 {
745 #ifdef ANDROID_INSTRUMENT
746     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
747 #endif
748     // always handle "POST" in place
749     if (equalIgnoringCase(request.httpMethod(), "POST"))
750         return true;
751     WebCore::KURL requestUrl = request.url();
752     if (!mUserInitiatedClick && !request.getUserGesture() &&
753         (requestUrl.protocolIs("http") || requestUrl.protocolIs("https") ||
754             requestUrl.protocolIs("file") || requestUrl.protocolIs("about") ||
755             WebCore::protocolIsJavaScript(requestUrl.string())))
756         return true;
757     WebCore::String url(request.url().string());
758     // Empty urls should not be sent to java
759     if (url.isEmpty())
760         return true;
761     JNIEnv* env = getJNIEnv();
762     jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length());
763 
764     // check to see whether browser app wants to hijack url loading.
765     // if browser app handles the url, we will return false to bail out WebCore loading
766     jboolean ret = env->CallBooleanMethod(mJavaFrame->frame(env).get(), mJavaFrame->mHandleUrl, jUrlStr);
767     checkException(env);
768     return (ret == 0);
769 }
770 
771 WebCore::Frame*
createWindow(bool dialog,bool userGesture)772 WebFrame::createWindow(bool dialog, bool userGesture)
773 {
774 #ifdef ANDROID_INSTRUMENT
775     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
776 #endif
777     JNIEnv* env = getJNIEnv();
778     jobject obj = env->CallObjectMethod(mJavaFrame->frame(env).get(),
779             mJavaFrame->mCreateWindow, dialog, userGesture);
780     if (obj) {
781         WebCore::Frame* frame = GET_NATIVE_FRAME(env, obj);
782         return frame;
783     }
784     return NULL;
785 }
786 
787 void
requestFocus() const788 WebFrame::requestFocus() const
789 {
790 #ifdef ANDROID_INSTRUMENT
791     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
792 #endif
793     JNIEnv* env = getJNIEnv();
794     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mRequestFocus);
795     checkException(env);
796 }
797 
798 void
closeWindow(WebViewCore * webViewCore)799 WebFrame::closeWindow(WebViewCore* webViewCore)
800 {
801 #ifdef ANDROID_INSTRUMENT
802     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
803 #endif
804     assert(webViewCore);
805     JNIEnv* env = getJNIEnv();
806     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mCloseWindow,
807             webViewCore->getJavaObject().get());
808 }
809 
810 struct PolicyFunctionWrapper {
811     WebCore::FramePolicyFunction func;
812 };
813 
814 void
decidePolicyForFormResubmission(WebCore::FramePolicyFunction func)815 WebFrame::decidePolicyForFormResubmission(WebCore::FramePolicyFunction func)
816 {
817 #ifdef ANDROID_INSTRUMENT
818     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
819 #endif
820     JNIEnv* env = getJNIEnv();
821     PolicyFunctionWrapper* p = new PolicyFunctionWrapper;
822     p->func = func;
823     env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDecidePolicyForFormResubmission, p);
824 }
825 
826 WebCore::String
getRawResourceFilename(WebCore::PlatformBridge::rawResId id) const827 WebFrame::getRawResourceFilename(WebCore::PlatformBridge::rawResId id) const
828 {
829     JNIEnv* env = getJNIEnv();
830     jstring ret = (jstring) env->CallObjectMethod(mJavaFrame->frame(env).get(),
831             mJavaFrame->mGetRawResFilename, (int)id);
832 
833     return to_string(env, ret);
834 }
835 
836 float
density() const837 WebFrame::density() const
838 {
839     JNIEnv* env = getJNIEnv();
840     jfloat dpi = env->CallFloatMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDensity);
841     checkException(env);
842     return dpi;
843 }
844 
845 // ----------------------------------------------------------------------------
CallPolicyFunction(JNIEnv * env,jobject obj,jint func,jint decision)846 static void CallPolicyFunction(JNIEnv* env, jobject obj, jint func, jint decision)
847 {
848 #ifdef ANDROID_INSTRUMENT
849     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
850 #endif
851     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
852     LOG_ASSERT(pFrame, "nativeCallPolicyFunction must take a valid frame pointer!");
853     PolicyFunctionWrapper* pFunc = (PolicyFunctionWrapper*)func;
854     LOG_ASSERT(pFunc, "nativeCallPolicyFunction must take a valid function pointer!");
855 
856     // If we are resending the form then we should reset the multiple submission protection.
857     if (decision == WebCore::PolicyUse)
858         pFrame->loader()->resetMultipleFormSubmissionProtection();
859 
860     (pFrame->loader()->policyChecker()->*(pFunc->func))((WebCore::PolicyAction)decision);
861 }
862 
CreateFrame(JNIEnv * env,jobject obj,jobject javaview,jobject jAssetManager,jobject historyList)863 static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAssetManager, jobject historyList)
864 {
865     ScriptController::initializeThreading();
866 
867 #ifdef ANDROID_INSTRUMENT
868 #if USE(V8)
869     V8Counters::initCounters();
870 #endif
871     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
872 #endif
873     ChromeClientAndroid*      chromeC = new ChromeClientAndroid;
874     EditorClientAndroid*      editorC = new EditorClientAndroid;
875     WebCore::ContextMenuClient* contextMenuC = new ContextMenuClientAndroid;
876     WebCore::DragClient*        dragC = new DragClientAndroid;
877     InspectorClientAndroid* inspectorC = new InspectorClientAndroid;
878     // Create a new page
879     WebCore::Page* page = new WebCore::Page(chromeC,
880                                             contextMenuC,
881                                             editorC,
882                                             dragC,
883                                             inspectorC,
884                                             0, // PluginHalterClient
885                                             0); // GeolocationControllerClient
886     // css files without explicit MIMETYPE is treated as generic text files in
887     // the Java side. So we can't enforce CSS MIMETYPE.
888     page->settings()->setEnforceCSSMIMETypeInStrictMode(false);
889     editorC->setPage(page);
890     page->setGroupName("android.webkit");
891 
892     // Create a WebFrame to access the Java BrowserFrame associated with this page
893     WebFrame* webFrame = new WebFrame(env, obj, historyList, page);
894     // Attach webFrame to chromeC and release our ownership
895     chromeC->setWebFrame(webFrame);
896     Release(webFrame);
897 
898     FrameLoaderClientAndroid* loaderC = new FrameLoaderClientAndroid(webFrame);
899     // Create a Frame and the page holds its reference
900     WebCore::Frame* frame = WebCore::Frame::create(page, NULL, loaderC).get();
901     loaderC->setFrame(frame);
902 #if ENABLE(WDS)
903     WDS::server()->addFrame(frame);
904 #endif
905 
906     // Create a WebViewCore to access the Java WebViewCore associated with this page
907     WebViewCore* webViewCore = new WebViewCore(env, javaview, frame);
908 
909     // Create a FrameView
910     RefPtr<WebCore::FrameView> frameView = WebCore::FrameView::create(frame);
911     // Create a WebFrameView
912     WebFrameView* webFrameView = new WebFrameView(frameView.get(), webViewCore);
913     // As webFrameView Retains webViewCore, release our ownership
914     Release(webViewCore);
915     // As frameView Retains webFrameView, release our ownership
916     Release(webFrameView);
917     // Attach the frameView to the frame and release our ownership
918     frame->setView(frameView);
919     // Set the frame to active to turn on keyboard focus.
920     frame->init();
921     frame->selection()->setFocused(true);
922 
923     // Allow local access to file:/// and substitute data
924     WebCore::SecurityOrigin::setLocalLoadPolicy(
925             WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
926 
927     LOGV("::WebCore:: createFrame %p", frame);
928 
929     // Set the mNativeFrame field in Frame
930     SET_NATIVE_FRAME(env, obj, (int)frame);
931 
932     String directory = webFrame->getRawResourceFilename(
933             WebCore::PlatformBridge::DrawableDir);
934     if (directory.isEmpty())
935         LOGE("Can't find the drawable directory");
936     else {
937         // Setup the asset manager.
938         AssetManager* am = assetManagerForJavaObject(env, jAssetManager);
939         // Initialize our skinning classes
940         WebCore::RenderSkinAndroid::Init(am, directory);
941     }
942     for (int i = WebCore::PlatformBridge::FileUploadLabel;
943             i <= WebCore::PlatformBridge::SubmitLabel; i++)
944         initGlobalLocalizedName(
945                 static_cast<WebCore::PlatformBridge::rawResId>(i), webFrame);
946 }
947 
DestroyFrame(JNIEnv * env,jobject obj)948 static void DestroyFrame(JNIEnv* env, jobject obj)
949 {
950 #ifdef ANDROID_INSTRUMENT
951     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
952 #endif
953     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
954     LOG_ASSERT(pFrame, "nativeDestroyFrame must take a valid frame pointer!");
955 
956     LOGV("::WebCore:: deleting frame %p", pFrame);
957 
958     WebCore::FrameView* view = pFrame->view();
959     view->ref();
960     // detachFromParent will cause the page to be closed.
961     WebCore::FrameLoader* fl = pFrame->loader();
962     // retain a pointer because detachFromParent will set the page to null.
963     WebCore::Page* page = pFrame->page();
964     if (fl)
965         fl->detachFromParent();
966     delete page;
967     view->deref();
968 
969     SET_NATIVE_FRAME(env, obj, 0);
970 #if ENABLE(WDS)
971     WDS::server()->removeFrame(pFrame);
972 #endif
973 }
974 
LoadUrl(JNIEnv * env,jobject obj,jstring url,jobject headers)975 static void LoadUrl(JNIEnv *env, jobject obj, jstring url, jobject headers)
976 {
977 #ifdef ANDROID_INSTRUMENT
978     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
979 #endif
980     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
981     LOG_ASSERT(pFrame, "nativeLoadUrl must take a valid frame pointer!");
982 
983     WebCore::String webcoreUrl = to_string(env, url);
984     WebCore::KURL kurl(WebCore::KURL(), webcoreUrl);
985     WebCore::ResourceRequest request(kurl);
986     if (headers) {
987         // dalvikvm will raise exception if any of these fail
988         jclass mapClass = env->FindClass("java/util/Map");
989         jmethodID entrySet = env->GetMethodID(mapClass, "entrySet",
990                 "()Ljava/util/Set;");
991         jobject set = env->CallObjectMethod(headers, entrySet);
992 
993         jclass setClass = env->FindClass("java/util/Set");
994         jmethodID iterator = env->GetMethodID(setClass, "iterator",
995                 "()Ljava/util/Iterator;");
996         jobject iter = env->CallObjectMethod(set, iterator);
997 
998         jclass iteratorClass = env->FindClass("java/util/Iterator");
999         jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z");
1000         jmethodID next = env->GetMethodID(iteratorClass, "next",
1001                 "()Ljava/lang/Object;");
1002         jclass entryClass = env->FindClass("java/util/Map$Entry");
1003         jmethodID getKey = env->GetMethodID(entryClass, "getKey",
1004                 "()Ljava/lang/Object;");
1005         jmethodID getValue = env->GetMethodID(entryClass, "getValue",
1006                 "()Ljava/lang/Object;");
1007 
1008         while (env->CallBooleanMethod(iter, hasNext)) {
1009             jobject entry = env->CallObjectMethod(iter, next);
1010             jstring key = (jstring) env->CallObjectMethod(entry, getKey);
1011             jstring value = (jstring) env->CallObjectMethod(entry, getValue);
1012             request.setHTTPHeaderField(to_string(env, key), to_string(env, value));
1013             env->DeleteLocalRef(entry);
1014             env->DeleteLocalRef(key);
1015             env->DeleteLocalRef(value);
1016         }
1017 
1018         env->DeleteLocalRef(entryClass);
1019         env->DeleteLocalRef(iteratorClass);
1020         env->DeleteLocalRef(iter);
1021         env->DeleteLocalRef(setClass);
1022         env->DeleteLocalRef(set);
1023         env->DeleteLocalRef(mapClass);
1024     }
1025     LOGV("LoadUrl %s", kurl.string().latin1().data());
1026     pFrame->loader()->load(request, false);
1027 }
1028 
PostUrl(JNIEnv * env,jobject obj,jstring url,jbyteArray postData)1029 static void PostUrl(JNIEnv *env, jobject obj, jstring url, jbyteArray postData)
1030 {
1031 #ifdef ANDROID_INSTRUMENT
1032     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1033 #endif
1034     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1035     LOG_ASSERT(pFrame, "nativePostUrl must take a valid frame pointer!");
1036 
1037     WebCore::KURL kurl(WebCore::KURL(), to_string(env, url));
1038     WebCore::ResourceRequest request(kurl);
1039     request.setHTTPMethod("POST");
1040     request.setHTTPContentType("application/x-www-form-urlencoded");
1041 
1042     if (postData) {
1043         jsize size = env->GetArrayLength(postData);
1044         jbyte* bytes = env->GetByteArrayElements(postData, NULL);
1045         RefPtr<FormData> formData = FormData::create((const void*)bytes, size);
1046         // the identifier uses the same logic as generateFormDataIdentifier() in
1047         // HTMLFormElement.cpp
1048         formData->setIdentifier(static_cast<int64_t>(WTF::currentTime() * 1000000.0));
1049         request.setHTTPBody(formData);
1050         env->ReleaseByteArrayElements(postData, bytes, 0);
1051     }
1052 
1053     LOGV("PostUrl %s", kurl.string().latin1().data());
1054     WebCore::FrameLoadRequest frameRequest(request);
1055     pFrame->loader()->loadFrameRequest(frameRequest, false, false, 0, 0, WebCore::SendReferrer);
1056 }
1057 
LoadData(JNIEnv * env,jobject obj,jstring baseUrl,jstring data,jstring mimeType,jstring encoding,jstring failUrl)1058 static void LoadData(JNIEnv *env, jobject obj, jstring baseUrl, jstring data,
1059         jstring mimeType, jstring encoding, jstring failUrl)
1060 {
1061 #ifdef ANDROID_INSTRUMENT
1062     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1063 #endif
1064     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1065     LOG_ASSERT(pFrame, "nativeLoadData must take a valid frame pointer!");
1066 
1067     // Setup the resource request
1068     WebCore::ResourceRequest request(to_string(env, baseUrl));
1069 
1070     // Setup the substituteData
1071     const char* dataStr = env->GetStringUTFChars(data, NULL);
1072     WTF::PassRefPtr<WebCore::SharedBuffer> sharedBuffer =
1073         WebCore::SharedBuffer::create();
1074     LOG_ASSERT(dataStr, "nativeLoadData has a null data string.");
1075     sharedBuffer->append(dataStr, strlen(dataStr));
1076     env->ReleaseStringUTFChars(data, dataStr);
1077 
1078     WebCore::SubstituteData substituteData(sharedBuffer,
1079             to_string(env, mimeType), to_string(env, encoding),
1080             WebCore::KURL(ParsedURLString, to_string(env, failUrl)));
1081 
1082     // Perform the load
1083     pFrame->loader()->load(request, substituteData, false);
1084 }
1085 
StopLoading(JNIEnv * env,jobject obj)1086 static void StopLoading(JNIEnv *env, jobject obj)
1087 {
1088 #ifdef ANDROID_INSTRUMENT
1089     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1090 #endif
1091     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1092     LOG_ASSERT(pFrame, "nativeStopLoading must take a valid frame pointer!");
1093     LOGV("::WebCore:: stopLoading %p", pFrame);
1094 
1095     // Stop loading the page and do not send an unload event
1096     pFrame->loader()->stopForUserCancel();
1097 }
1098 
ExternalRepresentation(JNIEnv * env,jobject obj)1099 static jstring ExternalRepresentation(JNIEnv *env, jobject obj)
1100 {
1101 #ifdef ANDROID_INSTRUMENT
1102     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1103 #endif
1104     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1105     LOG_ASSERT(pFrame, "android_webcore_nativeExternalRepresentation must take a valid frame pointer!");
1106 
1107     // Request external representation of the render tree
1108     WebCore::String renderDump = WebCore::externalRepresentation(pFrame);
1109     unsigned len = renderDump.length();
1110     if (!len)
1111         return NULL;
1112     return env->NewString(renderDump.characters(), len);
1113 }
1114 
DocumentAsText(JNIEnv * env,jobject obj)1115 static jstring DocumentAsText(JNIEnv *env, jobject obj)
1116 {
1117 #ifdef ANDROID_INSTRUMENT
1118     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1119 #endif
1120     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1121     LOG_ASSERT(pFrame, "android_webcore_nativeDocumentAsText must take a valid frame pointer!");
1122 
1123     WebCore::Element *documentElement = pFrame->document()->documentElement();
1124     if (!documentElement)
1125         return NULL;
1126     WebCore::String renderDump = ((WebCore::HTMLElement*)documentElement)->innerText();
1127     renderDump.append("\n");
1128     unsigned len = renderDump.length();
1129     if (!len)
1130         return NULL;
1131     return env->NewString((unsigned short*)renderDump.characters(), len);
1132 }
1133 
Reload(JNIEnv * env,jobject obj,jboolean allowStale)1134 static void Reload(JNIEnv *env, jobject obj, jboolean allowStale)
1135 {
1136 #ifdef ANDROID_INSTRUMENT
1137     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1138 #endif
1139     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1140     LOG_ASSERT(pFrame, "nativeReload must take a valid frame pointer!");
1141 
1142     WebCore::FrameLoader* loader = pFrame->loader();
1143     if (allowStale) {
1144         // load the current page with FrameLoadTypeIndexedBackForward so that it
1145         // will use cache when it is possible
1146         WebCore::Page* page = pFrame->page();
1147         WebCore::HistoryItem* item = page->backForwardList()->currentItem();
1148         if (item)
1149             page->goToItem(item, FrameLoadTypeIndexedBackForward);
1150     } else
1151         loader->reload(true);
1152 }
1153 
GoBackOrForward(JNIEnv * env,jobject obj,jint pos)1154 static void GoBackOrForward(JNIEnv *env, jobject obj, jint pos)
1155 {
1156 #ifdef ANDROID_INSTRUMENT
1157     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1158 #endif
1159     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1160     LOG_ASSERT(pFrame, "nativeGoBackOrForward must take a valid frame pointer!");
1161 
1162     if (pos == 1)
1163         pFrame->page()->goForward();
1164     else if (pos == -1)
1165         pFrame->page()->goBack();
1166     else
1167         pFrame->page()->goBackOrForward(pos);
1168 }
1169 
StringByEvaluatingJavaScriptFromString(JNIEnv * env,jobject obj,jstring script)1170 static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj, jstring script)
1171 {
1172 #ifdef ANDROID_INSTRUMENT
1173     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1174 #endif
1175     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1176     LOG_ASSERT(pFrame, "stringByEvaluatingJavaScriptFromString must take a valid frame pointer!");
1177 
1178     WebCore::ScriptValue value =
1179             pFrame->script()->executeScript(to_string(env, script), true);
1180     WebCore::String result = WebCore::String();
1181     ScriptState* scriptState = mainWorldScriptState(pFrame);
1182     if (!value.getString(scriptState, result))
1183         return NULL;
1184     unsigned len = result.length();
1185     if (len == 0)
1186         return NULL;
1187     return env->NewString((unsigned short*)result.characters(), len);
1188 }
1189 
1190 // Wrap the JavaInstance used when binding custom javascript interfaces. Use a
1191 // weak reference so that the gc can collect the WebView. Override virtualBegin
1192 // and virtualEnd and swap the weak reference for the real object.
1193 class WeakJavaInstance : public JavaInstance {
1194 public:
1195 #if USE(JSC)
create(jobject obj,PassRefPtr<RootObject> root)1196     static PassRefPtr<WeakJavaInstance> create(jobject obj, PassRefPtr<RootObject> root)
1197     {
1198         return adoptRef(new WeakJavaInstance(obj, root));
1199     }
1200 #elif USE(V8)
1201     static PassRefPtr<WeakJavaInstance> create(jobject obj)
1202     {
1203         return adoptRef(new WeakJavaInstance(obj));
1204     }
1205 #endif
1206 
1207 private:
1208 #if USE(JSC)
WeakJavaInstance(jobject instance,PassRefPtr<RootObject> rootObject)1209     WeakJavaInstance(jobject instance, PassRefPtr<RootObject> rootObject)
1210         : JavaInstance(instance, rootObject)
1211 #elif USE(V8)
1212     WeakJavaInstance(jobject instance)
1213         : JavaInstance(instance)
1214 #endif
1215         , m_beginEndDepth(0)
1216     {
1217         JNIEnv* env = getJNIEnv();
1218         // JavaInstance creates a global ref to instance in its constructor.
1219         env->DeleteGlobalRef(m_instance->instance());
1220         // Set the object to a weak reference.
1221         m_instance->setInstance(env->NewWeakGlobalRef(instance));
1222     }
~WeakJavaInstance()1223     ~WeakJavaInstance()
1224     {
1225         JNIEnv* env = getJNIEnv();
1226         // Store the weak reference so we can delete it later.
1227         jweak weak = m_instance->instance();
1228         // The JavaInstance destructor attempts to delete the global ref stored
1229         // in m_instance. Since we replaced it in our constructor with a weak
1230         // reference, restore the global ref here so the vm will not complain.
1231         m_instance->setInstance(env->NewGlobalRef(
1232                 getRealObject(env, m_instance->instance()).get()));
1233         // Delete the weak reference.
1234         env->DeleteWeakGlobalRef(weak);
1235     }
1236 
virtualBegin()1237     virtual void virtualBegin()
1238     {
1239         if (m_beginEndDepth++ > 0)
1240             return;
1241         m_weakRef = m_instance->instance();
1242         JNIEnv* env = getJNIEnv();
1243         // This is odd. getRealObject returns an AutoJObject which is used to
1244         // cleanly create and delete a local reference. But, here we need to
1245         // maintain the local reference across calls to virtualBegin() and
1246         // virtualEnd(). So, release the local reference from the AutoJObject
1247         // and delete the local reference in virtualEnd().
1248         m_realObject = getRealObject(env, m_weakRef).release();
1249         // Point to the real object
1250         m_instance->setInstance(m_realObject);
1251         // Call the base class method
1252         INHERITED::virtualBegin();
1253     }
1254 
virtualEnd()1255     virtual void virtualEnd()
1256     {
1257         if (--m_beginEndDepth > 0)
1258             return;
1259         // Call the base class method first to pop the local frame.
1260         INHERITED::virtualEnd();
1261         // Get rid of the local reference to the real object.
1262         getJNIEnv()->DeleteLocalRef(m_realObject);
1263         // Point back to the WeakReference.
1264         m_instance->setInstance(m_weakRef);
1265     }
1266 
1267 private:
1268     typedef JavaInstance INHERITED;
1269     jobject m_realObject;
1270     jweak m_weakRef;
1271     // The current depth of nested calls to virtualBegin and virtualEnd.
1272     int m_beginEndDepth;
1273 };
1274 
AddJavascriptInterface(JNIEnv * env,jobject obj,jint nativeFramePointer,jobject javascriptObj,jstring interfaceName)1275 static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePointer,
1276         jobject javascriptObj, jstring interfaceName)
1277 {
1278 #ifdef ANDROID_INSTRUMENT
1279     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1280 #endif
1281     WebCore::Frame* pFrame = 0;
1282     if (nativeFramePointer == 0)
1283         pFrame = GET_NATIVE_FRAME(env, obj);
1284     else
1285         pFrame = (WebCore::Frame*)nativeFramePointer;
1286     LOG_ASSERT(pFrame, "nativeAddJavascriptInterface must take a valid frame pointer!");
1287 
1288     JavaVM* vm;
1289     env->GetJavaVM(&vm);
1290     LOGV("::WebCore:: addJSInterface: %p", pFrame);
1291 
1292 #if USE(JSC)
1293     // Copied from qwebframe.cpp
1294     JSC::JSLock lock(false);
1295     WebCore::JSDOMWindow *window = WebCore::toJSDOMWindow(pFrame, mainThreadNormalWorld());
1296     if (window) {
1297         RootObject *root = pFrame->script()->bindingRootObject();
1298         setJavaVM(vm);
1299         // Add the binding to JS environment
1300         JSC::ExecState* exec = window->globalExec();
1301         JSC::JSObject* addedObject = WeakJavaInstance::create(javascriptObj,
1302                 root)->createRuntimeObject(exec);
1303         const jchar* s = env->GetStringChars(interfaceName, NULL);
1304         if (s) {
1305             // Add the binding name to the window's table of child objects.
1306             JSC::PutPropertySlot slot;
1307             window->put(exec, JSC::Identifier(exec, (const UChar *)s,
1308                     env->GetStringLength(interfaceName)), addedObject, slot);
1309             env->ReleaseStringChars(interfaceName, s);
1310             checkException(env);
1311         }
1312     }
1313 #elif USE(V8)
1314     if (pFrame) {
1315         PassRefPtr<JavaInstance> addedObject = WeakJavaInstance::create(javascriptObj);
1316         const char* name = getCharactersFromJStringInEnv(env, interfaceName);
1317         // Pass ownership of the added object to bindToWindowObject.
1318         NPObject* npObject = JavaInstanceToNPObject(addedObject);
1319         pFrame->script()->bindToWindowObject(pFrame, name, npObject);
1320         // bindToWindowObject calls NPN_RetainObject on the
1321         // returned one (see createV8ObjectForNPObject in V8NPObject.cpp).
1322         // bindToWindowObject also increases obj's ref count and decreases
1323         // the ref count when the object is not reachable from JavaScript
1324         // side. Code here must release the reference count increased by
1325         // bindToWindowObject.
1326 
1327         // Note that while this function is declared in WebCore/bridge/npruntime.h, for V8 builds
1328         // we use WebCore/bindings/v8/npruntime.cpp (rather than
1329         // WebCore/bridge/npruntime.cpp), so the function is implemented there.
1330         // TODO: Combine the two versions of these NPAPI files.
1331         NPN_ReleaseObject(npObject);
1332         releaseCharactersForJString(interfaceName, name);
1333     }
1334 #endif
1335 
1336 }
1337 
SetCacheDisabled(JNIEnv * env,jobject obj,jboolean disabled)1338 static void SetCacheDisabled(JNIEnv *env, jobject obj, jboolean disabled)
1339 {
1340 #ifdef ANDROID_INSTRUMENT
1341     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1342 #endif
1343     WebCore::cache()->setDisabled(disabled);
1344 }
1345 
CacheDisabled(JNIEnv * env,jobject obj)1346 static jboolean CacheDisabled(JNIEnv *env, jobject obj)
1347 {
1348 #ifdef ANDROID_INSTRUMENT
1349     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1350 #endif
1351     return WebCore::cache()->disabled();
1352 }
1353 
ClearCache(JNIEnv * env,jobject obj)1354 static void ClearCache(JNIEnv *env, jobject obj)
1355 {
1356 #ifdef ANDROID_INSTRUMENT
1357     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1358 #if USE(JSC)
1359     JSC::JSLock lock(false);
1360     JSC::Heap::Statistics jsHeapStatistics = WebCore::JSDOMWindow::commonJSGlobalData()->heap.statistics();
1361     LOGD("About to gc and JavaScript heap size is %d and has %d bytes free",
1362             jsHeapStatistics.size, jsHeapStatistics.free);
1363 #endif  // USE(JSC)
1364     LOGD("About to clear cache and current cache has %d bytes live and %d bytes dead",
1365             cache()->getLiveSize(), cache()->getDeadSize());
1366 #endif  // ANDROID_INSTRUMENT
1367     if (!WebCore::cache()->disabled()) {
1368         // Disabling the cache will remove all resources from the cache.  They may
1369         // still live on if they are referenced by some Web page though.
1370         WebCore::cache()->setDisabled(true);
1371         WebCore::cache()->setDisabled(false);
1372     }
1373 
1374     // clear page cache
1375     int pageCapacity = WebCore::pageCache()->capacity();
1376     // Setting size to 0, makes all pages be released.
1377     WebCore::pageCache()->setCapacity(0);
1378     WebCore::pageCache()->releaseAutoreleasedPagesNow();
1379     WebCore::pageCache()->setCapacity(pageCapacity);
1380 
1381 #if USE(JSC)
1382     // force JavaScript to GC when clear cache
1383     WebCore::gcController().garbageCollectSoon();
1384 #elif USE(V8)
1385     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1386     pFrame->script()->lowMemoryNotification();
1387 #endif  // USE(JSC)
1388 }
1389 
DocumentHasImages(JNIEnv * env,jobject obj)1390 static jboolean DocumentHasImages(JNIEnv *env, jobject obj)
1391 {
1392 #ifdef ANDROID_INSTRUMENT
1393     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1394 #endif
1395     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1396     LOG_ASSERT(pFrame, "DocumentHasImages must take a valid frame pointer!");
1397 
1398     return pFrame->document()->images()->length() > 0;
1399 }
1400 
HasPasswordField(JNIEnv * env,jobject obj)1401 static jboolean HasPasswordField(JNIEnv *env, jobject obj)
1402 {
1403 #ifdef ANDROID_INSTRUMENT
1404     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1405 #endif
1406     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1407     LOG_ASSERT(pFrame, "HasPasswordField must take a valid frame pointer!");
1408 
1409     bool found = false;
1410     WTF::PassRefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms();
1411     WebCore::Node* node = form->firstItem();
1412     // Null/Empty namespace means that node is not created in HTMLFormElement
1413     // class, but just normal Element class.
1414     while (node && !found && !node->namespaceURI().isNull() &&
1415            !node->namespaceURI().isEmpty()) {
1416         WTF::Vector<WebCore::HTMLFormControlElement*>& elements =
1417         		((WebCore::HTMLFormElement*)node)->formElements;
1418         size_t size = elements.size();
1419         for (size_t i = 0; i< size && !found; i++) {
1420             WebCore::HTMLFormControlElement* e = elements[i];
1421             if (e->hasLocalName(WebCore::HTMLNames::inputTag)) {
1422                 if (((WebCore::HTMLInputElement*)e)->inputType() ==
1423                 		WebCore::HTMLInputElement::PASSWORD)
1424                     found = true;
1425             }
1426         }
1427         node = form->nextItem();
1428     }
1429     return found;
1430 }
1431 
GetUsernamePassword(JNIEnv * env,jobject obj)1432 static jobjectArray GetUsernamePassword(JNIEnv *env, jobject obj)
1433 {
1434 #ifdef ANDROID_INSTRUMENT
1435     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1436 #endif
1437     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1438     LOG_ASSERT(pFrame, "GetUsernamePassword must take a valid frame pointer!");
1439     jobjectArray strArray = NULL;
1440 
1441     WebCore::String username, password;
1442     bool found = false;
1443     WTF::PassRefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms();
1444     WebCore::Node* node = form->firstItem();
1445     while (node && !found && !node->namespaceURI().isNull() &&
1446            !node->namespaceURI().isEmpty()) {
1447         WTF::Vector<WebCore::HTMLFormControlElement*>& elements =
1448         		((WebCore::HTMLFormElement*)node)->formElements;
1449         size_t size = elements.size();
1450         for (size_t i = 0; i< size && !found; i++) {
1451             WebCore::HTMLFormControlElement* e = elements[i];
1452             if (e->hasLocalName(WebCore::HTMLNames::inputTag)) {
1453                 WebCore::HTMLInputElement* input = (WebCore::HTMLInputElement*)e;
1454                 if (input->autoComplete() == false)
1455                     continue;
1456                 if (input->inputType() == WebCore::HTMLInputElement::PASSWORD)
1457                     password = input->value();
1458                 else if (input->inputType() == WebCore::HTMLInputElement::TEXT)
1459                     username = input->value();
1460                 if (!username.isNull() && !password.isNull())
1461                     found = true;
1462             }
1463         }
1464         node = form->nextItem();
1465     }
1466     if (found) {
1467         jclass stringClass = env->FindClass("java/lang/String");
1468         strArray = env->NewObjectArray(2, stringClass, NULL);
1469         env->SetObjectArrayElement(strArray, 0, env->NewString((unsigned short *)
1470                 username.characters(), username.length()));
1471         env->SetObjectArrayElement(strArray, 1, env->NewString((unsigned short *)
1472                 password.characters(), password.length()));
1473     }
1474     return strArray;
1475 }
1476 
SetUsernamePassword(JNIEnv * env,jobject obj,jstring username,jstring password)1477 static void SetUsernamePassword(JNIEnv *env, jobject obj,
1478     jstring username, jstring password)
1479 {
1480 #ifdef ANDROID_INSTRUMENT
1481     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1482 #endif
1483     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1484     LOG_ASSERT(pFrame, "SetUsernamePassword must take a valid frame pointer!");
1485 
1486     WebCore::HTMLInputElement* usernameEle = NULL;
1487     WebCore::HTMLInputElement* passwordEle = NULL;
1488     bool found = false;
1489     WTF::PassRefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms();
1490     WebCore::Node* node = form->firstItem();
1491     while (node && !found && !node->namespaceURI().isNull() &&
1492            !node->namespaceURI().isEmpty()) {
1493         WTF::Vector<WebCore::HTMLFormControlElement*>& elements =
1494         		((WebCore::HTMLFormElement*)node)->formElements;
1495         size_t size = elements.size();
1496         for (size_t i = 0; i< size && !found; i++) {
1497             WebCore::HTMLFormControlElement* e = elements[i];
1498             if (e->hasLocalName(WebCore::HTMLNames::inputTag)) {
1499                 WebCore::HTMLInputElement* input = (WebCore::HTMLInputElement*)e;
1500                 if (input->autoComplete() == false)
1501                     continue;
1502                 if (input->inputType() == WebCore::HTMLInputElement::PASSWORD)
1503                     passwordEle = input;
1504                 else if (input->inputType() == WebCore::HTMLInputElement::TEXT)
1505                     usernameEle = input;
1506                 if (usernameEle != NULL && passwordEle != NULL)
1507                     found = true;
1508             }
1509         }
1510         node = form->nextItem();
1511     }
1512     if (found) {
1513         usernameEle->setValue(to_string(env, username));
1514         passwordEle->setValue(to_string(env, password));
1515     }
1516 }
1517 
GetFormTextData(JNIEnv * env,jobject obj)1518 static jobject GetFormTextData(JNIEnv *env, jobject obj)
1519 {
1520 #ifdef ANDROID_INSTRUMENT
1521     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1522 #endif
1523     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1524     LOG_ASSERT(pFrame, "GetFormTextData must take a valid frame pointer!");
1525     jobject hashMap = NULL;
1526 
1527     WTF::PassRefPtr<WebCore::HTMLCollection> collection = pFrame->document()->forms();
1528     if (collection->length() > 0) {
1529         jclass mapClass = env->FindClass("java/util/HashMap");
1530         LOG_ASSERT(mapClass, "Could not find HashMap class!");
1531         jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V");
1532         LOG_ASSERT(init, "Could not find constructor for HashMap");
1533         hashMap = env->NewObject(mapClass, init, 1);
1534         LOG_ASSERT(hashMap, "Could not create a new HashMap");
1535         jmethodID put = env->GetMethodID(mapClass, "put",
1536                 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
1537         LOG_ASSERT(put, "Could not find put method on HashMap");
1538 
1539         WebCore::HTMLFormElement* form;
1540         WebCore::HTMLInputElement* input;
1541         for (WebCore::Node* node = collection->firstItem();
1542              node && !node->namespaceURI().isNull() && !node->namespaceURI().isEmpty();
1543              node = collection->nextItem()) {
1544             form = static_cast<WebCore::HTMLFormElement*>(node);
1545             if (form->autoComplete()) {
1546                 WTF::Vector<WebCore::HTMLFormControlElement*> elements = form->formElements;
1547                 size_t size = elements.size();
1548                 for (size_t i = 0; i < size; i++) {
1549                     WebCore::HTMLFormControlElement* e = elements[i];
1550                     if (e->hasTagName(WebCore::HTMLNames::inputTag)) {
1551                         input = static_cast<WebCore::HTMLInputElement*>(e);
1552                         if (input->isTextField() && !input->isPasswordField()
1553                                 && input->autoComplete()) {
1554                             WebCore::String value = input->value();
1555                             int len = value.length();
1556                             if (len) {
1557                                 const WebCore::AtomicString& name = input->name();
1558                                 jstring key = env->NewString((jchar *)name.characters(), name.length());
1559                                 jstring val = env->NewString((jchar *)value.characters(), len);
1560                                 LOG_ASSERT(key && val, "name or value not set");
1561                                 env->CallObjectMethod(hashMap, put, key, val);
1562                                 env->DeleteLocalRef(key);
1563                                 env->DeleteLocalRef(val);
1564                             }
1565                         }
1566                     }
1567                 }
1568             }
1569         }
1570         env->DeleteLocalRef(mapClass);
1571 
1572     }
1573     return hashMap;
1574 }
1575 
OrientationChanged(JNIEnv * env,jobject obj,int orientation)1576 static void OrientationChanged(JNIEnv *env, jobject obj, int orientation)
1577 {
1578 #ifdef ANDROID_INSTRUMENT
1579     TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
1580 #endif
1581     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
1582     LOGV("Sending orientation: %d", orientation);
1583     pFrame->sendOrientationChangeEvent(orientation);
1584 }
1585 
1586 // ----------------------------------------------------------------------------
1587 
1588 /*
1589  * JNI registration.
1590  */
1591 static JNINativeMethod gBrowserFrameNativeMethods[] = {
1592     /* name, signature, funcPtr */
1593     { "nativeCallPolicyFunction", "(II)V",
1594         (void*) CallPolicyFunction },
1595     { "nativeCreateFrame", "(Landroid/webkit/WebViewCore;Landroid/content/res/AssetManager;Landroid/webkit/WebBackForwardList;)V",
1596         (void*) CreateFrame },
1597     { "nativeDestroyFrame", "()V",
1598         (void*) DestroyFrame },
1599     { "nativeStopLoading", "()V",
1600         (void*) StopLoading },
1601     { "nativeLoadUrl", "(Ljava/lang/String;Ljava/util/Map;)V",
1602         (void*) LoadUrl },
1603     { "nativePostUrl", "(Ljava/lang/String;[B)V",
1604         (void*) PostUrl },
1605     { "nativeLoadData", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
1606         (void*) LoadData },
1607     { "externalRepresentation", "()Ljava/lang/String;",
1608         (void*) ExternalRepresentation },
1609     { "documentAsText", "()Ljava/lang/String;",
1610         (void*) DocumentAsText },
1611     { "reload", "(Z)V",
1612         (void*) Reload },
1613     { "nativeGoBackOrForward", "(I)V",
1614         (void*) GoBackOrForward },
1615     { "nativeAddJavascriptInterface", "(ILjava/lang/Object;Ljava/lang/String;)V",
1616         (void*) AddJavascriptInterface },
1617     { "stringByEvaluatingJavaScriptFromString",
1618             "(Ljava/lang/String;)Ljava/lang/String;",
1619         (void*) StringByEvaluatingJavaScriptFromString },
1620     { "setCacheDisabled", "(Z)V",
1621         (void*) SetCacheDisabled },
1622     { "cacheDisabled", "()Z",
1623         (void*) CacheDisabled },
1624     { "clearCache", "()V",
1625         (void*) ClearCache },
1626     { "documentHasImages", "()Z",
1627         (void*) DocumentHasImages },
1628     { "hasPasswordField", "()Z",
1629         (void*) HasPasswordField },
1630     { "getUsernamePassword", "()[Ljava/lang/String;",
1631         (void*) GetUsernamePassword },
1632     { "setUsernamePassword", "(Ljava/lang/String;Ljava/lang/String;)V",
1633         (void*) SetUsernamePassword },
1634     { "getFormTextData", "()Ljava/util/HashMap;",
1635         (void*) GetFormTextData },
1636     { "nativeOrientationChanged", "(I)V",
1637         (void*) OrientationChanged }
1638 };
1639 
register_webframe(JNIEnv * env)1640 int register_webframe(JNIEnv* env)
1641 {
1642     jclass clazz = env->FindClass("android/webkit/BrowserFrame");
1643     LOG_ASSERT(clazz, "Cannot find BrowserFrame");
1644     gFrameField = env->GetFieldID(clazz, "mNativeFrame", "I");
1645     LOG_ASSERT(gFrameField, "Cannot find mNativeFrame on BrowserFrame");
1646 
1647     return jniRegisterNativeMethods(env, "android/webkit/BrowserFrame",
1648             gBrowserFrameNativeMethods, NELEM(gBrowserFrameNativeMethods));
1649 }
1650 
1651 } /* namespace android */
1652