Home | History | Annotate | Download | only in jni
      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 
    137 String* WebCore::PlatformBridge::globalLocalizedName(
    138         WebCore::PlatformBridge::rawResId resId)
    139 {
    140     switch (resId) {
    141     case WebCore::PlatformBridge::FileUploadLabel:
    142         return gUploadFileLabel;
    143     case WebCore::PlatformBridge::ResetLabel:
    144         return gResetLabel;
    145     case WebCore::PlatformBridge::SubmitLabel:
    146         return gSubmitLabel;
    147     case WebCore::PlatformBridge::FileUploadNoFileChosenLabel:
    148         return gNoFileChosenLabel;
    149 
    150     default:
    151         return 0;
    152     }
    153 }
    154 /**
    155  * Instantiate the localized name desired.
    156  */
    157 void initGlobalLocalizedName(WebCore::PlatformBridge::rawResId resId,
    158         android::WebFrame* webFrame)
    159 {
    160     String** pointer;
    161     switch (resId) {
    162     case WebCore::PlatformBridge::FileUploadLabel:
    163         pointer = &gUploadFileLabel;
    164         break;
    165     case WebCore::PlatformBridge::ResetLabel:
    166         pointer = &gResetLabel;
    167         break;
    168     case WebCore::PlatformBridge::SubmitLabel:
    169         pointer = &gSubmitLabel;
    170         break;
    171     case WebCore::PlatformBridge::FileUploadNoFileChosenLabel:
    172         pointer = &gNoFileChosenLabel;
    173         break;
    174     default:
    175         return;
    176     }
    177     if (!(*pointer) && webFrame) {
    178         (*pointer) = new String(webFrame->getRawResourceFilename(resId).impl());
    179     }
    180 }
    181 
    182 namespace android {
    183 
    184 // ----------------------------------------------------------------------------
    185 
    186 #define WEBCORE_MEMORY_CAP 15 * 1024 * 1024
    187 
    188 // ----------------------------------------------------------------------------
    189 
    190 struct WebFrame::JavaBrowserFrame
    191 {
    192     jweak       mObj;
    193     jweak       mHistoryList; // WebBackForwardList object
    194     jmethodID   mStartLoadingResource;
    195     jmethodID   mMaybeSavePassword;
    196     jmethodID   mShouldInterceptRequest;
    197     jmethodID   mLoadStarted;
    198     jmethodID   mTransitionToCommitted;
    199     jmethodID   mLoadFinished;
    200     jmethodID   mReportError;
    201     jmethodID   mSetTitle;
    202     jmethodID   mWindowObjectCleared;
    203     jmethodID   mSetProgress;
    204     jmethodID   mDidReceiveIcon;
    205     jmethodID   mDidReceiveTouchIconUrl;
    206     jmethodID   mUpdateVisitedHistory;
    207     jmethodID   mHandleUrl;
    208     jmethodID   mCreateWindow;
    209     jmethodID   mCloseWindow;
    210     jmethodID   mDecidePolicyForFormResubmission;
    211     jmethodID   mRequestFocus;
    212     jmethodID   mGetRawResFilename;
    213     jmethodID   mDensity;
    214     jmethodID   mGetFileSize;
    215     jmethodID   mGetFile;
    216     jmethodID   mDidReceiveAuthenticationChallenge;
    217     jmethodID   mReportSslCertError;
    218     jmethodID   mRequestClientCert;
    219     jmethodID   mDownloadStart;
    220     jmethodID   mDidReceiveData;
    221     jmethodID   mDidFinishLoading;
    222     jmethodID   mSetCertificate;
    223     jmethodID   mShouldSaveFormData;
    224     jmethodID   mSaveFormData;
    225     jmethodID   mAutoLogin;
    226     AutoJObject frame(JNIEnv* env) {
    227         return getRealObject(env, mObj);
    228     }
    229     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 
    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 
    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 
    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 
    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:
    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     }
    405     ~FileInfo() {
    406         m_env->DeleteLocalRef(m_uri);
    407     }
    408     int getSize() { return m_size; }
    409     jstring getUri() { return m_uri; }
    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>
    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*
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    768 WebFrame::userAgentForURL(const WebCore::KURL* url)
    769 {
    770     return mUserAgent;
    771 }
    772 
    773 void
    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
    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
    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
    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
    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*
    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
    891 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
    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
    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
    941 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
    953 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
    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
    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
   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
   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
   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
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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)
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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)
   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)
   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     }
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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
   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 
   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 static jboolean GetShouldStartScrolledRight(JNIEnv *env, jobject obj,
   2121         jint browserFrame)
   2122 {
   2123     jboolean startScrolledRight = false; // default is start scrolled left
   2124     WebCore::Frame* frame = reinterpret_cast<WebCore::Frame*>(browserFrame);
   2125     WebCore::Document* document = frame->document();
   2126     if (document) {
   2127         RenderStyle* style = document->renderer()->style();
   2128         WritingMode writingMode = style->writingMode();
   2129         LOG_ASSERT(writingMode != WebCore::BottomToTopWritingMode,
   2130                 "BottomToTopWritingMode isn't supported");
   2131         if (writingMode == WebCore::RightToLeftWritingMode)
   2132             startScrolledRight = true; // vertical-rl pages start scrolled right
   2133         else if (writingMode == WebCore::TopToBottomWritingMode)
   2134             startScrolledRight = !style->isLeftToRightDirection(); // RTL starts right
   2135     }
   2136     return startScrolledRight;
   2137 }
   2138 
   2139 #if USE(CHROME_NETWORK_STACK)
   2140 
   2141 static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword)
   2142 {
   2143     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
   2144     std::string username = jstringToStdString(env, jUsername);
   2145     std::string password = jstringToStdString(env, jPassword);
   2146     client->setAuth(username, password);
   2147 }
   2148 
   2149 static void AuthenticationCancel(JNIEnv *env, jobject obj, int handle)
   2150 {
   2151     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
   2152     client->cancelAuth();
   2153 }
   2154 
   2155 static void SslCertErrorProceed(JNIEnv *env, jobject obj, int handle)
   2156 {
   2157     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
   2158     client->proceedSslCertError();
   2159 }
   2160 
   2161 static void SslCertErrorCancel(JNIEnv *env, jobject obj, int handle, int cert_error)
   2162 {
   2163     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
   2164     client->cancelSslCertError(cert_error);
   2165 }
   2166 
   2167 static void SslClientCert(JNIEnv *env, jobject obj, int handle, jbyteArray pkey, jobjectArray chain)
   2168 {
   2169     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
   2170     if (pkey == NULL || chain == NULL) {
   2171         client->sslClientCert(NULL, NULL);
   2172         return;
   2173     }
   2174 
   2175     // Based on Android's NativeCrypto_SSL_use_PrivateKey
   2176     ScopedByteArrayRO pkeyBytes(env, pkey);
   2177     if (pkeyBytes.get() == NULL) {
   2178         client->sslClientCert(NULL, NULL);
   2179         return;
   2180     }
   2181 
   2182     base::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> pkcs8;
   2183     const unsigned char* pkeyChars = reinterpret_cast<const unsigned char*>(pkeyBytes.get());
   2184     pkcs8.reset(d2i_PKCS8_PRIV_KEY_INFO(NULL, &pkeyChars, pkeyBytes.size()));
   2185     if (!pkcs8.get()) {
   2186         client->sslClientCert(NULL, NULL);
   2187         return;
   2188     }
   2189     base::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> privateKey(EVP_PKCS82PKEY(pkcs8.get()));
   2190     if (!privateKey.get()) {
   2191         client->sslClientCert(NULL, NULL);
   2192         return;
   2193     }
   2194 
   2195     // Based on Android's NativeCrypto_SSL_use_certificate
   2196     int length = env->GetArrayLength(chain);
   2197     if (length == 0) {
   2198         client->sslClientCert(NULL, NULL);
   2199         return;
   2200     }
   2201 
   2202     base::ScopedOpenSSL<X509, X509_free> first;
   2203     ScopedVector<base::ScopedOpenSSL<X509, X509_free> > rest;
   2204     for (int i = 0; i < length; i++) {
   2205         ScopedLocalRef<jbyteArray> cert(env,
   2206                 reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(chain, i)));
   2207         if (cert.get() == NULL) {
   2208             client->sslClientCert(NULL, NULL);
   2209             return;
   2210         }
   2211         ScopedByteArrayRO certBytes(env, cert.get());
   2212         if (certBytes.get() == NULL) {
   2213             client->sslClientCert(NULL, NULL);
   2214             return;
   2215         }
   2216         const char* data = reinterpret_cast<const char*>(certBytes.get());
   2217         int length = certBytes.size();
   2218         X509* x509 = net::X509Certificate::CreateOSCertHandleFromBytes(data, length);
   2219         if (x509 == NULL) {
   2220             client->sslClientCert(NULL, NULL);
   2221             return;
   2222         }
   2223         if (i == 0) {
   2224             first.reset(x509);
   2225         } else {
   2226             rest.push_back(new base::ScopedOpenSSL<X509, X509_free>(x509));
   2227         }
   2228     }
   2229 
   2230     std::vector<X509*> certChain(rest.size());
   2231     for (size_t i = 0; i < rest.size(); i++) {
   2232         certChain[i] = rest[i]->get();
   2233     }
   2234     net::X509Certificate* certificate
   2235             = net::X509Certificate::CreateFromHandle(first.get(),
   2236                                                      net::X509Certificate::SOURCE_FROM_NETWORK,
   2237                                                      certChain);
   2238     if (certificate == NULL) {
   2239         client->sslClientCert(NULL, NULL);
   2240         return;
   2241     }
   2242     client->sslClientCert(privateKey.release(), certificate);
   2243 }
   2244 
   2245 #else
   2246 
   2247 static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword)
   2248 {
   2249     LOGW("Chromium authentication API called, but libchromium is not available");
   2250 }
   2251 
   2252 static void AuthenticationCancel(JNIEnv *env, jobject obj, int handle)
   2253 {
   2254     LOGW("Chromium authentication API called, but libchromium is not available");
   2255 }
   2256 
   2257 static void SslCertErrorProceed(JNIEnv *env, jobject obj, int handle)
   2258 {
   2259     LOGW("Chromium SSL API called, but libchromium is not available");
   2260 }
   2261 
   2262 static void SslCertErrorCancel(JNIEnv *env, jobject obj, int handle, int cert_error)
   2263 {
   2264     LOGW("Chromium SSL API called, but libchromium is not available");
   2265 }
   2266 
   2267 static void SslClientCert(JNIEnv *env, jobject obj, int handle, jbyteArray privateKey, jobjectArray chain)
   2268 {
   2269     LOGW("Chromium SSL API called, but libchromium is not available");
   2270 }
   2271 #endif // USE(CHROME_NETWORK_STACK)
   2272 
   2273 // ----------------------------------------------------------------------------
   2274 
   2275 /*
   2276  * JNI registration.
   2277  */
   2278 static JNINativeMethod gBrowserFrameNativeMethods[] = {
   2279     /* name, signature, funcPtr */
   2280     { "nativeCallPolicyFunction", "(II)V",
   2281         (void*) CallPolicyFunction },
   2282     { "nativeCreateFrame", "(Landroid/webkit/WebViewCore;Landroid/content/res/AssetManager;Landroid/webkit/WebBackForwardList;)V",
   2283         (void*) CreateFrame },
   2284     { "nativeDestroyFrame", "()V",
   2285         (void*) DestroyFrame },
   2286     { "nativeStopLoading", "()V",
   2287         (void*) StopLoading },
   2288     { "nativeLoadUrl", "(Ljava/lang/String;Ljava/util/Map;)V",
   2289         (void*) LoadUrl },
   2290     { "nativePostUrl", "(Ljava/lang/String;[B)V",
   2291         (void*) PostUrl },
   2292     { "nativeLoadData", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
   2293         (void*) LoadData },
   2294     { "nativeSaveWebArchive", "(Ljava/lang/String;Z)Ljava/lang/String;",
   2295         (void*) SaveWebArchive },
   2296     { "externalRepresentation", "()Ljava/lang/String;",
   2297         (void*) ExternalRepresentation },
   2298     { "documentAsText", "()Ljava/lang/String;",
   2299         (void*) DocumentAsText },
   2300     { "childFramesAsText", "()Ljava/lang/String;",
   2301         (void*) ChildFramesAsText },
   2302     { "reload", "(Z)V",
   2303         (void*) Reload },
   2304     { "nativeGoBackOrForward", "(I)V",
   2305         (void*) GoBackOrForward },
   2306     { "nativeAddJavascriptInterface", "(ILjava/lang/Object;Ljava/lang/String;)V",
   2307         (void*) AddJavascriptInterface },
   2308     { "stringByEvaluatingJavaScriptFromString",
   2309             "(Ljava/lang/String;)Ljava/lang/String;",
   2310         (void*) StringByEvaluatingJavaScriptFromString },
   2311     { "setCacheDisabled", "(Z)V",
   2312         (void*) SetCacheDisabled },
   2313     { "cacheDisabled", "()Z",
   2314         (void*) CacheDisabled },
   2315     { "clearCache", "()V",
   2316         (void*) ClearCache },
   2317     { "documentHasImages", "()Z",
   2318         (void*) DocumentHasImages },
   2319     { "hasPasswordField", "()Z",
   2320         (void*) HasPasswordField },
   2321     { "getUsernamePassword", "()[Ljava/lang/String;",
   2322         (void*) GetUsernamePassword },
   2323     { "setUsernamePassword", "(Ljava/lang/String;Ljava/lang/String;)V",
   2324         (void*) SetUsernamePassword },
   2325     { "nativeOrientationChanged", "(I)V",
   2326         (void*) OrientationChanged },
   2327     { "nativeAuthenticationProceed", "(ILjava/lang/String;Ljava/lang/String;)V",
   2328         (void*) AuthenticationProceed },
   2329     { "nativeAuthenticationCancel", "(I)V",
   2330         (void*) AuthenticationCancel },
   2331     { "nativeSslCertErrorProceed", "(I)V",
   2332         (void*) SslCertErrorProceed },
   2333     { "nativeSslCertErrorCancel", "(II)V",
   2334         (void*) SslCertErrorCancel },
   2335     { "nativeSslClientCert", "(I[B[[B)V",
   2336         (void*) SslClientCert },
   2337     { "nativeGetShouldStartScrolledRight", "(I)Z",
   2338         (void*) GetShouldStartScrolledRight },
   2339 };
   2340 
   2341 int registerWebFrame(JNIEnv* env)
   2342 {
   2343     jclass clazz = env->FindClass("android/webkit/BrowserFrame");
   2344     LOG_ASSERT(clazz, "Cannot find BrowserFrame");
   2345     gFrameField = env->GetFieldID(clazz, "mNativeFrame", "I");
   2346     LOG_ASSERT(gFrameField, "Cannot find mNativeFrame on BrowserFrame");
   2347     env->DeleteLocalRef(clazz);
   2348 
   2349     return jniRegisterNativeMethods(env, "android/webkit/BrowserFrame",
   2350             gBrowserFrameNativeMethods, NELEM(gBrowserFrameNativeMethods));
   2351 }
   2352 
   2353 } /* namespace android */
   2354