/*
 * Copyright 2009, The Android Open Source Project
 * Copyright (C) 2006, 2007 Apple 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.
 *
 * 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 "WebCore"

#include "config.h"
#include "PluginView.h"

#include "Document.h"
#include "Element.h"
#include "EventNames.h"
#include "FocusController.h"
#include "FrameLoader.h"
#include "FrameLoadRequest.h"
#include "FrameTree.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
#include "HTMLPlugInElement.h"
#include "Image.h"
#include "KeyboardEvent.h"
#include "MIMETypeRegistry.h"
#include "MouseEvent.h"
#include "NetworkStateNotifier.h"
#include "NotImplemented.h"
#include "Page.h"
#include "PlatformGraphicsContext.h"
#include "PlatformKeyboardEvent.h"
#include "PluginMainThreadScheduler.h"
#include "PluginPackage.h"
#include "Touch.h"
#include "TouchEvent.h"
#include "TouchList.h"
#include "SkCanvas.h"
#include "npruntime_impl.h"
// #include "runtime_root.h"
#include "utils/SystemClock.h"
#include "ScriptController.h"
#include "Settings.h"

#include <wtf/ASCIICType.h>
// #include "runtime.h"
#include "WebViewCore.h"

/* Controls the printing of log messages in this file. This must be defined
   before PluginDebugAndroid.h is included.
 */
// #define PLUGIN_DEBUG_LOCAL
#define TRACE_KEY_EVENTS 0

#include "PluginDebug.h"
#include "PluginDebugAndroid.h"
#include "PluginViewBridgeAndroid.h"
#include "PluginWidgetAndroid.h"

#include "android_npapi.h"
#include "ANPNativeWindow_npapi.h"
#include "ANPSurface_npapi.h"
#include "ANPSystem_npapi.h"
#include "ANPVideo_npapi.h"
#include "SkANP.h"
#include "SkFlipPixelRef.h"

///////////////////////////////////////////////////////////////////////////////

extern void ANPAudioTrackInterfaceV0_Init(ANPInterface* value);
extern void ANPAudioTrackInterfaceV1_Init(ANPInterface* value);
extern void ANPBitmapInterfaceV0_Init(ANPInterface* value);
extern void ANPCanvasInterfaceV0_Init(ANPInterface* value);
extern void ANPEventInterfaceV0_Init(ANPInterface* value);
extern void ANPLogInterfaceV0_Init(ANPInterface* value);
extern void ANPMatrixInterfaceV0_Init(ANPInterface* value);
extern void ANPOffscreenInterfaceV0_Init(ANPInterface* value);
extern void ANPPaintInterfaceV0_Init(ANPInterface* value);
extern void ANPPathInterfaceV0_Init(ANPInterface* value);
extern void ANPSurfaceInterfaceV0_Init(ANPInterface* value);
extern void ANPTypefaceInterfaceV0_Init(ANPInterface* value);
extern void ANPWindowInterfaceV0_Init(ANPInterface* value);
extern void ANPWindowInterfaceV1_Init(ANPInterface* value);
extern void ANPWindowInterfaceV2_Init(ANPInterface* value);
extern void ANPSystemInterfaceV0_Init(ANPInterface* value);
extern void ANPSystemInterfaceV1_Init(ANPInterface* value);
extern void ANPSystemInterfaceV2_Init(ANPInterface* value);
extern void ANPNativeWindowInterfaceV0_Init(ANPInterface* value);
extern void ANPVideoInterfaceV0_Init(ANPInterface* value);
extern void ANPVideoInterfaceV1_Init(ANPInterface* value);

struct VarProcPair {
    int         enumValue;
    size_t      size;
    void        (*proc)(ANPInterface*);
};

#define VARPROCLINE(name)   \
    k##name##_ANPGetValue, sizeof(ANP##name), ANP##name##_Init

