summaryrefslogtreecommitdiffstats
path: root/Source/WebKit
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit')
-rw-r--r--Source/WebKit/Android.mk17
-rw-r--r--Source/WebKit/android/RenderSkinAndroid.cpp4
-rw-r--r--Source/WebKit/android/RenderSkinMediaButton.cpp2
-rw-r--r--Source/WebKit/android/RenderSkinNinePatch.cpp8
-rw-r--r--Source/WebKit/android/RenderSkinNinePatch.h2
-rw-r--r--Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp2
-rw-r--r--Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp3
-rw-r--r--Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h6
-rw-r--r--Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp4
-rw-r--r--Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp32
-rw-r--r--Source/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp9
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebCache.cpp17
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebCache.h3
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebRequest.cpp2
-rw-r--r--Source/WebKit/android/benchmark/Android.mk41
-rw-r--r--Source/WebKit/android/benchmark/Intercept.cpp190
-rw-r--r--Source/WebKit/android/benchmark/Intercept.h82
-rw-r--r--Source/WebKit/android/benchmark/MyJavaVM.cpp130
-rw-r--r--Source/WebKit/android/benchmark/MyJavaVM.h34
-rw-r--r--Source/WebKit/android/benchmark/main.cpp65
-rw-r--r--Source/WebKit/android/content/address_detector.cpp839
-rw-r--r--Source/WebKit/android/content/address_detector.h131
-rw-r--r--Source/WebKit/android/content/content_detector.cpp86
-rw-r--r--Source/WebKit/android/content/content_detector.h103
-rw-r--r--Source/WebKit/android/jni/AndroidHitTestResult.cpp121
-rw-r--r--Source/WebKit/android/jni/AndroidHitTestResult.h7
-rw-r--r--Source/WebKit/android/jni/CacheManager.cpp4
-rw-r--r--Source/WebKit/android/jni/CookieManager.cpp41
-rw-r--r--Source/WebKit/android/jni/JavaBridge.cpp2
-rw-r--r--Source/WebKit/android/jni/JniUtil.cpp58
-rw-r--r--Source/WebKit/android/jni/WebCoreFrameBridge.cpp212
-rw-r--r--Source/WebKit/android/jni/WebCoreFrameBridge.h6
-rw-r--r--Source/WebKit/android/jni/WebCoreJni.cpp4
-rw-r--r--Source/WebKit/android/jni/WebCoreJni.h2
-rw-r--r--Source/WebKit/android/jni/WebCoreJniOnLoad.cpp166
-rw-r--r--Source/WebKit/android/jni/WebCoreResourceLoader.cpp327
-rw-r--r--Source/WebKit/android/jni/WebCoreResourceLoader.h78
-rw-r--r--Source/WebKit/android/jni/WebSettings.cpp11
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp480
-rw-r--r--Source/WebKit/android/jni/WebViewCore.h51
-rw-r--r--Source/WebKit/android/nav/FindCanvas.cpp715
-rw-r--r--Source/WebKit/android/nav/FindCanvas.h268
-rw-r--r--Source/WebKit/android/nav/WebView.cpp224
-rw-r--r--Source/WebKit/chromium/public/WebRange.h6
-rw-r--r--Source/WebKit/chromium/public/android/WebDOMTextContentWalker.h69
-rw-r--r--Source/WebKit/chromium/public/android/WebHitTestInfo.h76
-rw-r--r--Source/WebKit/chromium/src/WebRange.cpp9
-rw-r--r--Source/WebKit/chromium/src/android/WebDOMTextContentWalker.cpp85
-rw-r--r--Source/WebKit/chromium/src/android/WebHitTestInfo.cpp95
49 files changed, 1997 insertions, 2932 deletions
diff --git a/Source/WebKit/Android.mk b/Source/WebKit/Android.mk
index ee7f3ce..6066f83 100644
--- a/Source/WebKit/Android.mk
+++ b/Source/WebKit/Android.mk
@@ -16,8 +16,10 @@
##
LOCAL_SRC_FILES := \
+ android/WebCoreSupport/CacheResult.cpp \
android/WebCoreSupport/CachedFramePlatformDataAndroid.cpp \
android/WebCoreSupport/ChromeClientAndroid.cpp \
+ android/WebCoreSupport/ChromiumInit.cpp \
android/WebCoreSupport/ContextMenuClientAndroid.cpp \
android/WebCoreSupport/DeviceMotionClientAndroid.cpp \
android/WebCoreSupport/DeviceOrientationClientAndroid.cpp \
@@ -31,11 +33,6 @@ LOCAL_SRC_FILES := \
android/WebCoreSupport/PlatformBridge.cpp \
android/WebCoreSupport/ResourceLoaderAndroid.cpp \
android/WebCoreSupport/UrlInterceptResponse.cpp \
-
-ifeq ($(HTTP_STACK),chrome)
-LOCAL_SRC_FILES += \
- android/WebCoreSupport/ChromiumInit.cpp \
- android/WebCoreSupport/CacheResult.cpp \
android/WebCoreSupport/WebCache.cpp \
android/WebCoreSupport/WebCookieJar.cpp \
android/WebCoreSupport/WebUrlLoader.cpp \
@@ -45,18 +42,17 @@ LOCAL_SRC_FILES += \
android/WebCoreSupport/WebResourceRequest.cpp \
android/WebCoreSupport/WebResponse.cpp \
android/WebCoreSupport/WebViewClientError.cpp
-endif # HTTP_STACK == chrome
LOCAL_SRC_FILES += \
android/RenderSkinAndroid.cpp \
android/RenderSkinMediaButton.cpp \
android/RenderSkinNinePatch.cpp \
\
- android/benchmark/Intercept.cpp \
- android/benchmark/MyJavaVM.cpp \
- \
android/icu/unicode/ucnv.cpp \
\
+ android/content/content_detector.cpp \
+ android/content/address_detector.cpp \
+ \
android/jni/AndroidHitTestResult.cpp \
android/jni/CacheManager.cpp \
android/jni/CookieManager.cpp \
@@ -66,13 +62,11 @@ LOCAL_SRC_FILES += \
android/jni/GeolocationPermissionsBridge.cpp \
android/jni/JavaBridge.cpp \
android/jni/JavaSharedClient.cpp \
- android/jni/JniUtil.cpp \
android/jni/MIMETypeRegistry.cpp \
android/jni/MockGeolocation.cpp \
android/jni/PictureSet.cpp \
android/jni/WebCoreFrameBridge.cpp \
android/jni/WebCoreJni.cpp \
- android/jni/WebCoreResourceLoader.cpp \
android/jni/WebFrameView.cpp \
android/jni/WebHistory.cpp \
android/jni/WebIconDatabase.cpp \
@@ -89,7 +83,6 @@ LOCAL_SRC_FILES += \
android/nav/CachedNode.cpp \
android/nav/CachedRoot.cpp \
android/nav/DrawExtra.cpp \
- android/nav/FindCanvas.cpp \
android/nav/SelectText.cpp \
android/nav/WebView.cpp \
\
diff --git a/Source/WebKit/android/RenderSkinAndroid.cpp b/Source/WebKit/android/RenderSkinAndroid.cpp
index 9a5a206..9529624 100644
--- a/Source/WebKit/android/RenderSkinAndroid.cpp
+++ b/Source/WebKit/android/RenderSkinAndroid.cpp
@@ -30,8 +30,8 @@
#include "RenderSkinMediaButton.h"
#include "SkImageDecoder.h"
-#include <utils/AssetManager.h>
-#include <utils/Asset.h>
+#include <androidfw/AssetManager.h>
+#include <androidfw/Asset.h>
namespace WebCore {
diff --git a/Source/WebKit/android/RenderSkinMediaButton.cpp b/Source/WebKit/android/RenderSkinMediaButton.cpp
index f99c731..febf575 100644
--- a/Source/WebKit/android/RenderSkinMediaButton.cpp
+++ b/Source/WebKit/android/RenderSkinMediaButton.cpp
@@ -36,7 +36,7 @@
#include "SkCanvas.h"
#include "SkNinePatch.h"
#include "SkRect.h"
-#include <utils/AssetManager.h>
+#include <androidfw/AssetManager.h>
#include <utils/Debug.h>
#include <utils/Log.h>
#include <wtf/text/CString.h>
diff --git a/Source/WebKit/android/RenderSkinNinePatch.cpp b/Source/WebKit/android/RenderSkinNinePatch.cpp
index d9f6011..ec748f7 100644
--- a/Source/WebKit/android/RenderSkinNinePatch.cpp
+++ b/Source/WebKit/android/RenderSkinNinePatch.cpp
@@ -16,18 +16,18 @@
#include "config.h"
-#include "RenderSkinNinePatch.h"
#include "NinePatchPeeker.h"
+#include "RenderSkinNinePatch.h"
#include "SkCanvas.h"
#include "SkImageDecoder.h"
#include "SkNinePatch.h"
#include "SkRect.h"
#include "SkStream.h"
#include "SkTemplates.h"
-#include <utils/Asset.h>
-#include <utils/AssetManager.h>
+#include <androidfw/Asset.h>
+#include <androidfw/AssetManager.h>
+#include <androidfw/ResourceTypes.h>
#include <utils/Log.h>
-#include <utils/ResourceTypes.h>
class SkPaint;
class SkRegion;
diff --git a/Source/WebKit/android/RenderSkinNinePatch.h b/Source/WebKit/android/RenderSkinNinePatch.h
index e4db260..8cda795 100644
--- a/Source/WebKit/android/RenderSkinNinePatch.h
+++ b/Source/WebKit/android/RenderSkinNinePatch.h
@@ -18,7 +18,7 @@
#define RenderSkinNinePatch_h
#include "SkBitmap.h"
-#include "utils/Asset.h"
+#include "androidfw/Asset.h"
namespace android {
class AssetManager;
diff --git a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index f907440..1328675 100644
--- a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -298,7 +298,7 @@ bool ChromeClientAndroid::shouldInterruptJavaScript() {
KeyboardUIMode ChromeClientAndroid::keyboardUIMode()
{
- return KeyboardAccessDefault;
+ return KeyboardAccessTabsToLinks;
}
IntRect ChromeClientAndroid::windowResizerRect() const { return IntRect(0, 0, 0, 0); }
diff --git a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
index d26d523..c573b4e 100644
--- a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
@@ -70,7 +70,6 @@
#include "SkRect.h"
#include "TextEncoding.h"
#include "WebCoreFrameBridge.h"
-#include "WebCoreResourceLoader.h"
#include "WebHistory.h"
#include "WebIconDatabase.h"
#include "WebFrameView.h"
@@ -79,7 +78,7 @@
#include "autofill/WebAutofill.h"
#include "android_graphics.h"
-#include <utils/AssetManager.h>
+#include <androidfw/AssetManager.h>
#include <wtf/text/CString.h>
#define verifiedOk() // Verified that we don't need to implement this.
diff --git a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
index 2464c58..51b67ba 100644
--- a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
+++ b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
@@ -200,14 +200,12 @@ namespace android {
virtual void documentElementAvailable();
virtual void didPerformFirstNavigation() const;
-#if USE(V8)
- // TODO(benm): Implement
+ // TODO: Implement
virtual void didCreateScriptContextForFrame() { }
virtual void didDestroyScriptContextForFrame() { }
virtual void didCreateIsolatedScriptContext() { }
- virtual bool allowScriptExtension(const String& extensionName, int extensionGroup) { return false; }
-#endif
+ virtual bool allowScriptExtension(const String& extensionName, int extensionGroup) { return false; }
virtual void registerForIconNotification(bool listen = true);
diff --git a/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp b/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp
index 32cdebf..592fad3 100644
--- a/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp
+++ b/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp
@@ -29,9 +29,7 @@
#include <malloc.h>
#include <wtf/CurrentTime.h>
-#if USE(V8)
#include <v8.h>
-#endif // USE(V8)
using namespace WTF;
@@ -59,12 +57,10 @@ int MemoryUsageCache::getCachedMemoryUsage(bool forceFresh)
struct mallinfo minfo = mallinfo();
m_cachedMemoryUsage = (minfo.hblkhd + minfo.arena) >> 20;
-#if USE(V8)
v8::HeapStatistics stat;
v8::V8::GetHeapStatistics(&stat);
unsigned v8Usage = stat.total_heap_size() >> 20;
m_cachedMemoryUsage += v8Usage;
-#endif // USE(V8)
m_cacheTime = currentTimeMS();
return m_cachedMemoryUsage;
diff --git a/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp
index 27fe208..8eb379a 100644
--- a/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp
+++ b/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp
@@ -71,62 +71,34 @@ String PlatformBridge::getSignedPublicKeyAndChallengeString(unsigned index, cons
void PlatformBridge::setCookies(const Document* document, const KURL& url, const String& value)
{
-#if USE(CHROME_NETWORK_STACK)
std::string cookieValue(value.utf8().data());
GURL cookieGurl(url.string().utf8().data());
bool isPrivateBrowsing = document->settings() && document->settings()->privateBrowsingEnabled();
WebCookieJar::get(isPrivateBrowsing)->cookieStore()->SetCookie(cookieGurl, cookieValue);
-#else
- CookieClient* client = JavaSharedClient::GetCookieClient();
- if (!client)
- return;
-
- client->setCookies(url, value);
-#endif
}
String PlatformBridge::cookies(const Document* document, const KURL& url)
{
-#if USE(CHROME_NETWORK_STACK)
GURL cookieGurl(url.string().utf8().data());
bool isPrivateBrowsing = document->settings() && document->settings()->privateBrowsingEnabled();
std::string cookies = WebCookieJar::get(isPrivateBrowsing)->cookieStore()->GetCookies(cookieGurl);
String cookieString(cookies.c_str());
return cookieString;
-#else
- CookieClient* client = JavaSharedClient::GetCookieClient();
- if (!client)
- return String();
-
- return client->cookies(url);
-#endif
}
bool PlatformBridge::cookiesEnabled(const Document* document)
{
-#if USE(CHROME_NETWORK_STACK)
bool isPrivateBrowsing = document->settings() && document->settings()->privateBrowsingEnabled();
return WebCookieJar::get(isPrivateBrowsing)->allowCookies();
-#else
- CookieClient* client = JavaSharedClient::GetCookieClient();
- if (!client)
- return false;
-
- return client->cookiesEnabled();
-#endif
}
NPObject* PlatformBridge::pluginScriptableObject(Widget* widget)
{
-#if USE(V8)
if (!widget->isPluginView())
return 0;
PluginView* pluginView = static_cast<PluginView*>(widget);
return pluginView->getNPObject();
-#else
- return 0;
-#endif
}
bool PlatformBridge::isWebViewPaused(const WebCore::FrameView* frameView)
@@ -175,15 +147,11 @@ int PlatformBridge::screenHeightInDocCoord(const WebCore::FrameView* frameView)
String PlatformBridge::computeDefaultLanguage()
{
-#if USE(CHROME_NETWORK_STACK)
String acceptLanguages = WebRequestContext::acceptLanguage();
size_t length = acceptLanguages.find(',');
if (length == std::string::npos)
length = acceptLanguages.length();
return acceptLanguages.substring(0, length);
-#else
- return "en";
-#endif
}
void PlatformBridge::updateViewport(FrameView* frameView)
diff --git a/Source/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp b/Source/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp
index 7f54810..92c39b8 100644
--- a/Source/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp
@@ -29,7 +29,6 @@
#include "Frame.h"
#include "FrameLoaderClientAndroid.h"
#include "WebCoreFrameBridge.h"
-#include "WebCoreResourceLoader.h"
#include "WebUrlLoader.h"
#include "WebViewCore.h"
@@ -42,18 +41,13 @@ PassRefPtr<ResourceLoaderAndroid> ResourceLoaderAndroid::start(
{
// Called on main thread
FrameLoaderClientAndroid* clientAndroid = static_cast<FrameLoaderClientAndroid*>(client);
-#if USE(CHROME_NETWORK_STACK)
WebViewCore* webViewCore = WebViewCore::getWebViewCore(clientAndroid->getFrame()->view());
bool isMainFrame = !(clientAndroid->getFrame()->tree() && clientAndroid->getFrame()->tree()->parent());
return WebUrlLoader::start(client, handle, request, isMainResource, isMainFrame, isSync, webViewCore->webRequestContext());
-#else
- return clientAndroid->webFrame()->startLoadingResource(handle, request, isMainResource, isSync);
-#endif
}
bool ResourceLoaderAndroid::willLoadFromCache(const WebCore::KURL& url, int64_t identifier)
{
-#if USE(CHROME_NETWORK_STACK)
// This method is used to determine if a POST request can be repeated from
// cache, but you cannot really know until you actually try to read from the
// cache. Even if we checked now, something else could come along and wipe
@@ -63,9 +57,6 @@ bool ResourceLoaderAndroid::willLoadFromCache(const WebCore::KURL& url, int64_t
// reload. Then in FrameLoaderClientImpl::dispatchWillSendRequest, we
// fix-up the cache policy of the request to force a load from the cache.
return true;
-#else
- return WebCoreResourceLoader::willLoadFromCache(url, identifier);
-#endif
}
}
diff --git a/Source/WebKit/android/WebCoreSupport/WebCache.cpp b/Source/WebKit/android/WebCoreSupport/WebCache.cpp
index 9b505ee..82e3b27 100644
--- a/Source/WebKit/android/WebCoreSupport/WebCache.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebCache.cpp
@@ -30,7 +30,7 @@
#include "WebCoreJni.h"
#include "WebRequestContext.h"
#include "WebUrlLoaderClient.h"
-
+#include "net/http/http_network_session.h"
#include <wtf/text/CString.h>
using namespace WTF;
@@ -131,6 +131,21 @@ void WebCache::clear()
thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, &WebCache::clearImpl));
}
+void WebCache::certTrustChanged()
+{
+ base::Thread* thread = WebUrlLoaderClient::ioThread();
+ if (thread)
+ thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, &WebCache::certTrustChangedImpl));
+}
+
+void WebCache::certTrustChangedImpl()
+{
+ net::HttpNetworkSession* session = m_cache->GetSession();
+ if (session)
+ session->cert_verifier()->ClearCache();
+ m_cache->CloseAllConnections();
+}
+
void WebCache::closeIdleConnections()
{
base::Thread* thread = WebUrlLoaderClient::ioThread();
diff --git a/Source/WebKit/android/WebCoreSupport/WebCache.h b/Source/WebKit/android/WebCoreSupport/WebCache.h
index c3b623d..ad57d88 100644
--- a/Source/WebKit/android/WebCoreSupport/WebCache.h
+++ b/Source/WebKit/android/WebCoreSupport/WebCache.h
@@ -48,7 +48,7 @@ public:
net::HttpCache* cache() { return m_cache.get(); }
net::ProxyConfigServiceAndroid* proxy() { return m_proxyConfigService; }
void closeIdleConnections();
-
+ void certTrustChanged();
private:
WebCache(bool isPrivateBrowsing);
@@ -60,6 +60,7 @@ private:
// For closeIdleConnections
void closeIdleImpl();
+ void certTrustChangedImpl();
// For getEntry()
void getEntryImpl();
diff --git a/Source/WebKit/android/WebCoreSupport/WebRequest.cpp b/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
index c239b80..fea7afa 100644
--- a/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
@@ -39,7 +39,7 @@
#include <cutils/log.h>
#include <openssl/x509.h>
#include <string>
-#include <utils/AssetManager.h>
+#include <androidfw/AssetManager.h>
extern android::AssetManager* globalAssetManager();
diff --git a/Source/WebKit/android/benchmark/Android.mk b/Source/WebKit/android/benchmark/Android.mk
deleted file mode 100644
index 5b189e1..0000000
--- a/Source/WebKit/android/benchmark/Android.mk
+++ /dev/null
@@ -1,41 +0,0 @@
-##
-##
-## Copyright 2009, The Android Open Source Project
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions
-## are met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in the
-## documentation and/or other materials provided with the distribution.
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
-## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
-## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-##
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- main.cpp
-
-# Pull the webkit definitions from the base webkit makefile.
-LOCAL_SHARED_LIBRARIES := libwebcore $(WEBKIT_SHARED_LIBRARIES)
-LOCAL_LDLIBS := $(WEBKIT_LDLIBS)
-
-LOCAL_MODULE := webcore_test
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/Source/WebKit/android/benchmark/Intercept.cpp b/Source/WebKit/android/benchmark/Intercept.cpp
deleted file mode 100644
index 28ada5a..0000000
--- a/Source/WebKit/android/benchmark/Intercept.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright 2009, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "webcore_test"
-#include "config.h"
-
-#include "Base64.h"
-#include "HTTPParsers.h"
-#include "Intercept.h"
-#include "ResourceHandle.h"
-#include "ResourceHandleClient.h"
-#include "ResourceRequest.h"
-#include "ResourceResponse.h"
-#include "TextEncoding.h"
-
-#include <utils/Log.h>
-#include <wtf/HashMap.h>
-#include <wtf/text/CString.h>
-#include <wtf/text/StringHash.h>
-
-PassRefPtr<WebCore::ResourceLoaderAndroid> MyResourceLoader::create(
- ResourceHandle* handle, String url)
-{
- return adoptRef<WebCore::ResourceLoaderAndroid>(
- new MyResourceLoader(handle, url));
-}
-
-void MyResourceLoader::handleRequest()
-{
- if (protocolIs(m_url, "data"))
- loadData(m_url.substring(5)); // 5 for data:
- else if (protocolIs(m_url, "file"))
- loadFile(m_url.substring(7)); // 7 for file://
-}
-
-void MyResourceLoader::loadData(const String& data)
-{
- ALOGD("Loading data (%s) ...", data.latin1().data());
- ResourceHandleClient* client = m_handle->client();
- int index = data.find(',');
- if (index == -1) {
- client->cannotShowURL(m_handle);
- return;
- }
-
- String mediaType = data.substring(0, index);
- String base64 = data.substring(index + 1);
-
- bool decode = mediaType.endsWith(";base64", false);
- if (decode)
- mediaType = mediaType.left(mediaType.length() - 7); // 7 for base64;
-
- if (mediaType.isEmpty())
- mediaType = "text/plain;charset=US-ASCII";
-
- String mimeType = extractMIMETypeFromMediaType(mediaType);
- String charset = extractCharsetFromMediaType(mediaType);
-
- ResourceResponse response;
- response.setMimeType(mimeType);
-
- if (decode) {
- base64 = decodeURLEscapeSequences(base64);
- response.setTextEncodingName(charset);
- client->didReceiveResponse(m_handle, response);
-
- // FIXME: This is annoying. WebCore's Base64 decoder chokes on spaces.
- // That is correct with strict decoding but html authors (particularly
- // the acid3 authors) put spaces in the data which should be ignored.
- // Remove them here before sending to the decoder.
- Vector<char> in;
- CString str = base64.latin1();
- const char* chars = str.data();
- unsigned i = 0;
- while (i < str.length()) {
- char c = chars[i];
- // Don't send spaces or control characters.
- if (c != ' ' && c != '\n' && c != '\t' && c != '\b'
- && c != '\f' && c != '\r')
- in.append(chars[i]);
- i++;
- }
- Vector<char> out;
- if (base64Decode(in, out) && out.size() > 0)
- client->didReceiveData(m_handle, out.data(), out.size(), 0);
- } else {
- base64 = decodeURLEscapeSequences(base64, TextEncoding(charset));
- response.setTextEncodingName("UTF-16");
- client->didReceiveResponse(m_handle, response);
- if (base64.length() > 0)
- client->didReceiveData(m_handle, (const char*)base64.characters(),
- base64.length() * sizeof(UChar), 0);
- }
- client->didFinishLoading(m_handle, 0);
-}
-static String mimeTypeForExtension(const String& file)
-{
- static HashMap<String, String, CaseFoldingHash> extensionToMime;
- if (extensionToMime.isEmpty()) {
- extensionToMime.set("txt", "text/plain");
- extensionToMime.set("html", "text/html");
- extensionToMime.set("htm", "text/html");
- extensionToMime.set("png", "image/png");
- extensionToMime.set("jpeg", "image/jpeg");
- extensionToMime.set("jpg", "image/jpeg");
- extensionToMime.set("gif", "image/gif");
- extensionToMime.set("ico", "image/x-icon");
- extensionToMime.set("js", "text/javascript");
- }
- int dot = file.reverseFind('.');
- String mime("text/plain");
- if (dot != -1) {
- String ext = file.substring(dot + 1);
- if (extensionToMime.contains(ext))
- mime = extensionToMime.get(ext);
- }
- return mime;
-}
-
-void MyResourceLoader::loadFile(const String& file)
-{
- ALOGD("Loading file (%s) ...", file.latin1().data());
- FILE* f = fopen(file.latin1().data(), "r");
- ResourceHandleClient* client = m_handle->client();
- if (!f) {
- client->didFail(m_handle,
- ResourceError("", -14, file, "Could not open file"));
- } else {
- ResourceResponse response;
- response.setTextEncodingName("utf-8");
- response.setMimeType(mimeTypeForExtension(file));
- client->didReceiveResponse(m_handle, response);
- char buf[512];
- while (true) {
- int res = fread(buf, 1, sizeof(buf), f);
- if (res <= 0)
- break;
- client->didReceiveData(m_handle, buf, res, 0);
- }
- fclose(f);
- client->didFinishLoading(m_handle, 0);
- }
-}
-
-PassRefPtr<WebCore::ResourceLoaderAndroid> MyWebFrame::startLoadingResource(
- ResourceHandle* handle, const ResourceRequest& req, bool ignore,
- bool ignore2)
-{
- RefPtr<WebCore::ResourceLoaderAndroid> loader =
- MyResourceLoader::create(handle, req.url().string());
- m_requests.append(loader);
- if (!m_timer.isActive())
- m_timer.startOneShot(0);
- return loader.release();
-}
-
-void MyWebFrame::timerFired(Timer<MyWebFrame>*)
-{
- ALOGD("Handling requests...");
- Vector<RefPtr<WebCore::ResourceLoaderAndroid> > reqs;
- reqs.swap(m_requests);
- Vector<RefPtr<WebCore::ResourceLoaderAndroid> >::iterator i = reqs.begin();
- Vector<RefPtr<WebCore::ResourceLoaderAndroid> >::iterator end = reqs.end();
- for (; i != end; i++)
- static_cast<MyResourceLoader*>((*i).get())->handleRequest();
-
- ALOGD("...done");
-}
diff --git a/Source/WebKit/android/benchmark/Intercept.h b/Source/WebKit/android/benchmark/Intercept.h
deleted file mode 100644
index 6694dba..0000000
--- a/Source/WebKit/android/benchmark/Intercept.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2009, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef Intercept_h
-#define Intercept_h
-
-#include "MyJavaVM.h"
-#include "PlatformString.h"
-#include "Timer.h"
-#include "WebCoreFrameBridge.h"
-#include "WebCoreResourceLoader.h"
-#include <JNIUtility.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
- class Page;
- class ResourceHandle;
- class ResourceRequest;
-}
-
-using namespace android;
-using namespace WebCore;
-using namespace WTF;
-
-class MyResourceLoader : public WebCoreResourceLoader {
-public:
- static PassRefPtr<WebCore::ResourceLoaderAndroid> create(
- ResourceHandle* handle, String url);
- void handleRequest();
-
-private:
- MyResourceLoader(ResourceHandle* handle, String url)
- : WebCoreResourceLoader(JSC::Bindings::getJNIEnv(), MY_JOBJECT)
- , m_handle(handle)
- , m_url(url) {}
-
- void loadData(const String&);
- void loadFile(const String&);
- ResourceHandle* m_handle;
- String m_url;
-};
-
-class MyWebFrame : public WebFrame {
-public:
- MyWebFrame(Page* page)
- : WebFrame(JSC::Bindings::getJNIEnv(), MY_JOBJECT, MY_JOBJECT, page)
- , m_timer(this, &MyWebFrame::timerFired) {}
-
- virtual PassRefPtr<WebCore::ResourceLoaderAndroid> startLoadingResource(
- ResourceHandle* handle, const ResourceRequest& req, bool, bool);
-
- virtual bool canHandleRequest(const ResourceRequest&) { return true; }
-
-private:
- void timerFired(Timer<MyWebFrame>*);
- Vector<RefPtr<WebCore::ResourceLoaderAndroid> > m_requests;
- Timer<MyWebFrame> m_timer;
-};
-
-#endif
diff --git a/Source/WebKit/android/benchmark/MyJavaVM.cpp b/Source/WebKit/android/benchmark/MyJavaVM.cpp
deleted file mode 100644
index 574c745..0000000
--- a/Source/WebKit/android/benchmark/MyJavaVM.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2009, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "MyJavaVM.h"
-
-#include <JNIUtility.h>
-#include <jni.h>
-
-static JNIEnv* s_env;
-static JavaVM* s_jvm;
-
-// JavaVM functions
-jint vm_attachCurrentThread(JavaVM*, JNIEnv** env, void*) {
- *env = s_env;
- return JNI_OK;
-}
-
-// JNIEnv functions
-jobject env_callObjectMethodV(JNIEnv*, jobject, jmethodID, va_list) {
- return MY_JOBJECT;
-}
-void env_callVoidMethodV(JNIEnv*, jobject, jmethodID, va_list) {}
-void env_deleteRef(JNIEnv*, jobject) {}
-jboolean env_exceptionCheck(JNIEnv*) {
- return false;
-}
-jclass env_findClass(JNIEnv*, const char*) {
- return (jclass) 1;
-}
-jbyte* env_getByteArrayElements(JNIEnv*, jbyteArray, jboolean*) {
- return NULL;
-}
-jmethodID env_getMethodID(JNIEnv*, jclass, const char*, const char*) {
- return (jmethodID) 1;
-}
-jclass env_getObjectClass(JNIEnv*, jobject) {
- return (jclass) 1;
-}
-static const char* s_fakeString = "Fake Java String";
-const jchar* env_getStringChars(JNIEnv*, jstring, jboolean* isCopy) {
- if (isCopy)
- *isCopy = false;
- return (const jchar*)s_fakeString;
-}
-jsize env_getStringLength(JNIEnv*, jstring) {
- return sizeof(s_fakeString) - 1;
-}
-jbyteArray env_newByteArray(JNIEnv*, jsize) {
- return (jbyteArray) 1;
-}
-jobject env_newRef(JNIEnv*, jobject obj) {
- return obj;
-}
-jobject env_newObjectV(JNIEnv*, jclass, jmethodID, va_list) {
- return MY_JOBJECT;
-}
-jstring env_newString(JNIEnv*, const jchar*, jsize) {
- return (jstring) 1;
-}
-void env_releaseByteArrayElements(JNIEnv*, jbyteArray, jbyte*, jint) {}
-void env_releaseStringChars(JNIEnv*, jstring, const jchar*) {}
-void env_setByteArrayRegion(JNIEnv*, jbyteArray, jsize, jsize, const jbyte*) {}
-void env_setIntField(JNIEnv*, jobject, jfieldID, jint) {}
-
-void InitializeJavaVM() {
- // First, create the fake vm
- s_jvm = new JavaVM;
- JNIInvokeInterface* i = new JNIInvokeInterface;
- memset(i, 0, sizeof(JNIInvokeInterface));
- s_jvm->functions = i;
-
- // Now, assign the functions of the vm to our fake ones.
- i->AttachCurrentThread = vm_attachCurrentThread;
-
- // Create the fake env next
- s_env = new JNIEnv;
- JNINativeInterface* n = new JNINativeInterface;
- memset(n, 0, sizeof(JNINativeInterface));
- s_env->functions = n;
-
- // Point the functions we care about to out fake ones.
- n->CallObjectMethodV = env_callObjectMethodV;
- n->CallVoidMethodV = env_callVoidMethodV;
- n->DeleteLocalRef = env_deleteRef;
- n->DeleteGlobalRef = env_deleteRef;
- n->DeleteWeakGlobalRef = env_deleteRef;
- n->ExceptionCheck = env_exceptionCheck;
- n->FindClass = env_findClass;
- n->GetByteArrayElements = env_getByteArrayElements;
- n->GetMethodID = env_getMethodID;
- n->GetObjectClass = env_getObjectClass;
- n->GetStringChars = env_getStringChars;
- n->GetStringLength = env_getStringLength;
- n->NewByteArray = env_newByteArray;
- n->NewLocalRef = env_newRef;
- n->NewGlobalRef = env_newRef;
- n->NewWeakGlobalRef = env_newRef;
- n->NewObjectV = env_newObjectV;
- n->NewString = env_newString;
- n->ReleaseByteArrayElements = env_releaseByteArrayElements;
- n->ReleaseStringChars = env_releaseStringChars;
- n->SetByteArrayRegion = env_setByteArrayRegion;
- n->SetIntField = env_setIntField;
-
- // Tell WebCore about the vm
- JSC::Bindings::setJavaVM(s_jvm);
-}
diff --git a/Source/WebKit/android/benchmark/MyJavaVM.h b/Source/WebKit/android/benchmark/MyJavaVM.h
deleted file mode 100644
index 3092161..0000000
--- a/Source/WebKit/android/benchmark/MyJavaVM.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2009, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef MyJavaVM_h
-#define MyJavaVM_h
-
-// Make it 1 just to appease any assertions or checks for valid objects
-#define MY_JOBJECT ((jobject) 1)
-
-void InitializeJavaVM();
-
-#endif
diff --git a/Source/WebKit/android/benchmark/main.cpp b/Source/WebKit/android/benchmark/main.cpp
deleted file mode 100644
index 0dcb80b..0000000
--- a/Source/WebKit/android/benchmark/main.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2009, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "webcore_test"
-
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <utils/Log.h>
-
-namespace android {
-extern void benchmark(const char*, int, int ,int);
-}
-
-int main(int argc, char** argv) {
- int width = 800;
- int height = 600;
- int reloadCount = 0;
- while (true) {
- int c = getopt(argc, argv, "d:r:");
- if (c == -1)
- break;
- else if (c == 'd') {
- char* x = strchr(optarg, 'x');
- if (x) {
- width = atoi(optarg);
- height = atoi(x + 1);
- ALOGD("Rendering page at %dx%d", width, height);
- }
- } else if (c == 'r') {
- reloadCount = atoi(optarg);
- if (reloadCount < 0)
- reloadCount = 0;
- ALOGD("Reloading %d times", reloadCount);
- }
- }
- if (optind >= argc) {
- ALOGE("Please supply a file to read\n");
- return 1;
- }
-
- android::benchmark(argv[optind], reloadCount, width, height);
-}
diff --git a/Source/WebKit/android/content/address_detector.cpp b/Source/WebKit/android/content/address_detector.cpp
new file mode 100644
index 0000000..d5ab6e8
--- /dev/null
+++ b/Source/WebKit/android/content/address_detector.cpp
@@ -0,0 +1,839 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+// Magic pretend-to-be-a-chromium-build flags
+#undef WEBKIT_IMPLEMENTATION
+#undef LOG
+
+#include "content/address_detector.h"
+
+#include <bitset>
+
+#include "base/utf_string_conversions.h"
+#include "net/base/escape.h"
+#include "WebString.h"
+
+namespace {
+
+// Prefix used for geographical address intent URIs.
+static const char kAddressSchemaPrefix[] = "geo:0,0?q=";
+
+// Maximum text length to be searched for address detection.
+static const size_t kMaxAddressLength = 500;
+
+// Minimum number of words in an address after the house number
+// before a state is expected to be found.
+// A value too high can miss short addresses.
+const size_t kMinAddressWords = 3;
+
+// Maximum number of words allowed in an address between the house number
+// and the state, both not included.
+const size_t kMaxAddressWords = 12;
+
+// Maximum number of lines allowed in an address between the house number
+// and the state, both not included.
+const size_t kMaxAddressLines = 5;
+
+// Maximum length allowed for any address word between the house number
+// and the state, both not included.
+const size_t kMaxAddressNameWordLength = 25;
+
+// Maximum number of words after the house number in which the location name
+// should be found.
+const size_t kMaxLocationNameDistance = 4;
+
+// Number of digits for a valid zip code.
+const size_t kZipDigits = 5;
+
+// Number of digits for a valid zip code in the Zip Plus 4 format.
+const size_t kZipPlus4Digits = 9;
+
+// Maximum number of digits of a house number, including possible hyphens.
+const size_t kMaxHouseDigits = 5;
+
+// Additional characters used as new line delimiters.
+const char16 kNewlineDelimiters[] = {
+ ',',
+ '*',
+ 0x2022, // Unicode bullet
+};
+
+char16 SafePreviousChar(const string16::const_iterator& it,
+ const string16::const_iterator& begin) {
+ if (it == begin)
+ return ' ';
+ return *(it - 1);
+}
+
+char16 SafeNextChar(const string16::const_iterator& it,
+ const string16::const_iterator& end) {
+ if (it == end)
+ return ' ';
+ return *(it + 1);
+}
+
+bool WordLowerCaseEqualsASCII(string16::const_iterator word_begin,
+ string16::const_iterator word_end, const char* ascii_to_match) {
+ for (string16::const_iterator it = word_begin; it != word_end;
+ ++it, ++ascii_to_match) {
+ if (!*ascii_to_match || base::ToLowerASCII(*it) != *ascii_to_match)
+ return false;
+ }
+ return *ascii_to_match == 0 || *ascii_to_match == ' ';
+}
+
+bool LowerCaseEqualsASCIIWithPlural(string16::const_iterator word_begin,
+ string16::const_iterator word_end, const char* ascii_to_match,
+ bool allow_plural) {
+ for (string16::const_iterator it = word_begin; it != word_end;
+ ++it, ++ascii_to_match) {
+ if (!*ascii_to_match && allow_plural && *it == 's' && it + 1 == word_end)
+ return true;
+
+ if (!*ascii_to_match || base::ToLowerASCII(*it) != *ascii_to_match)
+ return false;
+ }
+ return *ascii_to_match == 0;
+}
+
+} // anonymous namespace
+
+
+AddressDetector::AddressDetector() {
+}
+
+AddressDetector::~AddressDetector() {
+}
+
+std::string AddressDetector::GetContentText(const WebKit::WebRange& range) {
+ // Get the address and replace unicode bullets with commas.
+ string16 address_16 = CollapseWhitespace(range.toPlainText(), false);
+ std::replace(address_16.begin(), address_16.end(),
+ static_cast<char16>(0x2022), static_cast<char16>(','));
+ return UTF16ToUTF8(address_16);
+}
+
+GURL AddressDetector::GetIntentURL(const std::string& content_text) {
+ return GURL(kAddressSchemaPrefix +
+ EscapeQueryParamValue(content_text, true));
+}
+
+size_t AddressDetector::GetMaximumContentLength() {
+ return kMaxAddressLength;
+}
+
+bool AddressDetector::FindContent(const string16::const_iterator& begin,
+ const string16::const_iterator& end, size_t* start_pos, size_t* end_pos) {
+ HouseNumberParser house_number_parser;
+
+ // Keep going through the input string until a potential house number is
+ // detected. Start tokenizing the following words to find a valid
+ // street name within a word range. Then, find a state name followed
+ // by a valid zip code for that state. Also keep a look for any other
+ // possible house numbers to continue from in case of no match and for
+ // state names not followed by a zip code (e.g. New York, NY 10000).
+ const string16 newline_delimiters = kNewlineDelimiters;
+ const string16 delimiters = kWhitespaceUTF16 + newline_delimiters;
+ for (string16::const_iterator it = begin; it != end; ) {
+ Word house_number;
+ if (!house_number_parser.Parse(it, end, &house_number))
+ return false;
+
+ String16Tokenizer tokenizer(house_number.end, end, delimiters);
+ tokenizer.set_options(String16Tokenizer::RETURN_DELIMS);
+
+ std::vector<Word> words;
+ words.push_back(house_number);
+
+ bool found_location_name = false;
+ bool continue_on_house_number = true;
+ size_t next_house_number_word = 0;
+ size_t num_lines = 1;
+
+ // Don't include the house number in the word count.
+ size_t next_word = 1;
+ for (; next_word <= kMaxAddressWords + 1; ++next_word) {
+
+ // Extract a new word from the tokenizer.
+ if (next_word == words.size()) {
+ do {
+ if (!tokenizer.GetNext())
+ return false;
+
+ // Check the number of address lines.
+ if (tokenizer.token_is_delim() && newline_delimiters.find(
+ *tokenizer.token_begin()) != string16::npos) {
+ ++num_lines;
+ }
+ } while (tokenizer.token_is_delim());
+
+ if (num_lines > kMaxAddressLines)
+ break;
+
+ words.push_back(Word(tokenizer.token_begin(), tokenizer.token_end()));
+ }
+
+ // Check the word length. If too long, don't try to continue from
+ // the next house number as no address can hold this word.
+ const Word& current_word = words[next_word];
+ DCHECK_GT(std::distance(current_word.begin, current_word.end), 0);
+ size_t current_word_length = std::distance(
+ current_word.begin, current_word.end);
+ if (current_word_length > kMaxAddressNameWordLength) {
+ continue_on_house_number = false;
+ break;
+ }
+
+ // Check if the new word is a valid house number.
+ // This is used to properly resume parsing in case the maximum number
+ // of words is exceeded.
+ if (next_house_number_word == 0 &&
+ house_number_parser.Parse(current_word.begin, current_word.end, NULL)) {
+ next_house_number_word = next_word;
+ continue;
+ }
+
+ // Look for location names in the words after the house number.
+ // A range limitation is introduced to avoid matching
+ // anything that starts with a number before a legitimate address.
+ if (next_word <= kMaxLocationNameDistance &&
+ IsValidLocationName(current_word)) {
+ found_location_name = true;
+ continue;
+ }
+
+ // Don't count the house number.
+ if (next_word > kMinAddressWords) {
+ // Looking for the state is likely to add new words to the list while
+ // checking for multi-word state names.
+ size_t state_first_word = next_word;
+ size_t state_last_word, state_index;
+ if (FindStateStartingInWord(&words, state_first_word, &state_last_word,
+ &tokenizer, &state_index)) {
+
+ // A location name should have been found at this point.
+ if (!found_location_name)
+ break;
+
+ // Explicitly exclude "et al", as "al" is a valid state code.
+ if (current_word_length == 2 && words.size() > 2) {
+ const Word& previous_word = words[state_first_word - 1];
+ if (previous_word.end - previous_word.begin == 2 &&
+ LowerCaseEqualsASCII(previous_word.begin, previous_word.end,
+ "et") &&
+ LowerCaseEqualsASCII(current_word.begin, current_word.end,
+ "al"))
+ break;
+ }
+
+ // Extract one more word from the tokenizer if not already available.
+ size_t zip_word = state_last_word + 1;
+ if (zip_word == words.size()) {
+ do {
+ if (!tokenizer.GetNext())
+ return false;
+ } while (tokenizer.token_is_delim());
+ words.push_back(Word(tokenizer.token_begin(),
+ tokenizer.token_end()));
+ }
+
+ // Check the parsing validity and state range of the zip code.
+ next_word = state_last_word;
+ if (!IsZipValid(words[zip_word], state_index))
+ continue;
+
+ *start_pos = words[0].begin - begin;
+ *end_pos = words[zip_word].end - begin;
+ return true;
+ }
+ }
+ }
+
+ // Avoid skipping too many words because of a non-address number
+ // at the beginning of the contents to parse.
+ if (continue_on_house_number && next_house_number_word > 0) {
+ it = words[next_house_number_word].begin;
+ } else {
+ DCHECK(!words.empty());
+ next_word = std::min(next_word, words.size() - 1);
+ it = words[next_word].end;
+ }
+ }
+
+ return false;
+}
+
+bool AddressDetector::HouseNumberParser::IsPreDelimiter(
+ char16 character) {
+ return character == ':' || IsPostDelimiter(character);
+}
+
+bool AddressDetector::HouseNumberParser::IsPostDelimiter(
+ char16 character) {
+ return IsWhitespace(character) || strchr(",\"'", character);
+}
+
+void AddressDetector::HouseNumberParser::RestartOnNextDelimiter() {
+ ResetState();
+ for (; it_ != end_ && !IsPreDelimiter(*it_); ++it_) {}
+}
+
+void AddressDetector::HouseNumberParser::AcceptChars(size_t num_chars) {
+ size_t offset = std::min(static_cast<size_t>(std::distance(it_, end_)),
+ num_chars);
+ it_ += offset;
+ result_chars_ += offset;
+}
+
+void AddressDetector::HouseNumberParser::SkipChars(size_t num_chars) {
+ it_ += std::min(static_cast<size_t>(std::distance(it_, end_)), num_chars);
+}
+
+void AddressDetector::HouseNumberParser::ResetState() {
+ num_digits_ = 0;
+ result_chars_ = 0;
+}
+
+bool AddressDetector::HouseNumberParser::CheckFinished(Word* word) const {
+ // There should always be a number after a hyphen.
+ if (result_chars_ == 0 || SafePreviousChar(it_, begin_) == '-')
+ return false;
+
+ if (word) {
+ word->begin = it_ - result_chars_;
+ word->end = it_;
+ }
+ return true;
+}
+
+bool AddressDetector::HouseNumberParser::Parse(
+ const string16::const_iterator& begin,
+ const string16::const_iterator& end, Word* word) {
+ it_ = begin_ = begin;
+ end_ = end;
+ ResetState();
+
+ // Iterations only used as a fail-safe against any buggy infinite loops.
+ size_t iterations = 0;
+ size_t max_iterations = end - begin + 1;
+ for (; it_ != end_ && iterations < max_iterations; ++iterations) {
+
+ // Word finished case.
+ if (IsPostDelimiter(*it_)) {
+ if (CheckFinished(word))
+ return true;
+ else if (result_chars_)
+ ResetState();
+
+ SkipChars(1);
+ continue;
+ }
+
+ // More digits. There should be no more after a letter was found.
+ if (IsAsciiDigit(*it_)) {
+ if (num_digits_ >= kMaxHouseDigits) {
+ RestartOnNextDelimiter();
+ } else {
+ AcceptChars(1);
+ ++num_digits_;
+ }
+ continue;
+ }
+
+ if (IsAsciiAlpha(*it_)) {
+ // Handle special case 'one'.
+ if (result_chars_ == 0) {
+ if (it_ + 3 <= end_ && LowerCaseEqualsASCII(it_, it_ + 3, "one"))
+ AcceptChars(3);
+ else
+ RestartOnNextDelimiter();
+ continue;
+ }
+
+ // There should be more than 1 character because of result_chars.
+ DCHECK_GT(result_chars_, 0U);
+ DCHECK_NE(it_, begin_);
+ char16 previous = SafePreviousChar(it_, begin_);
+ if (IsAsciiDigit(previous)) {
+ // Check cases like '12A'.
+ char16 next = SafeNextChar(it_, end_);
+ if (IsPostDelimiter(next)) {
+ AcceptChars(1);
+ continue;
+ }
+
+ // Handle cases like 12a, 1st, 2nd, 3rd, 7th.
+ if (IsAsciiAlpha(next)) {
+ char16 last_digit = previous;
+ char16 first_letter = base::ToLowerASCII(*it_);
+ char16 second_letter = base::ToLowerASCII(next);
+ bool is_teen = SafePreviousChar(it_ - 1, begin_) == '1' &&
+ num_digits_ == 2;
+
+ switch (last_digit - '0') {
+ case 1:
+ if ((first_letter == 's' && second_letter == 't') ||
+ (first_letter == 't' && second_letter == 'h' && is_teen)) {
+ AcceptChars(2);
+ continue;
+ }
+ break;
+
+ case 2:
+ if ((first_letter == 'n' && second_letter == 'd') ||
+ (first_letter == 't' && second_letter == 'h' && is_teen)) {
+ AcceptChars(2);
+ continue;
+ }
+ break;
+
+ case 3:
+ if ((first_letter == 'r' && second_letter == 'd') ||
+ (first_letter == 't' && second_letter == 'h' && is_teen)) {
+ AcceptChars(2);
+ continue;
+ }
+ break;
+
+ case 0:
+ // Explicitly exclude '0th'.
+ if (num_digits_ == 1)
+ break;
+
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ if (first_letter == 't' && second_letter == 'h') {
+ AcceptChars(2);
+ continue;
+ }
+ break;
+
+ default:
+ NOTREACHED();
+ }
+ }
+ }
+
+ RestartOnNextDelimiter();
+ continue;
+ }
+
+ if (*it_ == '-' && num_digits_ > 0) {
+ AcceptChars(1);
+ ++num_digits_;
+ continue;
+ }
+
+ RestartOnNextDelimiter();
+ SkipChars(1);
+ }
+
+ if (iterations >= max_iterations)
+ return false;
+
+ return CheckFinished(word);
+}
+
+bool AddressDetector::FindStateStartingInWord(WordList* words,
+ size_t state_first_word, size_t* state_last_word,
+ String16Tokenizer* tokenizer, size_t* state_index) {
+
+ // Bitmasks containing the allowed suffixes for 2-letter state codes.
+ static const int state_two_letter_suffix[23] = {
+ 0x02060c00, // A followed by: [KLRSZ].
+ 0x00000000, // B.
+ 0x00084001, // C followed by: [AOT].
+ 0x00000014, // D followed by: [CE].
+ 0x00000000, // E.
+ 0x00001800, // F followed by: [LM].
+ 0x00100001, // G followed by: [AU].
+ 0x00000100, // H followed by: [I].
+ 0x00002809, // I followed by: [ADLN].
+ 0x00000000, // J.
+ 0x01040000, // K followed by: [SY].
+ 0x00000001, // L followed by: [A].
+ 0x000ce199, // M followed by: [ADEHINOPST].
+ 0x0120129c, // N followed by: [CDEHJMVY].
+ 0x00020480, // O followed by: [HKR].
+ 0x00420001, // P followed by: [ARW].
+ 0x00000000, // Q.
+ 0x00000100, // R followed by: [I].
+ 0x0000000c, // S followed by: [CD].
+ 0x00802000, // T followed by: [NX].
+ 0x00080000, // U followed by: [T].
+ 0x00080101, // V followed by: [AIT].
+ 0x01200101 // W followed by: [AIVY].
+ };
+
+ // Accumulative number of states for the 2-letter code indexed by the first.
+ static const int state_two_letter_accumulative[24] = {
+ 0, 5, 5, 8, 10, 10, 12, 14,
+ 15, 19, 19, 21, 22, 32, 40, 43,
+ 46, 46, 47, 49, 51, 52, 55, 59
+ };
+
+ // State names sorted alphabetically with their lengths.
+ // There can be more than one possible name for a same state if desired.
+ static const struct StateNameInfo {
+ const char* string;
+ char first_word_length;
+ char length;
+ char state_index; // Relative to two-character code alphabetical order.
+ } state_names[59] = {
+ { "alabama", 7, 7, 1 }, { "alaska", 6, 6, 0 },
+ { "american samoa", 8, 14, 3 }, { "arizona", 7, 7, 4 },
+ { "arkansas", 8, 8, 2 },
+ { "california", 10, 10, 5 }, { "colorado", 8, 8, 6 },
+ { "connecticut", 11, 11, 7 }, { "delaware", 8, 8, 9 },
+ { "district of columbia", 8, 20, 8 },
+ { "federated states of micronesia", 9, 30, 11 }, { "florida", 7, 7, 10 },
+ { "guam", 4, 4, 13 }, { "georgia", 7, 7, 12 },
+ { "hawaii", 6, 6, 14 },
+ { "idaho", 5, 5, 16 }, { "illinois", 8, 8, 17 }, { "indiana", 7, 7, 18 },
+ { "iowa", 4, 4, 15 },
+ { "kansas", 6, 6, 19 }, { "kentucky", 8, 8, 20 },
+ { "louisiana", 9, 9, 21 },
+ { "maine", 5, 5, 24 }, { "marshall islands", 8, 16, 25 },
+ { "maryland", 8, 8, 23 }, { "massachusetts", 13, 13, 22 },
+ { "michigan", 8, 8, 26 }, { "minnesota", 9, 9, 27 },
+ { "mississippi", 11, 11, 30 }, { "missouri", 8, 8, 28 },
+ { "montana", 7, 7, 31 },
+ { "nebraska", 8, 8, 34 }, { "nevada", 6, 6, 38 },
+ { "new hampshire", 3, 13, 35 }, { "new jersey", 3, 10, 36 },
+ { "new mexico", 3, 10, 37 }, { "new york", 3, 8, 39 },
+ { "north carolina", 5, 14, 32 }, { "north dakota", 5, 12, 33 },
+ { "northern mariana islands", 8, 24, 29 },
+ { "ohio", 4, 4, 40 }, { "oklahoma", 8, 8, 41 }, { "oregon", 6, 6, 42 },
+ { "palau", 5, 5, 45 }, { "pennsylvania", 12, 12, 43 },
+ { "puerto rico", 6, 11, 44 },
+ { "rhode island", 5, 5, 46 },
+ { "south carolina", 5, 14, 47 }, { "south dakota", 5, 12, 48 },
+ { "tennessee", 9, 9, 49 }, { "texas", 5, 5, 50 },
+ { "utah", 4, 4, 51 },
+ { "vermont", 7, 7, 54 }, { "virgin islands", 6, 14, 53 },
+ { "virginia", 8, 8, 52 },
+ { "washington", 10, 10, 55 }, { "west virginia", 4, 13, 57 },
+ { "wisconsin", 9, 9, 56 }, { "wyoming", 7, 7, 58 }
+ };
+
+ // Accumulative number of states for sorted names indexed by the first letter.
+ // Required a different one since there are codes that don't share their
+ // first letter with the name of their state (MP = Northern Mariana Islands).
+ static const int state_names_accumulative[24] = {
+ 0, 5, 5, 8, 10, 10, 12, 14,
+ 15, 19, 19, 21, 22, 31, 40, 43,
+ 46, 46, 47, 49, 51, 52, 55, 59
+ };
+
+ DCHECK_EQ(state_names_accumulative[arraysize(state_names_accumulative) - 1],
+ static_cast<int>(ARRAYSIZE_UNSAFE(state_names)));
+
+ const Word& first_word = words->at(state_first_word);
+ int length = first_word.end - first_word.begin;
+ if (length < 2 || !IsAsciiAlpha(*first_word.begin))
+ return false;
+
+ // No state names start with x, y, z.
+ char16 first_letter = base::ToLowerASCII(*first_word.begin);
+ if (first_letter > 'w')
+ return false;
+
+ DCHECK(first_letter >= 'a');
+ int first_index = first_letter - 'a';
+
+ // Look for two-letter state names.
+ if (length == 2 && IsAsciiAlpha(*(first_word.begin + 1))) {
+ char16 second_letter = base::ToLowerASCII(*(first_word.begin + 1));
+ DCHECK(second_letter >= 'a');
+
+ int second_index = second_letter - 'a';
+ if (!(state_two_letter_suffix[first_index] & (1 << second_index)))
+ return false;
+
+ std::bitset<32> previous_suffixes = state_two_letter_suffix[first_index] &
+ ((1 << second_index) - 1);
+ *state_last_word = state_first_word;
+ *state_index = state_two_letter_accumulative[first_index] +
+ previous_suffixes.count();
+ return true;
+ }
+
+ // Look for full state names by their first letter. Discard by length.
+ for (int state = state_names_accumulative[first_index];
+ state < state_names_accumulative[first_index + 1]; ++state) {
+ if (state_names[state].first_word_length != length)
+ continue;
+
+ bool state_match = false;
+ size_t state_word = state_first_word;
+ for (int pos = 0; true; ) {
+ if (!WordLowerCaseEqualsASCII(words->at(state_word).begin,
+ words->at(state_word).end, &state_names[state].string[pos]))
+ break;
+
+ pos += words->at(state_word).end - words->at(state_word).begin + 1;
+ if (pos >= state_names[state].length) {
+ state_match = true;
+ break;
+ }
+
+ // Ran out of words, extract more from the tokenizer.
+ if (++state_word == words->size()) {
+ do {
+ if (!tokenizer->GetNext())
+ break;
+ } while (tokenizer->token_is_delim());
+ words->push_back(Word(tokenizer->token_begin(), tokenizer->token_end()));
+ }
+ }
+
+ if (state_match) {
+ *state_last_word = state_word;
+ *state_index = state_names[state].state_index;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool AddressDetector::IsZipValid(const Word& word, size_t state_index) {
+ size_t length = word.end - word.begin;
+ if (length != kZipDigits && length != kZipPlus4Digits + 1)
+ return false;
+
+ for (string16::const_iterator it = word.begin; it != word.end; ++it) {
+ size_t pos = it - word.begin;
+ if (IsAsciiDigit(*it) || (*it == '-' && pos == kZipDigits))
+ continue;
+ return false;
+ }
+ return IsZipValidForState(word, state_index);
+}
+
+bool AddressDetector::IsZipValidForState(const Word& word, size_t state_index) {
+ // List of valid zip code ranges.
+ static const struct {
+ char low;
+ char high;
+ char exception1;
+ char exception2;
+ } zip_range[] = {
+ { 99, 99, -1, -1 }, // AK Alaska.
+ { 35, 36, -1, -1 }, // AL Alabama.
+ { 71, 72, -1, -1 }, // AR Arkansas.
+ { 96, 96, -1, -1 }, // AS American Samoa.
+ { 85, 86, -1, -1 }, // AZ Arizona.
+ { 90, 96, -1, -1 }, // CA California.
+ { 80, 81, -1, -1 }, // CO Colorado.
+ { 6, 6, -1, -1 }, // CT Connecticut.
+ { 20, 20, -1, -1 }, // DC District of Columbia.
+ { 19, 19, -1, -1 }, // DE Delaware.
+ { 32, 34, -1, -1 }, // FL Florida.
+ { 96, 96, -1, -1 }, // FM Federated States of Micronesia.
+ { 30, 31, -1, -1 }, // GA Georgia.
+ { 96, 96, -1, -1 }, // GU Guam.
+ { 96, 96, -1, -1 }, // HI Hawaii.
+ { 50, 52, -1, -1 }, // IA Iowa.
+ { 83, 83, -1, -1 }, // ID Idaho.
+ { 60, 62, -1, -1 }, // IL Illinois.
+ { 46, 47, -1, -1 }, // IN Indiana.
+ { 66, 67, 73, -1 }, // KS Kansas.
+ { 40, 42, -1, -1 }, // KY Kentucky.
+ { 70, 71, -1, -1 }, // LA Louisiana.
+ { 1, 2, -1, -1 }, // MA Massachusetts.
+ { 20, 21, -1, -1 }, // MD Maryland.
+ { 3, 4, -1, -1 }, // ME Maine.
+ { 96, 96, -1, -1 }, // MH Marshall Islands.
+ { 48, 49, -1, -1 }, // MI Michigan.
+ { 55, 56, -1, -1 }, // MN Minnesota.
+ { 63, 65, -1, -1 }, // MO Missouri.
+ { 96, 96, -1, -1 }, // MP Northern Mariana Islands.
+ { 38, 39, -1, -1 }, // MS Mississippi.
+ { 55, 56, -1, -1 }, // MT Montana.
+ { 27, 28, -1, -1 }, // NC North Carolina.
+ { 58, 58, -1, -1 }, // ND North Dakota.
+ { 68, 69, -1, -1 }, // NE Nebraska.
+ { 3, 4, -1, -1 }, // NH New Hampshire.
+ { 7, 8, -1, -1 }, // NJ New Jersey.
+ { 87, 88, 86, -1 }, // NM New Mexico.
+ { 88, 89, 96, -1 }, // NV Nevada.
+ { 10, 14, 0, 6 }, // NY New York.
+ { 43, 45, -1, -1 }, // OH Ohio.
+ { 73, 74, -1, -1 }, // OK Oklahoma.
+ { 97, 97, -1, -1 }, // OR Oregon.
+ { 15, 19, -1, -1 }, // PA Pennsylvania.
+ { 6, 6, 0, 9 }, // PR Puerto Rico.
+ { 96, 96, -1, -1 }, // PW Palau.
+ { 2, 2, -1, -1 }, // RI Rhode Island.
+ { 29, 29, -1, -1 }, // SC South Carolina.
+ { 57, 57, -1, -1 }, // SD South Dakota.
+ { 37, 38, -1, -1 }, // TN Tennessee.
+ { 75, 79, 87, 88 }, // TX Texas.
+ { 84, 84, -1, -1 }, // UT Utah.
+ { 22, 24, 20, -1 }, // VA Virginia.
+ { 6, 9, -1, -1 }, // VI Virgin Islands.
+ { 5, 5, -1, -1 }, // VT Vermont.
+ { 98, 99, -1, -1 }, // WA Washington.
+ { 53, 54, -1, -1 }, // WI Wisconsin.
+ { 24, 26, -1, -1 }, // WV West Virginia.
+ { 82, 83, -1, -1 } // WY Wyoming.
+ };
+
+ // Zip numeric value for the first two characters.
+ DCHECK(word.begin != word.end);
+ DCHECK(IsAsciiDigit(*word.begin));
+ DCHECK(IsAsciiDigit(*(word.begin + 1)));
+ int zip_prefix = (*word.begin - '0') * 10 + (*(word.begin + 1) - '0');
+
+ if ((zip_prefix >= zip_range[state_index].low &&
+ zip_prefix <= zip_range[state_index].high) ||
+ zip_prefix == zip_range[state_index].exception1 ||
+ zip_prefix == zip_range[state_index].exception2) {
+ return true;
+ }
+ return false;
+}
+
+bool AddressDetector::IsValidLocationName(const Word& word) {
+ // Supported location names sorted alphabetically and grouped by first letter.
+ static const struct LocationNameInfo {
+ const char* string;
+ char length;
+ bool allow_plural;
+ } location_names[157] = {
+ { "alley", 5, false }, { "annex", 5, false }, { "arcade", 6, false },
+ { "ave", 3, false }, { "ave.", 4, false }, { "avenue", 6, false },
+ { "alameda", 7, false },
+ { "bayou", 5, false }, { "beach", 5, false }, { "bend", 4, false },
+ { "bluff", 5, true }, { "bottom", 6, false }, { "boulevard", 9, false },
+ { "branch", 6, false }, { "bridge", 6, false }, { "brook", 5, true },
+ { "burg", 4, true }, { "bypass", 6, false }, { "broadway", 8, false },
+ { "camino", 6, false }, { "camp", 4, false }, { "canyon", 6, false },
+ { "cape", 4, false }, { "causeway", 8, false }, { "center", 6, true },
+ { "circle", 6, true }, { "cliff", 5, true }, { "club", 4, false },
+ { "common", 6, false }, { "corner", 6, true }, { "course", 6, false },
+ { "court", 5, true }, { "cove", 4, true }, { "creek", 5, false },
+ { "crescent", 8, false }, { "crest", 5, false }, { "crossing", 8, false },
+ { "crossroad", 9, false }, { "curve", 5, false }, { "circulo", 7, false },
+ { "dale", 4, false }, { "dam", 3, false }, { "divide", 6, false },
+ { "drive", 5, true },
+ { "estate", 6, true }, { "expressway", 10, false },
+ { "extension", 9, true },
+ { "fall", 4, true }, { "ferry", 5, false }, { "field", 5, true },
+ { "flat", 4, true }, { "ford", 4, true }, { "forest", 6, false },
+ { "forge", 5, true }, { "fork", 4, true }, { "fort", 4, false },
+ { "freeway", 7, false },
+ { "garden", 6, true }, { "gateway", 7, false }, { "glen", 4, true },
+ { "green", 5, true }, { "grove", 5, true },
+ { "harbor", 6, true }, { "haven", 5, false }, { "heights", 7, false },
+ { "highway", 7, false }, { "hill", 4, true }, { "hollow", 6, false },
+ { "inlet", 5, false }, { "island", 6, true }, { "isle", 4, false },
+ { "junction", 8, true },
+ { "key", 3, true }, { "knoll", 5, true },
+ { "lake", 4, true }, { "land", 4, false }, { "landing", 7, false },
+ { "lane", 4, false }, { "light", 5, true }, { "loaf", 4, false },
+ { "lock", 4, true }, { "lodge", 5, false }, { "loop", 4, false },
+ { "mall", 4, false }, { "manor", 5, true }, { "meadow", 6, true },
+ { "mews", 4, false }, { "mill", 4, true }, { "mission", 7, false },
+ { "motorway", 8, false }, { "mount", 5, false }, { "mountain", 8, true },
+ { "neck", 4, false },
+ { "orchard", 7, false }, { "oval", 4, false }, { "overpass", 8, false },
+ { "park", 4, true }, { "parkway", 7, true }, { "pass", 4, false },
+ { "passage", 7, false }, { "path", 4, false }, { "pike", 4, false },
+ { "pine", 4, true }, { "plain", 5, true }, { "plaza", 5, false },
+ { "point", 5, true }, { "port", 4, true }, { "prairie", 7, false },
+ { "privada", 7, false },
+ { "radial", 6, false }, { "ramp", 4, false }, { "ranch", 5, false },
+ { "rapid", 5, true }, { "rest", 4, false }, { "ridge", 5, true },
+ { "river", 5, false }, { "road", 4, true }, { "route", 5, false },
+ { "row", 3, false }, { "rue", 3, false }, { "run", 3, false },
+ { "shoal", 5, true }, { "shore", 5, true }, { "skyway", 6, false },
+ { "spring", 6, true }, { "spur", 4, true }, { "square", 6, true },
+ { "station", 7, false }, { "stravenue", 9, false }, { "stream", 6, false },
+ { "st", 2, false }, { "st.", 3, false }, { "street", 6, true },
+ { "summit", 6, false }, { "speedway", 8, false },
+ { "terrace", 7, false }, { "throughway", 10, false }, { "trace", 5, false },
+ { "track", 5, false }, { "trafficway", 10, false }, { "trail", 5, false },
+ { "tunnel", 6, false }, { "turnpike", 8, false },
+ { "underpass", 9, false }, { "union", 5, true },
+ { "valley", 6, true }, { "viaduct", 7, false }, { "view", 4, true },
+ { "village", 7, true }, { "ville", 5, false }, { "vista", 5, false },
+ { "walk", 4, true }, { "wall", 4, false }, { "way", 3, true },
+ { "well", 4, true },
+ { "xing", 4, false }, { "xrd", 3, false }
+ };
+
+ // Accumulative number of location names for each starting letter.
+ static const int location_names_accumulative[25] = {
+ 0, 7, 19, 40, 44,
+ 47, 57, 62, 68, 71,
+ 72, 74, 83, 92, 93,
+ 96, 109, 109, 121, 135,
+ 143, 145, 151, 155, 157
+ };
+
+ DCHECK_EQ(
+ location_names_accumulative[arraysize(location_names_accumulative) - 1],
+ static_cast<int>(ARRAYSIZE_UNSAFE(location_names)));
+
+ if (!IsAsciiAlpha(*word.begin))
+ return false;
+
+ // No location names start with y, z.
+ char16 first_letter = base::ToLowerASCII(*word.begin);
+ if (first_letter > 'x')
+ return false;
+
+ DCHECK(first_letter >= 'a');
+ int index = first_letter - 'a';
+ int length = std::distance(word.begin, word.end);
+ for (int i = location_names_accumulative[index];
+ i < location_names_accumulative[index + 1]; ++i) {
+ if (location_names[i].length != length &&
+ (location_names[i].allow_plural &&
+ location_names[i].length + 1 != length)) {
+ continue;
+ }
+
+ if (LowerCaseEqualsASCIIWithPlural(word.begin, word.end,
+ location_names[i].string, location_names[i].allow_plural)) {
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/Source/WebKit/android/content/address_detector.h b/Source/WebKit/android/content/address_detector.h
new file mode 100644
index 0000000..4ba7b47
--- /dev/null
+++ b/Source/WebKit/android/content/address_detector.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CONTENT_RENDERER_ANDROID_ADDRESS_DETECTOR_H_
+#define CONTENT_RENDERER_ANDROID_ADDRESS_DETECTOR_H_
+#pragma once
+
+#include "build/build_config.h" // Needed for OS_ANDROID
+
+#if defined(OS_ANDROID)
+
+#include <vector>
+
+#include "base/string_tokenizer.h"
+#include "base/string_util.h"
+#include "content/content_detector.h"
+
+// Finds a geographical address (currently US only) in the given text string.
+class AddressDetector : public ContentDetector {
+ public:
+ AddressDetector();
+ virtual ~AddressDetector();
+
+ private:
+ friend class AddressDetectorTest;
+
+ // Implementation of ContentDetector.
+ virtual bool FindContent(const string16::const_iterator& begin,
+ const string16::const_iterator& end,
+ size_t* start_pos,
+ size_t* end_pos) OVERRIDE;
+
+ virtual std::string GetContentText(const WebKit::WebRange& range) OVERRIDE;
+ virtual GURL GetIntentURL(const std::string& content_text) OVERRIDE;
+ virtual size_t GetMaximumContentLength() OVERRIDE;
+
+ // Internal structs and classes. Required to be visible by the unit tests.
+ struct Word {
+ string16::const_iterator begin;
+ string16::const_iterator end;
+
+ Word() {}
+ Word(const string16::const_iterator& begin_it,
+ const string16::const_iterator& end_it)
+ : begin(begin_it),
+ end(end_it) {
+ DCHECK(begin_it <= end_it);
+ }
+ };
+
+ class HouseNumberParser {
+ public:
+ HouseNumberParser() {}
+
+ bool Parse(const string16::const_iterator& begin,
+ const string16::const_iterator& end,
+ Word* word);
+
+ private:
+ static inline bool IsPreDelimiter(char16 character);
+ static inline bool IsPostDelimiter(char16 character);
+ inline void RestartOnNextDelimiter();
+
+ inline bool CheckFinished(Word* word) const;
+ inline void AcceptChars(size_t num_chars);
+ inline void SkipChars(size_t num_chars);
+ inline void ResetState();
+
+ // Iterators to the beginning, current position and ending of the string
+ // being currently parsed.
+ string16::const_iterator begin_;
+ string16::const_iterator it_;
+ string16::const_iterator end_;
+
+ // Number of digits found in the current result candidate.
+ size_t num_digits_;
+
+ // Number of characters previous to the current iterator that belong
+ // to the current result candidate.
+ size_t result_chars_;
+
+ DISALLOW_COPY_AND_ASSIGN(HouseNumberParser);
+ };
+
+ typedef std::vector<Word> WordList;
+ typedef StringTokenizerT<string16, string16::const_iterator>
+ String16Tokenizer;
+
+ static bool FindStateStartingInWord(WordList* words,
+ size_t state_first_word,
+ size_t* state_last_word,
+ String16Tokenizer* tokenizer,
+ size_t* state_index);
+
+ static bool IsValidLocationName(const Word& word);
+ static bool IsZipValid(const Word& word, size_t state_index);
+ static bool IsZipValidForState(const Word& word, size_t state_index);
+
+ DISALLOW_COPY_AND_ASSIGN(AddressDetector);
+};
+
+#endif // defined(OS_ANDROID)
+
+#endif // CONTENT_RENDERER_ANDROID_ADDRESS_DETECTOR_H_
diff --git a/Source/WebKit/android/content/content_detector.cpp b/Source/WebKit/android/content/content_detector.cpp
new file mode 100644
index 0000000..b29a457
--- /dev/null
+++ b/Source/WebKit/android/content/content_detector.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+// Magic pretend-to-be-a-chromium-build flags
+#undef WEBKIT_IMPLEMENTATION
+#undef LOG
+
+#include "content/content_detector.h"
+
+#include "public/android/WebDOMTextContentWalker.h"
+#include "public/android/WebHitTestInfo.h"
+
+using WebKit::WebDOMTextContentWalker;
+using WebKit::WebRange;
+
+ContentDetector::Result ContentDetector::FindTappedContent(
+ const WebKit::WebHitTestInfo& hit_test) {
+ WebKit::WebRange range = FindContentRange(hit_test);
+ if (range.isNull())
+ return Result();
+
+ std::string text = GetContentText(range);
+ GURL intent_url = GetIntentURL(text);
+ return Result(range, text, intent_url);
+}
+
+WebRange ContentDetector::FindContentRange(
+ const WebKit::WebHitTestInfo& hit_test) {
+ WebDOMTextContentWalker content_walker(hit_test, GetMaximumContentLength());
+ string16 content = content_walker.content();
+ if (content.empty())
+ return WebRange();
+
+ size_t selected_offset = content_walker.hitOffsetInContent();
+ for (size_t start_offset = 0; start_offset < content.length();) {
+ size_t relative_start, relative_end;
+ if (!FindContent(content.begin() + start_offset,
+ content.end(), &relative_start, &relative_end)) {
+ break;
+ } else {
+ size_t content_start = start_offset + relative_start;
+ size_t content_end = start_offset + relative_end;
+ DCHECK(content_end <= content.length());
+
+ if (selected_offset >= content_start && selected_offset < content_end) {
+ WebRange range = content_walker.contentOffsetsToRange(
+ content_start, content_end);
+ DCHECK(!range.isNull());
+ return range;
+ } else {
+ start_offset += relative_end;
+ }
+ }
+ }
+
+ return WebRange();
+}
diff --git a/Source/WebKit/android/content/content_detector.h b/Source/WebKit/android/content/content_detector.h
new file mode 100644
index 0000000..041cbc9
--- /dev/null
+++ b/Source/WebKit/android/content/content_detector.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CONTENT_RENDERER_ANDROID_CONTENT_DETECTOR_H_
+#define CONTENT_RENDERER_ANDROID_CONTENT_DETECTOR_H_
+#pragma once
+
+#include "build/build_config.h" // Needed for OS_ANDROID
+
+#if defined(OS_ANDROID)
+
+#include "base/string_util.h"
+#include "googleurl/src/gurl.h"
+#include "public/WebRange.h"
+
+namespace WebKit {
+class WebHitTestInfo;
+}
+
+// Base class for text-based content detectors.
+class ContentDetector {
+ public:
+
+ // Holds the content detection results.
+ struct Result {
+ bool valid; // Flag indicating if the result is valid.
+ WebKit::WebRange range; // Range describing the content boundaries.
+ std::string text; // Processed text of the content.
+ GURL intent_url; // URL of the intent that should process this content.
+
+ Result() : valid(false) {}
+
+ Result(const WebKit::WebRange& range,
+ const std::string& text,
+ const GURL& intent_url)
+ : valid(true),
+ range(range),
+ text(text),
+ intent_url(intent_url) {}
+ };
+
+ virtual ~ContentDetector() {}
+
+ // Returns a WebKit range delimiting the contents found around the tapped
+ // position. If no content is found a null range will be returned.
+ Result FindTappedContent(const WebKit::WebHitTestInfo& hit_test);
+
+ protected:
+ // Parses the input string defined by the begin/end iterators returning true
+ // if the desired content is found. The start and end positions relative to
+ // the input iterators are returned in start_pos and end_pos.
+ // The end position is assumed to be non-inclusive.
+ virtual bool FindContent(const string16::const_iterator& begin,
+ const string16::const_iterator& end,
+ size_t* start_pos,
+ size_t* end_pos) = 0;
+
+ // Extracts and processes the text of the detected content.
+ virtual std::string GetContentText(const WebKit::WebRange& range) = 0;
+
+ // Returns the intent URL that should process the content, if any.
+ virtual GURL GetIntentURL(const std::string& content_text) = 0;
+
+ // Returns the maximum length of text to be extracted around the tapped
+ // position in order to search for content.
+ virtual size_t GetMaximumContentLength() = 0;
+
+ ContentDetector() {}
+ WebKit::WebRange FindContentRange(const WebKit::WebHitTestInfo& hit_test);
+
+ DISALLOW_COPY_AND_ASSIGN(ContentDetector);
+};
+
+#endif // defined(OS_ANDROID)
+
+#endif // CONTENT_RENDERER_ANDROID_CONTENT_DETECTOR_H_
diff --git a/Source/WebKit/android/jni/AndroidHitTestResult.cpp b/Source/WebKit/android/jni/AndroidHitTestResult.cpp
index 0a69007..bd3f458 100644
--- a/Source/WebKit/android/jni/AndroidHitTestResult.cpp
+++ b/Source/WebKit/android/jni/AndroidHitTestResult.cpp
@@ -28,7 +28,11 @@
#include "config.h"
#include "AndroidHitTestResult.h"
+#include "content/address_detector.h"
+#include "android/WebHitTestInfo.h"
+#include "Document.h"
#include "Element.h"
+#include "Frame.h"
#include "HitTestResult.h"
#include "KURL.h"
#include "LayerAndroid.h"
@@ -49,18 +53,20 @@ namespace android {
using namespace WebCore;
static bool gJniInitialized = false;
-static struct JavaGlue {
- jmethodID m_hitTestInit;
- jfieldID m_hitTestLinkUrl;
- jfieldID m_hitTestAnchorText;
- jfieldID m_hitTestImageUrl;
- jfieldID m_hitTestAltDisplayString;
- jfieldID m_hitTestTitle;
- jfieldID m_hitTestEditable;
- jfieldID m_hitTestTouchRects;
- jfieldID m_hitTestTapHighlightColor;
- jfieldID m_hitTestEnclosingParentRects;
-} gJavaGlue;
+static struct {
+ jmethodID m_Init;
+ jfieldID m_LinkUrl;
+ jfieldID m_AnchorText;
+ jfieldID m_ImageUrl;
+ jfieldID m_AltDisplayString;
+ jfieldID m_Title;
+ jfieldID m_Editable;
+ jfieldID m_TouchRects;
+ jfieldID m_TapHighlightColor;
+ jfieldID m_EnclosingParentRects;
+ jfieldID m_HasFocus;
+ jfieldID m_IntentUrl;
+} gHitTestGlue;
struct field {
jclass m_class;
@@ -79,19 +85,21 @@ static void InitJni(JNIEnv* env)
jclass hitTestClass = env->FindClass("android/webkit/WebViewCore$WebKitHitTest");
ALOG_ASSERT(hitTestClass, "Could not find android/webkit/WebViewCore$WebKitHitTest");
- gJavaGlue.m_hitTestInit = env->GetMethodID(hitTestClass, "<init>", "()V");
- ALOG_ASSERT(gJavaGlue.m_hitTestInit, "Could not find init method on android/webkit/WebViewCore$WebKitHitTest");
+ gHitTestGlue.m_Init = env->GetMethodID(hitTestClass, "<init>", "()V");
+ ALOG_ASSERT(gHitTestGlue.m_Init, "Could not find init method on android/webkit/WebViewCore$WebKitHitTest");
field fields[] = {
- { hitTestClass, "mTouchRects", "[Landroid/graphics/Rect;", &gJavaGlue.m_hitTestTouchRects },
- { hitTestClass, "mEditable", "Z", &gJavaGlue.m_hitTestEditable },
- { hitTestClass, "mLinkUrl", "Ljava/lang/String;", &gJavaGlue.m_hitTestLinkUrl },
- { hitTestClass, "mAnchorText", "Ljava/lang/String;", &gJavaGlue.m_hitTestAnchorText },
- { hitTestClass, "mImageUrl", "Ljava/lang/String;", &gJavaGlue.m_hitTestImageUrl },
- { hitTestClass, "mAltDisplayString", "Ljava/lang/String;", &gJavaGlue.m_hitTestAltDisplayString },
- { hitTestClass, "mTitle", "Ljava/lang/String;", &gJavaGlue.m_hitTestTitle },
- { hitTestClass, "mTapHighlightColor", "I", &gJavaGlue.m_hitTestTapHighlightColor },
- { hitTestClass, "mEnclosingParentRects", "[Landroid/graphics/Rect;", &gJavaGlue.m_hitTestEnclosingParentRects },
+ { hitTestClass, "mTouchRects", "[Landroid/graphics/Rect;", &gHitTestGlue.m_TouchRects },
+ { hitTestClass, "mEditable", "Z", &gHitTestGlue.m_Editable },
+ { hitTestClass, "mLinkUrl", "Ljava/lang/String;", &gHitTestGlue.m_LinkUrl },
+ { hitTestClass, "mIntentUrl", "Ljava/lang/String;", &gHitTestGlue.m_IntentUrl },
+ { hitTestClass, "mAnchorText", "Ljava/lang/String;", &gHitTestGlue.m_AnchorText },
+ { hitTestClass, "mImageUrl", "Ljava/lang/String;", &gHitTestGlue.m_ImageUrl },
+ { hitTestClass, "mAltDisplayString", "Ljava/lang/String;", &gHitTestGlue.m_AltDisplayString },
+ { hitTestClass, "mTitle", "Ljava/lang/String;", &gHitTestGlue.m_Title },
+ { hitTestClass, "mTapHighlightColor", "I", &gHitTestGlue.m_TapHighlightColor },
+ { hitTestClass, "mEnclosingParentRects", "[Landroid/graphics/Rect;", &gHitTestGlue.m_EnclosingParentRects },
+ { hitTestClass, "mHasFocus", "Z", &gHitTestGlue.m_HasFocus },
{0, 0, 0, 0},
};
@@ -109,6 +117,45 @@ AndroidHitTestResult::AndroidHitTestResult(WebViewCore* webViewCore, WebCore::Hi
: m_webViewCore(webViewCore)
, m_hitTestResult(hitTestResult)
{
+ buildHighlightRects();
+}
+
+void AndroidHitTestResult::setURLElement(Element* element)
+{
+ m_hitTestResult.setURLElement(element);
+ buildHighlightRects();
+}
+
+void AndroidHitTestResult::buildHighlightRects()
+{
+ m_highlightRects.clear();
+ Node* node = m_hitTestResult.URLElement();
+ if (!node || !node->renderer())
+ node = m_hitTestResult.innerNode();
+ if (!node || !node->renderer())
+ return;
+ Frame* frame = node->document()->frame();
+ IntPoint frameOffset = m_webViewCore->convertGlobalContentToFrameContent(IntPoint(), frame);
+ RenderObject* renderer = node->renderer();
+ Vector<FloatQuad> quads;
+ renderer->absoluteFocusRingQuads(quads);
+ for (size_t i = 0; i < quads.size(); i++) {
+ IntRect boundingBox = quads[i].enclosingBoundingBox();
+ boundingBox.move(-frameOffset.x(), -frameOffset.y());
+ m_highlightRects.append(boundingBox);
+ }
+}
+
+void AndroidHitTestResult::searchContentDetectors()
+{
+ AddressDetector address;
+ WebKit::WebHitTestInfo webHitTest(m_hitTestResult);
+ m_searchResult = address.FindTappedContent(webHitTest);
+ if (m_searchResult.valid) {
+ m_highlightRects.clear();
+ RefPtr<Range> range = (PassRefPtr<Range>) m_searchResult.range;
+ range->textRects(m_highlightRects, true);
+ }
}
void setStringField(JNIEnv* env, jobject obj, jfieldID field, const String& str)
@@ -118,6 +165,13 @@ void setStringField(JNIEnv* env, jobject obj, jfieldID field, const String& str)
env->DeleteLocalRef(jstr);
}
+void setStringField(JNIEnv* env, jobject obj, jfieldID field, const GURL& url)
+{
+ jstring jstr = stdStringToJstring(env, url.spec(), false);
+ env->SetObjectField(obj, field, jstr);
+ env->DeleteLocalRef(jstr);
+}
+
void setRectArray(JNIEnv* env, jobject obj, jfieldID field, Vector<IntRect> &rects)
{
jobjectArray array = intRectVectorToRectArray(env, rects);
@@ -126,9 +180,9 @@ void setRectArray(JNIEnv* env, jobject obj, jfieldID field, Vector<IntRect> &rec
}
// Some helper macros specific to setting hitTest fields
-#define _SET(jtype, jfield, value) env->Set ## jtype ## Field(hitTest, gJavaGlue.m_hitTest ## jfield, value)
+#define _SET(jtype, jfield, value) env->Set ## jtype ## Field(hitTest, gHitTestGlue.m_ ## jfield, value)
#define SET_BOOL(jfield, value) _SET(Boolean, jfield, value)
-#define SET_STRING(jfield, value) setStringField(env, hitTest, gJavaGlue.m_hitTest ## jfield, value)
+#define SET_STRING(jfield, value) setStringField(env, hitTest, gHitTestGlue.m_ ## jfield, value)
#define SET_INT(jfield, value) _SET(Int, jfield, value)
jobject AndroidHitTestResult::createJavaObject(JNIEnv* env)
@@ -137,14 +191,16 @@ jobject AndroidHitTestResult::createJavaObject(JNIEnv* env)
jclass hitTestClass = env->FindClass("android/webkit/WebViewCore$WebKitHitTest");
ALOG_ASSERT(hitTestClass, "Could not find android/webkit/WebViewCore$WebKitHitTest");
- jobject hitTest = env->NewObject(hitTestClass, gJavaGlue.m_hitTestInit);
- setRectArray(env, hitTest, gJavaGlue.m_hitTestTouchRects, m_highlightRects);
+ jobject hitTest = env->NewObject(hitTestClass, gHitTestGlue.m_Init);
+ setRectArray(env, hitTest, gHitTestGlue.m_TouchRects, m_highlightRects);
Vector<IntRect> rects = enclosingParentRects(m_hitTestResult.innerNode());
- setRectArray(env, hitTest, gJavaGlue.m_hitTestEnclosingParentRects, rects);
+ setRectArray(env, hitTest, gHitTestGlue.m_EnclosingParentRects, rects);
SET_BOOL(Editable, m_hitTestResult.isContentEditable());
SET_STRING(LinkUrl, m_hitTestResult.absoluteLinkURL().string());
+ if (m_searchResult.valid)
+ SET_STRING(IntentUrl, m_searchResult.intent_url);
SET_STRING(ImageUrl, m_hitTestResult.absoluteImageURL().string());
SET_STRING(AltDisplayString, m_hitTestResult.altDisplayString());
TextDirection titleTextDirection;
@@ -157,6 +213,11 @@ jobject AndroidHitTestResult::createJavaObject(JNIEnv* env)
urlElement->renderer()->style()->tapHighlightColor().rgb());
}
}
+ Node* focusedNode = m_webViewCore->focusedFrame()->document()->focusedNode();
+ SET_BOOL(HasFocus,
+ focusedNode == m_hitTestResult.URLElement()
+ || focusedNode == m_hitTestResult.innerNode()
+ || focusedNode == m_hitTestResult.innerNonSharedNode());
env->DeleteLocalRef(hitTestClass);
@@ -165,8 +226,8 @@ jobject AndroidHitTestResult::createJavaObject(JNIEnv* env)
Vector<IntRect> AndroidHitTestResult::enclosingParentRects(Node* node)
{
- int lastX;
int count = 0;
+ int lastX = 0;
Vector<IntRect> rects;
while (node && count < 5) {
@@ -178,7 +239,7 @@ Vector<IntRect> AndroidHitTestResult::enclosingParentRects(Node* node)
node->document()->frame());
IntRect rect = render->absoluteBoundingBoxRect();
rect.move(-frameOffset.x(), -frameOffset.y());
- if (rect.x() != lastX) {
+ if (count == 0 || rect.x() != lastX) {
rects.append(rect);
lastX = rect.x();
count++;
diff --git a/Source/WebKit/android/jni/AndroidHitTestResult.h b/Source/WebKit/android/jni/AndroidHitTestResult.h
index e4233fd..5bbfc6b 100644
--- a/Source/WebKit/android/jni/AndroidHitTestResult.h
+++ b/Source/WebKit/android/jni/AndroidHitTestResult.h
@@ -26,6 +26,8 @@
#ifndef AndroidHitTestResult_h
#define AndroidHitTestResult_h
+#include "content/content_detector.h"
+#include "Element.h"
#include "HitTestResult.h"
#include "IntRect.h"
#include "wtf/Vector.h"
@@ -45,6 +47,10 @@ public:
WebCore::HitTestResult& hitTestResult() { return m_hitTestResult; }
Vector<WebCore::IntRect>& highlightRects() { return m_highlightRects; }
+ void setURLElement(WebCore::Element* element);
+ void buildHighlightRects();
+ void searchContentDetectors();
+
jobject createJavaObject(JNIEnv*);
private:
@@ -53,6 +59,7 @@ private:
WebViewCore* m_webViewCore;
WebCore::HitTestResult m_hitTestResult;
Vector<WebCore::IntRect> m_highlightRects;
+ ContentDetector::Result m_searchResult;
};
} // namespace android
diff --git a/Source/WebKit/android/jni/CacheManager.cpp b/Source/WebKit/android/jni/CacheManager.cpp
index d319054..b34776d 100644
--- a/Source/WebKit/android/jni/CacheManager.cpp
+++ b/Source/WebKit/android/jni/CacheManager.cpp
@@ -25,8 +25,6 @@
#include "config.h"
-#if USE(CHROME_NETWORK_STACK)
-
#include "ChromiumIncludes.h"
#include "WebCache.h"
#include "WebCoreJni.h"
@@ -140,5 +138,3 @@ int registerCacheManager(JNIEnv* env)
}
} // namespace android
-
-#endif // USE(CHROME_NETWORK_STACK)
diff --git a/Source/WebKit/android/jni/CookieManager.cpp b/Source/WebKit/android/jni/CookieManager.cpp
index 357d158..fca612f 100644
--- a/Source/WebKit/android/jni/CookieManager.cpp
+++ b/Source/WebKit/android/jni/CookieManager.cpp
@@ -40,49 +40,30 @@ static const char* javaCookieManagerClass = "android/webkit/CookieManager";
static bool acceptCookie(JNIEnv*, jobject)
{
-#if USE(CHROME_NETWORK_STACK)
// This is a static method which gets the cookie policy for all WebViews. We
// always apply the same configuration to the contexts for both regular and
// private browsing, so expect the same result here.
bool regularAcceptCookies = WebCookieJar::get(false)->allowCookies();
ASSERT(regularAcceptCookies == WebCookieJar::get(true)->allowCookies());
return regularAcceptCookies;
-#else
- // The Android HTTP stack is implemented Java-side.
- ASSERT_NOT_REACHED();
- return false;
-#endif
}
static jstring getCookie(JNIEnv* env, jobject, jstring url, jboolean privateBrowsing)
{
-#if USE(CHROME_NETWORK_STACK)
GURL gurl(jstringToStdString(env, url));
CookieOptions options;
options.set_include_httponly();
std::string cookies = WebCookieJar::get(privateBrowsing)->cookieStore()->GetCookieMonster()->GetCookiesWithOptions(gurl, options);
return stdStringToJstring(env, cookies);
-#else
- // The Android HTTP stack is implemented Java-side.
- ASSERT_NOT_REACHED();
- return jstring();
-#endif
}
static bool hasCookies(JNIEnv*, jobject, jboolean privateBrowsing)
{
-#if USE(CHROME_NETWORK_STACK)
return WebCookieJar::get(privateBrowsing)->getNumCookiesInDatabase() > 0;
-#else
- // The Android HTTP stack is implemented Java-side.
- ASSERT_NOT_REACHED();
- return false;
-#endif
}
static void removeAllCookie(JNIEnv*, jobject)
{
-#if USE(CHROME_NETWORK_STACK)
WebCookieJar::get(false)->cookieStore()->GetCookieMonster()->DeleteAll(true);
// This will lazily create a new private browsing context. However, if the
// context doesn't already exist, there's no need to create it, as cookies
@@ -94,84 +75,62 @@ static void removeAllCookie(JNIEnv*, jobject)
// The Java code removes cookies directly from the backing database, so we do the same,
// but with a NULL callback so it's asynchronous.
WebCookieJar::get(true)->cookieStore()->GetCookieMonster()->FlushStore(NULL);
-#endif
}
static void removeExpiredCookie(JNIEnv*, jobject)
{
-#if USE(CHROME_NETWORK_STACK)
// This simply forces a GC. The getters delete expired cookies so won't return expired cookies anyway.
WebCookieJar::get(false)->cookieStore()->GetCookieMonster()->GetAllCookies();
WebCookieJar::get(true)->cookieStore()->GetCookieMonster()->GetAllCookies();
-#endif
}
static void removeSessionCookies(WebCookieJar* cookieJar)
{
-#if USE(CHROME_NETWORK_STACK)
CookieMonster* cookieMonster = cookieJar->cookieStore()->GetCookieMonster();
CookieList cookies = cookieMonster->GetAllCookies();
for (CookieList::const_iterator iter = cookies.begin(); iter != cookies.end(); ++iter) {
if (iter->IsSessionCookie())
cookieMonster->DeleteCanonicalCookie(*iter);
}
-#endif
}
static void removeSessionCookie(JNIEnv*, jobject)
{
-#if USE(CHROME_NETWORK_STACK)
removeSessionCookies(WebCookieJar::get(false));
removeSessionCookies(WebCookieJar::get(true));
-#endif
}
static void setAcceptCookie(JNIEnv*, jobject, jboolean accept)
{
-#if USE(CHROME_NETWORK_STACK)
// This is a static method which configures the cookie policy for all
// WebViews, so we configure the contexts for both regular and private
// browsing.
WebCookieJar::get(false)->setAllowCookies(accept);
WebCookieJar::get(true)->setAllowCookies(accept);
-#endif
}
static void setCookie(JNIEnv* env, jobject, jstring url, jstring value, jboolean privateBrowsing)
{
-#if USE(CHROME_NETWORK_STACK)
GURL gurl(jstringToStdString(env, url));
std::string line(jstringToStdString(env, value));
CookieOptions options;
options.set_include_httponly();
WebCookieJar::get(privateBrowsing)->cookieStore()->GetCookieMonster()->SetCookieWithOptions(gurl, line, options);
-#endif
}
static void flushCookieStore(JNIEnv*, jobject)
{
-#if USE(CHROME_NETWORK_STACK)
WebCookieJar::flush();
-#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[] = {
diff --git a/Source/WebKit/android/jni/JavaBridge.cpp b/Source/WebKit/android/jni/JavaBridge.cpp
index 204ac4e..4c8234b 100644
--- a/Source/WebKit/android/jni/JavaBridge.cpp
+++ b/Source/WebKit/android/jni/JavaBridge.cpp
@@ -472,12 +472,10 @@ void JavaBridge::RemovePackageName(JNIEnv* env, jobject obj, jstring packageName
void JavaBridge::UpdateProxy(JNIEnv* env, jobject obj, jstring newProxy, jstring newExList)
{
-#if USE(CHROME_NETWORK_STACK)
std::string proxy = jstringToStdString(env, newProxy);
std::string exList = jstringToStdString(env, newExList);
WebCache::get(false)->proxy()->UpdateProxySettings(proxy, exList);
WebCache::get(true)->proxy()->UpdateProxySettings(proxy, exList);
-#endif
}
diff --git a/Source/WebKit/android/jni/JniUtil.cpp b/Source/WebKit/android/jni/JniUtil.cpp
deleted file mode 100644
index 651016e..0000000
--- a/Source/WebKit/android/jni/JniUtil.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "ChromiumIncludes.h"
-#include <JNIHelp.h>
-
-namespace android {
-
-static const char* javaJniUtilClass = "android/webkit/JniUtil";
-
-static bool useChromiumHttpStack(JNIEnv*, jobject)
-{
-#if USE(CHROME_NETWORK_STACK)
- return true;
-#else
- return false;
-#endif
-}
-
-static JNINativeMethod gJniUtilMethods[] = {
- { "nativeUseChromiumHttpStack", "()Z", (void*) useChromiumHttpStack },
-};
-
-int registerJniUtil(JNIEnv* env)
-{
-#ifndef NDEBUG
- jclass jniUtil = env->FindClass(javaJniUtilClass);
- ALOG_ASSERT(jniUtil, "Unable to find class");
- env->DeleteLocalRef(jniUtil);
-#endif
- return jniRegisterNativeMethods(env, javaJniUtilClass, gJniUtilMethods, NELEM(gJniUtilMethods));
-}
-
-} // namespace android
diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
index adacb49..d0f3830 100644
--- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
+++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
@@ -60,6 +60,8 @@
#include "IconDatabase.h"
#include "Image.h"
#include "InspectorClientAndroid.h"
+#include "JavaNPObjectV8.h"
+#include "JavaInstanceJobjectV8.h"
#include "KURL.h"
#include "Page.h"
#include "PageCache.h"
@@ -81,7 +83,6 @@
#include "WebArchiveAndroid.h"
#include "WebCache.h"
#include "WebCoreJni.h"
-#include "WebCoreResourceLoader.h"
#include "WebHistory.h"
#include "WebIconDatabase.h"
#include "WebFrameView.h"
@@ -99,25 +100,13 @@
#include <android_runtime/android_util_AssetManager.h>
#include <openssl/x509.h>
#include <utils/misc.h>
-#include <utils/AssetManager.h>
+#include <androidfw/AssetManager.h>
#include <wtf/CurrentTime.h>
#include <wtf/Platform.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
-#if USE(JSC)
-#include "GCController.h"
-#include "JSDOMWindow.h"
-#include "JavaInstanceJSC.h"
-#include <runtime_object.h>
-#include <runtime_root.h>
-#include <runtime/JSLock.h>
-#elif USE(V8)
-#include "JavaNPObjectV8.h"
-#include "JavaInstanceJobjectV8.h"
-#endif // USE(JSC)
-
#if ENABLE(WEB_AUTOFILL)
#include "autofill/WebAutofill.h"
#endif
@@ -239,8 +228,6 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page*
mJavaFrame = new JavaBrowserFrame;
mJavaFrame->mObj = env->NewWeakGlobalRef(obj);
mJavaFrame->mHistoryList = env->NewWeakGlobalRef(historyList);
- mJavaFrame->mStartLoadingResource = env->GetMethodID(clazz, "startLoadingResource",
- "(ILjava/lang/String;Ljava/lang/String;Ljava/util/HashMap;[BJIZZZLjava/lang/String;Ljava/lang/String;)Landroid/webkit/LoadListener;");
mJavaFrame->mMaybeSavePassword = env->GetMethodID(clazz, "maybeSavePassword",
"([BLjava/lang/String;Ljava/lang/String;)V");
mJavaFrame->mShouldInterceptRequest =
@@ -296,7 +283,6 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page*
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
env->DeleteLocalRef(clazz);
- ALOG_ASSERT(mJavaFrame->mStartLoadingResource, "Could not find method startLoadingResource");
ALOG_ASSERT(mJavaFrame->mMaybeSavePassword, "Could not find method maybeSavePassword");
ALOG_ASSERT(mJavaFrame->mShouldInterceptRequest, "Could not find method shouldInterceptRequest");
ALOG_ASSERT(mJavaFrame->mLoadStarted, "Could not find method loadStarted");
@@ -411,94 +397,6 @@ private:
int m_size;
};
-PassRefPtr<WebCore::ResourceLoaderAndroid>
-WebFrame::startLoadingResource(WebCore::ResourceHandle* loader,
- const WebCore::ResourceRequest& request,
- bool mainResource,
- bool synchronous)
-{
- ALOGV("::WebCore:: startLoadingResource(%p, %s)",
- loader, request.url().string().latin1().data());
-
- JNIEnv* env = getJNIEnv();
- AutoJObject javaFrame = mJavaFrame->frame(env);
- if (!javaFrame.get())
- return 0;
-
- WTF::String method = request.httpMethod();
- WebCore::HTTPHeaderMap headers = request.httpHeaderFields();
-
- WTF::String urlStr = request.url().string();
- int colon = urlStr.find(':');
- bool allLower = true;
- for (int index = 0; index < colon; index++) {
- UChar ch = urlStr[index];
- if (!WTF::isASCIIAlpha(ch))
- break;
- allLower &= WTF::isASCIILower(ch);
- if (index == colon - 1 && !allLower) {
- urlStr = urlStr.substring(0, colon).lower()
- + urlStr.substring(colon);
- }
- }
- ALOGV("%s lower=%s", __FUNCTION__, urlStr.latin1().data());
- jstring jUrlStr = wtfStringToJstring(env, urlStr);
- jstring jMethodStr = NULL;
- if (!method.isEmpty())
- jMethodStr = wtfStringToJstring(env, method);
- WebCore::FormData* formdata = request.httpBody();
- jbyteArray jPostDataStr = getPostData(request);
- jobject jHeaderMap = createJavaMapFromHTTPHeaders(env, headers);
-
- // Convert the WebCore Cache Policy to a WebView Cache Policy.
- int cacheMode = 0; // WebSettings.LOAD_NORMAL
- switch (request.cachePolicy()) {
- case WebCore::ReloadIgnoringCacheData:
- cacheMode = 2; // WebSettings.LOAD_NO_CACHE
- break;
- case WebCore::ReturnCacheDataDontLoad:
- cacheMode = 3; // WebSettings.LOAD_CACHE_ONLY
- break;
- case WebCore::ReturnCacheDataElseLoad:
- cacheMode = 1; // WebSettings.LOAD_CACHE_ELSE_NETWORK
- break;
- case WebCore::UseProtocolCachePolicy:
- default:
- break;
- }
-
- ALOGV("::WebCore:: startLoadingResource %s with cacheMode %d", urlStr.ascii().data(), cacheMode);
-
- ResourceHandleInternal* loaderInternal = loader->getInternal();
- jstring jUsernameString = loaderInternal->m_user.isEmpty() ?
- NULL : wtfStringToJstring(env, loaderInternal->m_user);
- jstring jPasswordString = loaderInternal->m_pass.isEmpty() ?
- NULL : wtfStringToJstring(env, loaderInternal->m_pass);
-
- bool isUserGesture = UserGestureIndicator::processingUserGesture();
- jobject jLoadListener =
- env->CallObjectMethod(javaFrame.get(), mJavaFrame->mStartLoadingResource,
- (int)loader, jUrlStr, jMethodStr, jHeaderMap,
- jPostDataStr, formdata ? formdata->identifier(): 0,
- cacheMode, mainResource, isUserGesture,
- synchronous, jUsernameString, jPasswordString);
-
- env->DeleteLocalRef(jUrlStr);
- env->DeleteLocalRef(jMethodStr);
- env->DeleteLocalRef(jPostDataStr);
- env->DeleteLocalRef(jHeaderMap);
- env->DeleteLocalRef(jUsernameString);
- env->DeleteLocalRef(jPasswordString);
- if (checkException(env))
- return 0;
-
- RefPtr<WebCore::ResourceLoaderAndroid> h;
- if (jLoadListener)
- h = WebCoreResourceLoader::create(env, jLoadListener);
- env->DeleteLocalRef(jLoadListener);
- return h;
-}
-
UrlInterceptResponse*
WebFrame::shouldInterceptRequest(const WTF::String& url)
{
@@ -539,7 +437,6 @@ WebFrame::reportError(int errorCode, const WTF::String& description,
WTF::String
WebFrame::convertIDNToUnicode(const WebCore::KURL& url) {
WTF::String converted = url.string();
-#if USE(CHROME_NETWORK_STACK)
const WTF::String host = url.host();
if (host.find("xn--") == notFound) // no punycode IDN found.
return converted;
@@ -552,7 +449,6 @@ WebFrame::convertIDNToUnicode(const WebCore::KURL& url) {
newUrl.setHost(convertedHost);
converted = newUrl.string();
}
-#endif
return converted;
}
@@ -896,7 +792,6 @@ WebFrame::density() const
return dpi;
}
-#if USE(CHROME_NETWORK_STACK)
void
WebFrame::didReceiveAuthenticationChallenge(WebUrlLoaderClient* client, const std::string& host, const std::string& realm, bool useCachedCredentials, bool suppressDialog)
{
@@ -1008,7 +903,6 @@ void WebFrame::setCertificate(const std::string& cert)
checkException(env);
}
-#endif // USE(CHROME_NETWORK_STACK)
void WebFrame::autoLogin(const std::string& loginHeader)
{
@@ -1198,10 +1092,8 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss
{
ScriptController::initializeThreading();
-#if USE(CHROME_NETWORK_STACK)
// needs to be called before any other chromium code
initChromium();
-#endif
// Create a new page
ChromeClientAndroid* chromeC = new ChromeClientAndroid;
@@ -1612,32 +1504,16 @@ static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj,
// Wrap the JavaInstance used when binding custom javascript interfaces. Use a
// weak reference so that the gc can collect the WebView. Override virtualBegin
// and virtualEnd and swap the weak reference for the real object.
-#if USE(JSC)
-class WeakJavaInstance : public JavaInstance {
-#elif USE(V8)
class WeakJavaInstance : public JavaInstanceJobject {
-#endif
public:
-#if USE(JSC)
- static PassRefPtr<WeakJavaInstance> create(jobject obj, PassRefPtr<RootObject> root)
- {
- return adoptRef(new WeakJavaInstance(obj, root));
- }
-#elif USE(V8)
static PassRefPtr<WeakJavaInstance> create(jobject obj)
{
return adoptRef(new WeakJavaInstance(obj));
}
-#endif
private:
-#if USE(JSC)
- WeakJavaInstance(jobject instance, PassRefPtr<RootObject> rootObject)
- : JavaInstance(instance, rootObject)
-#elif USE(V8)
WeakJavaInstance(jobject instance)
: JavaInstanceJobject(instance)
-#endif
, m_beginEndDepth(0)
{
JNIEnv* env = getJNIEnv();
@@ -1687,11 +1563,7 @@ private:
}
private:
-#if USE(JSC)
- typedef JavaInstance INHERITED;
-#elif USE(V8)
typedef JavaInstanceJobject INHERITED;
-#endif
jweak m_weakRef;
// The current depth of nested calls to virtualBegin and virtualEnd.
int m_beginEndDepth;
@@ -1711,28 +1583,6 @@ static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePoi
env->GetJavaVM(&vm);
ALOGV("::WebCore:: addJSInterface: %p", pFrame);
-#if USE(JSC)
- // Copied from qwebframe.cpp
- JSC::JSLock lock(JSC::SilenceAssertionsOnly);
- WebCore::JSDOMWindow *window = WebCore::toJSDOMWindow(pFrame, mainThreadNormalWorld());
- if (window) {
- RootObject *root = pFrame->script()->bindingRootObject();
- setJavaVM(vm);
- // Add the binding to JS environment
- JSC::ExecState* exec = window->globalExec();
- JSC::JSObject* addedObject = WeakJavaInstance::create(javascriptObj,
- root)->createRuntimeObject(exec);
- const jchar* s = env->GetStringChars(interfaceName, NULL);
- if (s) {
- // Add the binding name to the window's table of child objects.
- JSC::PutPropertySlot slot;
- window->put(exec, JSC::Identifier(exec, (const UChar *)s,
- env->GetStringLength(interfaceName)), addedObject, slot);
- env->ReleaseStringChars(interfaceName, s);
- checkException(env);
- }
- }
-#elif USE(V8)
if (pFrame) {
RefPtr<JavaInstance> addedObject = WeakJavaInstance::create(javascriptObj);
const char* name = getCharactersFromJStringInEnv(env, interfaceName);
@@ -1753,18 +1603,6 @@ static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePoi
NPN_ReleaseObject(npObject);
releaseCharactersForJString(interfaceName, name);
}
-#endif
-
-}
-
-static void SetCacheDisabled(JNIEnv *env, jobject obj, jboolean disabled)
-{
- WebCore::memoryCache()->setDisabled(disabled);
-}
-
-static jboolean CacheDisabled(JNIEnv *env, jobject obj)
-{
- return WebCore::memoryCache()->disabled();
}
static void ClearWebCoreCache()
@@ -1786,25 +1624,15 @@ static void ClearWebCoreCache()
static void ClearWebViewCache()
{
-#if USE(CHROME_NETWORK_STACK)
WebCache::get(false /*privateBrowsing*/)->clear();
-#else
- // The Android network stack provides a WebView cache in CacheManager.java.
- // Clearing this is handled entirely Java-side.
-#endif
}
static void ClearCache(JNIEnv *env, jobject obj)
{
ClearWebCoreCache();
ClearWebViewCache();
-#if USE(JSC)
- // force JavaScript to GC when clear cache
- WebCore::gcController().garbageCollectSoon();
-#elif USE(V8)
WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
pFrame->script()->lowMemoryNotification();
-#endif // USE(JSC)
}
static jboolean DocumentHasImages(JNIEnv *env, jobject obj)
@@ -1971,8 +1799,6 @@ static jboolean GetShouldStartScrolledRight(JNIEnv *env, jobject obj,
return startScrolledRight;
}
-#if USE(CHROME_NETWORK_STACK)
-
static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword)
{
WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
@@ -2077,34 +1903,6 @@ static void SslClientCert(JNIEnv *env, jobject obj, int handle, jbyteArray pkey,
client->sslClientCert(privateKey.release(), certificate);
}
-#else
-
-static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword)
-{
- ALOGW("Chromium authentication API called, but libchromium is not available");
-}
-
-static void AuthenticationCancel(JNIEnv *env, jobject obj, int handle)
-{
- ALOGW("Chromium authentication API called, but libchromium is not available");
-}
-
-static void SslCertErrorProceed(JNIEnv *env, jobject obj, int handle)
-{
- ALOGW("Chromium SSL API called, but libchromium is not available");
-}
-
-static void SslCertErrorCancel(JNIEnv *env, jobject obj, int handle, int cert_error)
-{
- ALOGW("Chromium SSL API called, but libchromium is not available");
-}
-
-static void SslClientCert(JNIEnv *env, jobject obj, int handle, jbyteArray privateKey, jobjectArray chain)
-{
- ALOGW("Chromium SSL API called, but libchromium is not available");
-}
-#endif // USE(CHROME_NETWORK_STACK)
-
// ----------------------------------------------------------------------------
/*
@@ -2143,10 +1941,6 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = {
{ "stringByEvaluatingJavaScriptFromString",
"(Ljava/lang/String;)Ljava/lang/String;",
(void*) StringByEvaluatingJavaScriptFromString },
- { "setCacheDisabled", "(Z)V",
- (void*) SetCacheDisabled },
- { "cacheDisabled", "()Z",
- (void*) CacheDisabled },
{ "clearCache", "()V",
(void*) ClearCache },
{ "documentHasImages", "()Z",
diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.h b/Source/WebKit/android/jni/WebCoreFrameBridge.h
index eaee63c..13f99af 100644
--- a/Source/WebKit/android/jni/WebCoreFrameBridge.h
+++ b/Source/WebKit/android/jni/WebCoreFrameBridge.h
@@ -64,10 +64,6 @@ class WebFrame : public WebCoreRefObject {
// helper function
static WebFrame* getWebFrame(const WebCore::Frame* frame);
- virtual PassRefPtr<WebCore::ResourceLoaderAndroid> startLoadingResource(WebCore::ResourceHandle*,
- const WebCore::ResourceRequest& request, bool mainResource,
- bool synchronous);
-
UrlInterceptResponse* shouldInterceptRequest(const WTF::String& url);
void reportError(int errorCode, const WTF::String& description,
@@ -117,7 +113,6 @@ class WebFrame : public WebCoreRefObject {
float density() const;
-#if USE(CHROME_NETWORK_STACK)
void didReceiveAuthenticationChallenge(WebUrlLoaderClient*, const std::string& host, const std::string& realm, bool useCachedCredentials, bool suppressDialog);
void reportSslCertError(WebUrlLoaderClient* client, int cert_error, const std::string& cert, const std::string& url);
void requestClientCert(WebUrlLoaderClient* client, const std::string& hostAndPort);
@@ -125,7 +120,6 @@ class WebFrame : public WebCoreRefObject {
void didReceiveData(const char* data, int size);
void didFinishLoading();
void setCertificate(const std::string& cert);
-#endif
void maybeSavePassword(WebCore::Frame* frame, const WebCore::ResourceRequest& request);
diff --git a/Source/WebKit/android/jni/WebCoreJni.cpp b/Source/WebKit/android/jni/WebCoreJni.cpp
index 65b6d20..5a142c8 100644
--- a/Source/WebKit/android/jni/WebCoreJni.cpp
+++ b/Source/WebKit/android/jni/WebCoreJni.cpp
@@ -79,8 +79,6 @@ jstring wtfStringToJstring(JNIEnv* env, const WTF::String& str, bool validOnZero
return length || validOnZeroLength ? env->NewString(str.characters(), length) : 0;
}
-
-#if USE(CHROME_NETWORK_STACK)
string16 jstringToString16(JNIEnv* env, jstring jstr)
{
if (!jstr || !env)
@@ -114,8 +112,6 @@ jstring stdStringToJstring(JNIEnv* env, const std::string& str, bool validOnZero
return !str.empty() || validOnZeroLength ? env->NewStringUTF(str.c_str()) : 0;
}
-#endif
-
jobjectArray intRectVectorToRectArray(JNIEnv* env, Vector<WebCore::IntRect>& rects)
{
jclass rectClass = env->FindClass("android/graphics/Rect");
diff --git a/Source/WebKit/android/jni/WebCoreJni.h b/Source/WebKit/android/jni/WebCoreJni.h
index 7a46f7b..25aa986 100644
--- a/Source/WebKit/android/jni/WebCoreJni.h
+++ b/Source/WebKit/android/jni/WebCoreJni.h
@@ -82,7 +82,6 @@ WTF::String jstringToWtfString(JNIEnv*, jstring);
// an empty WTF String returns 0.
jstring wtfStringToJstring(JNIEnv*, const WTF::String&, bool validOnZeroLength = false);
-#if USE(CHROME_NETWORK_STACK)
string16 jstringToString16(JNIEnv*, jstring);
std::string jstringToStdString(JNIEnv*, jstring);
@@ -90,7 +89,6 @@ std::string jstringToStdString(JNIEnv*, jstring);
// passing in an empty std::string will result in an empty jstring. Otherwise
// an empty std::string returns 0.
jstring stdStringToJstring(JNIEnv*, const std::string&, bool validOnZeroLength = false);
-#endif
jobjectArray intRectVectorToRectArray(JNIEnv*, Vector<WebCore::IntRect>&);
diff --git a/Source/WebKit/android/jni/WebCoreJniOnLoad.cpp b/Source/WebKit/android/jni/WebCoreJniOnLoad.cpp
index fb959ac..2644dab 100644
--- a/Source/WebKit/android/jni/WebCoreJniOnLoad.cpp
+++ b/Source/WebKit/android/jni/WebCoreJniOnLoad.cpp
@@ -62,8 +62,6 @@
#include "WebCoreViewBridge.h"
#include "WebFrameView.h"
#include "WebViewCore.h"
-#include "benchmark/Intercept.h"
-#include "benchmark/MyJavaVM.h"
#include <JNIUtility.h>
#include <jni.h>
@@ -75,7 +73,6 @@ namespace android {
extern int registerWebFrame(JNIEnv*);
extern int registerJavaBridge(JNIEnv*);
-extern int registerJniUtil(JNIEnv*);
extern int registerResourceLoader(JNIEnv*);
extern int registerWebViewCore(JNIEnv*);
extern int registerWebHistory(JNIEnv*);
@@ -94,9 +91,7 @@ extern int registerMediaPlayerVideo(JNIEnv*);
#endif
extern int registerDeviceMotionAndOrientationManager(JNIEnv*);
extern int registerCookieManager(JNIEnv*);
-#if USE(CHROME_NETWORK_STACK)
extern int registerCacheManager(JNIEnv*);
-#endif
}
@@ -107,9 +102,7 @@ struct RegistrationMethod {
static RegistrationMethod gWebCoreRegMethods[] = {
{ "JavaBridge", android::registerJavaBridge },
- { "JniUtil", android::registerJniUtil },
{ "WebFrame", android::registerWebFrame },
- { "WebCoreResourceLoader", android::registerResourceLoader },
{ "WebViewCore", android::registerWebViewCore },
{ "WebHistory", android::registerWebHistory },
{ "WebIconDatabase", android::registerWebIconDatabase },
@@ -127,9 +120,7 @@ static RegistrationMethod gWebCoreRegMethods[] = {
#endif
{ "DeviceMotionAndOrientationManager", android::registerDeviceMotionAndOrientationManager },
{ "CookieManager", android::registerCookieManager },
-#if USE(CHROME_NETWORK_STACK)
{ "CacheManager", android::registerCacheManager },
-#endif
};
EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
@@ -162,160 +153,3 @@ EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
return JNI_VERSION_1_4;
}
-
-class MyJavaSharedClient : public TimerClient, public CookieClient {
-public:
- MyJavaSharedClient() : m_hasTimer(false) {}
- virtual void setSharedTimer(long long timemillis) { m_hasTimer = true; }
- virtual void stopSharedTimer() { m_hasTimer = false; }
- virtual void setSharedTimerCallback(void (*f)()) { m_func = f; }
- virtual void signalServiceFuncPtrQueue() {}
-
- // Cookie methods that do nothing.
- virtual void setCookies(const KURL&, const String&) {}
- virtual String cookies(const KURL&) { return ""; }
- virtual bool cookiesEnabled() { return false; }
-
- bool m_hasTimer;
- void (*m_func)();
-};
-
-static void historyItemChanged(HistoryItem* i) {
- if (i->bridge())
- i->bridge()->updateHistoryItem(i);
-}
-
-namespace android {
-
-EXPORT void benchmark(const char* url, int reloadCount, int width, int height) {
- ScriptController::initializeThreading();
-
- // Setting this allows data: urls to load from a local file.
- SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll);
-
- // Create the fake JNIEnv and JavaVM
- InitializeJavaVM();
-
- // The real function is private to libwebcore but we know what it does.
- notifyHistoryItemChanged = historyItemChanged;
-
- // Implement the shared timer callback
- MyJavaSharedClient client;
- JavaSharedClient::SetTimerClient(&client);
- JavaSharedClient::SetCookieClient(&client);
-
- // Create the page with all the various clients
- ChromeClientAndroid* chrome = new ChromeClientAndroid;
- EditorClientAndroid* editor = new EditorClientAndroid;
- DeviceMotionClientAndroid* deviceMotion = new DeviceMotionClientAndroid;
- DeviceOrientationClientAndroid* deviceOrientation = new DeviceOrientationClientAndroid;
- WebCore::Page::PageClients pageClients;
- pageClients.chromeClient = chrome;
- pageClients.contextMenuClient = new ContextMenuClientAndroid;
- pageClients.editorClient = editor;
- pageClients.dragClient = new DragClientAndroid;
- pageClients.inspectorClient = new InspectorClientAndroid;
- pageClients.deviceMotionClient = deviceMotion;
- pageClients.deviceOrientationClient = deviceOrientation;
- WebCore::Page* page = new WebCore::Page(pageClients);
- editor->setPage(page);
-
- // Create MyWebFrame that intercepts network requests
- MyWebFrame* webFrame = new MyWebFrame(page);
- webFrame->setUserAgent("Performance testing"); // needs to be non-empty
- chrome->setWebFrame(webFrame);
- // ChromeClientAndroid maintains the reference.
- Release(webFrame);
-
- // Create the Frame and the FrameLoaderClient
- FrameLoaderClientAndroid* loader = new FrameLoaderClientAndroid(webFrame);
- RefPtr<Frame> frame = Frame::create(page, NULL, loader);
- loader->setFrame(frame.get());
-
- // Build our View system, resize it to the given dimensions and release our
- // references. Note: We keep a referenec to frameView so we can layout and
- // draw later without risk of it being deleted.
- WebViewCore* webViewCore = new WebViewCore(JSC::Bindings::getJNIEnv(),
- MY_JOBJECT, frame.get());
- RefPtr<FrameView> frameView = FrameView::create(frame.get());
- WebFrameView* webFrameView = new WebFrameView(frameView.get(), webViewCore);
- frame->setView(frameView);
- frameView->resize(width, height);
- Release(webViewCore);
- Release(webFrameView);
-
- // Initialize the frame and turn of low-bandwidth display (it fails an
- // assertion in the Cache code)
- frame->init();
- frame->selection()->setFocused(true);
- frame->page()->focusController()->setFocused(true);
-
- deviceMotion->setWebViewCore(webViewCore);
- deviceOrientation->setWebViewCore(webViewCore);
-
- // Set all the default settings the Browser normally uses.
- Settings* s = frame->settings();
-#ifdef ANDROID_LAYOUT
- s->setLayoutAlgorithm(Settings::kLayoutNormal); // Normal layout for now
-#endif
- s->setStandardFontFamily("sans-serif");
- s->setFixedFontFamily("monospace");
- s->setSansSerifFontFamily("sans-serif");
- s->setSerifFontFamily("serif");
- s->setCursiveFontFamily("cursive");
- s->setFantasyFontFamily("fantasy");
- s->setMinimumFontSize(8);
- s->setMinimumLogicalFontSize(8);
- s->setDefaultFontSize(16);
- s->setDefaultFixedFontSize(13);
- s->setLoadsImagesAutomatically(true);
- s->setJavaScriptEnabled(true);
- s->setDefaultTextEncodingName("latin1");
- s->setPluginsEnabled(false);
- s->setShrinksStandaloneImagesToFit(false);
-#ifdef ANDROID_LAYOUT
- s->setUseWideViewport(false);
-#endif
-
- // Finally, load the actual data
- ResourceRequest req(url);
- frame->loader()->load(req, false);
-
- do {
- // Layout the page and service the timer
- frame->view()->layout();
- while (client.m_hasTimer) {
- client.m_func();
- JavaSharedClient::ServiceFunctionPtrQueue();
- }
- JavaSharedClient::ServiceFunctionPtrQueue();
-
- // Layout more if needed.
- while (frame->view()->needsLayout())
- frame->view()->layout();
- JavaSharedClient::ServiceFunctionPtrQueue();
-
- if (reloadCount)
- frame->loader()->reload(true);
- } while (reloadCount--);
-
- // Draw into an offscreen bitmap
- SkBitmap bmp;
- bmp.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- bmp.allocPixels();
- SkCanvas canvas(bmp);
- PlatformGraphicsContext ctx(&canvas);
- GraphicsContext gc(&ctx);
- frame->view()->paintContents(&gc, IntRect(0, 0, width, height));
-
- // Write the bitmap to the sdcard
- SkImageEncoder* enc = SkImageEncoder::Create(SkImageEncoder::kPNG_Type);
- enc->encodeFile("/sdcard/webcore_test.png", bmp, 100);
- delete enc;
-
- // Tear down the world.
- frame->loader()->detachFromParent();
- delete page;
-}
-
-} // namespace android
diff --git a/Source/WebKit/android/jni/WebCoreResourceLoader.cpp b/Source/WebKit/android/jni/WebCoreResourceLoader.cpp
deleted file mode 100644
index f0861ff..0000000
--- a/Source/WebKit/android/jni/WebCoreResourceLoader.cpp
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright 2006, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "webcoreglue"
-
-#include "config.h"
-#include "WebCoreResourceLoader.h"
-
-#include "ResourceError.h"
-#include "ResourceHandle.h"
-#include "ResourceHandleClient.h"
-#include "ResourceHandleInternal.h"
-#include "ResourceResponse.h"
-#include "SkUtils.h"
-#include "WebCoreJni.h"
-
-#include <JNIHelp.h>
-#include <JNIUtility.h>
-#include <SkTypes.h>
-#include <stdlib.h>
-#include <utils/misc.h>
-#include <wtf/Platform.h>
-#include <wtf/text/CString.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-static struct resourceloader_t {
- jfieldID mObject;
- jmethodID mCancelMethodID;
- jmethodID mDownloadFileMethodID;
- jmethodID mWillLoadFromCacheMethodID;
- jmethodID mPauseLoadMethodID;
-} gResourceLoader;
-
-// ----------------------------------------------------------------------------
-
-#define GET_NATIVE_HANDLE(env, obj) ((WebCore::ResourceHandle*)env->GetIntField(obj, gResourceLoader.mObject))
-#define SET_NATIVE_HANDLE(env, obj, handle) (env->SetIntField(obj, gResourceLoader.mObject, handle))
-
-//-----------------------------------------------------------------------------
-// ResourceLoadHandler
-
-PassRefPtr<WebCore::ResourceLoaderAndroid> WebCoreResourceLoader::create(JNIEnv *env, jobject jLoadListener)
-{
- return adoptRef<WebCore::ResourceLoaderAndroid>(new WebCoreResourceLoader(env, jLoadListener));
-}
-
-WebCoreResourceLoader::WebCoreResourceLoader(JNIEnv *env, jobject jLoadListener)
- : mPausedLoad(false)
-{
- mJLoader = env->NewGlobalRef(jLoadListener);
-}
-
-WebCoreResourceLoader::~WebCoreResourceLoader()
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- SET_NATIVE_HANDLE(env, mJLoader, 0);
- env->DeleteGlobalRef(mJLoader);
- mJLoader = 0;
-}
-
-void WebCoreResourceLoader::cancel()
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(mJLoader, gResourceLoader.mCancelMethodID);
- checkException(env);
-}
-
-void WebCoreResourceLoader::downloadFile()
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(mJLoader, gResourceLoader.mDownloadFileMethodID);
- checkException(env);
-}
-
-void WebCoreResourceLoader::pauseLoad(bool pause)
-{
- if (mPausedLoad == pause)
- return;
-
- mPausedLoad = pause;
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(mJLoader, gResourceLoader.mPauseLoadMethodID, pause);
- checkException(env);
-}
-
-/*
-* This static method is called to check to see if a POST response is in
-* the cache. This may be slow, but is only used during a navigation to
-* a POST response.
-*/
-bool WebCoreResourceLoader::willLoadFromCache(const WebCore::KURL& url, int64_t identifier)
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- WTF::String urlStr = url.string();
- jstring jUrlStr = wtfStringToJstring(env, urlStr);
- jclass resourceLoader = env->FindClass("android/webkit/LoadListener");
- bool val = env->CallStaticBooleanMethod(resourceLoader, gResourceLoader.mWillLoadFromCacheMethodID, jUrlStr, identifier);
- checkException(env);
- env->DeleteLocalRef(resourceLoader);
- env->DeleteLocalRef(jUrlStr);
-
- return val;
-}
-
-// ----------------------------------------------------------------------------
-void WebCoreResourceLoader::SetResponseHeader(JNIEnv* env, jobject obj, jint nativeResponse, jstring key, jstring val)
-{
- WebCore::ResourceResponse* response = (WebCore::ResourceResponse*)nativeResponse;
- ALOG_ASSERT(response, "nativeSetResponseHeader must take a valid response pointer!");
-
- ALOG_ASSERT(key, "How did a null value become a key?");
- if (val)
- response->setHTTPHeaderField(jstringToWtfString(env, key), jstringToWtfString(env, val));
-}
-
-jint WebCoreResourceLoader::CreateResponse(JNIEnv* env, jobject obj, jstring url, jint statusCode,
- jstring statusText, jstring mimeType, jlong expectedLength,
- jstring encoding)
-{
- ALOG_ASSERT(url, "Must have a url in the response!");
- WebCore::KURL kurl(WebCore::ParsedURLString, jstringToWtfString(env, url));
- WTF::String encodingStr;
- WTF::String mimeTypeStr;
- if (mimeType) {
- mimeTypeStr = jstringToWtfString(env, mimeType);
- ALOGV("Response setMIMEType: %s", mimeTypeStr.latin1().data());
- }
- if (encoding) {
- encodingStr = jstringToWtfString(env, encoding);
- ALOGV("Response setTextEncodingName: %s", encodingStr.latin1().data());
- }
- WebCore::ResourceResponse* response = new WebCore::ResourceResponse(
- kurl, mimeTypeStr, (long long)expectedLength,
- encodingStr, WTF::String());
- response->setHTTPStatusCode(statusCode);
- if (statusText) {
- WTF::String status = jstringToWtfString(env, statusText);
- response->setHTTPStatusText(status);
- ALOGV("Response setStatusText: %s", status.latin1().data());
- }
- return (int)response;
-}
-
-void WebCoreResourceLoader::ReceivedResponse(JNIEnv* env, jobject obj, jint nativeResponse)
-{
- WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
- ALOG_ASSERT(handle, "nativeReceivedResponse must take a valid handle!");
- // ResourceLoader::didFail() can set handle to be NULL, we need to check
- if (!handle)
- return;
-
- WebCore::ResourceResponse* response = (WebCore::ResourceResponse*)nativeResponse;
- ALOG_ASSERT(response, "nativeReceivedResponse must take a valid resource pointer!");
- handle->client()->didReceiveResponse(handle, *response);
- // As the client makes a copy of the response, delete it here.
- delete response;
-}
-
-void WebCoreResourceLoader::AddData(JNIEnv* env, jobject obj, jbyteArray dataArray, jint length)
-{
- ALOGV("webcore_resourceloader data(%d)", length);
-
- WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
- ALOG_ASSERT(handle, "nativeAddData must take a valid handle!");
- // ResourceLoader::didFail() can set handle to be NULL, we need to check
- if (!handle)
- return;
-
- SkAutoMemoryUsageProbe mup("android_webcore_resourceloader_nativeAddData");
-
- bool result = false;
- jbyte * data = env->GetByteArrayElements(dataArray, NULL);
-
- ALOG_ASSERT(handle->client(), "Why do we not have a client?");
- handle->client()->didReceiveData(handle, (const char *)data, length, length);
- env->ReleaseByteArrayElements(dataArray, data, JNI_ABORT);
-}
-
-void WebCoreResourceLoader::Finished(JNIEnv* env, jobject obj)
-{
- ALOGV("webcore_resourceloader finished");
- WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
- ALOG_ASSERT(handle, "nativeFinished must take a valid handle!");
- // ResourceLoader::didFail() can set handle to be NULL, we need to check
- if (!handle)
- return;
-
- ALOG_ASSERT(handle->client(), "Why do we not have a client?");
- handle->client()->didFinishLoading(handle, 0);
-}
-
-jstring WebCoreResourceLoader::RedirectedToUrl(JNIEnv* env, jobject obj,
- jstring baseUrl, jstring redirectTo, jint nativeResponse)
-{
- ALOGV("webcore_resourceloader redirectedToUrl");
- WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
- ALOG_ASSERT(handle, "nativeRedirectedToUrl must take a valid handle!");
- // ResourceLoader::didFail() can set handle to be NULL, we need to check
- if (!handle)
- return NULL;
-
- ALOG_ASSERT(handle->client(), "Why do we not have a client?");
- WebCore::ResourceRequest r = handle->firstRequest();
- WebCore::KURL url(WebCore::KURL(WebCore::ParsedURLString, jstringToWtfString(env, baseUrl)),
- jstringToWtfString(env, redirectTo));
- WebCore::ResourceResponse* response = (WebCore::ResourceResponse*)nativeResponse;
- // If the url fails to resolve the relative path, return null.
- if (url.protocol().isEmpty()) {
- delete response;
- return NULL;
- } else {
- // Ensure the protocol is lowercase.
- url.setProtocol(url.protocol().lower());
- }
- // Set the url after updating the protocol.
- r.setURL(url);
- if (r.httpMethod() == "POST") {
- r.setHTTPMethod("GET");
- r.clearHTTPReferrer();
- r.setHTTPBody(0);
- r.setHTTPContentType("");
- }
- handle->client()->willSendRequest(handle, r, *response);
- delete response;
- return wtfStringToJstring(env, url.string());
-}
-
-void WebCoreResourceLoader::Error(JNIEnv* env, jobject obj, jint id, jstring description,
- jstring failingUrl)
-{
- ALOGV("webcore_resourceloader error");
- WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
- ALOG_ASSERT(handle, "nativeError must take a valid handle!");
- // ResourceLoader::didFail() can set handle to be NULL, we need to check
- if (!handle)
- return;
-
- handle->client()->didFail(handle, WebCore::ResourceError("", id,
- jstringToWtfString(env, failingUrl), jstringToWtfString(env, description)));
-}
-
-// ----------------------------------------------------------------------------
-
-/*
- * JNI registration.
- */
-static JNINativeMethod gResourceloaderMethods[] = {
- /* name, signature, funcPtr */
- { "nativeSetResponseHeader", "(ILjava/lang/String;Ljava/lang/String;)V",
- (void*) WebCoreResourceLoader::SetResponseHeader },
- { "nativeCreateResponse", "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;JLjava/lang/String;)I",
- (void*) WebCoreResourceLoader::CreateResponse },
- { "nativeReceivedResponse", "(I)V",
- (void*) WebCoreResourceLoader::ReceivedResponse },
- { "nativeAddData", "([BI)V",
- (void*) WebCoreResourceLoader::AddData },
- { "nativeFinished", "()V",
- (void*) WebCoreResourceLoader::Finished },
- { "nativeRedirectedToUrl", "(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;",
- (void*) WebCoreResourceLoader::RedirectedToUrl },
- { "nativeError", "(ILjava/lang/String;Ljava/lang/String;)V",
- (void*) WebCoreResourceLoader::Error }
-};
-
-int registerResourceLoader(JNIEnv* env)
-{
- jclass resourceLoader = env->FindClass("android/webkit/LoadListener");
- LOG_FATAL_IF(resourceLoader == NULL,
- "Unable to find class android/webkit/LoadListener");
-
- gResourceLoader.mObject =
- env->GetFieldID(resourceLoader, "mNativeLoader", "I");
- LOG_FATAL_IF(gResourceLoader.mObject == NULL,
- "Unable to find android/webkit/LoadListener.mNativeLoader");
-
- gResourceLoader.mCancelMethodID =
- env->GetMethodID(resourceLoader, "cancel", "()V");
- LOG_FATAL_IF(gResourceLoader.mCancelMethodID == NULL,
- "Could not find method cancel on LoadListener");
-
- gResourceLoader.mDownloadFileMethodID =
- env->GetMethodID(resourceLoader, "downloadFile", "()V");
- LOG_FATAL_IF(gResourceLoader.mDownloadFileMethodID == NULL,
- "Could not find method downloadFile on LoadListener");
-
- gResourceLoader.mPauseLoadMethodID =
- env->GetMethodID(resourceLoader, "pauseLoad", "(Z)V");
- LOG_FATAL_IF(gResourceLoader.mPauseLoadMethodID == NULL,
- "Could not find method pauseLoad on LoadListener");
-
- gResourceLoader.mWillLoadFromCacheMethodID =
- env->GetStaticMethodID(resourceLoader, "willLoadFromCache", "(Ljava/lang/String;J)Z");
- LOG_FATAL_IF(gResourceLoader.mWillLoadFromCacheMethodID == NULL,
- "Could not find static method willLoadFromCache on LoadListener");
-
- env->DeleteLocalRef(resourceLoader);
-
- return jniRegisterNativeMethods(env, "android/webkit/LoadListener",
- gResourceloaderMethods, NELEM(gResourceloaderMethods));
-}
-
-} /* namespace android */
diff --git a/Source/WebKit/android/jni/WebCoreResourceLoader.h b/Source/WebKit/android/jni/WebCoreResourceLoader.h
deleted file mode 100644
index 0e34a5b..0000000
--- a/Source/WebKit/android/jni/WebCoreResourceLoader.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2006, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef WebCoreResourceLoader_h
-#define WebCoreResourceLoader_h
-
-#include <KURL.h>
-#include <ResourceLoaderAndroid.h>
-#include <jni.h>
-
-namespace android {
-
-class WebCoreResourceLoader : public WebCore::ResourceLoaderAndroid
-{
-public:
- static PassRefPtr<WebCore::ResourceLoaderAndroid> create(JNIEnv *env, jobject jLoadListener);
- virtual ~WebCoreResourceLoader();
-
- /**
- * Call to java to cancel the current load.
- */
- virtual void cancel();
-
- /**
- * Call to java to download the current load rather than feed it
- * back to WebCore
- */
- virtual void downloadFile();
-
- virtual void pauseLoad(bool);
-
- /**
- * Call to java to find out if this URL is in the cache
- */
- static bool willLoadFromCache(const WebCore::KURL& url, int64_t identifier);
-
- // Native jni functions
- static void SetResponseHeader(JNIEnv*, jobject, jint, jstring, jstring);
- static jint CreateResponse(JNIEnv*, jobject, jstring, jint, jstring,
- jstring, jlong, jstring);
- static void ReceivedResponse(JNIEnv*, jobject, jint);
- static void AddData(JNIEnv*, jobject, jbyteArray, jint);
- static void Finished(JNIEnv*, jobject);
- static jstring RedirectedToUrl(JNIEnv*, jobject, jstring, jstring, jint);
- static void Error(JNIEnv*, jobject, jint, jstring, jstring);
-
-protected:
- WebCoreResourceLoader(JNIEnv *env, jobject jLoadListener);
-private:
- jobject mJLoader;
- bool mPausedLoad;
-};
-
-} // end namespace android
-
-#endif
diff --git a/Source/WebKit/android/jni/WebSettings.cpp b/Source/WebKit/android/jni/WebSettings.cpp
index 450b5c7..281e8ed 100644
--- a/Source/WebKit/android/jni/WebSettings.cpp
+++ b/Source/WebKit/android/jni/WebSettings.cpp
@@ -49,9 +49,7 @@
#include "Settings.h"
#include "WebCoreFrameBridge.h"
#include "WebCoreJni.h"
-#if USE(V8)
#include "WorkerContextExecutionProxy.h"
-#endif
#include "WebRequestContext.h"
#include "WebViewCore.h"
@@ -146,9 +144,7 @@ struct FieldIds {
mAutoFillProfilePhoneNumber = env->GetFieldID(autoFillProfileClass, "mPhoneNumber", "Ljava/lang/String;");
env->DeleteLocalRef(autoFillProfileClass);
#endif
-#if USE(CHROME_NETWORK_STACK)
mOverrideCacheMode = env->GetFieldID(clazz, "mOverrideCacheMode", "I");
-#endif
ALOG_ASSERT(mLayoutAlgorithm, "Could not find field mLayoutAlgorithm");
ALOG_ASSERT(mTextSize, "Could not find field mTextSize");
@@ -267,9 +263,7 @@ struct FieldIds {
jfieldID mAutoFillProfileCountry;
jfieldID mAutoFillProfilePhoneNumber;
#endif
-#if USE(CHROME_NETWORK_STACK)
jfieldID mOverrideCacheMode;
-#endif
};
static struct FieldIds* gFieldIds;
@@ -369,7 +363,6 @@ public:
str = (jstring)env->GetObjectField(obj, gFieldIds->mUserAgent);
WebFrame::getWebFrame(pFrame)->setUserAgent(jstringToWtfString(env, str));
-#if USE(CHROME_NETWORK_STACK)
WebViewCore::getWebViewCore(pFrame->view())->setWebRequestContextUserAgent();
jint cacheMode = env->GetIntField(obj, gFieldIds->mOverrideCacheMode);
@@ -377,7 +370,6 @@ public:
str = (jstring)env->GetObjectField(obj, gFieldIds->mAcceptLanguage);
WebRequestContext::setAcceptLanguage(jstringToWtfString(env, str));
-#endif
jint size = env->GetIntField(obj, gFieldIds->mMinimumFontSize);
s->setMinimumFontSize(size);
@@ -591,6 +583,9 @@ public:
// This is required to enable the XMLTreeViewer when loading an XML document that
// has no style attached to it. http://trac.webkit.org/changeset/79799
s->setDeveloperExtrasEnabled(true);
+#if !ENABLE(ANDROID_NAVCACHE)
+ s->setSpatialNavigationEnabled(true);
+#endif
}
};
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index dab5ed5..08ad3b6 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -44,6 +44,7 @@
#include "CSSValueKeywords.h"
#include "DatabaseTracker.h"
#include "Document.h"
+#include "DocumentMarkerController.h"
#include "DOMWindow.h"
#include "DOMSelection.h"
#include "Element.h"
@@ -79,6 +80,7 @@
#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "InlineTextBox.h"
+#include "KeyboardEvent.h"
#include "MemoryUsage.h"
#include "NamedNodeMap.h"
#include "Navigator.h"
@@ -104,6 +106,7 @@
#include "ResourceRequest.h"
#include "RuntimeEnabledFeatures.h"
#include "SchemeRegistry.h"
+#include "ScriptController.h"
#include "SelectionController.h"
#include "SelectText.h"
#include "Settings.h"
@@ -129,15 +132,12 @@
#include <JNIHelp.h>
#include <JNIUtility.h>
-#include <ui/KeycodeLabels.h>
+#include <androidfw/KeycodeLabels.h>
+#include <v8.h>
#include <wtf/CurrentTime.h>
#include <wtf/text/AtomicString.h>
-#include <wtf/text/StringImpl.h>
-
-#if USE(V8)
-#include "ScriptController.h"
#include <wtf/text/CString.h>
-#endif
+#include <wtf/text/StringImpl.h>
#if DEBUG_NAV_UI
#include "SkTime.h"
@@ -161,10 +161,6 @@ FILE* gRenderTreeFile = 0;
#include "RenderLayerCompositor.h"
#endif
-#if USE(V8)
-#include <v8.h>
-#endif
-
// In some cases, too many invalidations passed to the UI will slow us down.
// Limit ourselves to 32 rectangles, past this just send the area bounds to the UI.
// see WebViewCore::recordPictureSet().
@@ -292,6 +288,7 @@ struct WebViewCore::JavaGlue {
jmethodID m_getDeviceOrientationService;
jmethodID m_addMessageToConsole;
jmethodID m_formDidBlur;
+ jmethodID m_focusNodeChanged;
jmethodID m_getPluginClass;
jmethodID m_showFullScreenPlugin;
jmethodID m_hideFullScreenPlugin;
@@ -301,7 +298,6 @@ struct WebViewCore::JavaGlue {
jmethodID m_destroySurface;
jmethodID m_getContext;
jmethodID m_keepScreenOn;
- jmethodID m_sendFindAgain;
jmethodID m_showRect;
jmethodID m_centerFitRect;
jmethodID m_setScrollbarModes;
@@ -311,6 +307,7 @@ struct WebViewCore::JavaGlue {
jmethodID m_setWebTextViewAutoFillable;
jmethodID m_selectAt;
jmethodID m_initEditField;
+ jmethodID m_updateMatchCount;
AutoJObject object(JNIEnv* env) {
// We hold a weak reference to the Java WebViewCore to avoid memeory
// leaks due to circular references when WebView.destroy() is not
@@ -378,8 +375,10 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
, m_groupForVisitedLinks(0)
, m_isPaused(false)
, m_cacheMode(0)
- , m_shouldPaintCaret(true)
, m_fullscreenVideoMode(false)
+ , m_matchCount(0)
+ , m_activeMatchIndex(0)
+ , m_activeMatch(0)
, m_pluginInvalTimer(this, &WebViewCore::pluginInvalTimerFired)
, m_screenOnCounter(0)
, m_currentNodeDomNavigationAxis(0)
@@ -387,9 +386,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
#if ENABLE(TOUCH_EVENTS)
, m_forwardingTouchEvents(false)
#endif
-#if USE(CHROME_NETWORK_STACK)
, m_webRequestContext(0)
-#endif
{
ALOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!");
@@ -425,6 +422,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_getDeviceOrientationService = GetJMethod(env, clazz, "getDeviceOrientationService", "()Landroid/webkit/DeviceOrientationService;");
m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;I)V");
m_javaGlue->m_formDidBlur = GetJMethod(env, clazz, "formDidBlur", "(I)V");
+ m_javaGlue->m_focusNodeChanged = GetJMethod(env, clazz, "focusNodeChanged", "(Landroid/webkit/WebViewCore$WebKitHitTest;)V");
m_javaGlue->m_getPluginClass = GetJMethod(env, clazz, "getPluginClass", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;");
m_javaGlue->m_showFullScreenPlugin = GetJMethod(env, clazz, "showFullScreenPlugin", "(Landroid/webkit/ViewManager$ChildView;II)V");
m_javaGlue->m_hideFullScreenPlugin = GetJMethod(env, clazz, "hideFullScreenPlugin", "()V");
@@ -434,7 +432,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/webkit/ViewManager$ChildView;)V");
m_javaGlue->m_getContext = GetJMethod(env, clazz, "getContext", "()Landroid/content/Context;");
m_javaGlue->m_keepScreenOn = GetJMethod(env, clazz, "keepScreenOn", "(Z)V");
- m_javaGlue->m_sendFindAgain = GetJMethod(env, clazz, "sendFindAgain", "()V");
m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V");
m_javaGlue->m_centerFitRect = GetJMethod(env, clazz, "centerFitRect", "(IIII)V");
m_javaGlue->m_setScrollbarModes = GetJMethod(env, clazz, "setScrollbarModes", "(II)V");
@@ -445,7 +442,8 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
#endif
m_javaGlue->m_setWebTextViewAutoFillable = GetJMethod(env, clazz, "setWebTextViewAutoFillable", "(ILjava/lang/String;)V");
m_javaGlue->m_selectAt = GetJMethod(env, clazz, "selectAt", "(II)V");
- m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(ILjava/lang/String;II)V");
+ m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(ILjava/lang/String;IZZLjava/lang/String;III)V");
+ m_javaGlue->m_updateMatchCount = GetJMethod(env, clazz, "updateMatchCount", "(IILjava/lang/String;)V");
env->DeleteLocalRef(clazz);
env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
@@ -460,16 +458,12 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
WebViewCore::addInstance(this);
-#if USE(CHROME_NETWORK_STACK)
AndroidNetworkLibraryImpl::InitWithApplicationContext(env, 0);
-#endif
-#if USE(V8)
// Static initialisation of certain important V8 static data gets performed at system startup when
// libwebcore gets loaded. We now need to associate the WebCore thread with V8 to complete
// initialisation.
v8::V8::Initialize();
-#endif
// Configure any RuntimeEnabled features that we need to change from their default now.
// See WebCore/bindings/generic/RuntimeEnabledFeatures.h
@@ -541,7 +535,7 @@ CacheBuilder& WebViewCore::cacheBuilder()
WebCore::Node* WebViewCore::currentFocus()
{
- return m_mainFrame->document()->focusedNode();
+ return focusedFrame()->document()->focusedNode();
}
void WebViewCore::recordPicture(SkPicture* picture)
@@ -755,15 +749,6 @@ void WebViewCore::recordPictureSet(PictureSet* content)
DBG_NAV_LOG("call updateFrameCache");
updateFrameCache();
#endif
- if (m_findIsUp) {
- ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- AutoJObject javaObject = m_javaGlue->object(env);
- if (javaObject.get()) {
- env->CallVoidMethod(javaObject.get(), m_javaGlue->m_sendFindAgain);
- checkException(env);
- }
- }
}
// note: updateCursorBounds is called directly by the WebView thread
@@ -1637,7 +1622,7 @@ static IntRect getAbsoluteBoundingBox(Node* node) {
rect = toRenderText(render)->linesBoundingBox();
else
ALOGE("getAbsoluteBoundingBox failed for node %p, name %s", node, render->renderName());
- FloatPoint absPos = render->localToAbsolute();
+ FloatPoint absPos = render->localToAbsolute(FloatPoint(), false, true);
rect.move(absPos.x(), absPos.y());
return rect;
}
@@ -1768,7 +1753,8 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
{
// We need to agressively check to see if this is an empty selection to prevent
// accidentally entering text selection mode
- if (!selection.isRange() || !comparePositions(selection.start(), selection.end()))
+ bool isCaret = selection.isCaret();
+ if (selection.isNone() || (!selection.isContentEditable() && isCaret))
return 0;
RefPtr<Range> range = selection.firstRange();
@@ -1777,7 +1763,8 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
if (!startContainer || !endContainer)
return 0;
- if (startContainer == endContainer && range->startOffset() == range->endOffset())
+ if (!isCaret && startContainer == endContainer
+ && range->startOffset() == range->endOffset())
return 0;
SelectText* selectTextContainer = new SelectText();
@@ -1785,35 +1772,56 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
IntRect startHandle;
IntRect endHandle;
- Node* stopNode = range->pastLastNode();
- for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) {
- RenderObject* r = node->renderer();
- if (!r || !r->isText() || r->style()->visibility() != VISIBLE)
- continue;
- RenderText* renderText = toRenderText(r);
- int startOffset = node == startContainer ? range->startOffset() : 0;
- int endOffset = node == endContainer ? range->endOffset() : numeric_limits<int>::max();
+ if (isCaret) {
+ // Caret selection
+ Position start = selection.start();
+ Node* node = start.anchorNode();
LayerAndroid* layer = 0;
int layerId = platformLayerIdFromNode(node, &layer);
- Vector<IntRect> rects;
- renderText->absoluteRectsForRange(rects, startOffset, endOffset, true);
- if (rects.size()) {
- IntPoint offset;
- layerToAbsoluteOffset(layer, offset);
- endHandle = rects[rects.size() - 1];
- endHandle.move(-offset.x(), -offset.y());
- selectTextContainer->setCaretLayerId(SelectText::EndHandle, layerId);
- if (startHandle.isEmpty()) {
- startHandle = rects[0];
- startHandle.move(-offset.x(), -offset.y());
- selectTextContainer->setCaretLayerId(SelectText::StartHandle, layerId);
+ selectTextContainer->setCaretLayerId(SelectText::EndHandle, layerId);
+ selectTextContainer->setCaretLayerId(SelectText::StartHandle, layerId);
+ IntPoint layerOffset;
+ layerToAbsoluteOffset(layer, layerOffset);
+ RenderObject* r = node->renderer();
+ RenderText* renderText = toRenderText(r);
+ int caretOffset;
+ InlineBox* inlineBox;
+ start.getInlineBoxAndOffset(DOWNSTREAM, inlineBox, caretOffset);
+ startHandle = renderText->localCaretRect(inlineBox, caretOffset);
+ FloatPoint absoluteOffset = renderText->localToAbsolute(startHandle.location());
+ startHandle.setX(absoluteOffset.x() - layerOffset.x());
+ startHandle.setY(absoluteOffset.y() - layerOffset.y());
+ endHandle = startHandle;
+ } else {
+ // Selected range
+ Node* stopNode = range->pastLastNode();
+ for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) {
+ RenderObject* r = node->renderer();
+ if (!r || !r->isText() || r->style()->visibility() != VISIBLE)
+ continue;
+ RenderText* renderText = toRenderText(r);
+ int startOffset = node == startContainer ? range->startOffset() : 0;
+ int endOffset = node == endContainer ? range->endOffset() : numeric_limits<int>::max();
+ LayerAndroid* layer = 0;
+ int layerId = platformLayerIdFromNode(node, &layer);
+ Vector<IntRect> rects;
+ renderText->absoluteRectsForRange(rects, startOffset, endOffset, true);
+ if (rects.size()) {
+ IntPoint offset;
+ layerToAbsoluteOffset(layer, offset);
+ endHandle = rects[rects.size() - 1];
+ endHandle.move(-offset.x(), -offset.y());
+ selectTextContainer->setCaretLayerId(SelectText::EndHandle, layerId);
+ if (startHandle.isEmpty()) {
+ startHandle = rects[0];
+ startHandle.move(-offset.x(), -offset.y());
+ selectTextContainer->setCaretLayerId(SelectText::StartHandle, layerId);
+ }
}
+ selectTextContainer->addHighlightRegion(layer, rects, frameOffset);
}
- selectTextContainer->addHighlightRegion(layer, rects, frameOffset);
}
- IntRect caretRect;
- int layerId;
selectTextContainer->setBaseFirst(selection.isBaseFirst());
// Squish the handle rects
@@ -1846,7 +1854,7 @@ void WebViewCore::selectText(int startX, int startY, int endX, int endY)
IntPoint endPoint = convertGlobalContentToFrameContent(IntPoint(endX, endY));
VisiblePosition endPosition(visiblePositionForContentPoint(endPoint));
- if (startPosition.isNull() || endPosition.isNull() || startPosition == endPosition)
+ if (startPosition.isNull() || endPosition.isNull())
return;
// Ensure startPosition is before endPosition
@@ -1875,7 +1883,9 @@ void WebViewCore::selectText(int startX, int startY, int endX, int endY)
}
VisibleSelection selection(startPosition, endPosition);
- if (selection.isRange() && sc->shouldChangeSelection(selection))
+ // Only allow changes between caret positions or to text selection.
+ bool selectChangeAllowed = (!selection.isCaret() || sc->isCaret());
+ if (selectChangeAllowed && sc->shouldChangeSelection(selection))
sc->setSelection(selection);
}
@@ -2004,6 +2014,7 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do
}
}
if (!nodeDataList.size()) {
+ androidHitResult.searchContentDetectors();
return androidHitResult;
}
// finally select the node with the largest overlap with the fat point
@@ -2017,7 +2028,7 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do
IntRect rect = n->mBounds;
rect.intersect(testRect);
int a = rect.width() * rect.height();
- if (a > area) {
+ if (a > area || !final.mUrlNode) {
final = *n;
area = a;
}
@@ -2026,9 +2037,9 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do
if (final.mUrlNode) {
if (final.mUrlNode->isElementNode()) {
// We found a URL element. Update the hitTestResult
- androidHitResult.hitTestResult().setURLElement(static_cast<Element*>(final.mUrlNode));
+ androidHitResult.setURLElement(static_cast<Element*>(final.mUrlNode));
} else {
- androidHitResult.hitTestResult().setURLElement(0);
+ androidHitResult.setURLElement(0);
}
// Update innerNode and innerNonSharedNode
androidHitResult.hitTestResult().setInnerNode(final.mInnerNode);
@@ -2038,81 +2049,8 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do
frameAdjust = frame->view()->contentsToWindow(IntPoint());
frameAdjust.move(m_scrollOffsetX, m_scrollOffsetY);
}
- Vector<IntRect>& rects = androidHitResult.highlightRects();
- if (final.mUrlNode->isLink() && final.mUrlNode->renderer()) {
- // most of the links are inline instead of box style. So the bounding box is not
- // a good representation for the highlights. Get the list of rectangles instead.
- RenderObject* render = final.mUrlNode->renderer();
- IntPoint offset = roundedIntPoint(render->localToAbsolute());
- render->absoluteRects(rects, offset.x() + frameAdjust.x(), offset.y() + frameAdjust.y());
- if (final.mInnerNode && final.mInnerNode->renderer()) {
- final.mInnerNode->renderer()->absoluteRects(rects,
- offset.x() + frameAdjust.x(), offset.y() + frameAdjust.y());
- }
- bool inside = false;
- int distance = INT_MAX;
- int newx = x, newy = y;
- int i = rects.size();
- while (i--) {
- if (rects[i].isEmpty()) {
- rects.remove(i);
- continue;
- }
- // check whether the point (x, y) is inside one of the rectangles.
- if (inside)
- continue;
- if (rects[i].contains(x, y)) {
- inside = true;
- continue;
- }
- if (x >= rects[i].x() && x < rects[i].maxX()) {
- if (y < rects[i].y()) {
- if (rects[i].y() - y < distance) {
- newx = x;
- newy = rects[i].y();
- distance = rects[i].y() - y;
- }
- } else if (y >= rects[i].maxY()) {
- if (y - rects[i].maxY() + 1 < distance) {
- newx = x;
- newy = rects[i].maxY() - 1;
- distance = y - rects[i].maxY() + 1;
- }
- }
- } else if (y >= rects[i].y() && y < rects[i].maxY()) {
- if (x < rects[i].x()) {
- if (rects[i].x() - x < distance) {
- newx = rects[i].x();
- newy = y;
- distance = rects[i].x() - x;
- }
- } else if (x >= rects[i].maxX()) {
- if (x - rects[i].maxX() + 1 < distance) {
- newx = rects[i].maxX() - 1;
- newy = y;
- distance = x - rects[i].maxX() + 1;
- }
- }
- }
- }
- if (!rects.isEmpty()) {
- if (!inside && doMoveMouse) {
- // if neither x nor y has overlap, just pick the top/left of the first rectangle
- if (newx == x && newy == y) {
- newx = rects[0].x();
- newy = rects[0].y();
- }
- moveMouse(m_mainFrame, newx, newy);
- DBG_NAV_LOGD("Move x/y from (%d, %d) to (%d, %d) scrollOffset is (%d, %d)",
- x, y, m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY,
- m_scrollOffsetX, m_scrollOffsetY);
- }
- return androidHitResult;
- }
- }
IntRect rect = final.mBounds;
rect.move(frameAdjust.x(), frameAdjust.y());
- rects.append(rect);
if (doMoveMouse) {
// adjust m_mousePos if it is not inside the returned highlight rectangle
testRect.move(frameAdjust.x(), frameAdjust.y());
@@ -2124,6 +2062,8 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do
m_scrollOffsetX, m_scrollOffsetY);
}
}
+ } else {
+ androidHitResult.searchContentDetectors();
}
return androidHitResult;
}
@@ -3117,7 +3057,6 @@ void WebViewCore::deleteSelection(int start, int end, int textGeneration)
key(up);
client->setUiGeneratedSelectionChange(false);
m_textGeneration = textGeneration;
- m_shouldPaintCaret = true;
}
void WebViewCore::replaceTextfieldText(int oldStart,
@@ -3142,7 +3081,6 @@ void WebViewCore::replaceTextfieldText(int oldStart,
// setSelection calls revealSelection, so there is no need to do it here.
setSelection(start, end);
m_textGeneration = textGeneration;
- m_shouldPaintCaret = true;
}
void WebViewCore::passToJs(int generation, const WTF::String& current,
@@ -3174,7 +3112,6 @@ void WebViewCore::passToJs(int generation, const WTF::String& current,
}
// Now that the selection has settled down, send it.
updateTextSelection();
- m_shouldPaintCaret = true;
}
void WebViewCore::scrollFocusedTextInput(float xPercent, int y)
@@ -3323,8 +3260,6 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event)
{
WebCore::EventHandler* eventHandler;
WebCore::Node* focusNode = currentFocus();
- DBG_NAV_LOGD("keyCode=%s unichar=%d focusNode=%p",
- event.keyIdentifier().utf8().data(), event.unichar(), focusNode);
if (focusNode) {
WebCore::Frame* frame = focusNode->document()->frame();
WebFrame* webFrame = WebFrame::getWebFrame(frame);
@@ -3344,7 +3279,7 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event)
}
return handled;
} else {
- eventHandler = m_mainFrame->eventHandler();
+ eventHandler = focusedFrame()->eventHandler();
}
return eventHandler->keyEvent(event);
}
@@ -3594,6 +3529,46 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node
return handled;
}
+WebViewCore::InputType WebViewCore::getInputType(Node* node)
+{
+ WebCore::RenderObject* renderer = node->renderer();
+ if (!renderer)
+ return WebViewCore::NONE;
+ if (renderer->isTextArea())
+ return WebViewCore::TEXT_AREA;
+
+ if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
+ HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
+ if (htmlInput->isPasswordField())
+ return WebViewCore::PASSWORD;
+ if (htmlInput->isSearchField())
+ return WebViewCore::SEARCH;
+ if (htmlInput->isEmailField())
+ return WebViewCore::EMAIL;
+ if (htmlInput->isNumberField())
+ return WebViewCore::NUMBER;
+ if (htmlInput->isTelephoneField())
+ return WebViewCore::TELEPHONE;
+ if (htmlInput->isTextField())
+ return WebViewCore::NORMAL_TEXT_FIELD;
+ }
+
+ if (node->isContentEditable())
+ return WebViewCore::TEXT_AREA;
+
+ return WebViewCore::NONE;
+}
+
+bool WebViewCore::isSpellCheckEnabled(Node* node)
+{
+ bool isEnabled = true;
+ if (node->isElementNode()) {
+ WebCore::Element* element = static_cast<WebCore::Element*>(node);
+ isEnabled = element->isSpellCheckingEnabled();
+ }
+ return isEnabled;
+}
+
void WebViewCore::initEditField(Node* node)
{
String text = getInputText(node);
@@ -3605,9 +3580,22 @@ void WebViewCore::initEditField(Node* node)
if (!javaObject.get())
return;
m_textGeneration = 0;
+ InputType inputType = getInputType(node);
+ Document* document = node->document();
+ PlatformKeyboardEvent tab(AKEYCODE_TAB, 0, 0, false, false, false, false);
+ PassRefPtr<KeyboardEvent> tabEvent =
+ KeyboardEvent::create(tab, document->defaultView());
+ Node* nextFocus = document->nextFocusableNode(node, tabEvent.get());
+ bool isNextText = isTextInput(nextFocus);
+ bool spellCheckEnabled = isSpellCheckEnabled(node);
+ String label = requestLabel(document->frame(), node);
jstring fieldText = wtfStringToJstring(env, text, true);
+ jstring labelText = wtfStringToJstring(env, text, false);
+ SelectText* selectText = createSelectText(focusedFrame()->selection()->selection());
env->CallVoidMethod(javaObject.get(), m_javaGlue->m_initEditField,
- reinterpret_cast<int>(node), fieldText, start, end);
+ reinterpret_cast<int>(node), fieldText, inputType,
+ spellCheckEnabled, isNextText, labelText, start, end,
+ reinterpret_cast<int>(selectText));
checkException(env);
}
@@ -3638,19 +3626,65 @@ void WebViewCore::formDidBlur(const WebCore::Node* node)
m_blurringNodePointer = reinterpret_cast<int>(node);
}
-void WebViewCore::focusNodeChanged(const WebCore::Node* newFocus)
+// This is a slightly modified Node::nextNodeConsideringAtomicNodes() with the
+// extra constraint of limiting the search to inside a containing parent
+WebCore::Node* nextNodeWithinParent(WebCore::Node* parent, WebCore::Node* start)
{
- if (isTextInput(newFocus))
- m_shouldPaintCaret = true;
- else if (m_blurringNodePointer) {
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- AutoJObject javaObject = m_javaGlue->object(env);
- if (!javaObject.get())
- return;
+ if (!isAtomicNode(start) && start->firstChild())
+ return start->firstChild();
+ if (start->nextSibling())
+ return start->nextSibling();
+ const Node *n = start;
+ while (n && !n->nextSibling()) {
+ n = n->parentNode();
+ if (n == parent)
+ return 0;
+ }
+ if (n)
+ return n->nextSibling();
+ return 0;
+}
+
+void WebViewCore::focusNodeChanged(WebCore::Node* newFocus)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
+ return;
+ if (!isTextInput(newFocus) && m_blurringNodePointer) {
env->CallVoidMethod(javaObject.get(), m_javaGlue->m_formDidBlur, m_blurringNodePointer);
checkException(env);
m_blurringNodePointer = 0;
}
+ HitTestResult focusHitResult;
+ focusHitResult.setInnerNode(newFocus);
+ focusHitResult.setInnerNonSharedNode(newFocus);
+ if (newFocus && newFocus->isLink() && newFocus->isElementNode()) {
+ focusHitResult.setURLElement(static_cast<Element*>(newFocus));
+ if (newFocus->hasChildNodes() && !newFocus->hasTagName(HTMLNames::imgTag)) {
+ // Check to see if any of the children are images, and if so
+ // set them as the innerNode and innerNonSharedNode
+ // This will stop when it hits the first image. I'm not sure what
+ // should be done in the case of multiple images inside one anchor...
+ Node* nextNode = newFocus->firstChild();
+ bool found = false;
+ while (nextNode) {
+ if (nextNode->hasTagName(HTMLNames::imgTag)) {
+ found = true;
+ break;
+ }
+ nextNode = nextNodeWithinParent(newFocus, nextNode);
+ }
+ if (found) {
+ focusHitResult.setInnerNode(nextNode);
+ focusHitResult.setInnerNonSharedNode(nextNode);
+ }
+ }
+ }
+ AndroidHitTestResult androidHitTest(this, focusHitResult);
+ jobject jHitTestObj = androidHitTest.createJavaObject(env);
+ env->CallVoidMethod(javaObject.get(), m_javaGlue->m_focusNodeChanged, jHitTestObj);
+ env->DeleteLocalRef(jHitTestObj);
}
void WebViewCore::addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID, int msgLevel) {
@@ -3916,7 +3950,7 @@ void WebViewCore::updateTextSelection()
SelectText* selectText = createSelectText(focusedFrame()->selection()->selection());
env->CallVoidMethod(javaObject.get(),
m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(focusNode),
- start, end, m_textGeneration, selectText);
+ start, end, m_textGeneration, reinterpret_cast<int>(selectText));
checkException(env);
}
@@ -4197,7 +4231,6 @@ bool WebViewCore::drawIsPaused() const
return false;
}
-#if USE(CHROME_NETWORK_STACK)
void WebViewCore::setWebRequestContextUserAgent()
{
// We cannot create a WebRequestContext, because we might not know it this is a private tab or not yet
@@ -4225,7 +4258,6 @@ WebRequestContext* WebViewCore::webRequestContext()
}
return m_webRequestContext.get();
}
-#endif
void WebViewCore::scrollRenderLayer(int layer, const SkRect& rect)
{
@@ -4322,6 +4354,111 @@ void WebViewCore::insertText(const WTF::String &text)
client->setUiGeneratedSelectionChange(false);
}
+void WebViewCore::resetFindOnPage()
+{
+ m_searchText.truncate(0);
+ m_matchCount = 0;
+ m_activeMatchIndex = 0;
+ m_activeMatch = 0;
+}
+
+int WebViewCore::findTextOnPage(const WTF::String &text)
+{
+ resetFindOnPage(); // reset even if parameters are bad
+
+ WebCore::Frame* frame = m_mainFrame;
+ if (!frame)
+ return 0;
+
+ m_searchText = text;
+ FindOptions findOptions = WebCore::CaseInsensitive;
+
+ do {
+ frame->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
+ m_matchCount += frame->editor()->countMatchesForText(text, findOptions,
+ 0, true);
+ updateMatchCount();
+ frame->editor()->setMarkedTextMatchesAreHighlighted(true);
+ frame = frame->tree()->traverseNextWithWrap(false);
+ } while (frame);
+
+ m_activeMatchIndex = m_matchCount - 1; // prime first findNext
+ findNextOnPage(true);
+ return m_matchCount;
+}
+
+void WebViewCore::findNextOnPage(bool forward)
+{
+ if (!m_mainFrame)
+ return;
+ if (!m_matchCount)
+ return;
+
+ EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
+ m_mainFrame->editor()->client());
+ client->setUiGeneratedSelectionChange(true);
+
+ // Clear previous active match.
+ if (m_activeMatch) {
+ m_mainFrame->document()->markers()->setMarkersActive(
+ m_activeMatch.get(), false);
+ }
+
+ FindOptions findOptions = WebCore::CaseInsensitive
+ | WebCore::StartInSelection | WebCore::WrapAround;
+ if (!forward)
+ findOptions |= WebCore::Backwards;
+
+ // Start from the previous active match.
+ if (m_activeMatch) {
+ m_mainFrame->selection()->setSelection(m_activeMatch.get());
+ }
+
+ bool found = m_mainFrame->editor()->findString(m_searchText, findOptions);
+ if (found) {
+ VisibleSelection selection(m_mainFrame->selection()->selection());
+ if (selection.isNone() || selection.start() == selection.end()) {
+ // Temporary workaround for findString() refusing to select text
+ // marked "-webkit-user-select: none".
+ m_activeMatchIndex = 0;
+ m_activeMatch = 0;
+ } else {
+ // Mark current match "active".
+ if (forward) {
+ ++m_activeMatchIndex;
+ if (m_activeMatchIndex == m_matchCount)
+ m_activeMatchIndex = 0;
+ } else {
+ if (m_activeMatchIndex == 0)
+ m_activeMatchIndex = m_matchCount;
+ --m_activeMatchIndex;
+ }
+ m_activeMatch = selection.firstRange();
+ m_mainFrame->document()->markers()->setMarkersActive(
+ m_activeMatch.get(), true);
+ m_mainFrame->selection()->revealSelection(
+ ScrollAlignment::alignCenterIfNeeded, true);
+ }
+ updateMatchCount();
+ }
+
+ // Clear selection so it doesn't display.
+ m_mainFrame->selection()->clear();
+ client->setUiGeneratedSelectionChange(false);
+}
+
+void WebViewCore::updateMatchCount() const
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
+ return;
+ jstring javaText = wtfStringToJstring(env, m_searchText, true);
+ env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateMatchCount,
+ m_activeMatchIndex, m_matchCount, javaText);
+ checkException(env);
+}
+
String WebViewCore::getText(int startX, int startY, int endX, int endY)
{
String text;
@@ -4647,11 +4784,6 @@ static jstring RetrieveImageSource(JNIEnv* env, jobject obj, jint nativeClass,
return !result.isEmpty() ? wtfStringToJstring(env, result) : 0;
}
-static void StopPaintingCaret(JNIEnv* env, jobject obj, jint nativeClass)
-{
- reinterpret_cast<WebViewCore*>(nativeClass)->setShouldPaintCaret(false);
-}
-
static void MoveFocus(JNIEnv* env, jobject obj, jint nativeClass, jint framePtr,
jint nodePtr)
{
@@ -4762,11 +4894,9 @@ static void DumpNavTree(JNIEnv* env, jobject obj, jint nativeClass)
static void SetJsFlags(JNIEnv* env, jobject obj, jint nativeClass, jstring flags)
{
-#if USE(V8)
WTF::String flagsString = jstringToWtfString(env, flags);
WTF::CString utf8String = flagsString.utf8();
WebCore::ScriptController::setFlags(utf8String.data(), utf8String.length());
-#endif
}
@@ -4936,7 +5066,6 @@ static jobject HitTest(JNIEnv* env, jobject obj, jint nativeClass, jint x,
return 0;
Node* node = 0;
AndroidHitTestResult result = viewImpl->hitTestAtPoint(x, y, slop, doMoveMouse);
- Vector<IntRect>& rects = result.highlightRects();
return result.createJavaObject(env);
}
@@ -4959,9 +5088,15 @@ static void AutoFillForm(JNIEnv* env, jobject obj, jint nativeClass,
static void CloseIdleConnections(JNIEnv* env, jobject obj, jint nativeClass)
{
-#if USE(CHROME_NETWORK_STACK)
WebCache::get(true)->closeIdleConnections();
WebCache::get(false)->closeIdleConnections();
+}
+
+static void nativeCertTrustChanged(JNIEnv *env, jobject obj)
+{
+#if USE(CHROME_NETWORK_STACK)
+ WebCache::get(true)->certTrustChanged();
+ WebCache::get(false)->certTrustChanged();
#endif
}
@@ -5021,6 +5156,21 @@ static void SelectAll(JNIEnv* env, jobject obj, jint nativeClass)
viewImpl->focusedFrame()->selection()->selectAll();
}
+static int FindAll(JNIEnv* env, jobject obj, jint nativeClass,
+ jstring text)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ WTF::String wtfText = jstringToWtfString(env, text);
+ return viewImpl->findTextOnPage(wtfText);
+}
+
+static void FindNext(JNIEnv* env, jobject obj, jint nativeClass,
+ jboolean forward)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ viewImpl->findNextOnPage(forward);
+}
+
// ----------------------------------------------------------------------------
/*
@@ -5081,8 +5231,6 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) RetrieveAnchorText },
{ "nativeRetrieveImageSource", "(III)Ljava/lang/String;",
(void*) RetrieveImageSource },
- { "nativeStopPaintingCaret", "(I)V",
- (void*) StopPaintingCaret },
{ "nativeUpdateFrameCache", "(I)V",
(void*) UpdateFrameCache },
{ "nativeGetContentMinPrefWidth", "(I)I",
@@ -5151,6 +5299,12 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) SelectWordAt },
{ "nativeSelectAll", "(I)V",
(void*) SelectAll },
+ { "nativeCertTrustChanged","()V",
+ (void*) nativeCertTrustChanged },
+ { "nativeFindAll", "(ILjava/lang/String;)I",
+ (void*) FindAll },
+ { "nativeFindNext", "(IZ)V",
+ (void*) FindNext },
};
int registerWebViewCore(JNIEnv* env)
diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h
index 956ffed..38bde58 100644
--- a/Source/WebKit/android/jni/WebViewCore.h
+++ b/Source/WebKit/android/jni/WebViewCore.h
@@ -47,7 +47,7 @@
#include "VisiblePosition.h"
#include <jni.h>
-#include <ui/KeycodeLabels.h>
+#include <androidfw/KeycodeLabels.h>
#include <ui/PixelFormat.h>
namespace WebCore {
@@ -142,7 +142,7 @@ namespace android {
* @param Node The Node that blurred.
*/
void formDidBlur(const WebCore::Node*);
- void focusNodeChanged(const WebCore::Node*);
+ void focusNodeChanged(WebCore::Node*);
/**
* Scroll to an absolute position.
@@ -152,7 +152,7 @@ namespace android {
*
* This method calls Java to trigger a gradual scroll event.
*/
- void scrollTo(int x, int y, bool animate = false);
+ void scrollTo(int x, int y, bool animate = true);
/**
* Record the invalid rectangle
@@ -560,6 +560,12 @@ namespace android {
WTF::String getText(int startX, int startY, int endX, int endY);
void insertText(const WTF::String &text);
+ // find on page
+ void resetFindOnPage();
+ int findTextOnPage(const WTF::String &text);
+ void findNextOnPage(bool forward);
+ void updateMatchCount() const;
+
#if ENABLE(VIDEO)
void enterFullscreenForVideoLayer(int layerId, const WTF::String& url);
void exitFullscreenVideo();
@@ -572,19 +578,15 @@ namespace android {
void listBoxRequest(WebCoreReply* reply, const uint16_t** labels,
size_t count, const int enabled[], size_t enabledCount,
bool multiple, const int selected[], size_t selectedCountOrSelection);
- bool shouldPaintCaret() { return m_shouldPaintCaret; }
- void setShouldPaintCaret(bool should) { m_shouldPaintCaret = should; }
bool isPaused() const { return m_isPaused; }
void setIsPaused(bool isPaused) { m_isPaused = isPaused; }
bool drawIsPaused() const;
// 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);
WebRequestContext* webRequestContext();
-#endif
// Attempts to scroll the layer to the x,y coordinates of rect. The
// layer is the id of the LayerAndroid.
void scrollRenderLayer(int layer, const SkRect& rect);
@@ -637,6 +639,18 @@ namespace android {
// internal functions
private:
+ enum InputType {
+ NONE = -1,
+ NORMAL_TEXT_FIELD = 0,
+ TEXT_AREA = 1,
+ PASSWORD = 2,
+ SEARCH = 3,
+ EMAIL = 4,
+ NUMBER = 5,
+ TELEPHONE = 6,
+ URL = 7,
+ };
+
#ifndef DISABLE_NAVCACHE
CacheBuilder& cacheBuilder();
#endif
@@ -682,6 +696,19 @@ namespace android {
* current contents and selection.
*/
void initEditField(Node* node);
+
+ /**
+ * Gets the input type a Node. NONE is returned if it isn't an
+ * input field.
+ */
+ InputType getInputType(Node* node);
+
+ /**
+ * If node is an input field, the spellcheck value for the
+ * field is returned. Otherwise true is returned.
+ */
+ static bool isSpellCheckEnabled(Node* node);
+
/**
* Returns the offsets of the selection area for both normal text
* fields and content editable fields. start and end are modified
@@ -757,9 +784,14 @@ namespace android {
PageGroup* m_groupForVisitedLinks;
bool m_isPaused;
int m_cacheMode;
- bool m_shouldPaintCaret;
bool m_fullscreenVideoMode;
+ // find on page data
+ WTF::String m_searchText;
+ int m_matchCount;
+ int m_activeMatchIndex;
+ RefPtr<WebCore::Range> m_activeMatch;
+
SkTDArray<PluginWidgetAndroid*> m_plugins;
WebCore::Timer<WebViewCore> m_pluginInvalTimer;
void pluginInvalTimerFired(WebCore::Timer<WebViewCore>*) {
@@ -774,10 +806,7 @@ namespace android {
bool m_forwardingTouchEvents;
#endif
-#if USE(CHROME_NETWORK_STACK)
scoped_refptr<WebRequestContext> m_webRequestContext;
-#endif
-
};
} // namespace android
diff --git a/Source/WebKit/android/nav/FindCanvas.cpp b/Source/WebKit/android/nav/FindCanvas.cpp
deleted file mode 100644
index dca9a75..0000000
--- a/Source/WebKit/android/nav/FindCanvas.cpp
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- * Copyright 2008, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "webviewglue"
-
-#include "config.h"
-#include "FindCanvas.h"
-#include "LayerAndroid.h"
-#include "IntRect.h"
-#include "SelectText.h"
-#include "SkBlurMaskFilter.h"
-#include "SkCornerPathEffect.h"
-#include "SkRect.h"
-#include "SkUtils.h"
-
-#include <utils/Log.h>
-
-#define INTEGER_OUTSET 2
-
-namespace android {
-
-// MatchInfo methods
-////////////////////////////////////////////////////////////////////////////////
-
-MatchInfo::MatchInfo() {
- m_picture = 0;
-}
-
-MatchInfo::~MatchInfo() {
- SkSafeUnref(m_picture);
-}
-
-MatchInfo::MatchInfo(const MatchInfo& src) {
- m_layerId = src.m_layerId;
- m_location = src.m_location;
- m_picture = src.m_picture;
- SkSafeRef(m_picture);
-}
-
-void MatchInfo::set(const SkRegion& region, SkPicture* pic, int layerId) {
- SkSafeUnref(m_picture);
- m_layerId = layerId;
- m_location = region;
- m_picture = pic;
- SkASSERT(pic);
- pic->ref();
-}
-
-// GlyphSet methods
-////////////////////////////////////////////////////////////////////////////////
-
-GlyphSet::GlyphSet(const SkPaint& paint, const UChar* lower, const UChar* upper,
- size_t byteLength) {
- SkPaint clonePaint(paint);
- clonePaint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- mTypeface = paint.getTypeface();
- mCount = clonePaint.textToGlyphs(lower, byteLength, NULL);
- if (mCount > MAX_STORAGE_COUNT) {
- mLowerGlyphs = new uint16_t[2*mCount];
- } else {
- mLowerGlyphs = &mStorage[0];
- }
- // Use one array, and have mUpperGlyphs point to a portion of it,
- // so that we can reduce the number of new/deletes
- mUpperGlyphs = mLowerGlyphs + mCount;
- int count2 = clonePaint.textToGlyphs(lower, byteLength, mLowerGlyphs);
- SkASSERT(mCount == count2);
- count2 = clonePaint.textToGlyphs(upper, byteLength, mUpperGlyphs);
- SkASSERT(mCount == count2);
-}
-
-GlyphSet::~GlyphSet() {
- // Do not need to delete mTypeface, which is not owned by us.
- if (mCount > MAX_STORAGE_COUNT) {
- delete[] mLowerGlyphs;
- } // Otherwise, we just used local storage space, so no need to delete
- // Also do not need to delete mUpperGlyphs, which simply points to a
- // part of mLowerGlyphs
-}
-
-GlyphSet& GlyphSet::operator=(GlyphSet& src) {
- mTypeface = src.mTypeface;
- mCount = src.mCount;
- if (mCount > MAX_STORAGE_COUNT) {
- mLowerGlyphs = new uint16_t[2*mCount];
- } else {
- mLowerGlyphs = &mStorage[0];
- }
- memcpy(mLowerGlyphs, src.mLowerGlyphs, 2*mCount*sizeof(uint16_t));
- mUpperGlyphs = mLowerGlyphs + mCount;
- return *this;
-}
-
-bool GlyphSet::characterMatches(uint16_t c, int index) {
- SkASSERT(index < mCount && index >= 0);
- return c == mLowerGlyphs[index] || c == mUpperGlyphs[index];
-}
-
-// FindCanvas methods
-////////////////////////////////////////////////////////////////////////////////
-
-FindCanvas::FindCanvas(int width, int height, const UChar* lower,
- const UChar* upper, size_t byteLength)
- : mLowerText(lower)
- , mUpperText(upper)
- , mLength(byteLength)
- , mNumFound(0) {
- // the text has been provided in read order. Reverse as needed so the
- // result contains left-to-right characters.
- const uint16_t* start = mLowerText;
- size_t count = byteLength >> 1;
- const uint16_t* end = mLowerText + count;
- while (start < end) {
- SkUnichar ch = SkUTF16_NextUnichar(&start);
- WTF::Unicode::Direction charDirection = WTF::Unicode::direction(ch);
- if (WTF::Unicode::RightToLeftArabic == charDirection
- || WTF::Unicode::RightToLeft == charDirection) {
- mLowerReversed.clear();
- mLowerReversed.append(mLowerText, count);
- WebCore::ReverseBidi(mLowerReversed.begin(), count);
- mLowerText = mLowerReversed.begin();
- mUpperReversed.clear();
- mUpperReversed.append(mUpperText, count);
- WebCore::ReverseBidi(mUpperReversed.begin(), count);
- mUpperText = mUpperReversed.begin();
- break;
- }
- }
-
- setBounder(&mBounder);
- mOutset = -SkIntToScalar(INTEGER_OUTSET);
- mMatches = new WTF::Vector<MatchInfo>();
- mWorkingIndex = 0;
- mWorkingCanvas = 0;
- mWorkingPicture = 0;
-}
-
-FindCanvas::~FindCanvas() {
- setBounder(NULL);
- /* Just in case getAndClear was not called. */
- delete mMatches;
- SkSafeUnref(mWorkingPicture);
-}
-
-// Each version of addMatch returns a rectangle for a match.
-// Not all of the parameters are used by each version.
-SkRect FindCanvas::addMatchNormal(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar pos[], SkScalar y) {
- const uint16_t* lineStart = glyphs - index;
- /* Use the original paint, since "text" is in glyphs */
- SkScalar before = paint.measureText(lineStart, index * sizeof(uint16_t), 0);
- SkRect rect;
- rect.fLeft = pos[0] + before;
- int countInBytes = count * sizeof(uint16_t);
- rect.fRight = paint.measureText(glyphs, countInBytes, 0) + rect.fLeft;
- SkPaint::FontMetrics fontMetrics;
- paint.getFontMetrics(&fontMetrics);
- SkScalar baseline = y;
- rect.fTop = baseline + fontMetrics.fAscent;
- rect.fBottom = baseline + fontMetrics.fDescent;
- const SkMatrix& matrix = getTotalMatrix();
- matrix.mapRect(&rect);
- // Add the text to our picture.
- SkCanvas* canvas = getWorkingCanvas();
- int saveCount = canvas->save();
- canvas->concat(matrix);
- canvas->drawText(glyphs, countInBytes, pos[0] + before, y, paint);
- canvas->restoreToCount(saveCount);
- return rect;
-}
-
-SkRect FindCanvas::addMatchPos(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar xPos[], SkScalar /* y */) {
- SkRect r;
- r.setEmpty();
- const SkPoint* temp = reinterpret_cast<const SkPoint*> (xPos);
- const SkPoint* points = &temp[index];
- int countInBytes = count * sizeof(uint16_t);
- SkPaint::FontMetrics fontMetrics;
- paint.getFontMetrics(&fontMetrics);
- // Need to check each character individually, since the heights may be
- // different.
- for (int j = 0; j < count; j++) {
- SkRect bounds;
- bounds.fLeft = points[j].fX;
- bounds.fRight = bounds.fLeft +
- paint.measureText(&glyphs[j], sizeof(uint16_t), 0);
- SkScalar baseline = points[j].fY;
- bounds.fTop = baseline + fontMetrics.fAscent;
- bounds.fBottom = baseline + fontMetrics.fDescent;
- /* Accumulate and then add the resulting rect to mMatches */
- r.join(bounds);
- }
- SkMatrix matrix = getTotalMatrix();
- matrix.mapRect(&r);
- SkCanvas* canvas = getWorkingCanvas();
- int saveCount = canvas->save();
- canvas->concat(matrix);
- canvas->drawPosText(glyphs, countInBytes, points, paint);
- canvas->restoreToCount(saveCount);
- return r;
-}
-
-SkRect FindCanvas::addMatchPosH(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar position[], SkScalar constY) {
- SkRect r;
- // We only care about the positions starting at the index of our match
- const SkScalar* xPos = &position[index];
- // This assumes that the position array is monotonic increasing
- // The left bounds will be the position of the left most character
- r.fLeft = xPos[0];
- // The right bounds will be the position of the last character plus its
- // width
- int lastIndex = count - 1;
- r.fRight = paint.measureText(&glyphs[lastIndex], sizeof(uint16_t), 0)
- + xPos[lastIndex];
- // Grab font metrics to determine the top and bottom of the bounds
- SkPaint::FontMetrics fontMetrics;
- paint.getFontMetrics(&fontMetrics);
- r.fTop = constY + fontMetrics.fAscent;
- r.fBottom = constY + fontMetrics.fDescent;
- const SkMatrix& matrix = getTotalMatrix();
- matrix.mapRect(&r);
- SkCanvas* canvas = getWorkingCanvas();
- int saveCount = canvas->save();
- canvas->concat(matrix);
- canvas->drawPosTextH(glyphs, count * sizeof(uint16_t), xPos, constY, paint);
- canvas->restoreToCount(saveCount);
- return r;
-}
-
-void FindCanvas::drawLayers(LayerAndroid* layer, FindOnPage& findOnPage) {
-#if USE(ACCELERATED_COMPOSITING)
- int layerId = layer->uniqueId();
- unsigned matchesBegin = found();
- SkPicture* picture = layer->picture();
- if (picture) {
- setLayerId(layerId);
- drawPicture(*picture);
- }
- findOnPage.setLayerMatchRange(layerId,
- std::pair<unsigned, unsigned>(matchesBegin, found()));
- for (int i = 0; i < layer->countChildren(); i++)
- drawLayers(layer->getChild(i), findOnPage);
-#endif
-}
-
-void FindCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
- findHelper(text, byteLength, paint, &x, y, &FindCanvas::addMatchNormal);
-}
-
-void FindCanvas::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
- // Pass in the first y coordinate for y so that we can check to see whether
- // it is lower than the last draw call (to check if we are continuing to
- // another line).
- findHelper(text, byteLength, paint, (const SkScalar*) pos, pos[0].fY,
- &FindCanvas::addMatchPos);
-}
-
-void FindCanvas::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
- findHelper(text, byteLength, paint, xpos, constY,
- &FindCanvas::addMatchPosH);
-}
-
-/* The current behavior is to skip substring matches. This means that in the
- * string
- * batbatbat
- * a search for
- * batbat
- * will return 1 match. If the desired behavior is to return 2 matches, define
- * INCLUDE_SUBSTRING_MATCHES to be 1.
- */
-#define INCLUDE_SUBSTRING_MATCHES 0
-
-// Need a quick way to know a maximum distance between drawText calls to know if
-// they are part of the same logical phrase when searching. By crude
-// inspection, half the point size seems a good guess at the width of a space
-// character.
-static inline SkScalar approximateSpaceWidth(const SkPaint& paint) {
- return SkScalarHalf(paint.getTextSize());
-}
-
-void FindCanvas::findHelper(const void* text, size_t byteLength,
- const SkPaint& paint, const SkScalar positions[],
- SkScalar y,
- SkRect (FindCanvas::*addMatch)(int index,
- const SkPaint& paint, int count,
- const uint16_t* glyphs,
- const SkScalar positions[], SkScalar y)) {
- SkASSERT(paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
- SkASSERT(mMatches);
- GlyphSet* glyphSet = getGlyphs(paint);
- const int count = glyphSet->getCount();
- int numCharacters = byteLength >> 1;
- const uint16_t* chars = (const uint16_t*) text;
- // This block will check to see if we are continuing from another line. If
- // so, the user needs to have added a space, which we do not draw.
- if (mWorkingIndex) {
- SkPoint newY;
- getTotalMatrix().mapXY(0, y, &newY);
- SkIRect workingBounds = mWorkingRegion.getBounds();
- int newYInt = SkScalarRound(newY.fY);
- if (workingBounds.fTop > newYInt) {
- // The new text is above the working region, so we know it's not
- // a continuation.
- resetWorkingCanvas();
- mWorkingIndex = 0;
- mWorkingRegion.setEmpty();
- } else if (workingBounds.fBottom < newYInt) {
- // Now we know that this line is lower than our partial match.
- SkPaint clonePaint(paint);
- clonePaint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
- uint16_t space;
- clonePaint.textToGlyphs(" ", 1, &space);
- if (glyphSet->characterMatches(space, mWorkingIndex)) {
- mWorkingIndex++;
- if (mWorkingIndex == count) {
- // We already know that it is not clipped out because we
- // checked for that before saving the working region.
- insertMatchInfo(mWorkingRegion);
-
- resetWorkingCanvas();
- mWorkingIndex = 0;
- mWorkingRegion.setEmpty();
- // We have found a match, so continue on this line from
- // scratch.
- }
- } else {
- resetWorkingCanvas();
- mWorkingIndex = 0;
- mWorkingRegion.setEmpty();
- }
- }
- // If neither one is true, then we are likely continuing on the same
- // line, but are in a new draw call because the paint has changed. In
- // this case, we can continue without adding a space.
- }
- // j is the position in the search text
- // Start off with mWorkingIndex in case we are continuing from a prior call
- int j = mWorkingIndex;
- // index is the position in the drawn text
- int index = 0;
- for ( ; index != numCharacters; index++) {
- if (glyphSet->characterMatches(chars[index], j)) {
- // The jth character in the search text matches the indexth position
- // in the drawn text, so increase j.
- j++;
- if (j != count) {
- continue;
- }
- // The last count characters match, so we found the entire
- // search string.
- int remaining = count - mWorkingIndex;
- int matchIndex = index - remaining + 1;
- // Set up a pointer to the matching text in 'chars'.
- const uint16_t* glyphs = chars + matchIndex;
- SkRect rect = (this->*addMatch)(matchIndex, paint,
- remaining, glyphs, positions, y);
- // We need an SkIRect for SkRegion operations.
- SkIRect iRect;
- rect.roundOut(&iRect);
- // Want to outset the drawn rectangle by the same amount as
- // mOutset
- iRect.inset(-INTEGER_OUTSET, -INTEGER_OUTSET);
- SkRegion regionToAdd(iRect);
- if (!mWorkingRegion.isEmpty()) {
- // If this is on the same line as our working region, make
- // sure that they are close enough together that they are
- // supposed to be part of the same text string.
- // The width of two spaces has arbitrarily been chosen.
- const SkIRect& workingBounds = mWorkingRegion.getBounds();
- if (workingBounds.fTop <= iRect.fBottom &&
- workingBounds.fBottom >= iRect.fTop &&
- SkIntToScalar(iRect.fLeft - workingBounds.fRight) >
- approximateSpaceWidth(paint)) {
- index = -1; // Will increase to 0 on next run
- // In this case, we need to start from the beginning of
- // the text being searched and our search term.
- j = 0;
- mWorkingIndex = 0;
- mWorkingRegion.setEmpty();
- continue;
- }
- // Add the mWorkingRegion, which contains rectangles from
- // the previous line(s).
- regionToAdd.op(mWorkingRegion, SkRegion::kUnion_Op);
- }
- insertMatchInfo(regionToAdd);
-#if INCLUDE_SUBSTRING_MATCHES
- // Reset index to the location of the match and reset j to the
- // beginning, so that on the next iteration of the loop, index
- // will advance by 1 and we will compare the next character in
- // chars to the first character in the GlyphSet.
- index = matchIndex;
-#endif
- // Whether the clip contained it or not, we need to start over
- // with our recording canvas
- resetWorkingCanvas();
- } else {
- // Index needs to be set to index - j + 1.
- // This is a ridiculous case, but imagine the situation where the
- // user is looking for the string "jjog" in the drawText call for
- // "jjjog". The first two letters match. However, when the index
- // is 2, and we discover that 'o' and 'j' do not match, we should go
- // back to 1, where we do, in fact, have a match
- // FIXME: This does not work if (as in our example) "jj" is in one
- // draw call and "jog" is in the next. Doing so would require a
- // stack, keeping track of multiple possible working indeces and
- // regions. This is likely an uncommon case.
- index = index - j; // index will be increased by one on the next
- // iteration
- }
- // We reach here in one of two cases:
- // 1) We just completed a match, so any working rectangle/index is no
- // longer needed, and we will start over from the beginning
- // 2) The glyphs do not match, so we start over at the beginning of
- // the search string.
- j = 0;
- mWorkingIndex = 0;
- mWorkingRegion.setEmpty();
- }
- // At this point, we have searched all of the text in the current drawText
- // call.
- // Keep track of a partial match that may start on this line.
- if (j > 0) { // if j is greater than 0, we have a partial match
- int relativeCount = j - mWorkingIndex; // Number of characters in this
- // part of the match.
- int partialIndex = index - relativeCount; // Index that starts our
- // partial match.
- const uint16_t* partialGlyphs = chars + partialIndex;
- SkRect partial = (this->*addMatch)(partialIndex, paint, relativeCount,
- partialGlyphs, positions, y);
- partial.inset(mOutset, mOutset);
- SkIRect dest;
- partial.roundOut(&dest);
- mWorkingRegion.op(dest, SkRegion::kUnion_Op);
- mWorkingIndex = j;
- return;
- }
- // This string doesn't go into the next drawText, so reset our working
- // variables
- mWorkingRegion.setEmpty();
- mWorkingIndex = 0;
-}
-
-SkCanvas* FindCanvas::getWorkingCanvas() {
- if (!mWorkingPicture) {
- mWorkingPicture = new SkPicture;
- mWorkingCanvas = mWorkingPicture->beginRecording(0,0);
- }
- return mWorkingCanvas;
-}
-
-GlyphSet* FindCanvas::getGlyphs(const SkPaint& paint) {
- SkTypeface* typeface = paint.getTypeface();
- GlyphSet* end = mGlyphSets.end();
- for (GlyphSet* ptr = mGlyphSets.begin();ptr != end; ptr++) {
- if (ptr->getTypeface() == typeface) {
- return ptr;
- }
- }
-
- GlyphSet set(paint, mLowerText, mUpperText, mLength);
- *mGlyphSets.append() = set;
- return &(mGlyphSets.top());
-}
-
-void FindCanvas::insertMatchInfo(const SkRegion& region) {
- mNumFound++;
- mWorkingPicture->endRecording();
- MatchInfo matchInfo;
- mMatches->append(matchInfo);
- ALOGD("%s region=%p pict=%p layer=%d", __FUNCTION__,
- &region, mWorkingPicture, mLayerId);
- mMatches->last().set(region, mWorkingPicture, mLayerId);
-}
-
-void FindCanvas::resetWorkingCanvas() {
- mWorkingPicture->unref();
- mWorkingPicture = 0;
- // Do not need to reset mWorkingCanvas itself because we only access it via
- // getWorkingCanvas.
-}
-
-// This function sets up the paints that are used to draw the matches.
-void FindOnPage::setUpFindPaint() {
- // Set up the foreground paint
- m_findPaint.setAntiAlias(true);
- const SkScalar roundiness = SkIntToScalar(2);
- SkCornerPathEffect* cornerEffect = new SkCornerPathEffect(roundiness);
- m_findPaint.setPathEffect(cornerEffect);
- m_findPaint.setARGB(255, 132, 190, 0);
-
- // Set up the background blur paint.
- m_findBlurPaint.setAntiAlias(true);
- m_findBlurPaint.setARGB(204, 0, 0, 0);
- m_findBlurPaint.setPathEffect(cornerEffect);
- cornerEffect->unref();
- SkMaskFilter* blurFilter = SkBlurMaskFilter::Create(SK_Scalar1,
- SkBlurMaskFilter::kNormal_BlurStyle);
- m_findBlurPaint.setMaskFilter(blurFilter)->unref();
- m_isFindPaintSetUp = true;
-}
-
-IntRect FindOnPage::currentMatchBounds() const {
- IntRect noBounds = IntRect(0, 0, 0, 0);
- if (!m_matches || !m_matches->size())
- return noBounds;
- MatchInfo& info = (*m_matches)[m_findIndex];
- return info.getLocation().getBounds();
-}
-
-bool FindOnPage::currentMatchIsInLayer() const {
- if (!m_matches || !m_matches->size())
- return false;
- MatchInfo& info = (*m_matches)[m_findIndex];
- return info.isInLayer();
-}
-
-int FindOnPage::currentMatchLayerId() const {
- return (*m_matches)[m_findIndex].layerId();
-}
-
-// This function is only used by findNext and setMatches. In it, we store
-// upper left corner of the match specified by m_findIndex in
-// m_currentMatchLocation.
-void FindOnPage::storeCurrentMatchLocation() {
- SkASSERT(m_findIndex < m_matches->size());
- const SkIRect& bounds = (*m_matches)[m_findIndex].getLocation().getBounds();
- m_currentMatchLocation.set(bounds.fLeft, bounds.fTop);
- m_hasCurrentLocation = true;
-}
-
-// Put a cap on the number of matches to draw. If the current page has more
-// matches than this, only draw the focused match.
-#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101
-
-void FindOnPage::drawLegacy(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval) {
- if (!m_lastBounds.isEmpty()) {
- inval->unite(m_lastBounds);
- m_lastBounds.setEmpty();
- }
- if (!m_hasCurrentLocation || !m_matches || !m_matches->size())
- return;
- int layerId = layer ? layer->uniqueId() : -1;
- if (m_findIndex >= m_matches->size())
- m_findIndex = 0;
- const MatchInfo& matchInfo = (*m_matches)[m_findIndex];
- const SkRegion& currentMatchRegion = matchInfo.getLocation();
-
- // Set up the paints used for drawing the matches
- if (!m_isFindPaintSetUp)
- setUpFindPaint();
-
- // Draw the current match
- if (matchInfo.layerId() == layerId) {
- drawMatch(currentMatchRegion, canvas, true);
- // Now draw the picture, so that it shows up on top of the rectangle
- int saveCount = canvas->save();
- SkPath matchPath;
- currentMatchRegion.getBoundaryPath(&matchPath);
- canvas->clipPath(matchPath);
- canvas->drawPicture(*matchInfo.getPicture());
- canvas->restoreToCount(saveCount);
- const SkMatrix& matrix = canvas->getTotalMatrix();
- const SkRect& localBounds = matchPath.getBounds();
- SkRect globalBounds;
- matrix.mapRect(&globalBounds, localBounds);
- globalBounds.round(&m_lastBounds);
- inval->unite(m_lastBounds);
- }
- // Draw the rest
- unsigned numberOfMatches = m_matches->size();
- if (numberOfMatches > 1
- && numberOfMatches < MAX_NUMBER_OF_MATCHES_TO_DRAW) {
- for (unsigned i = 0; i < numberOfMatches; i++) {
- // The current match has already been drawn
- if (i == m_findIndex)
- continue;
- if ((*m_matches)[i].layerId() != layerId)
- continue;
- const SkRegion& region = (*m_matches)[i].getLocation();
- // Do not draw matches which intersect the current one, or if it is
- // offscreen
- if (currentMatchRegion.intersects(region))
- continue;
- SkRect bounds;
- bounds.set(region.getBounds());
- if (canvas->quickReject(bounds, SkCanvas::kAA_EdgeType))
- continue;
- drawMatch(region, canvas, false);
- }
- }
-}
-
-// Draw the match specified by region to the canvas.
-void FindOnPage::drawMatch(const SkRegion& region, SkCanvas* canvas,
- bool focused)
-{
- // For the match which has focus, use a filled paint. For the others, use
- // a stroked paint.
- if (focused) {
- m_findPaint.setStyle(SkPaint::kFill_Style);
- m_findBlurPaint.setStyle(SkPaint::kFill_Style);
- } else {
- m_findPaint.setStyle(SkPaint::kStroke_Style);
- m_findPaint.setStrokeWidth(SK_Scalar1);
- m_findBlurPaint.setStyle(SkPaint::kStroke_Style);
- m_findBlurPaint.setStrokeWidth(SkIntToScalar(2));
- }
- // Find the path for the current match
- SkPath matchPath;
- region.getBoundaryPath(&matchPath);
- // Offset the path for a blurred shadow
- SkPath blurPath;
- matchPath.offset(SK_Scalar1, SkIntToScalar(2), &blurPath);
- int saveCount = 0;
- if (!focused) {
- saveCount = canvas->save();
- canvas->clipPath(matchPath, SkRegion::kDifference_Op);
- }
- // Draw the blurred background
- canvas->drawPath(blurPath, m_findBlurPaint);
- if (!focused)
- canvas->restoreToCount(saveCount);
- // Draw the foreground
- canvas->drawPath(matchPath, m_findPaint);
-}
-
-void FindOnPage::findNext(bool forward)
-{
- if (!m_matches || !m_matches->size() || !m_hasCurrentLocation)
- return;
- if (forward) {
- m_findIndex++;
- if (m_findIndex == m_matches->size())
- m_findIndex = 0;
- } else {
- if (m_findIndex == 0) {
- m_findIndex = m_matches->size() - 1;
- } else {
- m_findIndex--;
- }
- }
- storeCurrentMatchLocation();
-}
-
-// With this call, WebView takes ownership of matches, and is responsible for
-// deleting it.
-void FindOnPage::setMatches(WTF::Vector<MatchInfo>* matches)
-{
- if (m_matches)
- delete m_matches;
- m_matches = matches;
- if (m_matches->size()) {
- if (m_hasCurrentLocation) {
- for (unsigned i = 0; i < m_matches->size(); i++) {
- const SkIRect& rect = (*m_matches)[i].getLocation().getBounds();
- if (rect.fLeft == m_currentMatchLocation.fX
- && rect.fTop == m_currentMatchLocation.fY) {
- m_findIndex = i;
- return;
- }
- }
- }
- // If we did not have a stored location, or if we were unable to restore
- // it, store the new one.
- m_findIndex = 0;
- storeCurrentMatchLocation();
- } else {
- m_hasCurrentLocation = false;
- }
-}
-
-std::pair<unsigned, unsigned> FindOnPage::getLayerMatchRange(int layerId) const
-{
- return m_layerMatchRangeMap.get(layerId);
-}
-
-void FindOnPage::setLayerMatchRange(int layerId,
- const std::pair<unsigned, unsigned> range)
-{
- m_layerMatchRangeMap.set(layerId, range);
-}
-
-}
diff --git a/Source/WebKit/android/nav/FindCanvas.h b/Source/WebKit/android/nav/FindCanvas.h
deleted file mode 100644
index 1d81f9a..0000000
--- a/Source/WebKit/android/nav/FindCanvas.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright 2008, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef Find_Canvas_h
-#define Find_Canvas_h
-
-#include "DrawExtra.h"
-#include "IntRect.h"
-#include "SkBounder.h"
-#include "SkCanvas.h"
-#include "SkPicture.h"
-#include "SkRect.h"
-#include "SkRegion.h"
-#include "SkTDArray.h"
-
-#include <unicode/umachine.h>
-#include <wtf/Vector.h>
-#include <wtf/HashMap.h>
-
-namespace android {
-class FindOnPage;
-
-// Stores both region information and an SkPicture of the match, so that the
-// region can be drawn, followed by drawing the matching text on top of it.
-// This class owns its SkPicture
-class MatchInfo {
-public:
- MatchInfo();
- ~MatchInfo();
- MatchInfo(const MatchInfo& src);
- const SkRegion& getLocation() const { return m_location; }
- // Return a pointer to our picture, representing the matching text. Does
- // not transfer ownership of the picture.
- SkPicture* getPicture() const { return m_picture; }
- // This will make a copy of the region, and increase the ref count on the
- // SkPicture. If this MatchInfo already had one, unref it.
- void set(const SkRegion& region, SkPicture* pic, int layerId);
- bool isInLayer() const { return m_layerId >= 0; }
- int layerId() const { return m_layerId; }
-private:
- MatchInfo& operator=(MatchInfo& src);
- SkRegion m_location;
- SkPicture* m_picture;
- int m_layerId;
-};
-
-// A class containing a typeface for reference, the length in glyphs, and
-// the upper and lower case representations of the search string.
-class GlyphSet {
-public:
- GlyphSet(const SkPaint& paint, const UChar* lower, const UChar* upper,
- size_t byteLength);
- ~GlyphSet();
- GlyphSet& operator=(GlyphSet& src);
-
- // Return true iff c matches one of our glyph arrays at index
- bool characterMatches(uint16_t c, int index);
-
- int getCount() const { return mCount; }
-
- const SkTypeface* getTypeface() const { return mTypeface; }
-
-private:
- // Disallow copy constructor
- GlyphSet(GlyphSet& src) { }
-
- // mTypeface is used for comparison only
- const SkTypeface* mTypeface;
- // mLowerGlyphs points to all of our storage space: the lower set followed
- // by the upper set. mUpperGlyphs is purely a convenience pointer to the
- // start of the upper case glyphs.
- uint16_t* mLowerGlyphs;
- uint16_t* mUpperGlyphs;
- // mCount is the number of glyphs of the search string. Must be the same
- // for both the lower case set and the upper case set.
- int mCount;
-
- // Arbitrarily chose the maximum storage to use in the GlyphSet. This is
- // based on the length of the word being searched. If users are always
- // searching for 3 letter words (for example), an ideal number would be 3.
- // Each time the user searches for a word longer than (in this case, 3) that
- // will result in calling new/delete.
- enum Storage {
- MAX_STORAGE_COUNT = 16
- };
- // In order to eliminate new/deletes, create storage that will be enough
- // most of the time
- uint16_t mStorage[2*MAX_STORAGE_COUNT];
-};
-
-class FindBounder : public SkBounder {
-public:
- FindBounder() {}
- ~FindBounder() {}
-protected:
- virtual bool onIRect(const SkIRect&) { return false; }
-};
-
-class FindCanvas : public SkCanvas {
-public:
- FindCanvas(int width, int height, const UChar* , const UChar*,
- size_t byteLength);
-
- virtual ~FindCanvas();
-
- virtual void drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint);
-
- /* FIXME: This path has not been tested. */
- virtual void drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint);
-
- /* Also untested */
- virtual void drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint);
-
- /* Not sure what to do here or for drawTextOnPathHV */
- virtual void drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
- }
-
- void drawLayers(LayerAndroid* rootLayer, FindOnPage& findOnPage);
- int found() const { return mNumFound; }
- void setLayerId(int layerId) { mLayerId = layerId; }
-
- // This method detaches our array of matches and passes ownership to
- // the caller, who is then responsible for deleting them.
- WTF::Vector<MatchInfo>* detachMatches() {
- WTF::Vector<MatchInfo>* array = mMatches;
- mMatches = NULL;
- return array;
- }
-
-private:
- // These calls are made by findHelper to store information about each match
- // that is found. They return a rectangle which is used to highlight the
- // match. They also add to our SkPicture (which can be accessed with
- // getDrawnMatches) a draw of each match. This way it can be drawn after
- // the rectangle. The rect that is returned is in device coordinates.
- SkRect addMatchNormal(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar pos[], SkScalar y);
-
- SkRect addMatchPos(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar xPos[], SkScalar /* y */);
-
- SkRect addMatchPosH(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar position[], SkScalar constY);
-
- // Helper for each of our draw calls
- void findHelper(const void* text, size_t byteLength, const SkPaint& paint,
- const SkScalar xPos[], SkScalar y,
- SkRect (FindCanvas::*addMatch)(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar pos[], SkScalar y));
-
- // If we already have a working canvas, grab it. Otherwise, create a new
- // one.
- SkCanvas* getWorkingCanvas();
-
- // Return the set of glyphs and its count for the text being searched for
- // and the parameter paint. If one has already been created and cached
- // for this paint, use it. If not, create a new one and cache it.
- GlyphSet* getGlyphs(const SkPaint& paint);
-
- // Store all the accumulated info about a match in our vector.
- void insertMatchInfo(const SkRegion& region);
-
- // Throw away our cumulative information about our working SkCanvas. After
- // this call, next call to getWorkingCanvas will create a new one.
- void resetWorkingCanvas();
-
- // Since we may transfer ownership of this array (see detachRects()), we
- // hold a pointer to the array instead of just the array itself.
- WTF::Vector<MatchInfo>* mMatches;
- const UChar* mLowerText;
- const UChar* mUpperText;
- Vector<UChar> mLowerReversed;
- Vector<UChar> mUpperReversed;
- size_t mLength;
- FindBounder mBounder;
- int mNumFound;
- SkScalar mOutset;
- SkTDArray<GlyphSet> mGlyphSets;
-
- SkPicture* mWorkingPicture;
- SkCanvas* mWorkingCanvas;
- SkRegion mWorkingRegion;
- int mWorkingIndex;
- int mLayerId;
-};
-
-class FindOnPage : public DrawExtra {
-public:
- FindOnPage() {
- m_matches = 0;
- m_hasCurrentLocation = false;
- m_isFindPaintSetUp = false;
- m_lastBounds.setEmpty();
- }
- virtual ~FindOnPage() { if (m_matches) delete m_matches; }
- void clearCurrentLocation() { m_hasCurrentLocation = false; }
- IntRect currentMatchBounds() const;
- int currentMatchIndex() const { return m_findIndex; }
- bool currentMatchIsInLayer() const;
- // This requires the current match to be in a layer. See
- // currentMatchIsInLayer().
- int currentMatchLayerId() const;
- virtual void drawLegacy(SkCanvas* , LayerAndroid* , IntRect* );
- void findNext(bool forward);
- bool isCurrentLocationValid() { return m_hasCurrentLocation; }
- void setMatches(WTF::Vector<MatchInfo>* matches);
- WTF::Vector<MatchInfo>* matches() { return m_matches; }
-
- // Some functions to determine which matches belong to which layers.
- std::pair<unsigned, unsigned> getLayerMatchRange(int layerId) const;
- void setLayerMatchRange(int layerId,
- const std::pair<unsigned, unsigned> range);
-
-private:
- void drawMatch(const SkRegion& region, SkCanvas* canvas, bool focused);
- void setUpFindPaint();
- void storeCurrentMatchLocation();
- WTF::Vector<MatchInfo>* m_matches;
- WTF::HashMap< int, std::pair<unsigned, unsigned> > m_layerMatchRangeMap;
- // Stores the location of the current match.
- SkIPoint m_currentMatchLocation;
- // Tells whether the value in m_currentMatchLocation is valid.
- bool m_hasCurrentLocation;
- // Tells whether we have done the setup to draw the Find matches.
- bool m_isFindPaintSetUp;
- // Paint used to draw our Find matches.
- SkPaint m_findPaint;
- // Paint used for the background of our Find matches.
- SkPaint m_findBlurPaint;
- unsigned m_findIndex;
- SkIRect m_lastBounds;
-};
-
-}
-
-#endif // Find_Canvas_h
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index 5d01e49..2bd76f5 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -34,7 +34,6 @@
#include "CachedNode.h"
#include "CachedRoot.h"
#include "DrawExtra.h"
-#include "FindCanvas.h"
#include "Frame.h"
#include "GraphicsJNI.h"
#include "HTMLInputElement.h"
@@ -68,7 +67,7 @@
#include <JNIUtility.h>
#include <JNIHelp.h>
#include <jni.h>
-#include <ui/KeycodeLabels.h>
+#include <androidfw/KeycodeLabels.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/CString.h>
@@ -107,12 +106,11 @@ enum FrameCachePermission {
AllowNewer
};
-#define DRAW_EXTRAS_SIZE 3
+#define DRAW_EXTRAS_SIZE 2
enum DrawExtras { // keep this in sync with WebView.java
DrawExtrasNone = 0,
- DrawExtrasFind = 1,
- DrawExtrasSelection = 2,
- DrawExtrasCursorRing = 3
+ DrawExtrasSelection = 1,
+ DrawExtrasCursorRing = 2
};
struct JavaGlue {
@@ -243,9 +241,6 @@ DrawExtra* getDrawExtraLegacy(DrawExtras extras)
DrawExtra* extra = getDrawExtra(extras);
if (!extra) {
switch (extras) {
- case DrawExtrasFind:
- extra = &m_findOnPage;
- break;
case DrawExtrasCursorRing:
if (drawCursorPreamble(root) && m_ring.setup()) {
if (m_ring.m_isPressed || m_ringAnimationEnd == UINT_MAX)
@@ -313,71 +308,6 @@ void debugDump()
}
#endif
-void scrollToCurrentMatch()
-{
- if (!m_findOnPage.currentMatchIsInLayer()) {
- scrollRectOnScreen(m_findOnPage.currentMatchBounds());
- return;
- }
-
- SkRect matchBounds = m_findOnPage.currentMatchBounds();
- LayerAndroid* rootLayer = compositeRoot();
- if (!rootLayer)
- return;
-
- Layer* layerContainingMatch = rootLayer->findById(m_findOnPage.currentMatchLayerId());
- if (!layerContainingMatch)
- return;
-
- // If the match is in a fixed position layer, there's nothing to do.
- if (layerContainingMatch->shouldInheritFromRootTransform())
- return;
-
- // If the match is in a scrollable layer or a descendant of such a layer,
- // there may be a range of of scroll configurations that will make the
- // current match visible. Our approach is the simplest possible. Starting at
- // the layer in which the match is found, we move up the layer tree,
- // scrolling any scrollable layers as little as possible to make sure that
- // the current match is in view. This approach has the disadvantage that we
- // may end up scrolling a larger number of elements than is necessary, which
- // may be visually jarring. However, minimising the number of layers
- // scrolled would complicate the code significantly.
-
- bool didScrollLayer = false;
- for (Layer* layer = layerContainingMatch; layer; layer = layer->getParent()) {
- ASSERT(layer->getParent() || layer == rootLayer);
-
- if (layer->contentIsScrollable()) {
- // Convert the match location to layer's local space and scroll it.
- // Repeatedly calling Layer::localToAncestor() is inefficient as
- // each call repeats part of the calculation. It would be more
- // efficient to maintain the transform here and update it on each
- // iteration, but that would mean duplicating logic from
- // Layer::localToAncestor() and would complicate things.
- SkMatrix transform;
- layerContainingMatch->localToAncestor(layer, &transform);
- SkRect transformedMatchBounds;
- transform.mapRect(&transformedMatchBounds, matchBounds);
- SkIRect roundedTransformedMatchBounds;
- transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
- // Only ScrollableLayerAndroid returns true for contentIsScrollable().
- didScrollLayer |= static_cast<ScrollableLayerAndroid*>(layer)->scrollRectIntoView(roundedTransformedMatchBounds);
- }
- }
- // Invalidate, as the call below to scroll the main page may be a no-op.
- if (didScrollLayer)
- viewInvalidate();
-
- // Convert matchBounds to the global space so we can scroll the main page.
- SkMatrix transform;
- layerContainingMatch->localToGlobal(&transform);
- SkRect transformedMatchBounds;
- transform.mapRect(&transformedMatchBounds, matchBounds);
- SkIRect roundedTransformedMatchBounds;
- transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
- scrollRectOnScreen(roundedTransformedMatchBounds);
-}
-
void scrollRectOnScreen(const IntRect& rect)
{
if (rect.isEmpty())
@@ -471,7 +401,6 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect,
TilesManager::instance()->setHighEndGfx(m_isHighEndGfx);
m_glWebViewState = new GLWebViewState();
m_glWebViewState->glExtras()->setCursorRingExtra(&m_ring);
- m_glWebViewState->glExtras()->setFindOnPageExtra(&m_findOnPage);
if (m_baseLayer->content()) {
SkRegion region;
SkIRect rect;
@@ -1083,12 +1012,6 @@ void setFindIsUp(bool up)
m_viewImpl->m_findIsUp = up;
}
-void setFindIsEmpty()
-{
- DBG_NAV_LOG("");
- m_findOnPage.clearCurrentLocation();
-}
-
void showCursorTimed()
{
DBG_NAV_LOG("");
@@ -1165,39 +1088,6 @@ void sendMotionUp(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y
checkException(env);
}
-void findNext(bool forward)
-{
- m_findOnPage.findNext(forward);
- scrollToCurrentMatch();
- viewInvalidate();
-}
-
-// With this call, WebView takes ownership of matches, and is responsible for
-// deleting it.
-void setMatches(WTF::Vector<MatchInfo>* matches, jboolean sameAsLastSearch)
-{
- // If this search is the same as the last one, check against the old
- // location to determine whether to scroll. If the same word is found
- // in the same place, then do not scroll.
- IntRect oldLocation;
- bool checkAgainstOldLocation = false;
- if (sameAsLastSearch && m_findOnPage.isCurrentLocationValid()) {
- oldLocation = m_findOnPage.currentMatchBounds();
- checkAgainstOldLocation = true;
- }
-
- m_findOnPage.setMatches(matches);
-
- if (!checkAgainstOldLocation || oldLocation != m_findOnPage.currentMatchBounds())
- scrollToCurrentMatch();
- viewInvalidate();
-}
-
-int currentMatchIndex()
-{
- return m_findOnPage.currentMatchIndex();
-}
-
bool scrollBy(int dx, int dy)
{
ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
@@ -1394,10 +1284,6 @@ void setVisibleRect(SkRect& visibleRect) {
m_visibleRect = visibleRect;
}
-FindOnPage& findOnPage() {
- return m_findOnPage;
-}
-
void setDrawExtra(DrawExtra *extra, DrawExtras type)
{
if (type == DrawExtrasNone)
@@ -1415,7 +1301,7 @@ void setTextSelection(SelectText *selection) {
int getHandleLayerId(SelectText::HandleId handleId, SkIRect& cursorRect) {
SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection));
- if (!selectText)
+ if (!selectText || !m_baseLayer)
return -1;
int layerId = selectText->caretLayerId(handleId);
IntRect rect = selectText->caretRect(handleId);
@@ -1442,7 +1328,6 @@ private: // local state for WebView
bool m_heightCanMeasure;
int m_lastDx;
SkMSec m_lastDxTime;
- FindOnPage m_findOnPage;
CursorRing m_ring;
DrawExtra* m_extras[DRAW_EXTRAS_SIZE];
BaseLayerAndroid* m_baseLayer;
@@ -1666,6 +1551,7 @@ static const CachedInput* getInputCandidate(JNIEnv *env, jobject obj)
static jboolean nativePageShouldHandleShiftAndArrows(JNIEnv *env, jobject obj)
{
+#if ENABLE(ANDROID_NAVCACHE)
const CachedNode* focus = getFocusNode(env, obj);
if (!focus) return false;
// Plugins handle shift and arrows whether or not they have focus.
@@ -1675,6 +1561,9 @@ static jboolean nativePageShouldHandleShiftAndArrows(JNIEnv *env, jobject obj)
// both the cursor and the focus.
return cursor && cursor->nodePointer() == focus->nodePointer()
&& cursor->isContentEditable();
+#else
+ return true;
+#endif
}
static jobject nativeCursorNodeBounds(JNIEnv *env, jobject obj)
@@ -2159,11 +2048,6 @@ static void nativeSetFindIsUp(JNIEnv *env, jobject obj, jboolean isUp)
view->setFindIsUp(isUp);
}
-static void nativeSetFindIsEmpty(JNIEnv *env, jobject obj)
-{
- GET_NATIVE_VIEW(env, obj)->setFindIsEmpty();
-}
-
static void nativeShowCursorTimed(JNIEnv *env, jobject obj)
{
GET_NATIVE_VIEW(env, obj)->showCursorTimed();
@@ -2192,88 +2076,6 @@ static jobject nativeGetCursorRingBounds(JNIEnv *env, jobject obj)
return rect;
}
-static int nativeFindAll(JNIEnv *env, jobject obj, jstring findLower,
- jstring findUpper, jboolean sameAsLastSearch)
-{
- // If one or the other is null, do not search.
- if (!(findLower && findUpper))
- return 0;
- // Obtain the characters for both the lower case string and the upper case
- // string representing the same word.
- const jchar* findLowerChars = env->GetStringChars(findLower, 0);
- const jchar* findUpperChars = env->GetStringChars(findUpper, 0);
- // If one or the other is null, do not search.
- if (!(findLowerChars && findUpperChars)) {
- if (findLowerChars)
- env->ReleaseStringChars(findLower, findLowerChars);
- if (findUpperChars)
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return 0;
- }
- WebView* view = GET_NATIVE_VIEW(env, obj);
- ALOG_ASSERT(view, "view not set in nativeFindAll");
- BaseLayerAndroid* baseLayer = view->getBaseLayer();
- android::PictureSet* pictureSet = baseLayer ? baseLayer->content() : 0;
- if (!pictureSet) {
- env->ReleaseStringChars(findLower, findLowerChars);
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return 0;
- }
- int length = env->GetStringLength(findLower);
- // If the lengths of the strings do not match, then they are not the same
- // word, so do not search.
- if (!length || env->GetStringLength(findUpper) != length) {
- env->ReleaseStringChars(findLower, findLowerChars);
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return 0;
- }
- int width = pictureSet->width();
- int height = pictureSet->height();
- // Create a FindCanvas, which allows us to fake draw into it so we can
- // figure out where our search string is rendered (and how many times).
- FindCanvas canvas(width, height, (const UChar*) findLowerChars,
- (const UChar*) findUpperChars, length << 1);
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- canvas.setBitmapDevice(bitmap);
- FindOnPage& findOnPage = view->findOnPage();
- canvas.setLayerId(-1);
- unsigned matchesBegin = canvas.found();
- baseLayer->drawCanvas(&canvas);
- findOnPage.setLayerMatchRange(-1,
- std::pair<unsigned, unsigned>(matchesBegin, canvas.found()));
-#if USE(ACCELERATED_COMPOSITING)
- LayerAndroid* compositeLayer = view->compositeRoot();
- if (compositeLayer)
- canvas.drawLayers(compositeLayer, findOnPage);
-#endif
- WTF::Vector<MatchInfo>* matches = canvas.detachMatches();
- // With setMatches, the WebView takes ownership of matches
- view->setMatches(matches, sameAsLastSearch);
-
- env->ReleaseStringChars(findLower, findLowerChars);
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return canvas.found();
-}
-
-static void nativeFindNext(JNIEnv *env, jobject obj, bool forward)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- ALOG_ASSERT(view, "view not set in nativeFindNext");
- view->findNext(forward);
-}
-
-static int nativeFindIndex(JNIEnv *env, jobject obj)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- ALOG_ASSERT(view, "view not set in nativeFindIndex");
- return view->currentMatchIndex();
-}
-
static void nativeUpdateCachedTextfield(JNIEnv *env, jobject obj, jstring updatedText, jint generation)
{
WebView* view = GET_NATIVE_VIEW(env, obj);
@@ -2673,12 +2475,6 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeDumpDisplayTree },
{ "nativeEvaluateLayersAnimations", "(I)Z",
(void*) nativeEvaluateLayersAnimations },
- { "nativeFindAll", "(Ljava/lang/String;Ljava/lang/String;Z)I",
- (void*) nativeFindAll },
- { "nativeFindNext", "(Z)V",
- (void*) nativeFindNext },
- { "nativeFindIndex", "()I",
- (void*) nativeFindIndex},
{ "nativeFocusCandidateFramePointer", "()I",
(void*) nativeFocusCandidateFramePointer },
{ "nativeFocusCandidateHasNextTextfield", "()Z",
@@ -2747,8 +2543,6 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeSelectBestAt },
{ "nativeSelectAt", "(II)V",
(void*) nativeSelectAt },
- { "nativeSetFindIsEmpty", "()V",
- (void*) nativeSetFindIsEmpty },
{ "nativeSetFindIsUp", "(Z)V",
(void*) nativeSetFindIsUp },
{ "nativeSetHeightCanMeasure", "(Z)V",
diff --git a/Source/WebKit/chromium/public/WebRange.h b/Source/WebKit/chromium/public/WebRange.h
index 89fc8f6..3da3d95 100644
--- a/Source/WebKit/chromium/public/WebRange.h
+++ b/Source/WebKit/chromium/public/WebRange.h
@@ -37,10 +37,10 @@
namespace WebCore { class Range; }
namespace WTF { template <typename T> class PassRefPtr; }
#endif
+namespace WebCore { class Node; }
namespace WebKit {
-class WebNode;
class WebRangePrivate;
class WebString;
@@ -64,8 +64,8 @@ public:
WEBKIT_API int startOffset() const;
WEBKIT_API int endOffset() const;
- WEBKIT_API WebNode startContainer(int& exceptionCode) const;
- WEBKIT_API WebNode endContainer(int& exceptionCode) const;
+ WEBKIT_API WebCore::Node* startContainer(int& exceptionCode) const;
+ WEBKIT_API WebCore::Node* endContainer(int& exceptionCode) const;
WEBKIT_API WebString toHTMLText() const;
WEBKIT_API WebString toPlainText() const;
diff --git a/Source/WebKit/chromium/public/android/WebDOMTextContentWalker.h b/Source/WebKit/chromium/public/android/WebDOMTextContentWalker.h
new file mode 100644
index 0000000..26ba589
--- /dev/null
+++ b/Source/WebKit/chromium/public/android/WebDOMTextContentWalker.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebDOMTextContentWalker_h
+#define WebDOMTextContentWalker_h
+
+#include "../WebPrivateOwnPtr.h"
+#include "../WebRange.h"
+#include "../WebString.h"
+
+namespace WebCore {
+class DOMTextContentWalker;
+class Node;
+}
+
+namespace WebKit {
+
+class WebHitTestInfo;
+
+class WebDOMTextContentWalker {
+public:
+ WebDOMTextContentWalker();
+ ~WebDOMTextContentWalker();
+
+ // Creates a new text content walker centered in the position described by the hit test.
+ // The maximum length of the contents retrieved by the walker is defined by maxLength.
+ WEBKIT_API WebDOMTextContentWalker(const WebHitTestInfo&, size_t maxLength);
+
+ // Creates a new text content walker centered in the selected offset of the given text node.
+ // The maximum length of the contents retrieved by the walker is defined by maxLength.
+ WEBKIT_API WebDOMTextContentWalker(WebCore::Node* textNode, size_t offset, size_t maxLength);
+
+ // Text content retrieved by the walker.
+ WEBKIT_API WebString content() const;
+
+ // Position of the initial text node offset in the content string.
+ WEBKIT_API size_t hitOffsetInContent() const;
+
+ // Convert start/end positions in the content text string into a WebKit text range.
+ WEBKIT_API WebRange contentOffsetsToRange(size_t startInContent, size_t endInContent);
+
+protected:
+ WebPrivateOwnPtr<WebCore::DOMTextContentWalker> m_private;
+};
+
+} // namespace WebKit
+
+#endif
diff --git a/Source/WebKit/chromium/public/android/WebHitTestInfo.h b/Source/WebKit/chromium/public/android/WebHitTestInfo.h
new file mode 100644
index 0000000..79b354e
--- /dev/null
+++ b/Source/WebKit/chromium/public/android/WebHitTestInfo.h
@@ -0,0 +1,76 @@
+/*
+* Copyright (C) 2011 Google Inc. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebHitTestInfo_h
+#define WebHitTestInfo_h
+
+#include "../WebPoint.h"
+#include "../WebPrivateOwnPtr.h"
+#include "../WebURL.h"
+
+namespace WebCore {
+class HitTestResult;
+class Node;
+}
+
+namespace WebKit {
+
+// Properties of a hit test result, i.e. properties of the nodes at a given point
+// (the hit point) on the page. Both urls may be populated at the same time, for
+// example in the instance of an <img> inside an <a>.
+class WebHitTestInfo {
+public:
+ WebHitTestInfo();
+ WebHitTestInfo(const WebHitTestInfo&);
+ ~WebHitTestInfo();
+
+ // The absolute URL of the link returned by the hit test.
+ WEBKIT_API WebURL linkURL() const;
+
+ // The absolute URL of the image returned by the hit test.
+ WEBKIT_API WebURL imageURL() const;
+
+ // The node that got hit.
+ WEBKIT_API WebCore::Node* node() const;
+
+ // Point coordinates of the hit.
+ WEBKIT_API WebPoint point() const;
+
+ // True iff the hit was on an editable field or node.
+ WEBKIT_API bool isContentEditable() const;
+
+#if WEBKIT_IMPLEMENTATION
+ WebHitTestInfo(const WebCore::HitTestResult&);
+ WebHitTestInfo& operator=(const WebCore::HitTestResult&);
+ operator WebCore::HitTestResult() const;
+#endif
+
+protected:
+ WebPrivateOwnPtr<WebCore::HitTestResult> m_private;
+};
+
+} // namespace WebKit
+
+#endif
diff --git a/Source/WebKit/chromium/src/WebRange.cpp b/Source/WebKit/chromium/src/WebRange.cpp
index 3dd000d..5ea3990 100644
--- a/Source/WebKit/chromium/src/WebRange.cpp
+++ b/Source/WebKit/chromium/src/WebRange.cpp
@@ -32,7 +32,6 @@
#include "WebRange.h"
#include "Range.h"
-#include "WebNode.h"
#include "WebString.h"
#include <wtf/PassRefPtr.h>
@@ -66,14 +65,14 @@ int WebRange::endOffset() const
return m_private->endOffset();
}
-WebNode WebRange::startContainer(int& exceptionCode) const
+Node* WebRange::startContainer(int& exceptionCode) const
{
- return PassRefPtr<Node>(m_private->startContainer(exceptionCode));
+ return m_private->startContainer(exceptionCode);
}
-WebNode WebRange::endContainer(int& exceptionCode) const
+Node* WebRange::endContainer(int& exceptionCode) const
{
- return PassRefPtr<Node>(m_private->endContainer(exceptionCode));
+ return m_private->endContainer(exceptionCode);
}
WebString WebRange::toHTMLText() const
diff --git a/Source/WebKit/chromium/src/android/WebDOMTextContentWalker.cpp b/Source/WebKit/chromium/src/android/WebDOMTextContentWalker.cpp
new file mode 100644
index 0000000..80155fb
--- /dev/null
+++ b/Source/WebKit/chromium/src/android/WebDOMTextContentWalker.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "android/WebDOMTextContentWalker.h"
+
+#include "DOMTextContentWalker.h"
+#include "Element.h"
+#include "Node.h"
+#include "Range.h"
+#include "RenderObject.h"
+#include "Text.h"
+#include "VisiblePosition.h"
+#include "android/WebHitTestInfo.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebDOMTextContentWalker::WebDOMTextContentWalker()
+{
+}
+
+WebDOMTextContentWalker::~WebDOMTextContentWalker()
+{
+ m_private.reset(0);
+}
+
+WebDOMTextContentWalker::WebDOMTextContentWalker(const WebHitTestInfo& hitTestInfo, size_t maxLength)
+{
+ Node* node = hitTestInfo.node();
+ if (!node)
+ return;
+
+ Element* element = node->parentElement();
+ if (!node->inDocument() && element && element->inDocument())
+ node = element;
+ m_private.reset(new DOMTextContentWalker(node->renderer()->positionForPoint(hitTestInfo.point()), maxLength));
+}
+
+WebDOMTextContentWalker::WebDOMTextContentWalker(Node* node, size_t offset, size_t maxLength)
+{
+ if (!node || !node->isTextNode() || offset >= node->nodeValue().length())
+ return;
+
+ m_private.reset(new DOMTextContentWalker(VisiblePosition(Position(static_cast<Text*>(node), offset).parentAnchoredEquivalent(), DOWNSTREAM), maxLength));
+}
+
+WebString WebDOMTextContentWalker::content() const
+{
+ return m_private->content();
+}
+
+size_t WebDOMTextContentWalker::hitOffsetInContent() const
+{
+ return m_private->hitOffsetInContent();
+}
+
+WebRange WebDOMTextContentWalker::contentOffsetsToRange(size_t startInContent, size_t endInContent)
+{
+ return m_private->contentOffsetsToRange(startInContent, endInContent);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/chromium/src/android/WebHitTestInfo.cpp b/Source/WebKit/chromium/src/android/WebHitTestInfo.cpp
new file mode 100644
index 0000000..948c6fb
--- /dev/null
+++ b/Source/WebKit/chromium/src/android/WebHitTestInfo.cpp
@@ -0,0 +1,95 @@
+/*
+* Copyright (C) 2011 Google Inc. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "android/WebHitTestInfo.h"
+
+#include "Element.h"
+#include "HitTestResult.h"
+#include "KURL.h"
+#include "Node.h"
+#include "RenderObject.h"
+#include "VisiblePosition.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebHitTestInfo::WebHitTestInfo()
+{
+}
+
+WebHitTestInfo::WebHitTestInfo(const WebHitTestInfo& testInfo)
+ : m_private(new HitTestResult(testInfo))
+{
+}
+
+WebURL WebHitTestInfo::linkURL() const
+{
+ return m_private->absoluteLinkURL();
+}
+
+WebHitTestInfo::~WebHitTestInfo()
+{
+ m_private.reset(0);
+}
+
+WebURL WebHitTestInfo::imageURL() const
+{
+ return m_private->absoluteImageURL();
+}
+
+Node* WebHitTestInfo::node() const
+{
+ return m_private->innerNode();
+}
+
+WebPoint WebHitTestInfo::point() const
+{
+ return WebPoint(m_private->localPoint());
+}
+
+bool WebHitTestInfo::isContentEditable() const
+{
+ return m_private->isContentEditable();
+}
+
+WebHitTestInfo::WebHitTestInfo(const HitTestResult& result)
+{
+ m_private.reset(new HitTestResult(result));
+}
+
+WebHitTestInfo& WebHitTestInfo::operator=(const HitTestResult& result)
+{
+ m_private.reset(new HitTestResult(result));
+ return *this;
+}
+
+WebHitTestInfo::operator HitTestResult() const
+{
+ return *m_private.get();
+}
+
+} // namespace WebKit