Enable longpress and doubletap to WebKit as touch
event if it is requested.
diff --git a/WebCore/dom/EventNames.h b/WebCore/dom/EventNames.h
index 930ef3a..b2db177 100644
--- a/WebCore/dom/EventNames.h
+++ b/WebCore/dom/EventNames.h
@@ -96,6 +96,8 @@
     macro(touchmove) \
     macro(touchend) \
     macro(touchcancel) \
+    macro(touchlongpress) \
+    macro(touchdoubletap) \
 /* #endif */ \
     macro(unload) \
     macro(updateready) \
diff --git a/WebCore/dom/TouchEvent.cpp b/WebCore/dom/TouchEvent.cpp
index d02bac8..7ce856f 100644
--- a/WebCore/dom/TouchEvent.cpp
+++ b/WebCore/dom/TouchEvent.cpp
@@ -39,6 +39,8 @@
     , m_touches(touches)
     , m_targetTouches(targetTouches)
     , m_changedTouches(changedTouches)
+    , m_longPressPrevented(false)
+    , m_doubleTapPrevented(false)
 {
 }
 
diff --git a/WebCore/dom/TouchEvent.h b/WebCore/dom/TouchEvent.h
index e8423e5..6b7d384 100644
--- a/WebCore/dom/TouchEvent.h
+++ b/WebCore/dom/TouchEvent.h
@@ -57,6 +57,14 @@
         TouchList* targetTouches() const {return m_targetTouches.get();}
         TouchList* changedTouches() const {return m_changedTouches.get();}
 
+        bool longPressPrevented() const { return m_longPressPrevented; }
+        void preventLongPress() { m_longPressPrevented = true; }
+        void setLongPressPrevented(bool prevented) { m_longPressPrevented = prevented; }
+
+        bool doubleTapPrevented() const { return m_doubleTapPrevented; }
+        void preventDoubleTap() { m_doubleTapPrevented = true; }
+        void setDoubleTapPrevented(bool prevented) { m_doubleTapPrevented = prevented; }
+
     private:
         TouchEvent() {}
         TouchEvent(TouchList* touches, TouchList* targetTouches,
@@ -69,6 +77,9 @@
         RefPtr<TouchList> m_touches;
         RefPtr<TouchList> m_targetTouches;
         RefPtr<TouchList> m_changedTouches;
+
+        bool m_longPressPrevented;
+        bool m_doubleTapPrevented;
     };
 
 } // namespace WebCore
diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp
index 9d45ca7..6a92aa8 100644
--- a/WebCore/page/EventHandler.cpp
+++ b/WebCore/page/EventHandler.cpp
@@ -2525,7 +2525,7 @@
 }
 
 #if ENABLE(TOUCH_EVENTS) // Android
-bool EventHandler::handleTouchEvent(const PlatformTouchEvent& e)
+int EventHandler::handleTouchEvent(const PlatformTouchEvent& e)
 {
     // only handle the touch event in the top frame handler
     if (m_frame->tree()->parent(true))
@@ -2533,17 +2533,17 @@
 
     Document* doc = m_frame->document();
     if (!doc)
-        return false;
+        return 0;
 
     RenderObject* docRenderer = doc->renderer();
     if (!docRenderer)
-        return false;
+        return 0;
 
     if (doc->touchEventListeners().size() == 0)
-        return false;
+        return 0;
 
     TouchEventType type = e.eventType();
-    if (type == TouchEventStart) {
+    if (type == TouchEventStart || type == TouchEventLongPress || type == TouchEventDoubleTap) {
         Frame* frame = m_frame;
         IntPoint vPoint = frame->view()->windowToContents(e.pos());
         HitTestRequest request(HitTestRequest::ReadOnly);
@@ -2583,13 +2583,13 @@
         if ((type == TouchEventMove) && (e.x() == m_touch->screenX()) &&
                 (e.y() == m_touch->screenY())) {
             // don't trigger the event if it hasn't really moved
-            return false;
+            return 0;
         }
 
         IntPoint vPoint = m_touch->frame()->view()->windowToContents(e.pos());
         m_touch->updateLocation(e.x(), e.y(), vPoint.x(), vPoint.y());
     } else {
-        return false;
+        return 0;
     }
 
     RefPtr<TouchList> touchList = TouchList::create();
@@ -2622,15 +2622,30 @@
                     m_touch->screenX(), m_touch->screenY(), m_touch->pageX(), m_touch->pageY());
             break;
 
+        case TouchEventLongPress:
+            te = TouchEvent::create(touchList.get(), touchList.get(), touchList.get(),
+                    eventNames().touchlongpressEvent, m_touch->frame()->document()->defaultView(),
+                    m_touch->screenX(), m_touch->screenY(), m_touch->pageX(), m_touch->pageY());
+            break;
+
+        case TouchEventDoubleTap:
+            te = TouchEvent::create(touchList.get(), touchList.get(), touchList.get(),
+                    eventNames().touchdoubletapEvent, m_touch->frame()->document()->defaultView(),
+                    m_touch->screenX(), m_touch->screenY(), m_touch->pageX(), m_touch->pageY());
+            break;
+
         default:
             return false;
     }
     ExceptionCode ec = 0;
     m_touch->target()->dispatchEvent(te.get(), ec);