static const VarProcPair gVarProcs[] = {
    { VARPROCLINE(AudioTrackInterfaceV0)    },
    { VARPROCLINE(AudioTrackInterfaceV1)    },
    { VARPROCLINE(BitmapInterfaceV0)        },
    { VARPROCLINE(CanvasInterfaceV0)        },
    { VARPROCLINE(EventInterfaceV0)         },
    { VARPROCLINE(LogInterfaceV0)           },
    { VARPROCLINE(MatrixInterfaceV0)        },
    { VARPROCLINE(PaintInterfaceV0)         },
    { VARPROCLINE(PathInterfaceV0)          },
    { VARPROCLINE(SurfaceInterfaceV0)       },
    { VARPROCLINE(TypefaceInterfaceV0)      },
    { VARPROCLINE(WindowInterfaceV0)        },
    { VARPROCLINE(WindowInterfaceV1)        },
    { VARPROCLINE(WindowInterfaceV2)        },
    { VARPROCLINE(SystemInterfaceV0)        },
    { VARPROCLINE(SystemInterfaceV1)        },
    { VARPROCLINE(SystemInterfaceV2)        },
    { VARPROCLINE(NativeWindowInterfaceV0)  },
    { VARPROCLINE(VideoInterfaceV0)         },
    { VARPROCLINE(VideoInterfaceV1)         },
};

/*  return true if var was an interface request (error will be set accordingly)
    return false if var is not a recognized interface (and ignore error param)
 */
static bool anp_getInterface(NPNVariable var, void* value, NPError* error) {
    const VarProcPair* iter = gVarProcs;
    const VarProcPair* stop = gVarProcs + SK_ARRAY_COUNT(gVarProcs);
    while (iter < stop) {
        if (iter->enumValue == var) {
            ANPInterface* i = reinterpret_cast<ANPInterface*>(value);
            if (i->inSize < iter->size) {
                SkDebugf("------- interface %d, expected size %d, allocated %d\n",
                         var, iter->size, i->inSize);
                *error = NPERR_INCOMPATIBLE_VERSION_ERROR;
            } else {
                iter->proc(i);
                *error = NPERR_NO_ERROR;
            }
            return true;
        }
        iter += 1;
    }
    SkDebugf("------ unknown NPNVariable %d\n", var);
    return false;
}

///////////////////////////////////////////////////////////////////////////////

using std::min;

using namespace WTF;

namespace WebCore {

using namespace HTMLNames;

void PluginView::platformInit()
{
    setPlatformWidget(new PluginViewBridgeAndroid());

    m_isWindowed = false;   // we don't support windowed yet

    m_window = new PluginWidgetAndroid(this);

    m_npWindow.type = NPWindowTypeDrawable;
    m_npWindow.window = 0;
}

bool PluginView::platformStart()
{
    return true;
}

void PluginView::platformDestroy()
{
    delete m_window;
}

PlatformLayer* PluginView::platformLayer() const
{
    return (PlatformLayer*) m_window->getLayer();
}

#if ENABLE(TOUCH_EVENTS)
void PluginView::handleTouchEvent(TouchEvent* event)
{
    if (!m_window->isAcceptingEvent(kTouch_ANPEventFlag))
        return;

    if (!m_window->inFullScreen() && m_parentFrame->document()->focusedNode() != m_element)
        return;

    ANPEvent evt;
    SkANP::InitEvent(&evt, kMultiTouch_ANPEventType);

    const AtomicString& type = event->type();
    if (eventNames().touchstartEvent == type)
        evt.data.multiTouch.action = kDown_ANPTouchAction;
    else if (eventNames().touchendEvent == type)
        evt.data.multiTouch.action = kUp_ANPTouchAction;
    else if (eventNames().touchmoveEvent == type)
        evt.data.multiTouch.action = kMove_ANPTouchAction;
    else if (eventNames().touchcancelEvent == type)
        evt.data.multiTouch.action = kCancel_ANPTouchAction;
    else if (eventNames().touchlongpressEvent == type)
        evt.data.multiTouch.action = kLongPress_ANPTouchAction;
    else if (eventNames().touchdoubletapEvent == type)
        evt.data.multiTouch.action = kDoubleTap_ANPTouchAction;
    else
        return;

    // set the id and timestamp
    evt.data.multiTouch.id = 0; // TODO
    evt.data.multiTouch.timestamp = 0; // TODO

    // In the event of a touchend (up) or touchcancel event, we must ask the changedTouch for the
    // co-ordinates as there is no touch in touches anymore.
    TouchList* touches = (evt.data.multiTouch.action == kUp_ANPTouchAction
        || evt.data.multiTouch.action == kCancel_ANPTouchAction) ? event->changedTouches() : event->touches();

    // set each touchPoint
    int pointerCount = touches->length();
    evt.data.multiTouch.pointerCount = pointerCount;
    evt.data.multiTouch.touchPoint = new TouchPoint[pointerCount];

    for (int x = 0; x < evt.data.multiTouch.pointerCount; x++) {
        Touch* touch = touches->item(x);
        // Convert to coordinates that are relative to the plugin.
        IntPoint localPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(IntPoint(touch->pageX(), touch->pageY())));

        evt.data.multiTouch.touchPoint[x].id = touch->identifier();
        evt.data.multiTouch.touchPoint[x].x = localPos.x();
        evt.data.multiTouch.touchPoint[x].y = localPos.y();
        evt.data.multiTouch.touchPoint[x].pressure = 1; // TODO
        evt.data.multiTouch.touchPoint[x].size = 1; // TODO
    }

