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