-    if (type == TouchEventEnd || type == TouchEventCancel) {
+    if (type == TouchEventEnd || type == TouchEventCancel)
         m_touch = 0;
-    }
-    return te->defaultPrevented();
+    if (type == TouchEventLongPress || type == TouchEventDoubleTap)
+        return 0;
+    return (te->defaultPrevented() ? preventTouch : 0)
+            | (te->longPressPrevented() ? preventLongPress : 0)
+            | (te->doubleTapPrevented() ? preventDoubleTap : 0);
 }
 #endif
 
diff --git a/WebCore/page/EventHandler.h b/WebCore/page/EventHandler.h
index daf5a67..d8cd3a2 100644
--- a/WebCore/page/EventHandler.h
+++ b/WebCore/page/EventHandler.h
@@ -75,6 +75,14 @@
 
 enum HitTestScrollbars { ShouldHitTestScrollbars, DontHitTestScrollbars };
 
+#if ENABLE(TOUCH_EVENTS) // Android
+enum TouchResultMask {
+    preventTouch        = 1 << 0,
+    preventLongPress    = 1 << 1,
+    preventDoubleTap    = 1 << 2,
+};
+#endif
+
 class EventHandler : public Noncopyable {
 public:
     EventHandler(Frame*);
@@ -144,7 +152,8 @@
     bool handleWheelEvent(PlatformWheelEvent&);
 
 #if ENABLE(TOUCH_EVENTS) // Android
-    bool handleTouchEvent(const PlatformTouchEvent&);
+    // See TouchResultMask for the return value options
+    int handleTouchEvent(const PlatformTouchEvent&);
 #endif
 
 #if ENABLE(CONTEXT_MENUS)
diff --git a/WebCore/platform/PlatformTouchEvent.h b/WebCore/platform/PlatformTouchEvent.h
index 4f547b2..6c8629c 100644
--- a/WebCore/platform/PlatformTouchEvent.h
+++ b/WebCore/platform/PlatformTouchEvent.h
@@ -32,7 +32,7 @@
 
 namespace WebCore {
 
-    enum TouchEventType {TouchEventStart, TouchEventMove, TouchEventEnd, TouchEventCancel};
+    enum TouchEventType {TouchEventStart, TouchEventMove, TouchEventEnd, TouchEventCancel, TouchEventLongPress, TouchEventDoubleTap};
 
     class PlatformTouchEvent {
     public:
diff --git a/WebCore/plugins/android/PluginViewAndroid.cpp b/WebCore/plugins/android/PluginViewAndroid.cpp
index 08ac7c8..4266a9a 100644
--- a/WebCore/plugins/android/PluginViewAndroid.cpp
+++ b/WebCore/plugins/android/PluginViewAndroid.cpp
@@ -183,6 +183,7 @@
     ANPEvent evt;
     SkANP::InitEvent(&evt, kTouch_ANPEventType);
 
+    bool ignoreRet = false;
     const AtomicString& type = event->type();
     if (eventNames().touchstartEvent == type)
         evt.data.touch.action = kDown_ANPTouchAction;
@@ -192,7 +193,13 @@
         evt.data.touch.action = kMove_ANPTouchAction;
     else if (eventNames().touchcancelEvent == type)
         evt.data.touch.action = kCancel_ANPTouchAction;
-    else
+    else if (eventNames().touchlongpressEvent == type) {
+        evt.data.touch.action = kLongPress_ANPTouchAction;
+        ignoreRet = true;
+    } else if (eventNames().touchdoubletapEvent == type) {
+        evt.data.touch.action = kDoubleTap_ANPTouchAction;
+        ignoreRet = true;
+    } else
         return;
 
     evt.data.touch.modifiers = 0;   // todo
@@ -203,14 +210,22 @@
     evt.data.touch.x = event->pageX() - m_npWindow.x;
     evt.data.touch.y = event->pageY() - m_npWindow.y;
 
-    if (m_plugin->pluginFuncs()->event(m_instance, &evt)) {
+    int16 ret = m_plugin->pluginFuncs()->event(m_instance, &evt);
+    if (ignoreRet)
+        return;
+    if (ret & kHandleTouch_ANPTouchResult) {
         // The plugin needs focus to receive keyboard events
         if (evt.data.touch.action == kDown_ANPTouchAction) {
             if (Page* page = m_parentFrame->page())
                 page->focusController()->setFocusedFrame(m_parentFrame);
             m_parentFrame->document()->setFocusedNode(m_element);
         }
-        event->setDefaultPrevented(true);
+        event->preventDefault();
+    } else {
+        if (ret & kHandleLongPress_ANPTouchResult)
+            event->preventLongPress();
+        if (ret & kHandleDoubleTap_ANPTouchResult)
+            event->preventDoubleTap();
     }
 }
 
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 135d1b2..0b7e63b 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -2052,9 +2052,9 @@
     }
 }
 
-bool WebViewCore::handleTouchEvent(int action, int x, int y)
+int WebViewCore::handleTouchEvent(int action, int x, int y)
 {
-    bool preventDefault = false;
+    int preventDefault = 0;
 
 #if ENABLE(TOUCH_EVENTS) // Android
     WebCore::TouchEventType type = WebCore::TouchEventCancel;
@@ -2071,6 +2071,12 @@
     case 3: // MotionEvent.ACTION_CANCEL
         type = WebCore::TouchEventCancel;
         break;
+    case 0x100: // WebViewCore.ACTION_LONGPRESS
+        type = WebCore::TouchEventLongPress;
+        break;
+    case 0x200: // WebViewCore.ACTION_DOUBLETAP
+        type = WebCore::TouchEventDoubleTap;
+        break;
     }
     WebCore::IntPoint pt(x - m_scrollOffsetX, y - m_scrollOffsetY);
     WebCore::PlatformTouchEvent te(pt, pt, type);
@@ -2829,7 +2835,7 @@
     return ret;
 }
 