    if (m_window->sendEvent(evt))
        event->preventDefault();

    // cleanup the touch points we allocated
    delete[] evt.data.multiTouch.touchPoint;
}
#endif

void PluginView::handleMouseEvent(MouseEvent* event)
{
    const AtomicString& type = event->type();
    bool isUp = (eventNames().mouseupEvent == type);
    bool isDown = (eventNames().mousedownEvent == type);

    ANPEvent    evt;

    if (isUp || isDown) {
        SkANP::InitEvent(&evt, kMouse_ANPEventType);
        evt.data.mouse.action = isUp ? kUp_ANPMouseAction : kDown_ANPMouseAction;

        // Convert to coordinates that are relative to the plugin.
        IntPoint localPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation()));
        evt.data.mouse.x = localPos.x();
        evt.data.mouse.y = localPos.y();

        if (isDown) {
            // The plugin needs focus to receive keyboard and touch events
            m_element->focus();
            event->setDefaultHandled();
        }
    }
    else {
      return;
    }

    if (m_window->sendEvent(evt)) {
        event->setDefaultHandled();
    }
}

static ANPKeyModifier make_modifiers(bool shift, bool alt) {
    ANPKeyModifier mod = 0;
    if (shift) {
        mod |= kShift_ANPKeyModifier;
    }
    if (alt) {
        mod |= kAlt_ANPKeyModifier;
    }
    return mod;
}

void PluginView::handleFocusEvent(bool hasFocus)
{
    ANPEvent evt;
    SkANP::InitEvent(&evt, kLifecycle_ANPEventType);
    evt.data.lifecycle.action = hasFocus ? kGainFocus_ANPLifecycleAction :
                                           kLoseFocus_ANPLifecycleAction;
    m_window->sendEvent(evt);

    // redraw the plugin which subsequently invalidates the nav cache
    IntRect rect = IntRect(m_npWindow.x, m_npWindow.y,
                           m_npWindow.width, m_npWindow.height);
    m_window->webViewCore()->contentInvalidate(rect);
}

