summaryrefslogtreecommitdiffstats
path: root/WebKit/android/jni/WebCoreFrameBridge.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android/jni/WebCoreFrameBridge.cpp')
-rw-r--r--WebKit/android/jni/WebCoreFrameBridge.cpp193
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",