-static jboolean HandleTouchEvent(JNIEnv *env, jobject obj, jint action, jint x, jint y)
+static jint HandleTouchEvent(JNIEnv *env, jobject obj, jint action, jint x, jint y)
 {
 #ifdef ANDROID_INSTRUMENT
     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
@@ -3216,7 +3222,7 @@
         (void*) SaveDocumentState },
     { "nativeFindAddress", "(Ljava/lang/String;Z)Ljava/lang/String;",
         (void*) FindAddress },
-    { "nativeHandleTouchEvent", "(III)Z",
+    { "nativeHandleTouchEvent", "(III)I",
             (void*) HandleTouchEvent },
     { "nativeTouchUp", "(IIIII)V",
         (void*) TouchUp },
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index 09f02a5..d1c8511 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -278,7 +278,7 @@
         /**
          * Handle touch event
          */
-        bool handleTouchEvent(int action, int x, int y);
+        int handleTouchEvent(int action, int x, int y);
 
         /**
          * Handle motionUp event from the UI thread (called touchUp in the
diff --git a/WebKit/android/plugins/android_npapi.h b/WebKit/android/plugins/android_npapi.h
index e52debb..14553ff 100644
--- a/WebKit/android/plugins/android_npapi.h
+++ b/WebKit/android/plugins/android_npapi.h
@@ -790,13 +790,29 @@
         the plugin chooses to not handle this action then no other events
         related to that particular touch gesture will be generated.
      */
-    kDown_ANPTouchAction   = 0,
-    kUp_ANPTouchAction     = 1,
-    kMove_ANPTouchAction   = 2,
-    kCancel_ANPTouchAction = 3,
+    kDown_ANPTouchAction        = 0,
+    kUp_ANPTouchAction          = 1,
+    kMove_ANPTouchAction        = 2,
+    kCancel_ANPTouchAction      = 3,
+    // The web view will ignore the return value from the following actions
+    kLongPress_ANPTouchAction   = 4,
+    kDoubleTap_ANPTouchAction   = 5,
 };
 typedef int32_t ANPTouchAction;
 
+/**
+ * When a plugin returns from NPP_HandleEvent() for a touch event, it can use
+ * ANPTouchResultMask to tell the web view which touch event it wants to handle.
+ * kHandleTouch_ANPTouchResult will handle all touch event inside the plugin. If
+ * it is not set, a plugin can choose only handle individual event like long
+ * press, or double tap.
+ */
+enum ANPTouchResultMask {
+    kHandleTouch_ANPTouchResult     = 1,
+    kHandleLongPress_ANPTouchResult = 2,
+    kHandleDoubleTap_ANPTouchResult = 4,
+};
+
 enum ANPLifecycleActions {
     /** The web view containing this plugin has been paused.  See documentation
         on the android activity lifecycle for more information.