void PluginView::handleKeyboardEvent(KeyboardEvent* event)
{
    if (!m_window->isAcceptingEvent(kKey_ANPEventFlag))
        return;

    const PlatformKeyboardEvent* pke = event->keyEvent();
    if (NULL == pke) {
        return;
    }

    bool ignoreEvent = false;

    ANPEvent evt;
    SkANP::InitEvent(&evt, kKey_ANPEventType);

    switch (pke->type()) {
        case PlatformKeyboardEvent::KeyDown:
#if TRACE_KEY_EVENTS
            PLUGIN_LOG("--------- KeyDown, ignore\n");
#endif
            ignoreEvent = true;
            break;
        case PlatformKeyboardEvent::RawKeyDown:
            evt.data.key.action = kDown_ANPKeyAction;
            break;
        case PlatformKeyboardEvent::Char:
#if TRACE_KEY_EVENTS
            PLUGIN_LOG("--------- Char, ignore\n");
#endif
            ignoreEvent = true;
            break;
        case PlatformKeyboardEvent::KeyUp:
            evt.data.key.action = kUp_ANPKeyAction;
            break;
        default:
#if TRACE_KEY_EVENTS
            PLUGIN_LOG("------ unexpected keyevent type %d\n", pke->type());
#endif
            ignoreEvent = true;
            break;
    }

    /* the plugin should be the only party able to return nav control to the
     * browser UI. Therefore, if we discard an event on behalf of the plugin
     * we should mark the event as being handled.
     */
    if (ignoreEvent) {
        int keyCode = pke->nativeVirtualKeyCode();
        if (keyCode >= kDpadUp_ANPKeyCode && keyCode <= kDpadCenter_ANPKeyCode)
            event->setDefaultHandled();
        return;
    }

    evt.data.key.nativeCode = pke->nativeVirtualKeyCode();
    evt.data.key.virtualCode = pke->windowsVirtualKeyCode();
    evt.data.key.repeatCount = pke->repeatCount();
    evt.data.key.modifiers = make_modifiers(pke->shiftKey(), pke->altKey());
    evt.data.key.unichar = pke->unichar();

    if (m_window->sendEvent(evt)) {
        event->setDefaultHandled();
    } else if (m_window->inFullScreen()){
        // while in the full screen mode, always consumes the key events and
        // keeps the document focus
        event->setDefaultHandled();
    } else {
        // remove the plugin from the document's focus
        m_parentFrame->document()->focusedNodeRemoved();
    }
}

NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf)
{
    notImplemented();
    return NPERR_GENERIC_ERROR;
}

bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPError* result)
{
    // our interface query is valid with no NPP instance
    *result = NPERR_GENERIC_ERROR;

    switch ((int)variable) {
        case NPNVisOfflineBool: {
            if (value != NULL) {
                bool* retValue = static_cast<bool*>(value);
                *retValue = !networkStateNotifier().onLine();
                *result = NPERR_NO_ERROR;
                return true;
            }
            break;
        }
        case kJavaContext_ANPGetValue: {
            jobject* retObject = static_cast<jobject*>(value);
            *retObject = android::WebViewCore::getApplicationContext();
            *result = NPERR_NO_ERROR;
            return true;
        }
        default:
            break; // do nothing
    }

    (void)anp_getInterface(variable, value, result);
    return true;
}

void PluginView::setParent(ScrollView* parent)
{
    PLUGIN_LOG("--%p SetParent old=[%p], new=[%p] \n", instance(), this->parent(), parent);

    Widget::setParent(parent);

    if (parent) {
        // the widget needs initialized now so that the plugin has access to
        // WebViewCore when NPP_New is called
        if (m_window && !m_window->webViewCore()) {
            android::WebViewCore* c = android::WebViewCore::getWebViewCore(this->parent());
            m_window->init(c);
        }
        init();

        /* Our widget needs to recompute its m_windowRect which then sets
           the NPWindowRect if necessary.  This ensures that if NPWindowRect
           is set prior to parent() being set that we still (1) notify the
           plugin of its current rect and (2) that we execute our logic in
           PluginWidgetAndroid in response to changes to NPWindowRect.
         */
        updatePluginWidget();
    }
}

