summaryrefslogtreecommitdiffstats
path: root/WebKit
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit')
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp2
-rw-r--r--WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp6
-rw-r--r--WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h2
-rw-r--r--WebKit/android/WebCoreSupport/PlatformBridge.cpp8
-rw-r--r--WebKit/android/WebCoreSupport/WebCookieJar.cpp27
-rw-r--r--WebKit/android/WebCoreSupport/WebCookieJar.h6
-rw-r--r--WebKit/android/WebCoreSupport/WebRequest.cpp2
-rw-r--r--WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp39
-rw-r--r--WebKit/android/jni/CookieManager.cpp21
-rw-r--r--WebKit/android/jni/WebCoreFrameBridge.cpp103
-rw-r--r--WebKit/android/jni/WebCoreFrameBridge.h14
-rw-r--r--WebKit/android/jni/WebViewCore.cpp858
-rw-r--r--WebKit/android/jni/WebViewCore.h38
-rw-r--r--WebKit/android/nav/CachedFrame.cpp18
-rw-r--r--WebKit/android/nav/CachedLayer.cpp1
-rw-r--r--WebKit/android/nav/WebView.cpp30
-rw-r--r--WebKit/android/plugins/ANPOpenGLInterface.cpp3
-rw-r--r--WebKit/android/plugins/PluginWidgetAndroid.cpp32
-rw-r--r--WebKit/android/plugins/PluginWidgetAndroid.h2
19 files changed, 575 insertions, 637 deletions
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index f0958d9..fb5701a 100644
--- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -536,7 +536,7 @@ bool ChromeClientAndroid::selectItemWritingDirectionIsNatural()
PassRefPtr<PopupMenu> ChromeClientAndroid::createPopupMenu(PopupMenuClient* client) const
{
- return adoptRef(new PopupMenuAndroid(client));
+ return adoptRef(new PopupMenuAndroid(static_cast<ListPopupMenuClient*>(client)));
}
PassRefPtr<SearchPopupMenu> ChromeClientAndroid::createSearchPopupMenu(PopupMenuClient*) const
diff --git a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
index cc21dad..535c0da 100644
--- a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
@@ -577,6 +577,12 @@ void FrameLoaderClientAndroid::dispatchWillSubmitForm(FramePolicyFunction func,
(m_frame->loader()->policyChecker()->*func)(PolicyUse);
}
+void FrameLoaderClientAndroid::dispatchWillSendSubmitEvent(HTMLFormElement* form)
+{
+ if (m_webFrame->shouldSaveFormData())
+ m_webFrame->saveFormData(form);
+}
+
void FrameLoaderClientAndroid::dispatchDidLoadMainResource(DocumentLoader*) {
notImplemented();
}
diff --git a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
index 964ac6e..034333e 100644
--- a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
@@ -223,7 +223,7 @@ namespace android {
void enableOnDemandPlugins() { m_onDemandPluginsEnabled = true; }
void dispatchDidChangeIcons();
- void dispatchWillSendSubmitEvent(HTMLFormElement*) { }
+ void dispatchWillSendSubmitEvent(HTMLFormElement*);
private:
CacheBuilder m_cacheBuilder;
Frame* m_frame;
diff --git a/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/WebKit/android/WebCoreSupport/PlatformBridge.cpp
index b34ff8c..8d8d809 100644
--- a/WebKit/android/WebCoreSupport/PlatformBridge.cpp
+++ b/WebKit/android/WebCoreSupport/PlatformBridge.cpp
@@ -160,16 +160,16 @@ FloatRect PlatformBridge::screenRect()
}
// The visible size on screen in document coordinate
-int PlatformBridge::visibleScreenWidth(const WebCore::FrameView* frameView)
+int PlatformBridge::screenWidthInDocCoord(const WebCore::FrameView* frameView)
{
android::WebViewCore* webViewCore = android::WebViewCore::getWebViewCore(frameView);
- return webViewCore->visibleScreenWidth();
+ return webViewCore->screenWidth();
}
-int PlatformBridge::visibleScreenHeight(const WebCore::FrameView* frameView)
+int PlatformBridge::screenHeightInDocCoord(const WebCore::FrameView* frameView)
{
android::WebViewCore* webViewCore = android::WebViewCore::getWebViewCore(frameView);
- return webViewCore->visibleScreenHeight();
+ return webViewCore->screenHeight();
}
String PlatformBridge::computeDefaultLanguage()
diff --git a/WebKit/android/WebCoreSupport/WebCookieJar.cpp b/WebKit/android/WebCoreSupport/WebCookieJar.cpp
index d290b5a..9c1d7fa 100644
--- a/WebKit/android/WebCoreSupport/WebCookieJar.cpp
+++ b/WebKit/android/WebCoreSupport/WebCookieJar.cpp
@@ -37,6 +37,8 @@
namespace android {
static WTF::Mutex instanceMutex;
+static bool isFirstInstanceCreated = false;
+static bool fileSchemeCookiesEnabled = false;
static const std::string& databaseDirectory()
{
@@ -99,6 +101,9 @@ scoped_refptr<WebCookieJar>* instance(bool isPrivateBrowsing)
WebCookieJar* WebCookieJar::get(bool isPrivateBrowsing)
{
MutexLocker lock(instanceMutex);
+ if (!isFirstInstanceCreated && fileSchemeCookiesEnabled)
+ net::CookieMonster::EnableFileScheme();
+ isFirstInstanceCreated = true;
scoped_refptr<WebCookieJar>* instancePtr = instance(isPrivateBrowsing);
if (!instancePtr->get())
*instancePtr = new WebCookieJar(databaseDirectory(isPrivateBrowsing));
@@ -117,9 +122,6 @@ void WebCookieJar::cleanup(bool isPrivateBrowsing)
WebCookieJar::WebCookieJar(const std::string& databaseFilePath)
: m_allowCookies(true)
{
- // This is needed for the page cycler. See http://b/2944150
- net::CookieMonster::EnableFileScheme();
-
// Setup the permissions for the file
const char* cDatabasePath = databaseFilePath.c_str();
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
@@ -130,6 +132,7 @@ WebCookieJar::WebCookieJar(const std::string& databaseFilePath)
if (fd >= 0)
close(fd);
}
+
FilePath cookiePath(databaseFilePath.c_str());
m_cookieDb = new SQLitePersistentCookieStore(cookiePath);
m_cookieStore = new net::CookieMonster(m_cookieDb.get(), 0);
@@ -227,4 +230,22 @@ void WebCookieJar::flush()
semaphore->Wait(2);
}
+bool WebCookieJar::acceptFileSchemeCookies()
+{
+ MutexLocker lock(instanceMutex);
+ return fileSchemeCookiesEnabled;
+}
+
+void WebCookieJar::setAcceptFileSchemeCookies(bool accept)
+{
+ // The Chromium HTTP stack only reflects changes to this flag when creating
+ // a new CookieMonster instance. While we could track whether any
+ // CookieMonster instances currently exist, this would be complicated and is
+ // not required, so we only allow this flag to be changed before the first
+ // instance is created.
+ MutexLocker lock(instanceMutex);
+ if (!isFirstInstanceCreated)
+ fileSchemeCookiesEnabled = accept;
+}
+
}
diff --git a/WebKit/android/WebCoreSupport/WebCookieJar.h b/WebKit/android/WebCoreSupport/WebCookieJar.h
index 2f32e1a..1f4266c 100644
--- a/WebKit/android/WebCoreSupport/WebCookieJar.h
+++ b/WebKit/android/WebCoreSupport/WebCookieJar.h
@@ -49,6 +49,12 @@ public:
bool allowCookies();
void setAllowCookies(bool allow);
+ // Getter and setter for whether we accept cookies for file scheme URLS.
+ // Defaults to false. Note that calls to the setter are ignored once the
+ // first instance of this class has been created.
+ static bool acceptFileSchemeCookies();
+ static void setAcceptFileSchemeCookies(bool);
+
// Instead of this it would probably be better to add the cookie methods
// here so the rest of WebKit doesn't have to know about Chromium classes
net::CookieStore* cookieStore() { return m_cookieStore.get(); }
diff --git a/WebKit/android/WebCoreSupport/WebRequest.cpp b/WebKit/android/WebCoreSupport/WebRequest.cpp
index e44b600..a14036f 100644
--- a/WebKit/android/WebCoreSupport/WebRequest.cpp
+++ b/WebKit/android/WebCoreSupport/WebRequest.cpp
@@ -473,7 +473,7 @@ void WebRequest::startReading()
if (!read(&bytesRead)) {
if (m_request && m_request->status().is_io_pending())
return; // Wait for OnReadCompleted()
- finish(false);
+ return finish(false);
}
// bytesRead == 0 indicates finished
diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
index 5c54000..642a81a 100644
--- a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
+++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
@@ -38,7 +38,6 @@
#include "WebResourceRequest.h"
#include <wtf/text/CString.h>
-#include <sstream>
namespace android {
@@ -88,6 +87,8 @@ bool WebUrlLoaderClient::isActive() const
{
if (m_cancelling)
return false;
+ if (!m_resourceHandle)
+ return false;
if (!m_resourceHandle->client())
return false;
if (m_finished)
@@ -344,30 +345,6 @@ void WebUrlLoaderClient::maybeCallOnMainThread(Task* task)
}
}
-namespace {
-// Convert a CertPrincipal into string readable by Java code.
-// The expected format is "CN=xxx, O=xxx, OU=xxx" (see SslCertificate.DName).
-// If there are multiple organization names, we print them all.
-static std::string certPrincipalToString(const net::CertPrincipal& cp)
-{
- std::string result;
- if (!cp.common_name.empty()) {
- result += "CN=";
- result += cp.common_name;
- }
- std::vector<std::string>::const_iterator i;
- for (i = cp.organization_names.begin(); i != cp.organization_names.end(); ++i) {
- result += result.empty() ? "O=" : ", O=";
- result += *i;
- }
- for (i = cp.organization_unit_names.begin(); i != cp.organization_unit_names.end(); ++i) {
- result += result.empty() ? "OU=" : ", OU=";
- result += *i;
- }
- return result;
-}
-}
-
// Response methods
void WebUrlLoaderClient::didReceiveResponse(PassOwnPtr<WebResponse> webResponse)
{
@@ -379,13 +356,11 @@ void WebUrlLoaderClient::didReceiveResponse(PassOwnPtr<WebResponse> webResponse)
if (m_isMainResource) {
// If we got an SSL certificate, tell the WebView about it.
- const net::SSLInfo& ssl = m_response->getSslInfo();
- if (ssl.cert) {
- m_webFrame->setCertificate(
- certPrincipalToString(ssl.cert->subject()),
- certPrincipalToString(ssl.cert->issuer()),
- 1000L * ssl.cert->valid_start().ToDoubleT(),
- 1000L * ssl.cert->valid_expiry().ToDoubleT());
+ const net::SSLInfo& ssl_info = m_response->getSslInfo();
+ if (ssl_info.is_valid()) {
+ std::vector<std::string> chain_bytes;
+ ssl_info.cert->GetChainDEREncodedBytes(&chain_bytes);
+ m_webFrame->setCertificate(chain_bytes[0]);
}
}
}
diff --git a/WebKit/android/jni/CookieManager.cpp b/WebKit/android/jni/CookieManager.cpp
index 87c7fa8..a9c68fd 100644
--- a/WebKit/android/jni/CookieManager.cpp
+++ b/WebKit/android/jni/CookieManager.cpp
@@ -155,6 +155,25 @@ static void flushCookieStore(JNIEnv*, jobject)
#endif
}
+static bool acceptFileSchemeCookies(JNIEnv*, jobject)
+{
+#if USE(CHROME_NETWORK_STACK)
+ return WebCookieJar::acceptFileSchemeCookies();
+#else
+ // File scheme cookies are always accepted with the Android HTTP stack.
+ return true;
+#endif
+}
+
+static void setAcceptFileSchemeCookies(JNIEnv*, jobject, jboolean accept)
+{
+#if USE(CHROME_NETWORK_STACK)
+ WebCookieJar::setAcceptFileSchemeCookies(accept);
+#else
+ // File scheme cookies are always accepted with the Android HTTP stack.
+#endif
+}
+
static JNINativeMethod gCookieManagerMethods[] = {
{ "nativeAcceptCookie", "()Z", (void*) acceptCookie },
{ "nativeGetCookie", "(Ljava/lang/String;)Ljava/lang/String;", (void*) getCookie },
@@ -165,6 +184,8 @@ static JNINativeMethod gCookieManagerMethods[] = {
{ "nativeSetAcceptCookie", "(Z)V", (void*) setAcceptCookie },
{ "nativeSetCookie", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) setCookie },
{ "nativeFlushCookieStore", "()V", (void*) flushCookieStore },
+ { "nativeAcceptFileSchemeCookies", "()Z", (void*) acceptFileSchemeCookies },
+ { "nativeSetAcceptFileSchemeCookies", "(Z)V", (void*) setAcceptFileSchemeCookies },
};
int registerCookieManager(JNIEnv* env)
diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp
index 9780d2d..c187d92 100644
--- a/WebKit/android/jni/WebCoreFrameBridge.cpp
+++ b/WebKit/android/jni/WebCoreFrameBridge.cpp
@@ -44,7 +44,6 @@
#include "Element.h"
#include "FocusController.h"
#include "Font.h"
-#include "FormState.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClientAndroid.h"
@@ -220,6 +219,8 @@ struct WebFrame::JavaBrowserFrame
jmethodID mDidReceiveData;
jmethodID mDidFinishLoading;
jmethodID mSetCertificate;
+ jmethodID mShouldSaveFormData;
+ jmethodID mSaveFormData;
AutoJObject frame(JNIEnv* env) {
return getRealObject(env, mObj);
}
@@ -290,8 +291,9 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page*
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V");
mJavaFrame->mDidReceiveData = env->GetMethodID(clazz, "didReceiveData", "([BI)V");
mJavaFrame->mDidFinishLoading = env->GetMethodID(clazz, "didFinishLoading", "()V");
- mJavaFrame->mSetCertificate = env->GetMethodID(clazz, "setCertificate",
- "(Ljava/lang/String;Ljava/lang/String;JJ)V");
+ mJavaFrame->mSetCertificate = env->GetMethodID(clazz, "setCertificate", "([B)V");
+ mJavaFrame->mShouldSaveFormData = env->GetMethodID(clazz, "shouldSaveFormData", "()Z");
+ mJavaFrame->mSaveFormData = env->GetMethodID(clazz, "saveFormData", "(Ljava/util/HashMap;)V");
env->DeleteLocalRef(clazz);
LOG_ASSERT(mJavaFrame->mStartLoadingResource, "Could not find method startLoadingResource");
@@ -322,6 +324,8 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page*
LOG_ASSERT(mJavaFrame->mDidReceiveData, "Could not find method didReceiveData");
LOG_ASSERT(mJavaFrame->mDidFinishLoading, "Could not find method didFinishLoading");
LOG_ASSERT(mJavaFrame->mSetCertificate, "Could not find method setCertificate");
+ LOG_ASSERT(mJavaFrame->mShouldSaveFormData, "Could not find method shouldSaveFormData");
+ LOG_ASSERT(mJavaFrame->mSaveFormData, "Could not find method saveFormData");
mUserAgent = WTF::String();
mUserInitiatedAction = false;
@@ -782,6 +786,16 @@ WebFrame::canHandleRequest(const WebCore::ResourceRequest& request)
return (ret == 0);
}
+bool
+WebFrame::shouldSaveFormData()
+{
+ JNIEnv* env = getJNIEnv();
+ jboolean ret = env->CallBooleanMethod(mJavaFrame->frame(env).get(),
+ mJavaFrame->mShouldSaveFormData);
+ checkException(env);
+ return ret;
+}
+
WebCore::Frame*
WebFrame::createWindow(bool dialog, bool userGesture)
{
@@ -950,20 +964,21 @@ WebFrame::didFinishLoading() {
#endif
#if USE(CHROME_NETWORK_STACK)
-void WebFrame::setCertificate(const std::string& issuedTo, const std::string& issuedBy, long long validNotBeforeMillis, long long validNotAfterMillis)
+void WebFrame::setCertificate(const std::string& cert)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
#endif
JNIEnv* env = getJNIEnv();
- jstring jIssuedTo = stdStringToJstring(env, issuedTo, true);
- jstring jIssuedBy = stdStringToJstring(env, issuedBy, true);
- env->CallVoidMethod(mJavaFrame->frame(env).get(),
- mJavaFrame->mSetCertificate, jIssuedTo, jIssuedBy, validNotBeforeMillis, validNotAfterMillis);
+ int len = cert.length();
+ jbyteArray jCert = env->NewByteArray(len);
+ jbyte* bytes = env->GetByteArrayElements(jCert, NULL);
+ cert.copy(reinterpret_cast<char*>(bytes), len);
+
+ env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSetCertificate, jCert);
- env->DeleteLocalRef(jIssuedTo);
- env->DeleteLocalRef(jIssuedBy);
+ env->DeleteLocalRef(jCert);
checkException(env);
}
#endif
@@ -1876,62 +1891,46 @@ static void SetUsernamePassword(JNIEnv *env, jobject obj,
}
}
-static jobject GetFormTextData(JNIEnv *env, jobject obj)
+void
+WebFrame::saveFormData(HTMLFormElement* form)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
-#endif
- WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
- LOG_ASSERT(pFrame, "GetFormTextData must take a valid frame pointer!");
- jobject hashMap = NULL;
-
- WTF::PassRefPtr<WebCore::HTMLCollection> collection = pFrame->document()->forms();
- if (collection->length() > 0) {
+ if (form->autoComplete()) {
+ JNIEnv* env = getJNIEnv();
jclass mapClass = env->FindClass("java/util/HashMap");
LOG_ASSERT(mapClass, "Could not find HashMap class!");
jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V");
LOG_ASSERT(init, "Could not find constructor for HashMap");
- hashMap = env->NewObject(mapClass, init, 1);
+ jobject hashMap = env->NewObject(mapClass, init, 1);
LOG_ASSERT(hashMap, "Could not create a new HashMap");
jmethodID put = env->GetMethodID(mapClass, "put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
LOG_ASSERT(put, "Could not find put method on HashMap");
-
- WebCore::HTMLFormElement* form;
- WebCore::HTMLInputElement* input;
- for (WebCore::Node* node = collection->firstItem();
- node && !node->namespaceURI().isNull() && !node->namespaceURI().isEmpty();
- node = collection->nextItem()) {
- form = static_cast<WebCore::HTMLFormElement*>(node);
- if (form->autoComplete()) {
- 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];
- if (e->hasTagName(WebCore::HTMLNames::inputTag)) {
- input = static_cast<WebCore::HTMLInputElement*>(e);
- if (input->isTextField() && !input->isPasswordField()
- && input->autoComplete()) {
- WTF::String value = input->value();
- int len = value.length();
- if (len) {
- const WTF::AtomicString& name = input->name();
- jstring key = wtfStringToJstring(env, name);
- jstring val = wtfStringToJstring(env, value);
- LOG_ASSERT(key && val, "name or value not set");
- env->CallObjectMethod(hashMap, put, key, val);
- env->DeleteLocalRef(key);
- env->DeleteLocalRef(val);
- }
- }
+ 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];
+ if (e->hasTagName(WebCore::HTMLNames::inputTag)) {
+ WebCore::HTMLInputElement* input = static_cast<WebCore::HTMLInputElement*>(e);
+ if (input->isTextField() && !input->isPasswordField()
+ && input->autoComplete()) {
+ WTF::String value = input->value();
+ int len = value.length();
+ if (len) {
+ const WTF::AtomicString& name = input->name();
+ jstring key = wtfStringToJstring(env, name);
+ jstring val = wtfStringToJstring(env, value);
+ LOG_ASSERT(key && val, "name or value not set");
+ env->CallObjectMethod(hashMap, put, key, val);
+ env->DeleteLocalRef(key);
+ env->DeleteLocalRef(val);
}
}
}
}
+ env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSaveFormData, hashMap);
+ env->DeleteLocalRef(hashMap);
env->DeleteLocalRef(mapClass);
-
}
- return hashMap;
}
static void OrientationChanged(JNIEnv *env, jobject obj, int orientation)
@@ -2048,8 +2047,6 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = {
(void*) GetUsernamePassword },
{ "setUsernamePassword", "(Ljava/lang/String;Ljava/lang/String;)V",
(void*) SetUsernamePassword },
- { "getFormTextData", "()Ljava/util/HashMap;",
- (void*) GetFormTextData },
{ "nativeOrientationChanged", "(I)V",
(void*) OrientationChanged },
{ "nativeAuthenticationProceed", "(ILjava/lang/String;Ljava/lang/String;)V",
diff --git a/WebKit/android/jni/WebCoreFrameBridge.h b/WebKit/android/jni/WebCoreFrameBridge.h
index ae62835..af7be60 100644
--- a/WebKit/android/jni/WebCoreFrameBridge.h
+++ b/WebKit/android/jni/WebCoreFrameBridge.h
@@ -37,6 +37,7 @@
#include <wtf/RefCounted.h>
namespace WebCore {
+ class HTMLFormElement;
class Frame;
class HistoryItem;
class Image;
@@ -125,18 +126,15 @@ class WebFrame : public WebCoreRefObject {
void maybeSavePassword(WebCore::Frame* frame, const WebCore::ResourceRequest& request);
- void setCertificate(const std::string& issuedTo, const std::string& issuedBy, long long validNotBeforeMillis, long long validNotAfterMillis);
+ void setCertificate(const std::string& cert);
/**
- * When the user initiates an action (via trackball, key-press, or touch),
- * we set mUserInitiatedAction to true. If a load happens due to this click,
- * then we ask the application if it wants to override
- * the load. Otherwise, we attempt to load the resource internally.
+ * When the user initiates a click, we set mUserInitiatedAction to true.
+ * If a load happens due to this click, then we ask the application if it wants
+ * to override the load. Otherwise, we attempt to load the resource internally.
*/
void setUserInitiatedAction(bool userInitiatedAction) { mUserInitiatedAction = userInitiatedAction; }
- bool userInitiatedAction() { return mUserInitiatedAction; }
-
WebCore::Page* page() const { return mPage; }
// Currently used only by the chrome net stack. A similar field is used by
@@ -151,6 +149,8 @@ class WebFrame : public WebCoreRefObject {
bool getUsernamePasswordFromDom(WebCore::Frame* frame, WTF::String& username, WTF::String& password);
jbyteArray getPostData(const WebCore::ResourceRequest& request);
+ bool shouldSaveFormData();
+ void saveFormData(WebCore::HTMLFormElement*);
private:
struct JavaBrowserFrame;
JavaBrowserFrame* mJavaFrame;
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 8361c17..8c0fade 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -35,6 +35,8 @@
#include "Chrome.h"
#include "ChromeClientAndroid.h"
#include "ChromiumIncludes.h"
+#include "ClientRect.h"
+#include "ClientRectList.h"
#include "Color.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
@@ -250,9 +252,7 @@ struct WebViewCoreFields {
struct WebViewCore::JavaGlue {
jweak m_obj;
- jmethodID m_spawnScrollTo;
jmethodID m_scrollTo;
- jmethodID m_scrollBy;
jmethodID m_contentDraw;
jmethodID m_layersDraw;
jmethodID m_requestListBox;
@@ -342,15 +342,14 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
#endif
m_isPaused = false;
m_screenOnCounter = 0;
+ m_onlyScrollIfImeIsShowing = false;
LOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!");
jclass clazz = env->GetObjectClass(javaWebViewCore);
m_javaGlue = new JavaGlue;
m_javaGlue->m_obj = env->NewWeakGlobalRef(javaWebViewCore);
- m_javaGlue->m_spawnScrollTo = GetJMethod(env, clazz, "contentSpawnScrollTo", "(II)V");
- m_javaGlue->m_scrollTo = GetJMethod(env, clazz, "contentScrollTo", "(II)V");
- m_javaGlue->m_scrollBy = GetJMethod(env, clazz, "contentScrollBy", "(IIZ)V");
+ m_javaGlue->m_scrollTo = GetJMethod(env, clazz, "contentScrollTo", "(IIZZ)V");
m_javaGlue->m_contentDraw = GetJMethod(env, clazz, "contentDraw", "()V");
m_javaGlue->m_layersDraw = GetJMethod(env, clazz, "layersDraw", "()V");
m_javaGlue->m_requestListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[I[I)V");
@@ -486,8 +485,6 @@ void WebViewCore::reset(bool fromConstructor)
m_scrollOffsetY = 0;
m_screenWidth = 0;
m_screenHeight = 0;
- m_visibleScreenWidth = 0;
- m_visibleScreenHeight = 0;
m_groupForVisitedLinks = NULL;
m_currentNodeDomNavigationAxis = 0;
}
@@ -947,9 +944,8 @@ void WebViewCore::scrollTo(int x, int y, bool animate)
// LOGD("WebViewCore::scrollTo(%d %d)\n", x, y);
JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(),
- animate ? m_javaGlue->m_spawnScrollTo : m_javaGlue->m_scrollTo,
- x, y);
+ env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollTo,
+ x, y, animate, m_onlyScrollIfImeIsShowing);
checkException(env);
}
@@ -971,16 +967,6 @@ void WebViewCore::viewInvalidate(const WebCore::IntRect& rect)
checkException(env);
}
-void WebViewCore::scrollBy(int dx, int dy, bool animate)
-{
- if (!(dx | dy))
- return;
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollBy,
- dx, dy, animate);
- checkException(env);
-}
-
void WebViewCore::contentDraw()
{
JNIEnv* env = JSC::Bindings::getJNIEnv();
@@ -1151,13 +1137,14 @@ void WebViewCore::doMaxScroll(CacheBuilder::Direction dir)
default:
LOG_ASSERT(0, "unexpected focus selector");
}
- this->scrollBy(dx, dy, true);
+ WebCore::FrameView* view = m_mainFrame->view();
+ this->scrollTo(view->scrollX() + dx, view->scrollY() + dy, true);
}
-void WebViewCore::setScrollOffset(int moveGeneration, int userScrolled, int dx, int dy)
+void WebViewCore::setScrollOffset(int moveGeneration, bool sendScrollEvent, int dx, int dy)
{
- DBG_NAV_LOGD("{%d,%d} m_scrollOffset=(%d,%d), userScrolled=%d", dx, dy,
- m_scrollOffsetX, m_scrollOffsetY, userScrolled);
+ DBG_NAV_LOGD("{%d,%d} m_scrollOffset=(%d,%d), sendScrollEvent=%d", dx, dy,
+ m_scrollOffsetX, m_scrollOffsetY, sendScrollEvent);
if (m_scrollOffsetX != dx || m_scrollOffsetY != dy) {
m_scrollOffsetX = dx;
m_scrollOffsetY = dy;
@@ -1166,24 +1153,25 @@ void WebViewCore::setScrollOffset(int moveGeneration, int userScrolled, int dx,
// testing work correctly.
m_mainFrame->view()->platformWidget()->setLocation(m_scrollOffsetX,
m_scrollOffsetY);
- if (userScrolled) {
+ if (sendScrollEvent) {
m_mainFrame->eventHandler()->sendScrollEvent();
- }
- // Update history item to reflect the new scroll position.
- // This also helps save the history information when the browser goes to
- // background, so scroll position will be restored if browser gets
- // killed while in background.
- WebCore::HistoryController* history = m_mainFrame->loader()->history();
- // Because the history item saving could be heavy for large sites and
- // scrolling can generate lots of small scroll offset, the following code
- // reduces the saving frequency.
- static const int MIN_SCROLL_DIFF = 32;
- if (history->currentItem()) {
- WebCore::IntPoint currentPoint = history->currentItem()->scrollPoint();
- if (std::abs(currentPoint.x() - dx) >= MIN_SCROLL_DIFF ||
- std::abs(currentPoint.y() - dy) >= MIN_SCROLL_DIFF) {
- history->saveScrollPositionAndViewStateToItem(history->currentItem());
+ // Only update history position if it's user scrolled.
+ // Update history item to reflect the new scroll position.
+ // This also helps save the history information when the browser goes to
+ // background, so scroll position will be restored if browser gets
+ // killed while in background.
+ WebCore::HistoryController* history = m_mainFrame->loader()->history();
+ // Because the history item saving could be heavy for large sites and
+ // scrolling can generate lots of small scroll offset, the following code
+ // reduces the saving frequency.
+ static const int MIN_SCROLL_DIFF = 32;
+ if (history->currentItem()) {
+ WebCore::IntPoint currentPoint = history->currentItem()->scrollPoint();
+ if (std::abs(currentPoint.x() - dx) >= MIN_SCROLL_DIFF ||
+ std::abs(currentPoint.y() - dy) >= MIN_SCROLL_DIFF) {
+ history->saveScrollPositionAndViewStateToItem(history->currentItem());
+ }
}
}
@@ -1229,6 +1217,12 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
// Don't reflow if the diff is small.
const bool reflow = otw && textWrapWidth &&
((float) abs(otw - textWrapWidth) / textWrapWidth) >= 0.01f;
+
+ // When the screen size change, fixed positioned element should be updated.
+ // This is supposed to be light weighted operation without a full layout.
+ if (osh != screenHeight || osw != screenWidth)
+ m_mainFrame->view()->updatePositionedObjects();
+
if (ow != width || (!ignoreHeight && oh != height) || reflow) {
WebCore::RenderObject *r = m_mainFrame->contentRenderer();
DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r,
@@ -1322,8 +1316,11 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
// If this was in response to touching a textfield and showing the IME,
// the IME may now cover textfield. Bring it back into view.
// If the scale changed, however, this was the result of a zoom.
- if (oldScale == m_scale)
+ if (oldScale == m_scale && osh > screenHeight) {
+ m_onlyScrollIfImeIsShowing = true;
revealSelection();
+ m_onlyScrollIfImeIsShowing = false;
+ }
// update the currently visible screen as perceived by the plugin
sendPluginVisibleScreen();
}
@@ -2084,18 +2081,18 @@ String WebViewCore::modifySelection(const int direction, const int axis)
if (selection->rangeCount() > 1)
selection->removeAllRanges();
switch (axis) {
- case AXIS_CHARACTER:
- case AXIS_WORD:
- case AXIS_SENTENCE:
- return modifySelectionTextNavigationAxis(selection, direction, axis);
- case AXIS_HEADING:
- case AXIS_SIBLING:
- case AXIS_PARENT_FIRST_CHILD:
- case AXIS_DOCUMENT:
- return modifySelectionDomNavigationAxis(selection, direction, axis);
- default:
- LOGE("Invalid navigation axis: %d", axis);
- return String();
+ case AXIS_CHARACTER:
+ case AXIS_WORD:
+ case AXIS_SENTENCE:
+ return modifySelectionTextNavigationAxis(selection, direction, axis);
+ case AXIS_HEADING:
+ case AXIS_SIBLING:
+ case AXIS_PARENT_FIRST_CHILD:
+ case AXIS_DOCUMENT:
+ return modifySelectionDomNavigationAxis(selection, direction, axis);
+ default:
+ LOGE("Invalid navigation axis: %d", axis);
+ return String();
}
}
@@ -2123,10 +2120,10 @@ void WebViewCore::scrollNodeIntoView(Frame* frame, Node* node)
String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, int direction, int axis)
{
- // TODO: Add support of IFrames.
- HTMLElement* body = m_mainFrame->document()->body();
+ Node* body = m_mainFrame->document()->body();
ExceptionCode ec = 0;
+ String markup;
// initialize the selection if necessary
if (selection->rangeCount() == 0) {
@@ -2151,14 +2148,13 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
if (ec)
return String();
selection->addRange(rangeRef.get());
- } else if (direction == DIRECTION_FORWARD) {
- selection->setPosition(body->firstDescendant(), 0, ec);
} else {
- selection->setPosition(body->lastDescendant(), 0, ec);
+ selection->setPosition(body, 0, ec);
}
if (ec)
return String();
}
+
// collapse the selection
if (direction == DIRECTION_FORWARD)
selection->collapseToEnd(ec);
@@ -2167,126 +2163,52 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
if (ec)
return String();
- Node* oldAnchorNode = selection->anchorNode();
- if (!oldAnchorNode)
- return String();
-
// Make sure the anchor node is a text node since we are generating
// the markup of the selection which includes the anchor, the focus,
// and any crossed nodes. Forcing the condition that the selection
// starts and ends on text nodes guarantees symmetric selection markup.
+ // Also this way the text content, rather its container, is highlighted.
Node* anchorNode = selection->anchorNode();
if (anchorNode->isElementNode()) {
- int anchorOffset = rangeCompliantChildOffset(anchorNode,
- selection->anchorOffset());
- anchorNode = selection->anchorNode()->childNodes()->item(anchorOffset);
- Node* nextAnchorNode = traverseVisibleNonEmptyNonWhitespaceTextNode(
- anchorNode, body, direction);
- if (!nextAnchorNode)
+ // Collapsed selection while moving forward points to the
+ // next unvisited node and while moving backward to the
+ // last visited node.
+ if (direction == DIRECTION_FORWARD)
+ advanceAnchorNode(selection, direction, markup, false, ec);
+ else
+ advanceAnchorNode(selection, direction, markup, true, ec);
+ if (ec)
return String();
- if (direction == DIRECTION_FORWARD) {
- Node* skippedControl = getFirstIntermediaryInputOrButton(anchorNode,
- nextAnchorNode);
- if (skippedControl) {
- IntRect bounds = static_cast<Element*>(
- skippedControl)->boundsInWindowSpace();
- selectAt(bounds.center().x(), bounds.center().y());
- selection->setBaseAndExtent(skippedControl,
- caretMinOffset(skippedControl), skippedControl,
- caretMaxOffset(skippedControl), ec);
- if (ec)
- return String();
- return formatMarkup(selection).stripWhiteSpace();
- } else {
- selection->setPosition(nextAnchorNode, 0, ec);
- if (ec)
- return String();
- }
- } else {
- Node* skippedControl = getFirstIntermediaryInputOrButton(
- nextAnchorNode, anchorNode);
- if (skippedControl) {
- IntRect bounds = static_cast<Element*>(
- skippedControl)->boundsInWindowSpace();
- selectAt(bounds.center().x(), bounds.center().y());
- selection->setBaseAndExtent(skippedControl,
- caretMaxOffset(skippedControl), skippedControl,
- caretMinOffset(skippedControl), ec);
- if (ec)
- return String();
- return formatMarkup(selection).stripWhiteSpace();
- } else {
- selection->setPosition(nextAnchorNode,
- caretMaxOffset(nextAnchorNode), ec);
- if (ec)
- return String();
- }
- }
+ if (!markup.isEmpty())
+ return markup;
}
// If the selection is at the end of a non white space text move
// it to the next visible text node with non white space content.
// This is a workaround for the selection getting stuck.
anchorNode = selection->anchorNode();
- if (!anchorNode)
- return String();
if (anchorNode->isTextNode()) {
if (direction == DIRECTION_FORWARD) {
String suffix = anchorNode->textContent().substring(
- selection->anchorOffset(), caretMaxOffset(anchorNode));
+ selection->anchorOffset(), caretMaxOffset(anchorNode));
+ // If at the end of non white space text we advance the
+ // anchor node to either an input element or non empty text.
if (suffix.stripWhiteSpace().isEmpty()) {
- Node* nextAnchorNode =
- traverseVisibleNonEmptyNonWhitespaceTextNode(anchorNode,
- body, direction);
- if (!nextAnchorNode)
- return String();
- Node* skippedControl = getFirstIntermediaryInputOrButton(
- anchorNode, nextAnchorNode);
- if (skippedControl) {
- IntRect bounds = static_cast<Element*>(
- skippedControl)->boundsInWindowSpace();
- selectAt(bounds.center().x(), bounds.center().y());
- selection->setBaseAndExtent(skippedControl,
- caretMinOffset(skippedControl), skippedControl,
- caretMaxOffset(skippedControl), ec);
- if (ec)
- return String();
- return formatMarkup(selection).stripWhiteSpace();
- } else {
- selection->setPosition(nextAnchorNode, 0, ec);
- if (ec)
- return String();
- }
+ advanceAnchorNode(selection, direction, markup, true, ec);
}
} else {
String prefix = anchorNode->textContent().substring(0,
- selection->anchorOffset());
+ selection->anchorOffset());
+ // If at the end of non white space text we advance the
+ // anchor node to either an input element or non empty text.
if (prefix.stripWhiteSpace().isEmpty()) {
- Node* nextAnchorNode =
- traverseVisibleNonEmptyNonWhitespaceTextNode(anchorNode,
- body, direction);
- if (!nextAnchorNode)
- return String();
- Node* skippedControl = getFirstIntermediaryInputOrButton(
- nextAnchorNode, anchorNode);
- if (skippedControl) {
- IntRect bounds = static_cast<Element*>(
- skippedControl)->boundsInWindowSpace();
- selectAt(bounds.center().x(), bounds.center().y());
- selection->setBaseAndExtent(skippedControl,
- caretMaxOffset(skippedControl), skippedControl,
- caretMinOffset(skippedControl), ec);
- if (ec)
- return String();
- return formatMarkup(selection).stripWhiteSpace();
- } else {
- selection->setPosition(nextAnchorNode,
- caretMaxOffset(nextAnchorNode), ec);
- if (ec)
- return String();
- }
+ advanceAnchorNode(selection, direction, markup, true, ec);
}
}
+ if (ec)
+ return String();
+ if (!markup.isEmpty())
+ return markup;
}
// extend the selection
@@ -2308,176 +2230,111 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
// Make sure the focus node is a text node in order to have the
// selection generate symmetric markup because the latter
- // includes all nodes crossed by the selection.
+ // includes all nodes crossed by the selection. Also this way
+ // the text content, rather its container, is highlighted.
Node* focusNode = selection->focusNode();
if (focusNode->isElementNode()) {
- int focusOffset = rangeCompliantChildOffset(focusNode,
- selection->focusOffset());
+ focusNode = getImplicitAnchorOrFocusNode(selection->focusNode(),
+ selection->focusOffset(), direction);
+ if (!focusNode)
+ return String();
if (direction == DIRECTION_FORWARD) {
- focusNode =
- focusNode->childNodes()->item(focusOffset)->lastDescendant();
- if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
- focusNode = traverseVisibleNonEmptyNonWhitespaceTextNode(
- focusNode, body, DIRECTION_BACKWARD);
- if (!focusNode)
+ focusNode = focusNode->traversePreviousSiblingPostOrder(body);
+ if (focusNode && !isContentTextNode(focusNode)) {
+ Node* textNode = traverseNextContentTextNode(focusNode,
+ anchorNode, DIRECTION_BACKWARD);
+ if (textNode)
+ anchorNode = textNode;
+ }
+ if (focusNode && isContentTextNode(focusNode)) {
+ selection->extend(focusNode, caretMaxOffset(focusNode), ec);
+ if (ec)
return String();
}
- selection->extend(focusNode, caretMaxOffset(focusNode), ec);
- if (ec)
- return String();
} else {
- focusNode =
- focusNode->childNodes()->item(focusOffset)->firstDescendant();
- if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
- focusNode = traverseVisibleNonEmptyNonWhitespaceTextNode(
- focusNode, body, DIRECTION_FORWARD);
- if (!focusNode)
+ focusNode = focusNode->traverseNextSibling();
+ if (focusNode && !isContentTextNode(focusNode)) {
+ Node* textNode = traverseNextContentTextNode(focusNode,
+ anchorNode, DIRECTION_FORWARD);
+ if (textNode)
+ anchorNode = textNode;
+ }
+ if (anchorNode && isContentTextNode(anchorNode)) {
+ selection->extend(focusNode, 0, ec);
+ if (ec)
return String();
}
- selection->extend(focusNode, 0, ec);
- if (ec)
- return String();
}
}
// Enforce that the selection does not cross anchor boundaries. This is
// a workaround for the asymmetric behavior of WebKit while crossing
// anchors.
- // NOTE: The code is asymmetric since the logic is based off the common
- // ancestor in both directions - backward and forward.
- // TODO: Factor out common code repeated below.
- anchorNode = selection->anchorNode();
- focusNode = selection->focusNode();
- if (anchorNode != focusNode
- && anchorNode->isTextNode()
- && focusNode->isTextNode()) {
- Node* commonAncestor = Range::commonAncestorContainer(anchorNode,
- focusNode);
- Node* currentNode = 0;
- bool selectionAdjusted = false;
- if (direction == DIRECTION_FORWARD) {
- // catch if the anchor is in a link but the focus is not
- if (!commonAncestor->hasTagName(WebCore::HTMLNames::aTag)) {
- currentNode = anchorNode;
- while (currentNode != commonAncestor) {
- if (isVisible(currentNode) && isInputControl(currentNode)) {
- focusNode = currentNode->lastDescendant();
- if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
- focusNode =
- traverseVisibleNonEmptyNonWhitespaceTextNode(
- focusNode, commonAncestor,
- DIRECTION_BACKWARD);
- if (!focusNode)
- return String();
- }
- selection->extend(focusNode, caretMaxOffset(focusNode),
- ec);
- if (ec)
- return String();
- selectionAdjusted = true;
- break;
- }
- currentNode = currentNode->parentNode();
+ anchorNode = getImplicitAnchorOrFocusNode(selection->anchorNode(),
+ selection->anchorOffset(), direction);
+ focusNode = getImplicitAnchorOrFocusNode(selection->focusNode(),
+ selection->focusOffset(), direction);
+ if (anchorNode && focusNode && anchorNode != focusNode) {
+ Node* inputControl = getIntermediaryInputElement(anchorNode, focusNode,
+ direction);
+ if (inputControl) {
+ if (direction == DIRECTION_FORWARD) {
+ if (isDescendantOf(inputControl, anchorNode)) {
+ focusNode = inputControl;
+ } else {
+ focusNode = inputControl->traversePreviousSiblingPostOrder(
+ body);
+ if (!focusNode)
+ focusNode = inputControl;
}
- // catch if there is a link between the anchor and focus
- if (!selectionAdjusted) {
- currentNode = anchorNode;
- while (currentNode != focusNode) {
- if (isVisible(currentNode)
- && isInputControl(currentNode)) {
- focusNode = currentNode;
- if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
- focusNode =
- traverseVisibleNonEmptyNonWhitespaceTextNode(
- focusNode, commonAncestor,
- DIRECTION_BACKWARD);
- if (!focusNode)
- return String();
- }
- selection->extend(focusNode,
- caretMaxOffset(focusNode), ec);
- if (ec)
- return String();
- break;
- }
- currentNode = currentNode->traverseNextNode();
- }
+ // We prefer a text node contained in the input element.
+ if (!isContentTextNode(focusNode)) {
+ Node* textNode = traverseNextContentTextNode(focusNode,
+ anchorNode, DIRECTION_BACKWARD);
+ if (textNode)
+ focusNode = textNode;
}
- }
- } else {
- // catch if the anchor is in a link but the focus is not
- // NOTE: There is not such case in forward direction because
- // it is implicitly covered the second case. Also the
- // base position used for computing the the common
- // ancestor which is asymmteric.
- if (!commonAncestor->hasTagName(WebCore::HTMLNames::aTag)) {
- currentNode = anchorNode;
- while (currentNode != commonAncestor) {
- if (isVisible(currentNode) && isInputControl(currentNode)) {
- focusNode = currentNode->firstDescendant();
- if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
- focusNode =
- traverseVisibleNonEmptyNonWhitespaceTextNode(
- focusNode, commonAncestor,
- DIRECTION_FORWARD);
- if (!focusNode)
- return String();
- }
- selection->extend(focusNode, 0, ec);
- if (ec)
- return String();
- selectionAdjusted = true;
- break;
- }
- currentNode = currentNode->parentNode();
+ // If we found text in the input select it.
+ // Otherwise, select the input element itself.
+ if (isContentTextNode(focusNode)) {
+ selection->extend(focusNode, caretMaxOffset(focusNode), ec);
+ } else if (anchorNode != focusNode) {
+ // Note that the focusNode always has parent and that
+ // the offset can be one more that the index of the last
+ // element - this is how WebKit selects such elements.
+ selection->extend(focusNode->parentNode(),
+ focusNode->nodeIndex() + 1, ec);
}
- // catch if there is a link between the anchor and focus
- if (!selectionAdjusted) {
- currentNode = anchorNode;
- while (currentNode != focusNode) {
- if (isVisible(currentNode)
- && isInputControl(currentNode)) {
- focusNode = currentNode->traverseNextSibling();
- if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
- focusNode =
- traverseVisibleNonEmptyNonWhitespaceTextNode(
- focusNode, commonAncestor,
- DIRECTION_FORWARD);
- if (!focusNode)
- return String();
- }
- selection->extend(focusNode, 0, ec);
- if (ec)
- return String();
- selectionAdjusted = true;
- break;
- }
- currentNode = currentNode->traversePreviousNode();
- }
+ if (ec)
+ return String();
+ } else {
+ if (isDescendantOf(inputControl, anchorNode)) {
+ focusNode = inputControl;
+ } else {
+ focusNode = inputControl->traverseNextSibling();
+ if (!focusNode)
+ focusNode = inputControl;
}
- // catch if the focus is in a link but the anchor is not
- if (!selectionAdjusted) {
- currentNode = focusNode;
- while (currentNode != commonAncestor) {
- if (isVisible(currentNode)
- && isInputControl(currentNode)) {
- focusNode = currentNode->traverseNextSibling();
- if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
- focusNode =
- traverseVisibleNonEmptyNonWhitespaceTextNode(
- focusNode, commonAncestor,
- DIRECTION_FORWARD);
- if (!focusNode)
- return String();
- }
- selection->extend(focusNode, 0, ec);
- if (ec)
- return String();
- break;
- }
- currentNode = currentNode->parentNode();
- }
+ // We prefer a text node contained in the input element.
+ if (!isContentTextNode(focusNode)) {
+ Node* textNode = traverseNextContentTextNode(focusNode,
+ anchorNode, DIRECTION_FORWARD);
+ if (textNode)
+ focusNode = textNode;
+ }
+ // If we found text in the input select it.
+ // Otherwise, select the input element itself.
+ if (isContentTextNode(focusNode)) {
+ selection->extend(focusNode, caretMinOffset(focusNode), ec);
+ } else if (anchorNode != focusNode) {
+ // Note that the focusNode always has parent and that
+ // the offset can be one more that the index of the last
+ // element - this is how WebKit selects such elements.
+ selection->extend(focusNode->parentNode(),
+ focusNode->nodeIndex() + 1, ec);
}
+ if (ec)
+ return String();
}
}
}
@@ -2494,30 +2351,136 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
return String();
IntRect bounds = range->boundingBox();
selectAt(bounds.center().x(), bounds.center().y());
- String markup = formatMarkup(selection).stripWhiteSpace();
+ markup = formatMarkup(selection);
LOGV("Selection markup: %s", markup.utf8().data());
return markup;
}
-bool WebViewCore::isInputControl(Node* node)
+Node* WebViewCore::getImplicitAnchorOrFocusNode(Node* node, unsigned offset, int direction)
{
- return (node->hasTagName(WebCore::HTMLNames::aTag)
- || node->hasTagName(WebCore::HTMLNames::inputTag)
- || node->hasTagName(WebCore::HTMLNames::buttonTag));
+ if (node->offsetInCharacters())
+ return node;
+ if (!node->hasChildNodes())
+ return node;
+ if (offset < node->childNodeCount())
+ return node->childNode(offset);
+ else
+ if (direction == DIRECTION_FORWARD)
+ return node->traverseNextSibling();
+ else
+ return node->traversePreviousNodePostOrder(
+ node->document()->body());
}
-int WebViewCore::rangeCompliantChildOffset(Node* parent, int offset)
+Node* WebViewCore::getNextAnchorNode(Node* anchorNode, bool ignoreFirstNode, int direction)
{
- if (offset < 0)
- return 0;
- int lastChildIndex = parent->childNodes()->length() - 1;
- if (offset > lastChildIndex)
- return lastChildIndex;
- return offset;
+ Node* body = 0;
+ Node* currentNode = 0;
+ if (direction == DIRECTION_FORWARD) {
+ if (ignoreFirstNode)
+ currentNode = anchorNode->traverseNextNode(body);
+ else
+ currentNode = anchorNode;
+ } else {
+ body = anchorNode->document()->body();
+ if (ignoreFirstNode)
+ currentNode = anchorNode->traversePreviousSiblingPostOrder(body);
+ else
+ currentNode = anchorNode;
+ }
+ while (currentNode) {
+ if (isContentTextNode(currentNode)
+ || isContentInputElement(currentNode))
+ return currentNode;
+ if (direction == DIRECTION_FORWARD)
+ currentNode = currentNode->traverseNextNode();
+ else
+ currentNode = currentNode->traversePreviousNodePostOrder(body);
+ }
+ return 0;
+}
+
+void WebViewCore::advanceAnchorNode(DOMSelection* selection, int direction,
+ String& markup, bool ignoreFirstNode, ExceptionCode& ec)
+{
+ Node* anchorNode = getImplicitAnchorOrFocusNode(selection->anchorNode(),
+ selection->anchorOffset(), direction);
+ if (!anchorNode) {
+ ec = NOT_FOUND_ERR;
+ return;
+ }
+ // If the anchor offset is invalid i.e. the anchor node has no
+ // child with that index getImplicitAnchorNode returns the next
+ // logical node in the current direction. In such a case our
+ // position in the DOM tree was has already been advanced,
+ // therefore we there is no need to do that again.
+ if (selection->anchorNode()->isElementNode()) {
+ unsigned anchorOffset = selection->anchorOffset();
+ unsigned childNodeCount = selection->anchorNode()->childNodeCount();
+ if (anchorOffset >= childNodeCount)
+ ignoreFirstNode = false;
+ }
+ // Find the next anchor node given our position in the DOM and
+ // whether we want the current node to be considered as well.
+ Node* nextAnchorNode = getNextAnchorNode(anchorNode, ignoreFirstNode,
+ direction);
+ if (!nextAnchorNode) {
+ ec = NOT_FOUND_ERR;
+ return;
+ }
+ if (nextAnchorNode->isElementNode()) {
+ // If this is an input element tell the WebView thread
+ // to set the cursor to that control.
+ if (isContentInputElement(nextAnchorNode)) {
+ IntRect bounds = nextAnchorNode->getRect();
+ selectAt(bounds.center().x(), bounds.center().y());
+ }
+ Node* textNode = 0;
+ // Treat the text content of links as any other text but
+ // for the rest input elements select the control itself.
+ if (nextAnchorNode->hasTagName(WebCore::HTMLNames::aTag))
+ textNode = traverseNextContentTextNode(nextAnchorNode,
+ nextAnchorNode, direction);
+ // We prefer to select the text content of the link if such,
+ // otherwise just select the element itself.
+ if (textNode) {
+ nextAnchorNode = textNode;
+ } else {
+ if (direction == DIRECTION_FORWARD) {
+ selection->setBaseAndExtent(nextAnchorNode,
+ caretMinOffset(nextAnchorNode), nextAnchorNode,
+ caretMaxOffset(nextAnchorNode), ec);
+ } else {
+ selection->setBaseAndExtent(nextAnchorNode,
+ caretMaxOffset(nextAnchorNode), nextAnchorNode,
+ caretMinOffset(nextAnchorNode), ec);
+ }
+ if (!ec)
+ markup = formatMarkup(selection);
+ // make sure the selection is visible
+ scrollNodeIntoView(selection->frame(), nextAnchorNode);
+ return;
+ }
+ }
+ if (direction == DIRECTION_FORWARD)
+ selection->setPosition(nextAnchorNode,
+ caretMinOffset(nextAnchorNode), ec);
+ else
+ selection->setPosition(nextAnchorNode,
+ caretMaxOffset(nextAnchorNode), ec);
+}
+
+bool WebViewCore::isContentInputElement(Node* node)
+{
+ return (isVisible(node)
+ && (node->hasTagName(WebCore::HTMLNames::selectTag)
+ || node->hasTagName(WebCore::HTMLNames::aTag)
+ || node->hasTagName(WebCore::HTMLNames::inputTag)
+ || node->hasTagName(WebCore::HTMLNames::buttonTag)));
}
-bool WebViewCore::isVisibleNonEmptyNonWhitespaceTextNode(Node* node)
+bool WebViewCore::isContentTextNode(Node* node)
{
if (!node || !node->isTextNode())
return false;
@@ -2526,21 +2489,66 @@ bool WebViewCore::isVisibleNonEmptyNonWhitespaceTextNode(Node* node)
&& !textNode->containsOnlyWhitespace());
}
-Text* WebViewCore::traverseVisibleNonEmptyNonWhitespaceTextNode(Node* fromNode, Node* toNode, int direction)
+Text* WebViewCore::traverseNextContentTextNode(Node* fromNode, Node* toNode, int direction)
{
Node* currentNode = fromNode;
do {
if (direction == DIRECTION_FORWARD)
currentNode = currentNode->traverseNextNode(toNode);
else
- currentNode = currentNode->traversePreviousNode(toNode);
- } while (currentNode && !isVisibleNonEmptyNonWhitespaceTextNode(currentNode));
+ currentNode = currentNode->traversePreviousNodePostOrder(toNode);
+ } while (currentNode && !isContentTextNode(currentNode));
return static_cast<Text*>(currentNode);
}
+Node* WebViewCore::getIntermediaryInputElement(Node* fromNode, Node* toNode, int direction)
+{
+ if (fromNode == toNode)
+ return 0;
+ if (direction == DIRECTION_FORWARD) {
+ Node* currentNode = fromNode;
+ while (currentNode && currentNode != toNode) {
+ if (isContentInputElement(currentNode))
+ return currentNode;
+ currentNode = currentNode->traverseNextNodePostOrder();
+ }
+ currentNode = fromNode;
+ while (currentNode && currentNode != toNode) {
+ if (isContentInputElement(currentNode))
+ return currentNode;
+ currentNode = currentNode->traverseNextNode();
+ }
+ } else {
+ Node* currentNode = fromNode->traversePreviousNode();
+ while (currentNode && currentNode != toNode) {
+ if (isContentInputElement(currentNode))
+ return currentNode;
+ currentNode = currentNode->traversePreviousNode();
+ }
+ currentNode = fromNode->traversePreviousNodePostOrder();
+ while (currentNode && currentNode != toNode) {
+ if (isContentInputElement(currentNode))
+ return currentNode;
+ currentNode = currentNode->traversePreviousNodePostOrder();
+ }
+ }
+ return 0;
+}
+
+bool WebViewCore::isDescendantOf(Node* parent, Node* node)
+{
+ Node* currentNode = node;
+ while (currentNode) {
+ if (currentNode == parent) {
+ return true;
+ }
+ currentNode = currentNode->parentNode();
+ }
+ return false;
+}
+
String WebViewCore::modifySelectionDomNavigationAxis(DOMSelection* selection, int direction, int axis)
{
- // TODO: Add support of IFrames.
HTMLElement* body = m_mainFrame->document()->body();
if (!m_currentNodeDomNavigationAxis && selection->focusNode()) {
m_currentNodeDomNavigationAxis = selection->focusNode();
@@ -2633,12 +2641,27 @@ bool WebViewCore::isHeading(Node* node)
bool WebViewCore::isVisible(Node* node)
{
- // TODO: Use DOMWindow#getComputedStyle instead.
+ // start off an element
+ Element* element = 0;
+ if (node->isElementNode())
+ element = static_cast<Element*>(node);
+ else
+ element = node->parentElement();
+ // check renderer
+ if (!element->renderer()) {
+ return false;
+ }
+ // check size
+ if (element->offsetHeight() == 0 || element->offsetWidth() == 0) {
+ return false;
+ }
+ // check style
Node* body = m_mainFrame->document()->body();
- Node* currentNode = node;
+ Node* currentNode = element;
while (currentNode && currentNode != body) {
RenderStyle* style = currentNode->computedStyle();
- if (style->display() == NONE || style->visibility() == HIDDEN) {
+ if (style &&
+ (style->display() == NONE || style->visibility() == HIDDEN)) {
return false;
}
currentNode = currentNode->parentNode();
@@ -2650,20 +2673,18 @@ String WebViewCore::formatMarkup(DOMSelection* selection)
{
ExceptionCode ec = 0;
String markup = String();
-
PassRefPtr<Range> wholeRange = selection->getRangeAt(0, ec);
if (ec)
- return markup;
-
+ return String();
if (!wholeRange->startContainer() || !wholeRange->startContainer())
- return markup;
-
+ return String();
// Since formatted markup contains invisible nodes it
// is created from the concatenation of the visible fragments.
Node* firstNode = wholeRange->firstNode();
Node* pastLastNode = wholeRange->pastLastNode();
Node* currentNode = firstNode;
PassRefPtr<Range> currentRange;
+
while (currentNode != pastLastNode) {
Node* nextNode = currentNode->traverseNextNode();
if (!isVisible(currentNode)) {
@@ -2676,24 +2697,24 @@ String WebViewCore::formatMarkup(DOMSelection* selection)
if (!currentRange) {
currentRange = selection->frame()->document()->createRange();
if (ec)
- return markup;
+ break;
if (currentNode == firstNode) {
currentRange->setStart(wholeRange->startContainer(),
wholeRange->startOffset(), ec);
if (ec)
- return markup;
+ break;
} else {
currentRange->setStart(currentNode->parentNode(),
currentNode->nodeIndex(), ec);
if (ec)
- return markup;
+ break;
}
}
if (nextNode == pastLastNode) {
currentRange->setEnd(wholeRange->endContainer(),
wholeRange->endOffset(), ec);
if (ec)
- return markup;
+ break;
markup = markup + stripAppleSpanFromMarkup(
currentRange->toHTML()).utf8().data();
} else {
@@ -2704,12 +2725,12 @@ String WebViewCore::formatMarkup(DOMSelection* selection)
currentRange->setEnd(currentNode->parentNode(),
currentNode->nodeIndex() + 1, ec);
if (ec)
- return markup;
+ break;
}
}
currentNode = nextNode;
}
- return markup;
+ return markup.stripWhiteSpace();
}
String WebViewCore::stripAppleSpanFromMarkup(String markup)
@@ -2732,32 +2753,6 @@ void WebViewCore::selectAt(int x, int y)
checkException(env);
}
-Node* WebViewCore::getFirstIntermediaryInputOrButton(Node* fromNode, Node* toNode)
-{
- // do bidirectional traversal to catch the case in which
- // the toNode is a descendant of a control but the fromNode
- // is not and the other way around
- Node* currentNode = fromNode->traverseNextNode();
- while (currentNode && currentNode != toNode) {
- if (isVisible(currentNode)
- && (currentNode->hasTagName(WebCore::HTMLNames::inputTag)
- || currentNode->hasTagName(WebCore::HTMLNames::buttonTag))) {
- return currentNode;
- }
- currentNode = currentNode->traverseNextNode();
- }
- currentNode = fromNode->traverseNextNodePostOrder();
- while (currentNode && currentNode != toNode) {
- if (isVisible(currentNode)
- && (currentNode->hasTagName(WebCore::HTMLNames::inputTag)
- || currentNode->hasTagName(WebCore::HTMLNames::buttonTag))) {
- return currentNode;
- }
- currentNode = currentNode->traverseNextNodePostOrder();
- }
- return 0;
-}
-
void WebViewCore::deleteSelection(int start, int end, int textGeneration)
{
setSelection(start, end);
@@ -2882,94 +2877,6 @@ void WebViewCore::saveDocumentState(WebCore::Frame* frame)
}
}
-// Convert a WTF::String into an array of characters where the first
-// character represents the length, for easy conversion to java.
-static uint16_t* stringConverter(const WTF::String& text)
-{
- size_t length = text.length();
- uint16_t* itemName = new uint16_t[length+1];
- itemName[0] = (uint16_t)length;
- uint16_t* firstChar = &(itemName[1]);
- memcpy((void*)firstChar, text.characters(), sizeof(UChar)*length);
- return itemName;
-}
-
-// Response to dropdown created for a listbox.
-class ListBoxReply : public WebCoreReply {
-public:
- ListBoxReply(WebCore::HTMLSelectElement* select, WebCore::Frame* frame, WebViewCore* view)
- : m_select(select)
- , m_frame(frame)
- , m_viewImpl(view)
- {}
-
- // Response used for a multiple selection listbox if the user did not change
- // anything, in which case -2 is used.
- // Also used by a listbox which has single selection but a size is set.
- virtual void replyInt(int index)
- {
- if (-2 == index) {
- // Special value for cancel. Do nothing.
- return;
- }
- // If the select element no longer exists, due to a page change, etc,
- // silently return.
- if (!m_select || !CacheBuilder::validNode(m_viewImpl->m_mainFrame,
- m_frame, m_select))
- return;
- // Use a pointer to HTMLSelectElement's superclass, where
- // listToOptionIndex is public
- SelectElement* selectElement = m_select;
- int optionIndex = selectElement->listToOptionIndex(index);
- m_select->setSelectedIndex(optionIndex, true);
- m_select->dispatchFormControlChangeEvent();
- m_viewImpl->contentInvalidate(m_select->getRect());
- }
-
- // Response if the listbox allows multiple selection. array stores the listIndices
- // of selected positions.
- virtual void replyIntArray(const int* array, int count)
- {
- // If the select element no longer exists, due to a page change, etc,
- // silently return.
- if (!m_select || !CacheBuilder::validNode(m_viewImpl->m_mainFrame,
- m_frame, m_select))
- return;
-
- const WTF::Vector<Element*>& items = m_select->listItems();
- int totalItems = static_cast<int>(items.size());
- // Keep track of the position of the value we are comparing against.
- int arrayIndex = 0;
- // The value we are comparing against.
- int selection = array[arrayIndex];
- WebCore::HTMLOptionElement* option;
- for (int listIndex = 0; listIndex < totalItems; listIndex++) {
- if (items[listIndex]->hasLocalName(WebCore::HTMLNames::optionTag)) {
- option = static_cast<WebCore::HTMLOptionElement*>(
- items[listIndex]);
- if (listIndex == selection) {
- option->setSelectedState(true);
- arrayIndex++;
- if (arrayIndex == count)
- selection = -1;
- else
- selection = array[arrayIndex];
- } else
- option->setSelectedState(false);
- }
- }
- m_select->dispatchFormControlChangeEvent();
- m_viewImpl->contentInvalidate(m_select->getRect());
- }
-private:
- // The select element associated with this listbox.
- WebCore::HTMLSelectElement* m_select;
- // The frame of this select element, to verify that it is valid.
- WebCore::Frame* m_frame;
- // For calling invalidate and checking the select element's validity
- WebViewCore* m_viewImpl;
-};
-
// Create an array of java Strings.
static jobjectArray makeLabelArray(JNIEnv* env, const uint16_t** labels, size_t count)
{
@@ -3284,46 +3191,7 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node
return true;
}
- WebCore::RenderObject* renderer = nodePtr->renderer();
- if (renderer && renderer->isListBox()) {
- WebCore::HTMLSelectElement* select = static_cast<WebCore::HTMLSelectElement*>(nodePtr);
- const WTF::Vector<WebCore::Element*>& listItems = select->listItems();
- SkTDArray<const uint16_t*> names;
- // Possible values for enabledArray. Keep in Sync with values in
- // InvokeListBox.Container in WebView.java
- enum OptionStatus {
- OPTGROUP = -1,
- OPTION_DISABLED = 0,
- OPTION_ENABLED = 1,
- };
- SkTDArray<int> enabledArray;
- SkTDArray<int> selectedArray;
- int size = listItems.size();
- bool multiple = select->multiple();
- for (int i = 0; i < size; i++) {
- if (listItems[i]->hasTagName(WebCore::HTMLNames::optionTag)) {
- WebCore::HTMLOptionElement* option = static_cast<WebCore::HTMLOptionElement*>(listItems[i]);
- *names.append() = stringConverter(option->textIndentedToRespectGroupLabel());
- *enabledArray.append() = option->disabled() ? OPTION_DISABLED : OPTION_ENABLED;
- if (multiple && option->selected())
- *selectedArray.append() = i;
- } else if (listItems[i]->hasTagName(WebCore::HTMLNames::optgroupTag)) {
- WebCore::HTMLOptGroupElement* optGroup = static_cast<WebCore::HTMLOptGroupElement*>(listItems[i]);
- *names.append() = stringConverter(optGroup->groupLabelText());
- *enabledArray.append() = OPTGROUP;
- }
- }
- WebCoreReply* reply = new ListBoxReply(select, select->document()->frame(), this);
- // Use a pointer to HTMLSelectElement's superclass, where
- // optionToListIndex is public.
- SelectElement* selectElement = select;
- listBoxRequest(reply, names.begin(), size, enabledArray.begin(), enabledArray.count(),
- multiple, selectedArray.begin(), multiple ? selectedArray.count() :
- selectElement->optionToListIndex(select->selectedIndex()));
- DBG_NAV_LOG("list box");
- return true;
- }
- scrollLayer(renderer, &m_mousePos);
+ scrollLayer(nodePtr->renderer(), &m_mousePos);
}
if (!valid || !framePtr)
framePtr = m_mainFrame;
@@ -3789,10 +3657,12 @@ void WebViewCore::notifyWebAppCanBeInstalled()
void WebViewCore::setWebTextViewAutoFillable(int queryId, const string16& previewSummary)
{
+#if ENABLE(WEB_AUTOFILL)
JNIEnv* env = JSC::Bindings::getJNIEnv();
jstring preview = env->NewString(previewSummary.data(), previewSummary.length());
env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_setWebTextViewAutoFillable, queryId, preview);
env->DeleteLocalRef(preview);
+#endif
}
bool WebViewCore::drawIsPaused() const
@@ -3875,7 +3745,7 @@ static void SetSize(JNIEnv *env, jobject obj, jint width, jint height,
screenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
}
-static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint userScrolled, jint x, jint y)
+static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jboolean sendScrollEvent, jint x, jint y)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
@@ -3883,7 +3753,7 @@ static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint userScrolle
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
LOG_ASSERT(viewImpl, "need viewImpl");
- viewImpl->setScrollOffset(gen, userScrolled, x, y);
+ viewImpl->setScrollOffset(gen, sendScrollEvent, x, y);
}
static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h,
@@ -4535,7 +4405,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) SendListBoxChoice },
{ "nativeSetSize", "(IIIFIIIIZ)V",
(void*) SetSize },
- { "nativeSetScrollOffset", "(IIII)V",
+ { "nativeSetScrollOffset", "(IZII)V",
(void*) SetScrollOffset },
{ "nativeSetGlobalBounds", "(IIII)V",
(void*) SetGlobalBounds },
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index 1457089..d38be79 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -149,14 +149,6 @@ namespace android {
void scrollTo(int x, int y, bool animate = false);
/**
- * Scroll to the point x,y relative to the current position.
- * @param x The relative x position.
- * @param y The relative y position.
- * @param animate If it is true, animate to the new scroll position
- */
- void scrollBy(int x, int y, bool animate);
-
- /**
* Record the invalid rectangle
*/
void contentInvalidate(const WebCore::IntRect &rect);
@@ -311,7 +303,7 @@ namespace android {
WebCore::Frame* frame, int x, int y);
// set the scroll amount that webview.java is currently showing
- void setScrollOffset(int moveGeneration, int userScrolled, int dx, int dy);
+ void setScrollOffset(int moveGeneration, bool sendScrollEvent, int dx, int dy);
void setGlobalBounds(int x, int y, int h, int v);
@@ -579,10 +571,9 @@ namespace android {
bool isPaused() const { return m_isPaused; }
void setIsPaused(bool isPaused) { m_isPaused = isPaused; }
bool drawIsPaused() const;
- int visibleScreenWidth() const { return m_visibleScreenWidth; }
- int visibleScreenHeight() const { return m_visibleScreenHeight; }
- void setVisibleScreenWidth(int w) { m_visibleScreenWidth = w; }
- void setVisibleScreenHeight(int h) { m_visibleScreenHeight = h; }
+ // The actual content (without title bar) size in doc coordinate
+ int screenWidth() const { return m_screenWidth; }
+ int screenHeight() const { return m_screenHeight; }
#if USE(CHROME_NETWORK_STACK)
void setWebRequestContextUserAgent();
void setWebRequestContextCacheMode(int mode);
@@ -610,6 +601,9 @@ namespace android {
int m_blurringNodePointer;
int m_lastFocusedSelStart;
int m_lastFocusedSelEnd;
+ // Pass along with a scroll message to tell the UI thread to only
+ // scroll the page if the IME is showing.
+ bool m_onlyScrollIfImeIsShowing;
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
@@ -635,11 +629,6 @@ 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
- // The m_screenHeight is not equal to the visibleRect from WebView,
- // using m_visibleScreenHeight to store that info.
- // After we can fix the m_screenHeight in java side, we can merge them.
- int m_visibleScreenWidth;
- int m_visibleScreenHeight;
int m_textWrapWidth;
float m_scale;
unsigned m_domtree_version;
@@ -674,18 +663,21 @@ namespace android {
// below are members responsible for accessibility support
String modifySelectionTextNavigationAxis(DOMSelection* selection, int direction, int granularity);
String modifySelectionDomNavigationAxis(DOMSelection* selection, int direction, int granularity);
- Text* traverseVisibleNonEmptyNonWhitespaceTextNode(Node* fromNode, Node* toNode ,int direction);
+ Text* traverseNextContentTextNode(Node* fromNode, Node* toNode ,int direction);
bool isVisible(Node* node);
bool isHeading(Node* node);
String formatMarkup(DOMSelection* selection);
void selectAt(int x, int y);
Node* m_currentNodeDomNavigationAxis;
void scrollNodeIntoView(Frame* frame, Node* node);
- bool isVisibleNonEmptyNonWhitespaceTextNode(Node* node);
+ bool isContentTextNode(Node* node);
String stripAppleSpanFromMarkup(String markup);
- int rangeCompliantChildOffset(Node* parent, int offset);
- Node* getFirstIntermediaryInputOrButton(Node* fromNode, Node* toNode);
- bool isInputControl(Node* node);
+ Node* getIntermediaryInputElement(Node* fromNode, Node* toNode, int direction);
+ bool isContentInputElement(Node* node);
+ bool isDescendantOf(Node* parent, Node* node);
+ void advanceAnchorNode(DOMSelection* selection, int direction, String& markup, bool ignoreFirstNode, ExceptionCode& ec);
+ Node* getNextAnchorNode(Node* anchorNode, bool skipFirstHack, int direction);
+ Node* getImplicitAnchorOrFocusNode(Node* node, unsigned offset, int direction);
#if ENABLE(TOUCH_EVENTS)
bool m_forwardingTouchEvents;
diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp
index 27eebd3..b25ad7d 100644
--- a/WebKit/android/nav/CachedFrame.cpp
+++ b/WebKit/android/nav/CachedFrame.cpp
@@ -50,13 +50,17 @@ WebCore::IntRect CachedFrame::adjustBounds(const CachedNode* node,
mRoot->mViewBounds.x(), mRoot->mViewBounds.y(),
mRoot->mViewBounds.width(), mRoot->mViewBounds.height());
#if USE(ACCELERATED_COMPOSITING)
- if (mRoot) {
- const CachedLayer* cachedLayer = layer(node);
- const WebCore::LayerAndroid* rootLayer = mRoot->rootLayer();
- const LayerAndroid* aLayer = cachedLayer->layer(rootLayer);
- if (aLayer)
- return cachedLayer->adjustBounds(rootLayer, rect);
- }
+ if (!mRoot)
+ return rect;
+
+ const CachedLayer* cachedLayer = layer(node);
+ if (!cachedLayer)
+ return rect;
+
+ const WebCore::LayerAndroid* rootLayer = mRoot->rootLayer();
+ const LayerAndroid* aLayer = cachedLayer->layer(rootLayer);
+ if (aLayer)
+ return cachedLayer->adjustBounds(rootLayer, rect);
#endif
return rect;
}
diff --git a/WebKit/android/nav/CachedLayer.cpp b/WebKit/android/nav/CachedLayer.cpp
index c8220b3..d5385bd 100644
--- a/WebKit/android/nav/CachedLayer.cpp
+++ b/WebKit/android/nav/CachedLayer.cpp
@@ -177,7 +177,6 @@ void CachedLayer::Debug::print() const
{
CachedLayer* b = base();
DUMP_NAV_LOGD(" // int mCachedNodeIndex=%d;\n", b->mCachedNodeIndex);
- DUMP_NAV_LOGD(" // LayerAndroid* mLayer=%p;\n", b->mLayer);
DUMP_NAV_LOGD(" // int mOffset=(%d, %d);\n",
b->mOffset.x(), b->mOffset.y());
DUMP_NAV_LOGD(" // int mUniqueId=%p;\n", b->mUniqueId);
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
index f84f8b0..948ea6b 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -206,7 +206,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) :
// We must remove the m_glWebViewState prior to deleting m_baseLayer. If we
// do not remove it here, we risk having BaseTiles trying to paint using a
// deallocated base layer.
- delete m_glWebViewState;
+ stopGL();
#endif
delete m_frameCacheUI;
delete m_navPictureUI;
@@ -214,6 +214,14 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) :
delete m_glDrawFunctor;
}
+void stopGL()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ delete m_glWebViewState;
+ m_glWebViewState = 0;
+#endif
+}
+
WebViewCore* getWebViewCore() const {
return m_viewImpl;
}
@@ -481,9 +489,7 @@ bool drawGL(WebCore::IntRect& viewRect, float scale, int extras)
SkRect visibleRect;
calcOurContentVisibleRect(&visibleRect);
- m_viewImpl->setVisibleScreenWidth(visibleRect.width());
- m_viewImpl->setVisibleScreenHeight(visibleRect.height());
- bool ret = m_baseLayer->drawGL(viewRect, visibleRect, scale);
+ bool ret = m_glWebViewState->drawGL(viewRect, visibleRect, scale);
if (ret || m_glWebViewState->currentPictureCounter() != pic)
return true;
#endif
@@ -545,8 +551,6 @@ PictureSet* draw(SkCanvas* canvas, SkColor bgColor, int extras, bool split)
compositeLayer->setExtra(extra);
SkRect visible;
calcOurContentVisibleRect(&visible);
- m_viewImpl->setVisibleScreenWidth(visible.width());
- m_viewImpl->setVisibleScreenHeight(visible.height());
// call this to be sure we've adjusted for any scrolling or animations
// before we actually draw
compositeLayer->updateFixedLayersPositions(visible);
@@ -2207,6 +2211,11 @@ static void nativeDestroy(JNIEnv *env, jobject obj)
delete view;
}
+static void nativeStopGL(JNIEnv *env, jobject obj)
+{
+ GET_NATIVE_VIEW(env, obj)->stopGL();
+}
+
static bool nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj)
{
WebView* view = GET_NATIVE_VIEW(env, obj);
@@ -2395,6 +2404,11 @@ static bool nativeScrollLayer(JNIEnv* env, jobject obj, jint layerId, jint x,
return false;
}
+static void nativeSetExpandedTileBounds(JNIEnv*, jobject, jboolean enabled)
+{
+ TilesManager::instance()->setExpandedTileBounds(enabled);
+}
+
/*
* JNI registration
*/
@@ -2559,6 +2573,8 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeShowCursorTimed },
{ "nativeStartSelection", "(II)Z",
(void*) nativeStartSelection },
+ { "nativeStopGL", "()V",
+ (void*) nativeStopGL },
{ "nativeSubtractLayers", "(Landroid/graphics/Rect;)Landroid/graphics/Rect;",
(void*) nativeSubtractLayers },
{ "nativeTextGeneration", "()I",
@@ -2573,6 +2589,8 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeScrollableLayer },
{ "nativeScrollLayer", "(III)Z",
(void*) nativeScrollLayer },
+ { "nativeSetExpandedTileBounds", "(Z)V",
+ (void*) nativeSetExpandedTileBounds },
};
int registerWebView(JNIEnv* env)
diff --git a/WebKit/android/plugins/ANPOpenGLInterface.cpp b/WebKit/android/plugins/ANPOpenGLInterface.cpp
index 8f5f9b4..015a04c 100644
--- a/WebKit/android/plugins/ANPOpenGLInterface.cpp
+++ b/WebKit/android/plugins/ANPOpenGLInterface.cpp
@@ -87,6 +87,9 @@ static void anp_releaseTexture(NPP instance, const ANPTextureInfo* textureInfo)
info->m_internalFormat = textureInfo->internalFormat;
texture->producerReleaseAndSwap();
+
+ // invalidate the java view so that this content is drawn
+ pluginWidget->viewInvalidate();
}
static void anp_invertPluginContent(NPP instance, bool isContentInverted) {
diff --git a/WebKit/android/plugins/PluginWidgetAndroid.cpp b/WebKit/android/plugins/PluginWidgetAndroid.cpp
index 4dc12a3..06506ba 100644
--- a/WebKit/android/plugins/PluginWidgetAndroid.cpp
+++ b/WebKit/android/plugins/PluginWidgetAndroid.cpp
@@ -132,7 +132,19 @@ void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) {
m_pluginBounds.fRight, m_pluginBounds.fBottom);
const bool boundsChanged = m_pluginBounds != oldPluginBounds;
- sendSizeAndVisibilityEvents(boundsChanged);
+
+ //TODO hack to ensure that we grab the most recent screen dimensions and scale
+ ANPRectI screenCoords;
+ m_core->getVisibleScreen(screenCoords);
+ float scale = m_core->scale();
+ bool scaleChanged = m_cachedZoomLevel != scale;
+ setVisibleScreen(screenCoords, scale);
+
+ // if the scale changed then setVisibleScreen will call this function and
+ // this call will potentially fire a duplicate draw event
+ if (!scaleChanged) {
+ sendSizeAndVisibilityEvents(boundsChanged);
+ }
layoutSurface(boundsChanged);
if (m_drawingModel != kSurface_ANPDrawingModel) {
@@ -144,8 +156,14 @@ void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) {
bool PluginWidgetAndroid::setDrawingModel(ANPDrawingModel model) {
- if (model == kOpenGL_ANPDrawingModel && m_layer == 0)
- m_layer = new WebCore::MediaLayer();
+ if (model == kOpenGL_ANPDrawingModel && m_layer == 0) {
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ jobject webview = m_core->getWebViewJavaObject();
+ jobject weakWebViewRef = 0;
+ if (webview)
+ weakWebViewRef = env->NewWeakGlobalRef(webview);
+ m_layer = new WebCore::MediaLayer(weakWebViewRef);
+ }
else if (model != kOpenGL_ANPDrawingModel && m_layer != 0)
m_layer->unref();
@@ -192,6 +210,12 @@ void PluginWidgetAndroid::inval(const WebCore::IntRect& rect,
}
}
+void PluginWidgetAndroid::viewInvalidate() {
+ WebCore::IntRect rect(m_pluginBounds.fLeft, m_pluginBounds.fTop,
+ m_pluginBounds.width(), m_pluginBounds.height());
+ m_core->viewInvalidate(rect);
+}
+
void PluginWidgetAndroid::draw(SkCanvas* canvas) {
if (NULL == m_flipPixelRef || !m_flipPixelRef->isDirty()) {
return;
@@ -563,7 +587,7 @@ void PluginWidgetAndroid::scrollToVisiblePluginRect() {
#if DEBUG_VISIBLE_RECTS
PLUGIN_LOG("%s call scrollBy (%d,%d)", __FUNCTION__, deltaX, deltaY);
#endif
- core->scrollBy(deltaX, deltaY, true);
+ core->scrollTo(rectCenterX, rectCenterY, true);
}
void PluginWidgetAndroid::requestFullScreen() {
diff --git a/WebKit/android/plugins/PluginWidgetAndroid.h b/WebKit/android/plugins/PluginWidgetAndroid.h
index 9726a22..5d586b1 100644
--- a/WebKit/android/plugins/PluginWidgetAndroid.h
+++ b/WebKit/android/plugins/PluginWidgetAndroid.h
@@ -177,6 +177,8 @@ struct PluginWidgetAndroid {
void setPowerState(ANPPowerState powerState);
+ void viewInvalidate();
+
private:
void computeVisiblePluginRect();
void scrollToVisiblePluginRect();