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