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