void PluginView::setNPWindowRect(const IntRect&)
{
    setNPWindowIfNeeded();
}

void PluginView::setNPWindowIfNeeded()
{
    PLUGIN_LOG("--%p SetWindow isStarted=[%d] \n", instance(), m_isStarted);

    if (!m_isStarted || !parent())
        return;

    // in Android, plugin always get the setwindow() in the page coordinate.

    // the m_npWindow is relative to the page
    m_npWindow.x = m_pageRect.x();
    m_npWindow.y = m_pageRect.y();
    m_npWindow.width = m_pageRect.width();
    m_npWindow.height = m_pageRect.height();

    m_npWindow.clipRect.left = m_pageRect.x();
    m_npWindow.clipRect.top = m_pageRect.y();
    m_npWindow.clipRect.right = m_pageRect.x() + m_pageRect.width();
    m_npWindow.clipRect.bottom = m_pageRect.y() + m_pageRect.height();

    if (m_plugin->pluginFuncs()->setwindow) {
        setCallingPlugin(true);
        m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
        setCallingPlugin(false);
    }

    m_window->setWindow(&m_npWindow, m_isTransparent);
}

bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result)
{
    switch ((int)variable) {
        case NPNVWindowNPObject: {
            NPObject* windowScriptObject =
                    m_parentFrame->script()->windowScriptNPObject();

            // Return value is expected to be retained, as described
            // here:
            // <http://www.mozilla.org/projects/plugin/npruntime.html>
            if (windowScriptObject)
                _NPN_RetainObject(windowScriptObject);

            void** v = (void**)value;
            *v = windowScriptObject;

            *result = NPERR_NO_ERROR;
            return true;
        }

        case NPNVPluginElementNPObject: {
            NPObject* pluginScriptObject = 0;

            if (m_element->hasTagName(appletTag) ||
                m_element->hasTagName(embedTag) ||
                m_element->hasTagName(objectTag)) {
                HTMLPlugInElement* pluginElement =
                        static_cast<HTMLPlugInElement*>(m_element);
                pluginScriptObject = pluginElement->getNPObject();
            }

            // Return value is expected to be retained, as described
            // here:
            // <http://www.mozilla.org/projects/plugin/npruntime.html>
            if (pluginScriptObject)
                _NPN_RetainObject(pluginScriptObject);

            void** v = (void**)value;
            *v = pluginScriptObject;

           *result = NPERR_NO_ERROR;
            return true;
        }

        case NPNVnetscapeWindow: {
            // Return the top level WebView Java object associated
            // with this instance.
            jobject *retObject = static_cast<jobject*>(value);
            // TODO: Is it safe for this to be NULL? It looks from the NPNVWindowNPObject case that it is.
            *retObject = android::WebViewCore::getWebViewCore(parent())->getWebViewJavaObject();
            *result = NPERR_NO_ERROR;
            return true;
        }

        case NPNVisOfflineBool: {
            if (value == NULL) {
              *result = NPERR_GENERIC_ERROR;
              return true;
            }
            bool* retValue = static_cast<bool*>(value);
            *retValue = !networkStateNotifier().onLine();
            *result = NPERR_NO_ERROR;
            return true;
        }

        case kSupportedDrawingModel_ANPGetValue: {
            uint32_t* bits = reinterpret_cast<uint32_t*>(value);
            *bits = kBitmap_ANPDrawingModel & kSurface_ANPDrawingModel;
            *result = NPERR_NO_ERROR;
            return true;
        }

        case kJavaContext_ANPGetValue: {
            jobject* retObject = static_cast<jobject*>(value);
            // TODO: Is it safe for this to be NULL? It looks from the NPNVWindowNPObject case that it is.
            *retObject = android::WebViewCore::getWebViewCore(parent())->getContext();
            *result = NPERR_NO_ERROR;
            return true;
        }

        default: {
            NPError error = NPERR_GENERIC_ERROR;
            (void)anp_getInterface(variable, value, &error);
            *result = error;
            return true;
        }
    }
}

