diff options
Diffstat (limited to 'WebKit/android/jni/WebCoreFrameBridge.cpp')
| -rw-r--r-- | WebKit/android/jni/WebCoreFrameBridge.cpp | 193 |
1 files changed, 161 insertions, 32 deletions
diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index 250ffc9..bfd4b62 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -32,7 +32,6 @@ #include "AtomicString.h" #include "BackForwardList.h" #include "Cache.h" -#include "CString.h" #include "Chrome.h" #include "ChromeClientAndroid.h" #include "ContextMenuClientAndroid.h" @@ -74,6 +73,7 @@ #include "SecurityOrigin.h" #include "SelectionController.h" #include "Settings.h" +#include "StringBuilder.h" #include "SubstituteData.h" #include "WebCoreJni.h" #include "WebCoreResourceLoader.h" @@ -93,6 +93,7 @@ #include <utils/AssetManager.h> #include <wtf/CurrentTime.h> #include <wtf/Platform.h> +#include <wtf/text/CString.h> #if USE(JSC) #include "GCController.h" @@ -111,11 +112,16 @@ #include "TimeCounter.h" #endif +#if ENABLE(ARCHIVE) +#include "WebArchiveAndroid.h" +#endif + using namespace JSC::Bindings; static String* gUploadFileLabel; static String* gResetLabel; static String* gSubmitLabel; +static String* gNoFileChosenLabel; String* WebCore::PlatformBridge::globalLocalizedName( WebCore::PlatformBridge::rawResId resId) @@ -127,6 +133,9 @@ String* WebCore::PlatformBridge::globalLocalizedName( return gResetLabel; case WebCore::PlatformBridge::SubmitLabel: return gSubmitLabel; + case WebCore::PlatformBridge::FileUploadNoFileChosenLabel: + return gNoFileChosenLabel; + default: return 0; } @@ -148,6 +157,9 @@ void initGlobalLocalizedName(WebCore::PlatformBridge::rawResId resId, case WebCore::PlatformBridge::SubmitLabel: pointer = &gSubmitLabel; break; + case WebCore::PlatformBridge::FileUploadNoFileChosenLabel: + pointer = &gNoFileChosenLabel; + break; default: return; } @@ -310,9 +322,9 @@ static jobject createJavaMapFromHTTPHeaders(JNIEnv* env, const WebCore::HTTPHead jstring val = env->NewString((unsigned short *)i->second.characters(), i->second.length()); if (key && val) { env->CallObjectMethod(hashMap, put, key, val); - env->DeleteLocalRef(key); - env->DeleteLocalRef(val); } + env->DeleteLocalRef(key); + env->DeleteLocalRef(val); } env->DeleteLocalRef(mapClass); @@ -320,19 +332,6 @@ static jobject createJavaMapFromHTTPHeaders(JNIEnv* env, const WebCore::HTTPHead return hashMap; } -// In WebViewCore.java, we artificially append the filename to the URI so that -// webkit treats the actual display name of the file as the filename, rather -// than the last segment of the URI (which will simply be a number). When we -// pass the URI up to BrowserFrame, we no longer need the appended name (in fact -// it causes problems), so remove it here. -// FIXME: If we rewrite pathGetFileName (the current version is in -// FileSystemPOSIX), we can get the filename that way rather than appending it. -static jstring uriFromUriFileName(JNIEnv* env, const WebCore::String& name) -{ - const WebCore::String fileName = name.left(name.reverseFind('/')); - return env->NewString(fileName.characters(), fileName.length()); -} - // This class stores the URI and the size of each file for upload. The URI is // stored so we do not have to create it again. The size is stored so we can // compare the actual size of the file with the stated size. If the actual size @@ -341,7 +340,7 @@ static jstring uriFromUriFileName(JNIEnv* env, const WebCore::String& name) class FileInfo { public: FileInfo(JNIEnv* env, const WebCore::String& name) { - m_uri = uriFromUriFileName(env, name); + m_uri = env->NewString(name.characters(), name.length()); checkException(env); m_size = 0; m_env = env; @@ -722,6 +721,7 @@ WebFrame::didReceiveTouchIconURL(const WebCore::String& url, bool precomposed) env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDidReceiveTouchIconUrl, jUrlStr, precomposed); + env->DeleteLocalRef(jUrlStr); checkException(env); } @@ -736,6 +736,7 @@ WebFrame::updateVisitedHistory(const WebCore::KURL& url, bool reload) jstring jUrlStr = env->NewString((unsigned short*)urlStr.characters(), urlStr.length()); env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mUpdateVisitedHistory, jUrlStr, reload); + env->DeleteLocalRef(jUrlStr); checkException(env); } @@ -765,6 +766,7 @@ WebFrame::canHandleRequest(const WebCore::ResourceRequest& request) // if browser app handles the url, we will return false to bail out WebCore loading jboolean ret = env->CallBooleanMethod(mJavaFrame->frame(env).get(), mJavaFrame->mHandleUrl, jUrlStr); checkException(env); + env->DeleteLocalRef(jUrlStr); return (ret == 0); } @@ -882,7 +884,8 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss dragC, inspectorC, 0, // PluginHalterClient - 0); // GeolocationControllerClient + 0, // GeolocationControllerClient + 0); // DeviceOrientationClient // css files without explicit MIMETYPE is treated as generic text files in // the Java side. So we can't enforce CSS MIMETYPE. page->settings()->setEnforceCSSMIMETypeInStrictMode(false); @@ -940,7 +943,7 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss WebCore::RenderSkinAndroid::Init(am, directory); } for (int i = WebCore::PlatformBridge::FileUploadLabel; - i <= WebCore::PlatformBridge::SubmitLabel; i++) + i <= WebCore::PlatformBridge::FileUploadNoFileChosenLabel; i++) initGlobalLocalizedName( static_cast<WebCore::PlatformBridge::rawResId>(i), webFrame); } @@ -1096,6 +1099,91 @@ static void StopLoading(JNIEnv *env, jobject obj) pFrame->loader()->stopForUserCancel(); } +#if ENABLE(ARCHIVE) +static String saveArchiveAutoname(String basename, String name, String extension) { + if (name.isNull() || name.isEmpty()) { + name = String("index"); + } + + String testname = basename; + testname.append(name); + testname.append(extension); + + errno = 0; + struct stat permissions; + if (stat(testname.utf8().data(), &permissions) < 0) { + if (errno == ENOENT) + return testname; + return String(); + } + + const int maxAttempts = 100; + for (int i = 1; i < maxAttempts; i++) { + String testname = basename; + testname.append(name); + testname.append("-"); + testname.append(String::number(i)); + testname.append(extension); + + errno = 0; + if (stat(testname.utf8().data(), &permissions) < 0) { + if (errno == ENOENT) + return testname; + return String(); + } + } + + return String(); +} +#endif + +static jobject SaveWebArchive(JNIEnv *env, jobject obj, jstring basename, jboolean autoname) +{ +#if ENABLE(ARCHIVE) + WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj); + LOG_ASSERT(pFrame, "nativeSaveWebArchive must take a valid frame pointer!"); + + const char* basenameNative = getCharactersFromJStringInEnv(env, basename); + String basenameString = String::fromUTF8(basenameNative); + String filename; + + if (autoname) { + String name = pFrame->loader()->documentLoader()->originalURL().lastPathComponent(); + String extension = String(".webarchivexml"); + filename = saveArchiveAutoname(basenameString, name, extension); + } else { + filename = basenameString; + } + + if (filename.isNull() || filename.isEmpty()) { + LOGD("saveWebArchive: Failed to select a filename to save."); + releaseCharactersForJStringInEnv(env, basename, basenameNative); + return JNI_FALSE; + } + + const int noCompression = 0; + xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.utf8().data(), noCompression); + if (writer == NULL) { + LOGD("saveWebArchive: Failed to initialize xml writer."); + releaseCharactersForJStringInEnv(env, basename, basenameNative); + return JNI_FALSE; + } + + RefPtr<WebArchiveAndroid> archive = WebCore::WebArchiveAndroid::create(pFrame); + + bool result = archive->saveWebArchive(writer); + + releaseCharactersForJStringInEnv(env, basename, basenameNative); + xmlFreeTextWriter(writer); + + if (result) { + return env->NewStringUTF(filename.utf8().data()); + } + + return NULL; +#endif +} + static jstring ExternalRepresentation(JNIEnv *env, jobject obj) { #ifdef ANDROID_INSTRUMENT @@ -1112,6 +1200,28 @@ static jstring ExternalRepresentation(JNIEnv *env, jobject obj) return env->NewString(renderDump.characters(), len); } +static WebCore::StringBuilder FrameAsText(WebCore::Frame *pFrame, jboolean dumpChildFrames) { + WebCore::StringBuilder renderDump; + if (!pFrame) + return renderDump; + WebCore::Element *documentElement = pFrame->document()->documentElement(); + if (!documentElement) + return renderDump; + if (pFrame->tree()->parent()) { + renderDump.append("\n--------\nFrame: '"); + renderDump.append(pFrame->tree()->name()); + renderDump.append("'\n--------\n"); + } + renderDump.append(((WebCore::HTMLElement*)documentElement)->innerText()); + renderDump.append("\n"); + if (dumpChildFrames) { + for (unsigned i = 0; i < pFrame->tree()->childCount(); ++i) { + renderDump.append(FrameAsText(pFrame->tree()->child(i), dumpChildFrames).toString()); + } + } + return renderDump; +} + static jstring DocumentAsText(JNIEnv *env, jobject obj) { #ifdef ANDROID_INSTRUMENT @@ -1120,11 +1230,26 @@ static jstring DocumentAsText(JNIEnv *env, jobject obj) WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj); LOG_ASSERT(pFrame, "android_webcore_nativeDocumentAsText must take a valid frame pointer!"); - WebCore::Element *documentElement = pFrame->document()->documentElement(); - if (!documentElement) + WebCore::String renderDump = FrameAsText(pFrame, false /* dumpChildFrames */).toString(); + unsigned len = renderDump.length(); + if (!len) return NULL; - WebCore::String renderDump = ((WebCore::HTMLElement*)documentElement)->innerText(); - renderDump.append("\n"); + return env->NewString((unsigned short*)renderDump.characters(), len); +} + +static jstring ChildFramesAsText(JNIEnv *env, jobject obj) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter); +#endif + WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj); + LOG_ASSERT(pFrame, "android_webcore_nativeDocumentAsText must take a valid frame pointer!"); + + WebCore::StringBuilder renderDumpBuilder; + for (unsigned i = 0; i < pFrame->tree()->childCount(); ++i) { + renderDumpBuilder.append(FrameAsText(pFrame->tree()->child(i), true /* dumpChildFrames */).toString()); + } + WebCore::String renderDump = renderDumpBuilder.toString(); unsigned len = renderDump.length(); if (!len) return NULL; @@ -1413,8 +1538,8 @@ static jboolean HasPasswordField(JNIEnv *env, jobject obj) // class, but just normal Element class. while (node && !found && !node->namespaceURI().isNull() && !node->namespaceURI().isEmpty()) { - WTF::Vector<WebCore::HTMLFormControlElement*>& elements = - ((WebCore::HTMLFormElement*)node)->formElements; + const WTF::Vector<WebCore::HTMLFormControlElement*>& elements = + ((WebCore::HTMLFormElement*)node)->associatedElements(); size_t size = elements.size(); for (size_t i = 0; i< size && !found; i++) { WebCore::HTMLFormControlElement* e = elements[i]; @@ -1444,8 +1569,8 @@ static jobjectArray GetUsernamePassword(JNIEnv *env, jobject obj) WebCore::Node* node = form->firstItem(); while (node && !found && !node->namespaceURI().isNull() && !node->namespaceURI().isEmpty()) { - WTF::Vector<WebCore::HTMLFormControlElement*>& elements = - ((WebCore::HTMLFormElement*)node)->formElements; + const WTF::Vector<WebCore::HTMLFormControlElement*>& elements = + ((WebCore::HTMLFormElement*)node)->associatedElements(); size_t size = elements.size(); for (size_t i = 0; i< size && !found; i++) { WebCore::HTMLFormControlElement* e = elements[i]; @@ -1455,7 +1580,7 @@ static jobjectArray GetUsernamePassword(JNIEnv *env, jobject obj) continue; if (input->inputType() == WebCore::HTMLInputElement::PASSWORD) password = input->value(); - else if (input->inputType() == WebCore::HTMLInputElement::TEXT) + else if (input->inputType() == WebCore::HTMLInputElement::TEXT || input->inputType() == WebCore::HTMLInputElement::EMAIL) username = input->value(); if (!username.isNull() && !password.isNull()) found = true; @@ -1490,8 +1615,8 @@ static void SetUsernamePassword(JNIEnv *env, jobject obj, WebCore::Node* node = form->firstItem(); while (node && !found && !node->namespaceURI().isNull() && !node->namespaceURI().isEmpty()) { - WTF::Vector<WebCore::HTMLFormControlElement*>& elements = - ((WebCore::HTMLFormElement*)node)->formElements; + const WTF::Vector<WebCore::HTMLFormControlElement*>& elements = + ((WebCore::HTMLFormElement*)node)->associatedElements(); size_t size = elements.size(); for (size_t i = 0; i< size && !found; i++) { WebCore::HTMLFormControlElement* e = elements[i]; @@ -1501,7 +1626,7 @@ static void SetUsernamePassword(JNIEnv *env, jobject obj, continue; if (input->inputType() == WebCore::HTMLInputElement::PASSWORD) passwordEle = input; - else if (input->inputType() == WebCore::HTMLInputElement::TEXT) + else if (input->inputType() == WebCore::HTMLInputElement::TEXT || input->inputType() == WebCore::HTMLInputElement::EMAIL) usernameEle = input; if (usernameEle != NULL && passwordEle != NULL) found = true; @@ -1543,7 +1668,7 @@ static jobject GetFormTextData(JNIEnv *env, jobject obj) node = collection->nextItem()) { form = static_cast<WebCore::HTMLFormElement*>(node); if (form->autoComplete()) { - WTF::Vector<WebCore::HTMLFormControlElement*> elements = form->formElements; + WTF::Vector<WebCore::HTMLFormControlElement*> elements = form->associatedElements(); size_t size = elements.size(); for (size_t i = 0; i < size; i++) { WebCore::HTMLFormControlElement* e = elements[i]; @@ -1604,10 +1729,14 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = { (void*) PostUrl }, { "nativeLoadData", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", (void*) LoadData }, + { "nativeSaveWebArchive", "(Ljava/lang/String;Z)Ljava/lang/String;", + (void*) SaveWebArchive }, { "externalRepresentation", "()Ljava/lang/String;", (void*) ExternalRepresentation }, { "documentAsText", "()Ljava/lang/String;", (void*) DocumentAsText }, + { "childFramesAsText", "()Ljava/lang/String;", + (void*) ChildFramesAsText }, { "reload", "(Z)V", (void*) Reload }, { "nativeGoBackOrForward", "(I)V", |
