summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebCore/page/FrameView.cpp23
-rw-r--r--WebCore/page/FrameView.h4
-rw-r--r--WebCore/platform/android/PlatformBridge.h4
-rw-r--r--WebCore/rendering/RenderBox.cpp4
-rw-r--r--WebCore/rendering/RenderLayer.cpp8
-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/jni/CookieManager.cpp21
-rw-r--r--WebKit/android/jni/WebViewCore.cpp725
-rw-r--r--WebKit/android/jni/WebViewCore.h35
-rw-r--r--WebKit/android/nav/CachedLayer.cpp1
-rw-r--r--WebKit/android/nav/WebView.cpp4
-rw-r--r--WebKit/android/plugins/PluginWidgetAndroid.cpp2
14 files changed, 457 insertions, 415 deletions
diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp
index 5314a32..1f03599 100644
--- a/WebCore/page/FrameView.cpp
+++ b/WebCore/page/FrameView.cpp
@@ -1067,6 +1067,29 @@ void FrameView::removeFixedObject()
updateCanBlitOnScrollRecursively();
}
+#if PLATFORM(ANDROID)
+// When the screen size change, fixed positioned element should be updated.
+void FrameView::updatePositionedObjects()
+{
+ RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
+ if (RenderView* root = m_frame->contentRenderer())
+ positionedObjects = root->positionedObjects();
+
+ if (!positionedObjects || positionedObjects->isEmpty())
+ return;
+
+ RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
+ for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
+ RenderBox* renderBox = *it;
+ if (renderBox->style()->position() != FixedPosition)
+ continue;
+
+ renderBox->computeLogicalWidth();
+ renderBox->computeLogicalHeight();
+ }
+}
+#endif
+
bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
{
const size_t fixedObjectThreshold = 5;
diff --git a/WebCore/page/FrameView.h b/WebCore/page/FrameView.h
index 1b5b322..4135045 100644
--- a/WebCore/page/FrameView.h
+++ b/WebCore/page/FrameView.h
@@ -97,6 +97,10 @@ public:
bool needsFullRepaint() const { return m_doFullRepaint; }
+#if PLATFORM(ANDROID)
+ void updatePositionedObjects();
+#endif
+
#if USE(ACCELERATED_COMPOSITING)
void updateCompositingLayers();
diff --git a/WebCore/platform/android/PlatformBridge.h b/WebCore/platform/android/PlatformBridge.h
index 3f559d5..faa823e 100644
--- a/WebCore/platform/android/PlatformBridge.h
+++ b/WebCore/platform/android/PlatformBridge.h
@@ -149,8 +149,8 @@ public:
static int memoryUsageMB();
static int actualMemoryUsageMB();
- static int visibleScreenWidth(const FrameView*);
- static int visibleScreenHeight(const FrameView*);
+ static int screenWidthInDocCoord(const FrameView*);
+ static int screenHeightInDocCoord(const FrameView*);
};
}
diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp
index 3c8e2ca..ebd7d54 100644
--- a/WebCore/rendering/RenderBox.cpp
+++ b/WebCore/rendering/RenderBox.cpp
@@ -2085,7 +2085,7 @@ int RenderBox::containingBlockWidthForPositioned(const RenderBoxModelObject* con
// That is in the doc coordindate.
if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
const RenderView* view = toRenderView(containingBlock);
- return PlatformBridge::visibleScreenWidth(view->frameView());
+ return PlatformBridge::screenWidthInDocCoord(view->frameView());
}
#endif
if (containingBlock->isBox()) {
@@ -2123,7 +2123,7 @@ int RenderBox::containingBlockHeightForPositioned(const RenderBoxModelObject* co
// That is in the doc coordindate.
if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
const RenderView* view = toRenderView(containingBlock);
- return PlatformBridge::visibleScreenHeight(view->frameView());
+ return PlatformBridge::screenHeightInDocCoord(view->frameView());
}
#endif
int heightResult = 0;
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp
index b850ba3..559f25c 100644
--- a/WebCore/rendering/RenderLayer.cpp
+++ b/WebCore/rendering/RenderLayer.cpp
@@ -1159,14 +1159,6 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i
return;
EPosition position = renderer()->style()->position();
-#if PLATFORM(ANDROID)
- if (position == FixedPosition) {
- if (renderer() && renderer()->isBox()) {
- (toRenderBox(renderer()))->computeLogicalWidth();
- (toRenderBox(renderer()))->computeLogicalHeight();
- }
- }
-#endif
if (position == FixedPosition && (!ancestorLayer || ancestorLayer == renderer()->view()->layer())) {
// If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
// localToAbsolute() on the RenderView.
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/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/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index f5e6fdd..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;
@@ -349,9 +349,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
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", "(IIZ)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");
@@ -487,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;
}
@@ -948,11 +944,8 @@ void WebViewCore::scrollTo(int x, int y, bool animate)
// LOGD("WebViewCore::scrollTo(%d %d)\n", x, y);
JNIEnv* env = JSC::Bindings::getJNIEnv();
- if (animate)
- env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_spawnScrollTo, x, y);
- else
- env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollTo,
- x, y, m_onlyScrollIfImeIsShowing);
+ env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollTo,
+ x, y, animate, m_onlyScrollIfImeIsShowing);
checkException(env);
}
@@ -974,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();
@@ -1154,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;
@@ -1169,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());
+ }
}
}
@@ -1232,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,
@@ -2090,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();
}
}
@@ -2129,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) {
@@ -2157,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);
@@ -2173,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
@@ -2314,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();
}
}
}
@@ -2500,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::isVisibleNonEmptyNonWhitespaceTextNode(Node* node)
+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::isContentTextNode(Node* node)
{
if (!node || !node->isTextNode())
return false;
@@ -2532,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();
@@ -2639,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();
@@ -2656,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)) {
@@ -2682,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 {
@@ -2710,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)
@@ -2738,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);
@@ -3668,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
@@ -3754,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);
@@ -3762,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,
@@ -4414,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 5820dc5..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);
@@ -638,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;
@@ -677,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/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 935aecd..fff5737 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -489,8 +489,6 @@ 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);
if (ret || m_glWebViewState->currentPictureCounter() != pic)
return true;
@@ -553,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);
diff --git a/WebKit/android/plugins/PluginWidgetAndroid.cpp b/WebKit/android/plugins/PluginWidgetAndroid.cpp
index a02047b..06506ba 100644
--- a/WebKit/android/plugins/PluginWidgetAndroid.cpp
+++ b/WebKit/android/plugins/PluginWidgetAndroid.cpp
@@ -587,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() {