NPError PluginView::platformSetValue(NPPVariable variable, void* value)
{
    NPError error = NPERR_GENERIC_ERROR;

    switch ((int)variable) {
        case kRequestDrawingModel_ANPSetValue: {
            ANPDrawingModel model = reinterpret_cast<ANPDrawingModel>(value);
            if (m_window->setDrawingModel(model))
                error = NPERR_NO_ERROR;
            break;
        }
        case kAcceptEvents_ANPSetValue : {
            if(value) {
                ANPEventFlags flags = *reinterpret_cast<ANPEventFlags*>(value);
                m_window->updateEventFlags(flags);
                error = NPERR_NO_ERROR;
            }
            break;
        }
        default:
            break;
    }
    return error;
}

void PluginView::invalidateRect(const IntRect& r)
{
    m_window->inval(r, true);
}

void PluginView::invalidateRect(NPRect* rect)
{
    IntRect r;

    if (rect) {
        r = IntRect(rect->left, rect->top,
                    rect->right - rect->left, rect->bottom - rect->top);
    } else {
        r = IntRect(0, 0, m_npWindow.width, m_npWindow.height);
    }

    m_window->inval(r, true);
}

void PluginView::invalidateRegion(NPRegion region)
{
    // we don't support/define regions (yet), so do nothing
}

void PluginView::forceRedraw()
{
    this->invalidateRect(0);
}

void PluginView::setFocus(bool focused)
{
    Widget::setFocus(focused);
//    SkDebugf("------------- setFocus %p\n", this);
}

void PluginView::show()
{
    setSelfVisible(true);
    Widget::show();

    if (platformPluginWidget())
        platformPluginWidget()->layoutSurface();

}

void PluginView::hide()
{
    setSelfVisible(false);
    Widget::hide();

   if (platformPluginWidget())
        platformPluginWidget()->layoutSurface();
}

void PluginView::setParentVisible(bool visible) {

    if (isParentVisible() == visible)
        return;

    Widget::setParentVisible(visible);

    if (platformPluginWidget())
        platformPluginWidget()->layoutSurface();

}

void PluginView::paint(GraphicsContext* context, const IntRect& rect)
{
    if (!m_isStarted) {
        // Draw the "missing plugin" image
        paintMissingPluginIcon(context, rect);
        return;
    }

    IntRect frame = frameRect();
    if (!frame.width() || !frame.height()) {
        PLUGIN_LOG("--%p FrameRect Dimensions are (0,0).\n", instance());
        return;
    }

    if (m_window->isSurfaceDrawingModel()) {
        /* the document position of the frame (e.g. iFrame) containing the
           surface may have changed, which requires us to to update the global
           coordinates of the surface. This is necessary because the plugin has
           not moved within its parent frame and therefore will not get any
           notification of its global position change.
         */
        updatePluginWidget();
        m_window->setSurfaceClip(context->platformContext()->getTotalClipBounds());
    } else {
        m_window->inval(rect, false);
        context->save();
        context->translate(frame.x(), frame.y());
        m_window->draw(context->platformContext());
        context->restore();
    }


}

void PluginView::updatePluginWidget()
{
    FrameView* frameView = static_cast<FrameView*>(parent());
    PLUGIN_LOG("--%p UpdatePluginWidget frame=[%p] \n", instance(), frameView);
    if (frameView) {
        m_windowRect = frameView->contentsToWindow(frameRect());

        IntRect oldPageRect = m_pageRect;

        // only the top ScrollView can have the offset
        m_pageRect = m_windowRect;
        ScrollView* top = parent();
        while (top->parent())
            top = top->parent();
        m_pageRect.move(top->scrollOffset());

        if (m_pageRect != oldPageRect)
            setNPWindowIfNeeded();
    }
}

void PluginView::halt() {
    notImplemented();
}

void PluginView::restart() {
    notImplemented();
}

} // namespace WebCore
