summaryrefslogtreecommitdiffstats
path: root/WebKit/android/jni
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android/jni')
-rw-r--r--WebKit/android/jni/JavaBridge.cpp19
-rw-r--r--WebKit/android/jni/JavaSharedClient.cpp12
-rw-r--r--WebKit/android/jni/JavaSharedClient.h4
-rw-r--r--WebKit/android/jni/MIMETypeRegistry.cpp5
-rwxr-xr-xWebKit/android/jni/MockGeolocation.cpp2
-rw-r--r--WebKit/android/jni/WebCoreFrameBridge.cpp193
-rw-r--r--WebKit/android/jni/WebCoreJniOnLoad.cpp9
-rw-r--r--WebKit/android/jni/WebCoreResourceLoader.cpp2
-rw-r--r--WebKit/android/jni/WebCoreViewBridge.h48
-rw-r--r--WebKit/android/jni/WebHistory.cpp12
-rw-r--r--WebKit/android/jni/WebHistory.h6
-rw-r--r--WebKit/android/jni/WebIconDatabase.cpp1
-rw-r--r--WebKit/android/jni/WebSettings.cpp20
-rw-r--r--WebKit/android/jni/WebViewCore.cpp681
-rw-r--r--WebKit/android/jni/WebViewCore.h55
15 files changed, 770 insertions, 299 deletions
diff --git a/WebKit/android/jni/JavaBridge.cpp b/WebKit/android/jni/JavaBridge.cpp
index 0e65e1c..6aceb1c 100644
--- a/WebKit/android/jni/JavaBridge.cpp
+++ b/WebKit/android/jni/JavaBridge.cpp
@@ -31,6 +31,7 @@
#include "Cache.h"
#include "Connection.h"
#include "CookieClient.h"
+#include "FileSystemClient.h"
#include "JavaSharedClient.h"
#include "KeyGeneratorClient.h"
#include "KURL.h"
@@ -62,7 +63,7 @@ static jfieldID gJavaBridge_ObjectID;
// ----------------------------------------------------------------------------
-class JavaBridge : public TimerClient, public CookieClient, public PluginClient, public KeyGeneratorClient
+class JavaBridge : public TimerClient, public CookieClient, public PluginClient, public KeyGeneratorClient, public FileSystemClient
{
public:
JavaBridge(JNIEnv* env, jobject obj);
@@ -84,6 +85,7 @@ public:
virtual WTF::Vector<String> getSupportedKeyStrengthList();
virtual WebCore::String getSignedPublicKeyAndChallengeString(unsigned index,
const WebCore::String& challenge, const WebCore::KURL& url);
+ virtual WebCore::String resolveFilePathForContentUri(const WebCore::String& uri);
////////////////////////////////////////////
@@ -120,6 +122,7 @@ private:
jmethodID mSignalFuncPtrQueue;
jmethodID mGetKeyStrengthList;
jmethodID mGetSignedPublicKey;
+ jmethodID mResolveFilePathForContentUri;
};
static void (*sSharedTimerFiredCallback)();
@@ -139,6 +142,7 @@ JavaBridge::JavaBridge(JNIEnv* env, jobject obj)
mSignalFuncPtrQueue = env->GetMethodID(clazz, "signalServiceFuncPtrQueue", "()V");
mGetKeyStrengthList = env->GetMethodID(clazz, "getKeyStrengthList", "()[Ljava/lang/String;");
mGetSignedPublicKey = env->GetMethodID(clazz, "getSignedPublicKey", "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ mResolveFilePathForContentUri = env->GetMethodID(clazz, "resolveFilePathForContentUri", "(Ljava/lang/String;)Ljava/lang/String;");
LOG_ASSERT(mSetSharedTimer, "Could not find method setSharedTimer");
LOG_ASSERT(mStopSharedTimer, "Could not find method stopSharedTimer");
@@ -154,6 +158,7 @@ JavaBridge::JavaBridge(JNIEnv* env, jobject obj)
JavaSharedClient::SetCookieClient(this);
JavaSharedClient::SetPluginClient(this);
JavaSharedClient::SetKeyGeneratorClient(this);
+ JavaSharedClient::SetFileSystemClient(this);
}
JavaBridge::~JavaBridge()
@@ -168,6 +173,7 @@ JavaBridge::~JavaBridge()
JavaSharedClient::SetCookieClient(NULL);
JavaSharedClient::SetPluginClient(NULL);
JavaSharedClient::SetKeyGeneratorClient(NULL);
+ JavaSharedClient::SetFileSystemClient(NULL);
}
void
@@ -308,6 +314,17 @@ WebCore::String JavaBridge::getSignedPublicKeyAndChallengeString(unsigned index,
return ret;
}
+WebCore::String JavaBridge::resolveFilePathForContentUri(const WebCore::String& uri) {
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ jstring jUri = env->NewString(uri.characters(), uri.length());
+ AutoJObject obj = getRealObject(env, mJavaObject);
+ jstring path = static_cast<jstring>(env->CallObjectMethod(obj.get(), mResolveFilePathForContentUri, jUri));
+ WebCore::String ret = to_string(env, path);
+ env->DeleteLocalRef(jUri);
+ env->DeleteLocalRef(path);
+ return ret;
+}
+
// ----------------------------------------------------------------------------
void JavaBridge::Constructor(JNIEnv* env, jobject obj)
diff --git a/WebKit/android/jni/JavaSharedClient.cpp b/WebKit/android/jni/JavaSharedClient.cpp
index ce46570..e884c99 100644
--- a/WebKit/android/jni/JavaSharedClient.cpp
+++ b/WebKit/android/jni/JavaSharedClient.cpp
@@ -24,6 +24,7 @@
*/
#include "config.h"
+#include "FileSystemClient.h"
#include "JavaSharedClient.h"
#include "TimerClient.h"
#include "SkDeque.h"
@@ -50,6 +51,11 @@ namespace android {
return gKeyGeneratorClient;
}
+ FileSystemClient* JavaSharedClient::GetFileSystemClient()
+ {
+ return gFileSystemClient;
+ }
+
void JavaSharedClient::SetTimerClient(TimerClient* client)
{
gTimerClient = client;
@@ -70,10 +76,16 @@ namespace android {
gKeyGeneratorClient = client;
}
+ void JavaSharedClient::SetFileSystemClient(FileSystemClient* client)
+ {
+ gFileSystemClient = client;
+ }
+
TimerClient* JavaSharedClient::gTimerClient = NULL;
CookieClient* JavaSharedClient::gCookieClient = NULL;
PluginClient* JavaSharedClient::gPluginClient = NULL;
KeyGeneratorClient* JavaSharedClient::gKeyGeneratorClient = NULL;
+ FileSystemClient* JavaSharedClient::gFileSystemClient = NULL;
///////////////////////////////////////////////////////////////////////////
diff --git a/WebKit/android/jni/JavaSharedClient.h b/WebKit/android/jni/JavaSharedClient.h
index d33df67..9a09280 100644
--- a/WebKit/android/jni/JavaSharedClient.h
+++ b/WebKit/android/jni/JavaSharedClient.h
@@ -32,6 +32,7 @@ namespace android {
class CookieClient;
class PluginClient;
class KeyGeneratorClient;
+ class FileSystemClient;
class JavaSharedClient
{
@@ -40,11 +41,13 @@ namespace android {
static CookieClient* GetCookieClient();
static PluginClient* GetPluginClient();
static KeyGeneratorClient* GetKeyGeneratorClient();
+ static FileSystemClient* GetFileSystemClient();
static void SetTimerClient(TimerClient* client);
static void SetCookieClient(CookieClient* client);
static void SetPluginClient(PluginClient* client);
static void SetKeyGeneratorClient(KeyGeneratorClient* client);
+ static void SetFileSystemClient(FileSystemClient* client);
// can be called from any thread, to be executed in webkit thread
static void EnqueueFunctionPtr(void (*proc)(void*), void* payload);
@@ -56,6 +59,7 @@ namespace android {
static CookieClient* gCookieClient;
static PluginClient* gPluginClient;
static KeyGeneratorClient* gKeyGeneratorClient;
+ static FileSystemClient* gFileSystemClient;
};
}
#endif
diff --git a/WebKit/android/jni/MIMETypeRegistry.cpp b/WebKit/android/jni/MIMETypeRegistry.cpp
index 32f387d..5fe9ccd 100644
--- a/WebKit/android/jni/MIMETypeRegistry.cpp
+++ b/WebKit/android/jni/MIMETypeRegistry.cpp
@@ -58,4 +58,9 @@ String MIMETypeRegistry::getMIMETypeForExtension(const String& ext)
return result;
}
+bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&)
+{
+ return false;
+}
+
}
diff --git a/WebKit/android/jni/MockGeolocation.cpp b/WebKit/android/jni/MockGeolocation.cpp
index df580c3..1c236c3 100755
--- a/WebKit/android/jni/MockGeolocation.cpp
+++ b/WebKit/android/jni/MockGeolocation.cpp
@@ -53,7 +53,7 @@ static void setPosition(JNIEnv* env, jobject, double latitude, double longitude,
false, 0.0, // altitudeAccuracy,
false, 0.0, // heading
false, 0.0); // speed
- RefPtr<Geoposition> position = Geoposition::create(coordinates.release(), WTF::currentTime());
+ RefPtr<Geoposition> position = Geoposition::create(coordinates.release(), WTF::currentTimeMS());
GeolocationServiceMock::setPosition(position.release());
}
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",
diff --git a/WebKit/android/jni/WebCoreJniOnLoad.cpp b/WebKit/android/jni/WebCoreJniOnLoad.cpp
index b5bf9dd..1a3c676 100644
--- a/WebKit/android/jni/WebCoreJniOnLoad.cpp
+++ b/WebKit/android/jni/WebCoreJniOnLoad.cpp
@@ -82,7 +82,8 @@ extern int register_webstorage(JNIEnv*);
extern int register_geolocation_permissions(JNIEnv*);
extern int register_mock_geolocation(JNIEnv*);
#if ENABLE(VIDEO)
-extern int register_mediaplayer(JNIEnv*);
+extern int register_mediaplayer_audio(JNIEnv*);
+extern int register_mediaplayer_video(JNIEnv*);
#endif
}
@@ -107,7 +108,8 @@ static RegistrationMethod gWebCoreRegMethods[] = {
{ "GeolocationPermissions", android::register_geolocation_permissions },
{ "MockGeolocation", android::register_mock_geolocation },
#if ENABLE(VIDEO)
- { "HTML5VideoViewProxy", android::register_mediaplayer },
+ { "HTML5Audio", android::register_mediaplayer_audio },
+ { "HTML5VideoViewProxy", android::register_mediaplayer_video },
#endif
};
@@ -192,7 +194,8 @@ EXPORT void benchmark(const char* url, int reloadCount, int width, int height) {
new DragClientAndroid,
new InspectorClientAndroid,
0, // PluginHalterClient
- 0); // GeolocationControllerClient
+ 0, // GeolocationControllerClient
+ 0); // DeviceOrientationClient
editor->setPage(page);
// Create MyWebFrame that intercepts network requests
diff --git a/WebKit/android/jni/WebCoreResourceLoader.cpp b/WebKit/android/jni/WebCoreResourceLoader.cpp
index 297ecb0..32e8cd8 100644
--- a/WebKit/android/jni/WebCoreResourceLoader.cpp
+++ b/WebKit/android/jni/WebCoreResourceLoader.cpp
@@ -28,7 +28,6 @@
#include "config.h"
#include "WebCoreResourceLoader.h"
-#include "CString.h"
#include "ResourceError.h"
#include "ResourceHandle.h"
#include "ResourceHandleClient.h"
@@ -46,6 +45,7 @@
#include <stdlib.h>
#include <utils/misc.h>
#include <wtf/Platform.h>
+#include <wtf/text/CString.h>
namespace android {
diff --git a/WebKit/android/jni/WebCoreViewBridge.h b/WebKit/android/jni/WebCoreViewBridge.h
index 61990af..59e1c9a 100644
--- a/WebKit/android/jni/WebCoreViewBridge.h
+++ b/WebKit/android/jni/WebCoreViewBridge.h
@@ -38,20 +38,22 @@ namespace WebCore
class WebCoreViewBridge : public WebCoreRefObject {
public:
- WebCoreViewBridge() :
- mBounds(0,0,0,0),
- m_windowBounds(0,0,0,0)
- {}
- virtual ~WebCoreViewBridge() {}
+ WebCoreViewBridge() { }
+ virtual ~WebCoreViewBridge() { }
virtual void draw(WebCore::GraphicsContext* ctx,
const WebCore::IntRect& rect) = 0;
const WebCore::IntRect& getBounds() const
{
- return mBounds;
+ return m_bounds;
}
-
+
+ const WebCore::IntRect& getVisibleBounds() const
+ {
+ return m_visibleBounds;
+ }
+
const WebCore::IntRect& getWindowBounds() const
{
return m_windowBounds;
@@ -59,14 +61,22 @@ public:
void setSize(int w, int h)
{
- mBounds.setWidth(w);
- mBounds.setHeight(h);
+ m_bounds.setWidth(w);
+ m_bounds.setHeight(h);
+ }
+
+ void setVisibleSize(int w, int h)
+ {
+ m_visibleBounds.setWidth(w);
+ m_visibleBounds.setHeight(h);
}
void setLocation(int x, int y)
{
- mBounds.setX(x);
- mBounds.setY(y);
+ m_bounds.setX(x);
+ m_bounds.setY(y);
+ m_visibleBounds.setX(x);
+ m_visibleBounds.setY(y);
}
void setWindowBounds(int x, int y, int h, int v)
@@ -74,17 +84,23 @@ public:
m_windowBounds = WebCore::IntRect(x, y, h, v);
}
- int width() const { return mBounds.width(); }
- int height() const { return mBounds.height(); }
- int locX() const { return mBounds.x(); }
- int locY() const { return mBounds.y(); }
+ int width() const { return m_bounds.width(); }
+ int height() const { return m_bounds.height(); }
+ int locX() const { return m_bounds.x(); }
+ int locY() const { return m_bounds.y(); }
+
+ int visibleWidth() const { return m_visibleBounds.width(); }
+ int visibleHeight() const { return m_visibleBounds.height(); }
+ int visibleX() const { return m_visibleBounds.x(); }
+ int visibleY() const { return m_visibleBounds.y(); }
virtual bool forFrameView() const { return false; }
virtual bool forPluginView() const { return false; }
private:
- WebCore::IntRect mBounds;
+ WebCore::IntRect m_bounds;
WebCore::IntRect m_windowBounds;
+ WebCore::IntRect m_visibleBounds;
};
#endif // WEBCORE_VIEW_BRIDGE_H
diff --git a/WebKit/android/jni/WebHistory.cpp b/WebKit/android/jni/WebHistory.cpp
index d518ba8..37a4d1d 100644
--- a/WebKit/android/jni/WebHistory.cpp
+++ b/WebKit/android/jni/WebHistory.cpp
@@ -29,7 +29,6 @@
#include "WebHistory.h"
#include "BackForwardList.h"
-#include "CString.h"
#include "DocumentLoader.h"
#include "Frame.h"
#include "FrameLoader.h"
@@ -49,6 +48,7 @@
#include <utils/misc.h>
#include <wtf/OwnPtr.h>
#include <wtf/Platform.h>
+#include <wtf/text/CString.h>
namespace android {
@@ -419,9 +419,9 @@ static void write_item(WTF::Vector<char>& v, WebCore::HistoryItem* item)
const int scale = bridge->scale();
LOGV("Writing scale %d", scale);
v.append((char*)&scale, sizeof(int));
- const int screenWidthScale = bridge->screenWidthScale();
- LOGV("Writing screen width scale %d", screenWidthScale);
- v.append((char*)&screenWidthScale, sizeof(int));
+ const int textWrapScale = bridge->textWrapScale();
+ LOGV("Writing text wrap scale %d", textWrapScale);
+ v.append((char*)&textWrapScale, sizeof(int));
// Document state
const WTF::Vector<WebCore::String>& docState = item->documentState();
@@ -603,8 +603,8 @@ static bool read_item_recursive(WebCore::HistoryItem* newItem,
bridge->setScale(l);
data += sizeofUnsigned;
memcpy(&l, data, sizeofUnsigned);
- LOGV("Screen width scale %d", l);
- bridge->setScreenWidthScale(l);
+ LOGV("Text wrap scale %d", l);
+ bridge->setTextWrapScale(l);
data += sizeofUnsigned;
if (end - data < sizeofUnsigned)
diff --git a/WebKit/android/jni/WebHistory.h b/WebKit/android/jni/WebHistory.h
index 12bf00a..2d86aa4 100644
--- a/WebKit/android/jni/WebHistory.h
+++ b/WebKit/android/jni/WebHistory.h
@@ -44,9 +44,9 @@ public:
static void UpdateHistoryIndex(const AutoJObject&, int);
};
-// there are two scale factors saved with each history item. mScale reflects the
-// viewport scale factor, default to 100 means 100%. mScreenWidthScale records
-// the scale factor for the screen width used to wrap the text paragraph.
+// there are two scale factors saved with each history item. m_scale reflects the
+// viewport scale factor, default to 100 means 100%. m_textWrapScale records
+// the scale factor for wrapping the text paragraph.
class WebHistoryItem : public WebCore::AndroidWebHistoryBridge {
public:
WebHistoryItem(WebHistoryItem* parent)
diff --git a/WebKit/android/jni/WebIconDatabase.cpp b/WebKit/android/jni/WebIconDatabase.cpp
index 840d161..6a20f6f 100644
--- a/WebKit/android/jni/WebIconDatabase.cpp
+++ b/WebKit/android/jni/WebIconDatabase.cpp
@@ -38,6 +38,7 @@
#include <JNIHelp.h>
#include <JNIUtility.h>
+#include <SharedBuffer.h>
#include <SkBitmap.h>
#include <SkImageDecoder.h>
#include <SkTemplates.h>
diff --git a/WebKit/android/jni/WebSettings.cpp b/WebKit/android/jni/WebSettings.cpp
index 70ecded..d9a7cf0 100644
--- a/WebKit/android/jni/WebSettings.cpp
+++ b/WebKit/android/jni/WebSettings.cpp
@@ -29,7 +29,9 @@
#include <wtf/Platform.h>
#include "ApplicationCacheStorage.h"
+#include "BitmapAllocatorAndroid.h"
#include "DatabaseTracker.h"
+#include "Database.h"
#include "DocLoader.h"
#include "Document.h"
#include "Frame.h"
@@ -107,11 +109,13 @@ struct FieldIds {
#endif
mGeolocationEnabled = env->GetFieldID(clazz, "mGeolocationEnabled", "Z");
mGeolocationDatabasePath = env->GetFieldID(clazz, "mGeolocationDatabasePath", "Ljava/lang/String;");
+ mXSSAuditorEnabled = env->GetFieldID(clazz, "mXSSAuditorEnabled", "Z");
mJavaScriptCanOpenWindowsAutomatically = env->GetFieldID(clazz,
"mJavaScriptCanOpenWindowsAutomatically", "Z");
mUseWideViewport = env->GetFieldID(clazz, "mUseWideViewport", "Z");
mSupportMultipleWindows = env->GetFieldID(clazz, "mSupportMultipleWindows", "Z");
mShrinksStandaloneImagesToFit = env->GetFieldID(clazz, "mShrinksStandaloneImagesToFit", "Z");
+ mMaximumDecodedImageSize = env->GetFieldID(clazz, "mMaximumDecodedImageSize", "J");
mUseDoubleTree = env->GetFieldID(clazz, "mUseDoubleTree", "Z");
mPageCacheCapacity = env->GetFieldID(clazz, "mPageCacheCapacity", "I");
@@ -148,6 +152,7 @@ struct FieldIds {
LOG_ASSERT(mUseWideViewport, "Could not find field mUseWideViewport");
LOG_ASSERT(mSupportMultipleWindows, "Could not find field mSupportMultipleWindows");
LOG_ASSERT(mShrinksStandaloneImagesToFit, "Could not find field mShrinksStandaloneImagesToFit");
+ LOG_ASSERT(mMaximumDecodedImageSize, "Could not find field mMaximumDecodedImageSize");
LOG_ASSERT(mUseDoubleTree, "Could not find field mUseDoubleTree");
LOG_ASSERT(mPageCacheCapacity, "Could not find field mPageCacheCapacity");
@@ -193,6 +198,7 @@ struct FieldIds {
jfieldID mUseWideViewport;
jfieldID mSupportMultipleWindows;
jfieldID mShrinksStandaloneImagesToFit;
+ jfieldID mMaximumDecodedImageSize;
jfieldID mUseDoubleTree;
jfieldID mPageCacheCapacity;
// Ordinal() method and value field for enums
@@ -207,6 +213,7 @@ struct FieldIds {
#endif
jfieldID mGeolocationEnabled;
jfieldID mGeolocationDatabasePath;
+ jfieldID mXSSAuditorEnabled;
#if ENABLE(DATABASE) || ENABLE(DOM_STORAGE)
jfieldID mDatabasePath;
jfieldID mDatabasePathHasBeenSet;
@@ -260,8 +267,8 @@ public:
#endif
jobject textSize = env->GetObjectField(obj, gFieldIds->mTextSize);
float zoomFactor = env->GetIntField(textSize, gFieldIds->mTextSizeValue) / 100.0f;
- if (pFrame->zoomFactor() != zoomFactor)
- pFrame->setZoomFactor(zoomFactor, /*isTextOnly*/true);
+ if (pFrame->view()->zoomFactor() != zoomFactor)
+ pFrame->view()->setZoomFactor(zoomFactor, WebCore::ZoomTextOnly);
jstring str = (jstring)env->GetObjectField(obj, gFieldIds->mStandardFontFamily);
s->setStandardFontFamily(to_string(env, str));
@@ -352,9 +359,13 @@ public:
#endif
flag = env->GetBooleanField(obj, gFieldIds->mShrinksStandaloneImagesToFit);
s->setShrinksStandaloneImagesToFit(flag);
+ jlong maxImage = env->GetIntField(obj, gFieldIds->mMaximumDecodedImageSize);
+ if (maxImage == 0)
+ maxImage = computeMaxBitmapSizeForCache();
+ s->setMaximumDecodedImageSize(maxImage);
#if ENABLE(DATABASE)
flag = env->GetBooleanField(obj, gFieldIds->mDatabaseEnabled);
- s->setDatabasesEnabled(flag);
+ WebCore::Database::setIsAvailable(flag);
flag = env->GetBooleanField(obj, gFieldIds->mDatabasePathHasBeenSet);
if (flag) {
@@ -384,6 +395,9 @@ public:
WebCore::GeolocationPositionCache::setDatabasePath(to_string(env,str));
}
+ flag = env->GetBooleanField(obj, gFieldIds->mXSSAuditorEnabled);
+ s->setXSSAuditorEnabled(flag);
+
size = env->GetIntField(obj, gFieldIds->mPageCacheCapacity);
if (size > 0) {
s->setUsesPageCache(true);
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 1562775..d3e32d3 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -29,6 +29,7 @@
#include "WebViewCore.h"
#include "AtomicString.h"
+#include "BaseLayerAndroid.h"
#include "CachedNode.h"
#include "CachedRoot.h"
#include "Chrome.h"
@@ -37,6 +38,7 @@
#include "DatabaseTracker.h"
#include "Document.h"
#include "DOMWindow.h"
+#include "DOMSelection.h"
#include "Element.h"
#include "Editor.h"
#include "EditorClientAndroid.h"
@@ -65,9 +67,9 @@
#include "HTMLSelectElement.h"
#include "HTMLTextAreaElement.h"
#include "HistoryItem.h"
+#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "InlineTextBox.h"
-#include "KeyboardCodes.h"
#include "Navigator.h"
#include "Node.h"
#include "NodeList.h"
@@ -79,7 +81,9 @@
#include "PluginView.h"
#include "Position.h"
#include "ProgressTracker.h"
+#include "Range.h"
#include "RenderBox.h"
+#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderPart.h"
#include "RenderText.h"
@@ -101,6 +105,7 @@
#include "TypingCommand.h"
#include "WebCoreFrameBridge.h"
#include "WebFrameView.h"
+#include "WindowsKeyboardCodes.h"
#include "android_graphics.h"
#include <JNIHelp.h>
@@ -109,9 +114,9 @@
#include <wtf/CurrentTime.h>
#if USE(V8)
-#include "CString.h"
#include "ScriptController.h"
#include "V8Counters.h"
+#include <wtf/text/CString.h>
#endif
#if DEBUG_NAV_UI
@@ -125,7 +130,7 @@
#ifdef ANDROID_DOM_LOGGING
#include "AndroidLog.h"
#include "RenderTreeAsText.h"
-#include "CString.h"
+#include <wtf/text/CString.h>
FILE* gDomTreeFile = 0;
FILE* gRenderTreeFile = 0;
@@ -226,13 +231,10 @@ struct WebViewCore::JavaGlue {
jmethodID m_updateViewport;
jmethodID m_sendNotifyProgressFinished;
jmethodID m_sendViewInvalidate;
- jmethodID m_sendImmediateRepaint;
- jmethodID m_setRootLayer;
jmethodID m_updateTextfield;
jmethodID m_updateTextSelection;
jmethodID m_clearTextEntry;
jmethodID m_restoreScale;
- jmethodID m_restoreScreenWidthScale;
jmethodID m_needTouchEvents;
jmethodID m_requestKeyboard;
jmethodID m_requestKeyboardWithSelection;
@@ -253,6 +255,7 @@ struct WebViewCore::JavaGlue {
jmethodID m_showRect;
jmethodID m_centerFitRect;
jmethodID m_setScrollbarModes;
+ jmethodID m_setInstallableWebApp;
AutoJObject object(JNIEnv* env) {
return getRealObject(env, m_obj);
}
@@ -272,7 +275,6 @@ static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const
Mutex WebViewCore::gFrameCacheMutex;
Mutex WebViewCore::gButtonMutex;
Mutex WebViewCore::gCursorBoundsMutex;
-Mutex WebViewCore::m_contentMutex;
WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* mainframe)
: m_pluginInvalTimer(this, &WebViewCore::pluginInvalTimerFired)
@@ -289,8 +291,8 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_maxYScroll = 240/4;
m_textGeneration = 0;
m_screenWidth = 320;
+ m_textWrapWidth = 320;
m_scale = 1;
- m_screenWidthScale = 1;
#if ENABLE(TOUCH_EVENTS)
m_forwardingTouchEvents = false;
#endif
@@ -306,7 +308,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_scrollBy = GetJMethod(env, clazz, "contentScrollBy", "(IIZ)V");
m_javaGlue->m_contentDraw = GetJMethod(env, clazz, "contentDraw", "()V");
m_javaGlue->m_requestListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[I[I)V");
- m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "()Ljava/lang/String;");
+ m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "(Ljava/lang/String;)Ljava/lang/String;");
m_javaGlue->m_requestSingleListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[II)V");
m_javaGlue->m_jsAlert = GetJMethod(env, clazz, "jsAlert", "(Ljava/lang/String;Ljava/lang/String;)V");
m_javaGlue->m_jsConfirm = GetJMethod(env, clazz, "jsConfirm", "(Ljava/lang/String;Ljava/lang/String;)Z");
@@ -317,13 +319,10 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_updateViewport = GetJMethod(env, clazz, "updateViewport", "()V");
m_javaGlue->m_sendNotifyProgressFinished = GetJMethod(env, clazz, "sendNotifyProgressFinished", "()V");
m_javaGlue->m_sendViewInvalidate = GetJMethod(env, clazz, "sendViewInvalidate", "(IIII)V");
- m_javaGlue->m_sendImmediateRepaint = GetJMethod(env, clazz, "sendImmediateRepaint", "()V");
- m_javaGlue->m_setRootLayer = GetJMethod(env, clazz, "setRootLayer", "(I)V");
m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V");
m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIII)V");
m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
- m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(I)V");
- m_javaGlue->m_restoreScreenWidthScale = GetJMethod(env, clazz, "restoreScreenWidthScale", "(I)V");
+ m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(II)V");
m_javaGlue->m_needTouchEvents = GetJMethod(env, clazz, "needTouchEvents", "(Z)V");
m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(Z)V");
m_javaGlue->m_requestKeyboardWithSelection = GetJMethod(env, clazz, "requestKeyboardWithSelection", "(IIII)V");
@@ -344,6 +343,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V");
m_javaGlue->m_centerFitRect = GetJMethod(env, clazz, "centerFitRect", "(IIII)V");
m_javaGlue->m_setScrollbarModes = GetJMethod(env, clazz, "setScrollbarModes", "(II)V");
+ m_javaGlue->m_setInstallableWebApp = GetJMethod(env, clazz, "setInstallableWebApp", "()V");
env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
@@ -485,7 +485,8 @@ void WebViewCore::recordPicture(SkPicture* picture)
WebCore::PlatformGraphicsContext pgc(arp.getRecordingCanvas(), &buttons);
WebCore::GraphicsContext gc(&pgc);
- view->platformWidget()->draw(&gc, WebCore::IntRect(0, 0, INT_MAX, INT_MAX));
+ view->platformWidget()->draw(&gc, WebCore::IntRect(0, 0,
+ view->contentsWidth(), view->contentsHeight()));
gButtonMutex.lock();
updateButtonList(&buttons);
@@ -589,6 +590,9 @@ void WebViewCore::recordPictureSet(PictureSet* content)
height = view->contentsHeight();
}
+ if (cacheBuilder().pictureSetDisabled())
+ content->clear();
+
content->checkDimensions(width, height, &m_addInval);
// The inval region may replace existing pictures. The existing pictures
@@ -741,50 +745,11 @@ void WebViewCore::updateCursorBounds(const CachedRoot* root,
void WebViewCore::clearContent()
{
DBG_SET_LOG("");
- m_contentMutex.lock();
m_content.clear();
- m_contentMutex.unlock();
m_addInval.setEmpty();
m_rebuildInval.setEmpty();
}
-void WebViewCore::copyContentToPicture(SkPicture* picture)
-{
- DBG_SET_LOG("start");
- m_contentMutex.lock();
- PictureSet copyContent = PictureSet(m_content);
- m_contentMutex.unlock();
-
- int w = copyContent.width();
- int h = copyContent.height();
- copyContent.draw(picture->beginRecording(w, h, PICT_RECORD_FLAGS));
- picture->endRecording();
- DBG_SET_LOG("end");
-}
-
-bool WebViewCore::drawContent(SkCanvas* canvas, SkColor color)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewUIDrawTimeCounter);
-#endif
- DBG_SET_LOG("start");
- m_contentMutex.lock();
- PictureSet copyContent = PictureSet(m_content);
- m_contentMutex.unlock();
- int sc = canvas->save(SkCanvas::kClip_SaveFlag);
- SkRect clip;
- clip.set(0, 0, copyContent.width(), copyContent.height());
- canvas->clipRect(clip, SkRegion::kDifference_Op);
- canvas->drawColor(color);
- canvas->restoreToCount(sc);
- bool tookTooLong = copyContent.draw(canvas);
- m_contentMutex.lock();
- m_content.setDrawTimes(copyContent);
- m_contentMutex.unlock();
- DBG_SET_LOG("end");
- return tookTooLong;
-}
-
bool WebViewCore::focusBoundsChanged()
{
bool result = m_focusBoundsChanged;
@@ -792,18 +757,6 @@ bool WebViewCore::focusBoundsChanged()
return result;
}
-bool WebViewCore::pictureReady()
-{
- bool done;
- m_contentMutex.lock();
- PictureSet copyContent = PictureSet(m_content);
- done = m_progressDone;
- m_contentMutex.unlock();
- DBG_NAV_LOGD("done=%s empty=%s", done ? "true" : "false",
- copyContent.isEmpty() ? "true" : "false");
- return done || !copyContent.isEmpty();
-}
-
SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval)
{
WebCore::FrameView* view = m_mainFrame->view();
@@ -851,48 +804,52 @@ void WebViewCore::rebuildPictureSet(PictureSet* pictureSet)
pictureSet->validate(__FUNCTION__);
}
-bool WebViewCore::recordContent(SkRegion* region, SkIPoint* point)
+BaseLayerAndroid* WebViewCore::recordContent(SkRegion* region, SkIPoint* point)
{
DBG_SET_LOG("start");
float progress = (float) m_mainFrame->page()->progress()->estimatedProgress();
- m_contentMutex.lock();
- PictureSet contentCopy(m_content);
m_progressDone = progress <= 0.0f || progress >= 1.0f;
- m_contentMutex.unlock();
- recordPictureSet(&contentCopy);
- if (!m_progressDone && contentCopy.isEmpty()) {
+ recordPictureSet(&m_content);
+ if (!m_progressDone && m_content.isEmpty()) {
DBG_SET_LOGD("empty (progress=%g)", progress);
- return false;
+ return 0;
}
region->set(m_addInval);
m_addInval.setEmpty();
region->op(m_rebuildInval, SkRegion::kUnion_Op);
m_rebuildInval.setEmpty();
- m_contentMutex.lock();
- contentCopy.setDrawTimes(m_content);
- m_content.set(contentCopy);
point->fX = m_content.width();
point->fY = m_content.height();
- m_contentMutex.unlock();
DBG_SET_LOGD("region={%d,%d,r=%d,b=%d}", region->getBounds().fLeft,
region->getBounds().fTop, region->getBounds().fRight,
region->getBounds().fBottom);
DBG_SET_LOG("end");
- return true;
+
+ BaseLayerAndroid* base = new BaseLayerAndroid();
+ base->setContent(m_content);
+
+#if USE(ACCELERATED_COMPOSITING)
+ // We update the layers
+ ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
+ GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
+ if (root) {
+ root->notifyClientAnimationStarted();
+ LayerAndroid* copyLayer = new LayerAndroid(*root->contentLayer());
+ base->addChild(copyLayer);
+ copyLayer->unref();
+ }
+#endif
+
+ return base;
}
-void WebViewCore::splitContent()
+void WebViewCore::splitContent(PictureSet* content)
{
bool layoutSuceeded = layoutIfNeededRecursive(m_mainFrame);
LOG_ASSERT(layoutSuceeded, "Can never be called recursively");
- PictureSet tempPictureSet;
- m_contentMutex.lock();
- m_content.split(&tempPictureSet);
- m_contentMutex.unlock();
- rebuildPictureSet(&tempPictureSet);
- m_contentMutex.lock();
- m_content.set(tempPictureSet);
- m_contentMutex.unlock();
+ content->split(&m_content);
+ rebuildPictureSet(&m_content);
+ content->set(m_content);
}
void WebViewCore::scrollTo(int x, int y, bool animate)
@@ -936,28 +893,6 @@ void WebViewCore::scrollBy(int dx, int dy, bool animate)
checkException(env);
}
-#if USE(ACCELERATED_COMPOSITING)
-
-void WebViewCore::immediateRepaint()
-{
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(),
- m_javaGlue->m_sendImmediateRepaint);
- checkException(env);
-}
-
-void WebViewCore::setUIRootLayer(const LayerAndroid* layer)
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(),
- m_javaGlue->m_setRootLayer,
- reinterpret_cast<jint>(layer));
- checkException(env);
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
void WebViewCore::contentDraw()
{
JNIEnv* env = JSC::Bindings::getJNIEnv();
@@ -1034,24 +969,13 @@ void WebViewCore::updateViewport()
checkException(env);
}
-void WebViewCore::restoreScale(int scale)
+void WebViewCore::restoreScale(int scale, int textWrapScale)
{
DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_restoreScale, scale);
- checkException(env);
-}
-
-void WebViewCore::restoreScreenWidthScale(int scale)
-{
- DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
-
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(),
- m_javaGlue->m_restoreScreenWidthScale, scale);
+ env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_restoreScale, scale, textWrapScale);
checkException(env);
}
@@ -1162,42 +1086,45 @@ void WebViewCore::setGlobalBounds(int x, int y, int h, int v)
}
void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
- int screenWidth, float scale, int realScreenWidth, int screenHeight,
+ int textWrapWidth, float scale, int screenWidth, int screenHeight,
int anchorX, int anchorY, bool ignoreHeight)
{
WebCoreViewBridge* window = m_mainFrame->view()->platformWidget();
int ow = window->width();
int oh = window->height();
window->setSize(width, height);
+ window->setVisibleSize(screenWidth, screenHeight);
+ if (width != screenWidth) {
+ m_mainFrame->view()->setUseFixedLayout(true);
+ m_mainFrame->view()->setFixedLayoutSize(IntSize(width, height));
+ } else {
+ m_mainFrame->view()->setUseFixedLayout(false);
+ }
int osw = m_screenWidth;
- int orsw = m_screenWidth * m_screenWidthScale / m_scale;
int osh = m_screenHeight;
+ int otw = m_textWrapWidth;
DBG_NAV_LOGD("old:(w=%d,h=%d,sw=%d,scale=%g) new:(w=%d,h=%d,sw=%d,scale=%g)",
ow, oh, osw, m_scale, width, height, screenWidth, scale);
m_screenWidth = screenWidth;
m_screenHeight = screenHeight;
- if (scale >= 0) { // negative means ignore
+ m_textWrapWidth = textWrapWidth;
+ if (scale >= 0) // negative means keep the current scale
m_scale = scale;
- if (screenWidth != realScreenWidth)
- m_screenWidthScale = realScreenWidth * scale / screenWidth;
- else
- m_screenWidthScale = m_scale;
- }
m_maxXScroll = screenWidth >> 2;
- m_maxYScroll = (screenWidth * height / width) >> 2;
- if (ow != width || (!ignoreHeight && oh != height) || osw != screenWidth) {
+ m_maxYScroll = m_maxXScroll * height / width;
+ if (ow != width || (!ignoreHeight && oh != height) || otw != textWrapWidth) {
WebCore::RenderObject *r = m_mainFrame->contentRenderer();
DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r,
- realScreenWidth, screenHeight);
+ screenWidth, screenHeight);
if (r) {
WebCore::IntPoint anchorPoint = WebCore::IntPoint(anchorX, anchorY);
DBG_NAV_LOGD("anchorX=%d anchorY=%d", anchorX, anchorY);
- WebCore::Node* node = 0;
+ RefPtr<WebCore::Node> node;
WebCore::IntRect bounds;
WebCore::IntPoint offset;
- // If the screen width changed, it is probably zoom change or
+ // If the text wrap changed, it is probably zoom change or
// orientation change. Try to keep the anchor at the same place.
- if (osw && screenWidth && osw != screenWidth) {
+ if (otw && textWrapWidth && otw != textWrapWidth) {
WebCore::HitTestResult hitTestResult =
m_mainFrame->eventHandler()-> hitTestResultAtPoint(
anchorPoint, false);
@@ -1227,19 +1154,19 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d,"
"h=%d)", newBounds.x(), newBounds.y(),
newBounds.width(), newBounds.height());
- if ((orsw && osh && bounds.width() && bounds.height())
+ if ((osw && osh && bounds.width() && bounds.height())
&& (bounds != newBounds)) {
WebCore::FrameView* view = m_mainFrame->view();
// force left align if width is not changed while height changed.
// the anchorPoint is probably at some white space in the node
// which is affected by text wrap around the screen width.
- const bool leftAlign = (osw != m_screenWidth)
+ const bool leftAlign = (otw != textWrapWidth)
&& (bounds.width() == newBounds.width())
&& (bounds.height() != newBounds.height());
const float xPercentInDoc =
leftAlign ? 0.0 : (float) (anchorX - bounds.x()) / bounds.width();
const float xPercentInView =
- leftAlign ? 0.0 : (float) (anchorX - m_scrollOffsetX) / orsw;
+ leftAlign ? 0.0 : (float) (anchorX - m_scrollOffsetX) / osw;
const float yPercentInDoc = (float) (anchorY - bounds.y()) / bounds.height();
const float yPercentInView = (float) (anchorY - m_scrollOffsetY) / osh;
showRect(newBounds.x(), newBounds.y(), newBounds.width(),
@@ -1272,7 +1199,7 @@ void WebViewCore::dumpDomTree(bool useFile)
void WebViewCore::dumpRenderTree(bool useFile)
{
#ifdef ANDROID_DOM_LOGGING
- WebCore::CString renderDump = WebCore::externalRepresentation(m_mainFrame).utf8();
+ WTF::CString renderDump = WebCore::externalRepresentation(m_mainFrame).utf8();
const char* data = renderDump.data();
if (useFile) {
gRenderTreeFile = fopen(RENDER_TREE_LOG_FILE, "w");
@@ -1331,7 +1258,7 @@ WebCore::String WebViewCore::requestLabel(WebCore::Frame* frame,
for (unsigned i = 0; i < length; i++) {
WebCore::HTMLLabelElement* label = static_cast<WebCore::HTMLLabelElement*>(
list->item(i));
- if (label->correspondingControl() == node) {
+ if (label->control() == node) {
Node* node = label;
String result;
while ((node = node->traverseNextNode(label))) {
@@ -1437,6 +1364,252 @@ void WebViewCore::updateFrameCacheIfLoading()
updateFrameCache();
}
+struct TouchNodeData {
+ Node* mNode;
+ IntRect mBounds;
+};
+
+// get the bounding box of the Node
+static IntRect getAbsoluteBoundingBox(Node* node) {
+ IntRect rect;
+ RenderObject* render = node->renderer();
+ if (render->isRenderInline())
+ rect = toRenderInline(render)->linesVisibleOverflowBoundingBox();
+ else if (render->isBox())
+ rect = toRenderBox(render)->visualOverflowRect();
+ else if (render->isText())
+ rect = toRenderText(render)->linesBoundingBox();
+ else
+ LOGE("getAbsoluteBoundingBox failed for node %p, name %s", node, render->renderName());
+ FloatPoint absPos = render->localToAbsolute();
+ rect.move(absPos.x(), absPos.y());
+ return rect;
+}
+
+// get the highlight rectangles for the touch point (x, y) with the slop
+Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
+{
+ Vector<IntRect> rects;
+ m_mousePos = IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY);
+#ifdef ANDROID_HITTEST_WITHSIZE
+ HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
+ false, false, DontHitTestScrollbars, IntSize(slop, slop));
+ if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
+ LOGE("Should not happen: no in document Node found");
+ return rects;
+ }
+ const Vector<RefPtr<Node> >& list = hitTestResult.rawNodeList();
+ if (list.isEmpty()) {
+ LOGE("Should not happen: no raw node found");
+ return rects;
+ }
+ Frame* frame = hitTestResult.innerNode()->document()->frame();
+ Vector<TouchNodeData> nodeDataList;
+ Vector<RefPtr<Node> >::const_iterator last = list.end();
+ for (Vector<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it) {
+ // TODO: it seems reasonable to not search across the frame. Isn't it?
+ // if the node is not in the same frame as the innerNode, skip it
+ if (it->get()->document()->frame() != frame)
+ continue;
+ // traverse up the tree to find the first node that needs highlight
+ bool found = false;
+ Node* eventNode = it->get();
+ while (eventNode) {
+ RenderObject* render = eventNode->renderer();
+ if (render->isBody() || render->isRenderView())
+ break;
+ if (eventNode->supportsFocus()
+ || eventNode->hasEventListeners(eventNames().clickEvent)
+ || eventNode->hasEventListeners(eventNames().mousedownEvent)
+ || eventNode->hasEventListeners(eventNames().mouseupEvent)) {
+ found = true;
+ break;
+ }
+ // the nodes in the rawNodeList() are ordered based on z-index during hit testing.
+ // so do not search for the eventNode across explicit z-index border.
+ // TODO: this is a hard one to call. z-index is quite complicated as its value only
+ // matters when you compare two RenderLayer in the same hierarchy level. e.g. in
+ // the following example, "b" is on the top as its z level is the highest. even "c"
+ // has 100 as z-index, it is still below "d" as its parent has the same z-index as
+ // "d" and logically before "d". Of course "a" is the lowest in the z level.
+ //
+ // z-index:auto "a"
+ // z-index:2 "b"
+ // z-index:1
+ // z-index:100 "c"
+ // z-index:1 "d"
+ //
+ // If the fat point touches everyone, the order in the list should be "b", "d", "c"
+ // and "a". When we search for the event node for "b", we really don't want "a" as
+ // in the z-order it is behind everything else.
+ if (!render->style()->hasAutoZIndex())
+ break;
+ eventNode = eventNode->parentNode();
+ }
+ // didn't find any eventNode, skip it
+ if (!found)
+ continue;
+ // first quick check whether it is a duplicated node before computing bounding box
+ Vector<TouchNodeData>::const_iterator nlast = nodeDataList.end();
+ for (Vector<TouchNodeData>::const_iterator n = nodeDataList.begin(); n != nlast; ++n) {
+ // found the same node, skip it
+ if (eventNode == n->mNode) {
+ found = false;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ // next check whether the node is fully covered by or fully covering another node.
+ found = false;
+ IntRect rect = getAbsoluteBoundingBox(eventNode);
+ if (rect.isEmpty()) {
+ // if the node's bounds is empty and it is not a ContainerNode, skip it.
+ if (!eventNode->isContainerNode())
+ continue;
+ // if the node's children are all positioned objects, its bounds can be empty.
+ // Walk through the children to find the bounding box.
+ Node* child = static_cast<const ContainerNode*>(eventNode)->firstChild();
+ while (child) {
+ IntRect childrect;
+ if (child->renderer())
+ childrect = getAbsoluteBoundingBox(child);
+ if (!childrect.isEmpty()) {
+ rect.unite(childrect);
+ child = child->traverseNextSibling(eventNode);
+ } else
+ child = child->traverseNextNode(eventNode);
+ }
+ }
+ for (int i = nodeDataList.size() - 1; i >= 0; i--) {
+ TouchNodeData n = nodeDataList.at(i);
+ // the new node is enclosing an existing node, skip it
+ if (rect.contains(n.mBounds)) {
+ found = true;
+ break;
+ }
+ // the new node is fully inside an existing node, remove the existing node
+ if (n.mBounds.contains(rect))
+ nodeDataList.remove(i);
+ }
+ if (!found) {
+ TouchNodeData newNode;
+ newNode.mNode = eventNode;
+ newNode.mBounds = rect;
+ nodeDataList.append(newNode);
+ }
+ }
+ if (!nodeDataList.size())
+ return rects;
+ // finally select the node with the largest overlap with the fat point
+ TouchNodeData final;
+ final.mNode = 0;
+ IntPoint docPos = frame->view()->windowToContents(m_mousePos);
+ IntRect testRect(docPos.x() - slop, docPos.y() - slop, 2 * slop + 1, 2 * slop + 1);
+ int area = 0;
+ Vector<TouchNodeData>::const_iterator nlast = nodeDataList.end();
+ for (Vector<TouchNodeData>::const_iterator n = nodeDataList.begin(); n != nlast; ++n) {
+ IntRect rect = n->mBounds;
+ rect.intersect(testRect);
+ int a = rect.width() * rect.height();
+ if (a > area) {
+ final = *n;
+ area = a;
+ }
+ }
+ // now get the node's highlight rectangles in the page coordinate system
+ if (final.mNode) {
+ IntPoint frameAdjust;
+ if (frame != m_mainFrame) {
+ frameAdjust = frame->view()->contentsToWindow(IntPoint());
+ frameAdjust.move(m_scrollOffsetX, m_scrollOffsetY);
+ }
+ if (final.mNode->isLink()) {
+ // most of the links are inline instead of box style. So the bounding box is not
+ // a good representation for the highlights. Get the list of rectangles instead.
+ RenderObject* render = final.mNode->renderer();
+ IntPoint offset = roundedIntPoint(render->localToAbsolute());
+ render->absoluteRects(rects, offset.x() + frameAdjust.x(), offset.y() + frameAdjust.y());
+ bool inside = false;
+ int distance = INT_MAX;
+ int newx = x, newy = y;
+ int i = rects.size();
+ while (i--) {
+ if (rects[i].isEmpty()) {
+ rects.remove(i);
+ continue;
+ }
+ // check whether the point (x, y) is inside one of the rectangles.
+ if (inside)
+ continue;
+ if (rects[i].contains(x, y)) {
+ inside = true;
+ continue;
+ }
+ if (x >= rects[i].x() && x < rects[i].right()) {
+ if (y < rects[i].y()) {
+ if (rects[i].y() - y < distance) {
+ newx = x;
+ newy = rects[i].y();
+ distance = rects[i].y() - y;
+ }
+ } else if (y >= rects[i].bottom()) {
+ if (y - rects[i].bottom() + 1 < distance) {
+ newx = x;
+ newy = rects[i].bottom() - 1;
+ distance = y - rects[i].bottom() + 1;
+ }
+ }
+ } else if (y >= rects[i].y() && y < rects[i].bottom()) {
+ if (x < rects[i].x()) {
+ if (rects[i].x() - x < distance) {
+ newx = rects[i].x();
+ newy = y;
+ distance = rects[i].x() - x;
+ }
+ } else if (x >= rects[i].right()) {
+ if (x - rects[i].right() + 1 < distance) {
+ newx = rects[i].right() - 1;
+ newy = y;
+ distance = x - rects[i].right() + 1;
+ }
+ }
+ }
+ }
+ if (!rects.isEmpty()) {
+ if (!inside) {
+ // if neither x nor y has overlap, just pick the top/left of the first rectangle
+ if (newx == x && newy == y) {
+ newx = rects[0].x();
+ newy = rects[0].y();
+ }
+ m_mousePos.setX(newx - m_scrollOffsetX);
+ m_mousePos.setY(newy - m_scrollOffsetY);
+ DBG_NAV_LOGD("Move x/y from (%d, %d) to (%d, %d) scrollOffset is (%d, %d)",
+ x, y, m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY,
+ m_scrollOffsetX, m_scrollOffsetY);
+ }
+ return rects;
+ }
+ }
+ IntRect rect = final.mBounds;
+ rect.move(frameAdjust.x(), frameAdjust.y());
+ rects.append(rect);
+ // adjust m_mousePos if it is not inside the returned highlight rectangle
+ testRect.move(frameAdjust.x(), frameAdjust.y());
+ testRect.intersect(rect);
+ if (!testRect.contains(x, y)) {
+ m_mousePos = testRect.center();
+ m_mousePos.move(-m_scrollOffsetX, -m_scrollOffsetY);
+ DBG_NAV_LOGD("Move x/y from (%d, %d) to (%d, %d) scrollOffset is (%d, %d)",
+ x, y, m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY,
+ m_scrollOffsetX, m_scrollOffsetY);
+ }
+ }
+#endif
+ return rects;
+}
+
///////////////////////////////////////////////////////////////////////////////
void WebViewCore::addPlugin(PluginWidgetAndroid* w)
@@ -1675,6 +1848,51 @@ void WebViewCore::setSelection(int start, int end)
setFocusControllerActive(focusedFrame, true);
}
+String WebViewCore::modifySelection(const String& alter, const String& direction, const String& granularity)
+{
+ DOMSelection* selection = m_mainFrame->domWindow()->getSelection();
+
+ if (selection->rangeCount() == 0) {
+ Document* document = m_mainFrame->document();
+ HTMLElement* body = document->body();
+ ExceptionCode ec;
+
+ PassRefPtr<Range> rangeRef = document->createRange();
+ rangeRef->setStart(PassRefPtr<Node>(body), 0, ec);
+ if (ec) {
+ LOGE("Error setting range start. Error code: %d", ec);
+ return String();
+ }
+
+ rangeRef->setEnd(PassRefPtr<Node>(body), 0, ec);
+ if (ec) {
+ LOGE("Error setting range end. Error code: %d", ec);
+ return String();
+ }
+
+ selection->addRange(rangeRef.get());
+ }
+
+ if (equalIgnoringCase(direction, "forward")) {
+ selection->collapseToEnd();
+ } else if (equalIgnoringCase(direction, "backward")) {
+ selection->collapseToStart();
+ } else {
+ LOGE("Invalid direction: %s", direction.utf8().data());
+ return String();
+ }
+
+ // NOTE: The selection of WebKit misbehaves and I need to add some
+ // voodoo here to force it behave well. Rachel did something similar
+ // in JS and I want to make sure it is optimal before adding it here.
+
+ selection->modify(alter, direction, granularity);
+ String selection_string = selection->toString();
+ LOGD("Selection string: %s", selection_string.utf8().data());
+
+ return selection_string;
+}
+
void WebViewCore::deleteSelection(int start, int end, int textGeneration)
{
setSelection(start, end);
@@ -1918,15 +2136,24 @@ void WebViewCore::openFileChooser(PassRefPtr<WebCore::FileChooser> chooser) {
if (!chooser)
return;
JNIEnv* env = JSC::Bindings::getJNIEnv();
+
+ WebCore::String acceptType = chooser->acceptTypes();
+ jstring jAcceptType = env->NewString(const_cast<unsigned short*>(acceptType.characters()), acceptType.length());
jstring jName = (jstring) env->CallObjectMethod(
- m_javaGlue->object(env).get(), m_javaGlue->m_openFileChooser);
+ m_javaGlue->object(env).get(), m_javaGlue->m_openFileChooser, jAcceptType);
checkException(env);
- const UChar* string = (const UChar*) env->GetStringChars(jName, NULL);
+ env->DeleteLocalRef(jAcceptType);
+
+ const UChar* string = static_cast<const UChar*>(env->GetStringChars(jName, NULL));
+
if (!string)
return;
+
WebCore::String webcoreString = to_string(env, jName);
env->ReleaseStringChars(jName, string);
- chooser->chooseFile(webcoreString);
+
+ if (webcoreString.length())
+ chooser->chooseFile(webcoreString);
}
void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount,
@@ -1985,12 +2212,25 @@ void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, s
bool WebViewCore::key(const PlatformKeyboardEvent& event)
{
- WebCore::EventHandler* eventHandler = m_mainFrame->eventHandler();
+ WebCore::EventHandler* eventHandler;
WebCore::Node* focusNode = currentFocus();
- if (focusNode)
- eventHandler = focusNode->document()->frame()->eventHandler();
DBG_NAV_LOGD("keyCode=%s unichar=%d focusNode=%p",
event.keyIdentifier().utf8().data(), event.unichar(), focusNode);
+ if (focusNode) {
+ WebCore::Frame* frame = focusNode->document()->frame();
+ eventHandler = frame->eventHandler();
+ if (focusNode->isContentEditable()) {
+ // keyEvent will return true even if the contentEditable did not
+ // change its selection. In the case that it does not, we want to
+ // return false so that the key will be sent back to our navigation
+ // system.
+ VisibleSelection old = frame->selection()->selection();
+ eventHandler->keyEvent(event);
+ return frame->selection()->selection() != old;
+ }
+ } else {
+ eventHandler = m_mainFrame->eventHandler();
+ }
return eventHandler->keyEvent(event);
}
@@ -2075,14 +2315,6 @@ bool WebViewCore::handleTouchEvent(int action, int x, int y, int metaState)
// Track previous touch and if stationary set the state.
WebCore::IntPoint pt(x - m_scrollOffsetX, y - m_scrollOffsetY);
-// handleTouchEvent() in EventHandler.cpp doesn't handle TouchStationary, which
-// causes preventDefault be false when it returns. As our Java side may continue
-// process the events if WebKit doesn't, it can cause unexpected result.
-// if (type == WebCore::TouchMove && pt == m_lastTouchPoint)
-// touchState = WebCore::PlatformTouchPoint::TouchStationary;
-
- m_lastTouchPoint = pt;
-
WebCore::PlatformTouchEvent te(pt, type, touchState, metaState);
preventDefault = m_mainFrame->eventHandler()->handleTouchEvent(te);
#endif
@@ -2097,6 +2329,16 @@ bool WebViewCore::handleTouchEvent(int action, int x, int y, int metaState)
void WebViewCore::touchUp(int touchGeneration,
WebCore::Frame* frame, WebCore::Node* node, int x, int y)
{
+ if (touchGeneration == 0) {
+ // m_mousePos should be set in getTouchHighlightRects()
+ WebCore::HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(m_mousePos, false);
+ node = hitTestResult.innerNode();
+ if (node)
+ frame = node->document()->frame();
+ else
+ frame = 0;
+ DBG_NAV_LOGD("touch up on (%d, %d), scrollOffset is (%d, %d), node:%p, frame:%p", m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY, m_scrollOffsetX, m_scrollOffsetY, node, frame);
+ } else {
if (m_touchGeneration > touchGeneration) {
DBG_NAV_LOGD("m_touchGeneration=%d > touchGeneration=%d"
" x=%d y=%d", m_touchGeneration, touchGeneration, x, y);
@@ -2106,6 +2348,7 @@ void WebViewCore::touchUp(int touchGeneration,
// m_mousePos to determine where the click happens.
moveMouse(frame, x, y);
m_lastGeneration = touchGeneration;
+ }
if (frame && CacheBuilder::validNode(m_mainFrame, frame, 0)) {
frame->loader()->resetMultipleFormSubmissionProtection();
}
@@ -2203,6 +2446,9 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node
} else {
requestKeyboard(false);
}
+ } else if (focusNode->isContentEditable()) {
+ setFocusControllerActive(framePtr, true);
+ requestKeyboard(true);
}
}
return handled;
@@ -2542,6 +2788,13 @@ void WebViewCore::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode
checkException(env);
}
+void WebViewCore::notifyWebAppCanBeInstalled()
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_setInstallableWebApp);
+ checkException(env);
+}
+
//----------------------------------------------------------------------
// Native JNI methods
//----------------------------------------------------------------------
@@ -2568,7 +2821,7 @@ static void UpdateFrameCacheIfLoading(JNIEnv *env, jobject obj)
}
static void SetSize(JNIEnv *env, jobject obj, jint width, jint height,
- jint screenWidth, jfloat scale, jint realScreenWidth, jint screenHeight,
+ jint textWrapWidth, jfloat scale, jint screenWidth, jint screenHeight,
jint anchorX, jint anchorY, jboolean ignoreHeight)
{
#ifdef ANDROID_INSTRUMENT
@@ -2577,8 +2830,8 @@ static void SetSize(JNIEnv *env, jobject obj, jint width, jint height,
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
LOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl);
LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize");
- viewImpl->setSizeScreenWidthAndScale(width, height, screenWidth, scale,
- realScreenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
+ viewImpl->setSizeScreenWidthAndScale(width, height, textWrapWidth, scale,
+ screenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
}
static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint x, jint y)
@@ -2646,6 +2899,22 @@ static void SetSelection(JNIEnv *env, jobject obj, jint start, jint end)
viewImpl->setSelection(start, end);
}
+static jstring ModifySelection(JNIEnv *env, jobject obj, jstring alter, jstring direction, jstring granularity)
+{
+#ifdef ANDROID_INSTRUMENT
+ TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+ String alterString = to_string(env, alter);
+ String directionString = to_string(env, direction);
+ String granularityString = to_string(env, granularity);
+
+ WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ String selection_string = viewImpl->modifySelection(alterString,
+ directionString,
+ granularityString);
+
+ return WebCoreStringToJString(env, selection_string);
+}
static void ReplaceTextfieldText(JNIEnv *env, jobject obj,
jint oldStart, jint oldEnd, jstring replace, jint start, jint end,
@@ -2710,7 +2979,7 @@ void WebViewCore::addVisitedLink(const UChar* string, int length)
m_groupForVisitedLinks->addVisitedLink(string, length);
}
-static bool RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
+static jint RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
@@ -2718,18 +2987,18 @@ static bool RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
SkRegion* nativeRegion = GraphicsJNI::getNativeRegion(env, region);
SkIPoint nativePt;
- bool result = viewImpl->recordContent(nativeRegion, &nativePt);
+ BaseLayerAndroid* result = viewImpl->recordContent(nativeRegion, &nativePt);
GraphicsJNI::ipoint_to_jpoint(nativePt, env, pt);
- return result;
+ return reinterpret_cast<jint>(result);
}
-static void SplitContent(JNIEnv *env, jobject obj)
+static void SplitContent(JNIEnv *env, jobject obj, jint content)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
#endif
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- viewImpl->splitContent();
+ viewImpl->splitContent(reinterpret_cast<PictureSet*>(content));
}
static void SendListBoxChoice(JNIEnv* env, jobject obj, jint choice)
@@ -2981,7 +3250,7 @@ static void SetJsFlags(JNIEnv *env, jobject obj, jstring flags)
{
#if USE(V8)
WebCore::String flagsString = to_string(env, flags);
- WebCore::CString utf8String = flagsString.utf8();
+ WTF::CString utf8String = flagsString.utf8();
WebCore::ScriptController::setFlags(utf8String.data(), utf8String.length());
#endif
}
@@ -3018,45 +3287,11 @@ static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jstring scheme) {
WebCore::SecurityOrigin::registerURLSchemeAsLocal(to_string(env, scheme));
}
-static void ClearContent(JNIEnv *env, jobject obj)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- viewImpl->clearContent();
-}
-
-static void CopyContentToPicture(JNIEnv *env, jobject obj, jobject pict)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- if (!viewImpl)
- return;
- SkPicture* picture = GraphicsJNI::getNativePicture(env, pict);
- viewImpl->copyContentToPicture(picture);
-}
-
-static bool DrawContent(JNIEnv *env, jobject obj, jobject canv, jint color)
-{
- // Note: this is called from UI thread, don't count it for WebViewCoreTimeCounter
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
- return viewImpl->drawContent(canvas, color);
-}
-
static bool FocusBoundsChanged(JNIEnv* env, jobject obj)
{
return GET_NATIVE_VIEW(env, obj)->focusBoundsChanged();
}
-static bool PictureReady(JNIEnv* env, jobject obj)
-{
- return GET_NATIVE_VIEW(env, obj)->pictureReady();
-}
-
static void Pause(JNIEnv* env, jobject obj)
{
// This is called for the foreground tab when the browser is put to the
@@ -3151,26 +3386,54 @@ static bool ValidNodeAndBounds(JNIEnv *env, jobject obj, int frame, int node,
reinterpret_cast<Node*>(node), nativeRect);
}
+static jobject GetTouchHighlightRects(JNIEnv* env, jobject obj, jint x, jint y, jint slop)
+{
+ WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ if (!viewImpl)
+ return NULL;
+ Vector<IntRect> rects = viewImpl->getTouchHighlightRects(x, y, slop);
+ if (rects.isEmpty())
+ return NULL;
+
+ jclass arrayClass = env->FindClass("java/util/ArrayList");
+ LOG_ASSERT(arrayClass, "Could not find java/util/ArrayList");
+ jmethodID init = env->GetMethodID(arrayClass, "<init>", "(I)V");
+ LOG_ASSERT(init, "Could not find constructor for ArrayList");
+ jobject array = env->NewObject(arrayClass, init, rects.size());
+ LOG_ASSERT(vector, "Could not create a new ArrayList");
+ jmethodID add = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z");
+ LOG_ASSERT(add, "Could not find add method on ArrayList");
+ jclass rectClass = env->FindClass("android/graphics/Rect");
+ LOG_ASSERT(rectClass, "Could not find android/graphics/Rect");
+ jmethodID rectinit = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+ LOG_ASSERT(rectinit, "Could not find init method on Rect");
+
+ for (size_t i = 0; i < rects.size(); i++) {
+ jobject rect = env->NewObject(rectClass, rectinit, rects[i].x(),
+ rects[i].y(), rects[i].right(), rects[i].bottom());
+ if (rect) {
+ env->CallBooleanMethod(array, add, rect);
+ env->DeleteLocalRef(rect);
+ }
+ }
+
+ env->DeleteLocalRef(rectClass);
+ env->DeleteLocalRef(arrayClass);
+ return array;
+}
+
// ----------------------------------------------------------------------------
/*
* JNI registration.
*/
static JNINativeMethod gJavaWebViewCoreMethods[] = {
- { "nativeClearContent", "()V",
- (void*) ClearContent },
- { "nativeCopyContentToPicture", "(Landroid/graphics/Picture;)V",
- (void*) CopyContentToPicture },
- { "nativeDrawContent", "(Landroid/graphics/Canvas;I)Z",
- (void*) DrawContent } ,
{ "nativeFocusBoundsChanged", "()Z",
(void*) FocusBoundsChanged } ,
{ "nativeKey", "(IIIZZZZ)Z",
(void*) Key },
{ "nativeClick", "(II)V",
(void*) Click },
- { "nativePictureReady", "()Z",
- (void*) PictureReady } ,
{ "nativeSendListBoxChoices", "([ZI)V",
(void*) SendListBoxChoices },
{ "nativeSendListBoxChoice", "(I)V",
@@ -3183,6 +3446,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) SetGlobalBounds },
{ "nativeSetSelection", "(II)V",
(void*) SetSelection } ,
+ { "nativeModifySelection", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+ (void*) ModifySelection },
{ "nativeDeleteSelection", "(III)V",
(void*) DeleteSelection } ,
{ "nativeReplaceTextfieldText", "(IILjava/lang/String;III)V",
@@ -3215,11 +3480,11 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) UpdateFrameCache },
{ "nativeGetContentMinPrefWidth", "()I",
(void*) GetContentMinPrefWidth },
- { "nativeRecordContent", "(Landroid/graphics/Region;Landroid/graphics/Point;)Z",
+ { "nativeRecordContent", "(Landroid/graphics/Region;Landroid/graphics/Point;)I",
(void*) RecordContent },
{ "setViewportSettingsFromNative", "()V",
(void*) SetViewportSettingsFromNative },
- { "nativeSplitContent", "()V",
+ { "nativeSplitContent", "(I)V",
(void*) SplitContent },
{ "nativeSetBackgroundColor", "(I)V",
(void*) SetBackgroundColor },
@@ -3251,6 +3516,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) FullScreenPluginHidden },
{ "nativeValidNodeAndBounds", "(IILandroid/graphics/Rect;)Z",
(void*) ValidNodeAndBounds },
+ { "nativeGetTouchHighlightRects", "(III)Ljava/util/ArrayList;",
+ (void*) GetTouchHighlightRects },
};
int register_webviewcore(JNIEnv* env)
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index 056dba1..99f02e9 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -61,10 +61,13 @@ namespace WebCore {
#if USE(ACCELERATED_COMPOSITING)
namespace WebCore {
class GraphicsLayerAndroid;
- class LayerAndroid;
}
#endif
+namespace WebCore {
+ class BaseLayerAndroid;
+}
+
struct PluginWidgetAndroid;
class SkPicture;
class SkIRect;
@@ -137,8 +140,6 @@ namespace android {
#if USE(ACCELERATED_COMPOSITING)
GraphicsLayerAndroid* graphicsRootLayer() const;
- void immediateRepaint();
- void setUIRootLayer(const LayerAndroid* layer);
#endif
/** Invalidate the view/screen, NOT the content/DOM, but expressed in
@@ -170,15 +171,9 @@ namespace android {
/**
* Notify the view to restore the screen width, which in turn restores
- * the scale.
- */
- void restoreScale(int);
-
- /**
- * Notify the view to restore the scale used to calculate the screen
- * width for wrapping the text
+ * the scale. Also restore the scale for the text wrap.
*/
- void restoreScreenWidthScale(int);
+ void restoreScale(int scale, int textWrapScale);
/**
* Tell the java side to update the focused textfield
@@ -325,6 +320,18 @@ namespace android {
* If start and end are out of order, swap them.
*/
void setSelection(int start, int end);
+
+ /**
+ * Modifies the current selection.
+ *
+ * alter - Specifies how to alter the selection.
+ * direction - The direction in which to alter the selection.
+ * granularity - The granularity of the selection modification.
+ *
+ * returns - The selection as string.
+ */
+ String modifySelection(const String& alter, const String& direction, const String& granularity);
+
/**
* In the currently focused textfield, replace the characters from oldStart to oldEnd
* (if oldStart == oldEnd, this will be an insert at that position) with replace,
@@ -432,6 +439,9 @@ namespace android {
// in the current view.
void centerFitRect(int x, int y, int width, int height);
+ // return a list of rects matching the touch point (x, y) with the slop
+ Vector<IntRect> getTouchHighlightRects(int x, int y, int slop);
+
// other public functions
public:
// Open a file chooser for selecting a file to upload
@@ -440,27 +450,22 @@ namespace android {
// reset the picture set to empty
void clearContent();
- // flatten the picture set to a picture
- void copyContentToPicture(SkPicture* );
-
- // draw the picture set with the specified background color
- bool drawContent(SkCanvas* , SkColor );
bool focusBoundsChanged();
- bool pictureReady();
// record the inval area, and the picture size
- bool recordContent(SkRegion* , SkIPoint* );
- int screenWidth() const { return m_screenWidth; }
- int screenHeight() const { return m_screenHeight; }
+ BaseLayerAndroid* recordContent(SkRegion* , SkIPoint* );
+ int textWrapWidth() const { return m_textWrapWidth; }
float scale() const { return m_scale; }
- float screenWidthScale() const { return m_screenWidthScale; }
+ float textWrapScale() const { return m_screenWidth * m_scale / m_textWrapWidth; }
WebCore::Frame* mainFrame() const { return m_mainFrame; }
void updateCursorBounds(const CachedRoot* root,
const CachedFrame* cachedFrame, const CachedNode* cachedNode);
void updateFrameCacheIfLoading();
// utility to split slow parts of the picture set
- void splitContent();
+ void splitContent(PictureSet*);
+
+ void notifyWebAppCanBeInstalled();
// these members are shared with webview.cpp
static Mutex gFrameCacheMutex;
@@ -510,8 +515,7 @@ namespace android {
WebCore::IntRect m_lastFocusedBounds;
int m_lastFocusedSelStart;
int m_lastFocusedSelEnd;
- static Mutex m_contentMutex; // protects ui/core thread pictureset access
- PictureSet m_content; // the set of pictures to draw (accessed by UI too)
+ PictureSet m_content; // the set of pictures to draw
SkRegion m_addInval; // the accumulated inval region (not yet drawn)
SkRegion m_rebuildInval; // the accumulated region for rebuilt pictures
// Used in passToJS to avoid updating the UI text field until after the
@@ -536,8 +540,8 @@ namespace android {
CachedHistory m_history;
int m_screenWidth; // width of the visible rect in document coordinates
int m_screenHeight;// height of the visible rect in document coordinates
+ int m_textWrapWidth;
float m_scale;
- float m_screenWidthScale;
unsigned m_domtree_version;
bool m_check_domtree_version;
PageGroup* m_groupForVisitedLinks;
@@ -558,7 +562,6 @@ namespace android {
#if ENABLE(TOUCH_EVENTS)
bool m_forwardingTouchEvents;
- IntPoint m_lastTouchPoint;
#endif
#if DEBUG_NAV_UI