/*
 * 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:
 * 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 "PointerLockController.h"

#if ENABLE(POINTER_LOCK)

#include "Chrome.h"
#include "ChromeClient.h"
#include "Element.h"
#include "Event.h"
#include "EventNames.h"
#include "Page.h"
#include "PlatformMouseEvent.h"
#include "PointerCaptureController.h"
#include "UserGestureIndicator.h"
#include "VoidCallback.h"

namespace WebCore {

PointerLockController::PointerLockController(Page& page)
    : m_page(page)
{
}

void PointerLockController::requestPointerLock(Element* target)
{
    if (!target || !target->isConnected() || m_documentOfRemovedElementWhileWaitingForUnlock) {
        enqueueEvent(eventNames().pointerlockerrorEvent, target);
        return;
    }

    if (m_documentAllowedToRelockWithoutUserGesture != &target->document() && !UserGestureIndicator::processingUserGesture()) {
        enqueueEvent(eventNames().pointerlockerrorEvent, target);
        return;
    }

    if (target->document().isSandboxed(SandboxPointerLock)) {
        // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
        target->document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked pointer lock on an element because the element's frame is sandboxed and the 'allow-pointer-lock' permission is not set."_s);
        enqueueEvent(eventNames().pointerlockerrorEvent, target);
        return;
    }

    if (m_element) {
        if (&m_element->document() != &target->document()) {
            enqueueEvent(eventNames().pointerlockerrorEvent, target);
            return;
        }
        m_element = target;
        enqueueEvent(eventNames().pointerlockchangeEvent, target);
        m_page.pointerCaptureController().pointerLockWasApplied();
    } else {
        m_lockPending = true;
        m_element = target;
        if (!m_page.chrome().client().requestPointerLock()) {
            clearElement();
            enqueueEvent(eventNames().pointerlockerrorEvent, target);
        }
    }
}

void PointerLockController::requestPointerUnlock()
{
    if (!m_element)
        return;

    m_unlockPending = true;
    m_page.chrome().client().requestPointerUnlock();
}

void PointerLockController::requestPointerUnlockAndForceCursorVisible()
{
    m_documentAllowedToRelockWithoutUserGesture = nullptr;

    if (!m_element)
        return;

    m_unlockPending = true;
    m_page.chrome().client().requestPointerUnlock();
    m_forceCursorVisibleUponUnlock = true;
}

void PointerLockController::elementWasRemovedInternal()
{
    m_documentOfRemovedElementWhileWaitingForUnlock = m_element->document();
    // Set element null immediately to block any future interaction with it
    // including mouse events received before the unlock completes.
    requestPointerUnlock();
    clearElement();
}

void PointerLockController::documentDetached(Document& document)
{
    if (m_documentAllowedToRelockWithoutUserGesture == &document)
        m_documentAllowedToRelockWithoutUserGesture = nullptr;

    if (m_element && &m_element->document() == &document) {
        m_documentOfRemovedElementWhileWaitingForUnlock = m_element->document();
        requestPointerUnlock();
        clearElement();
    }
}

bool PointerLockController::isLocked() const
{
    return m_element && !m_lockPending;
}

bool PointerLockController::lockPending() const
{
    return m_lockPending;
}

Element* PointerLockController::element() const
{
    return m_element.get();
}

void PointerLockController::didAcquirePointerLock()
{
    if (!m_lockPending)
        return;
    
    ASSERT(m_element);
    
    enqueueEvent(eventNames().pointerlockchangeEvent, m_element.get());
    m_lockPending = false;
    m_forceCursorVisibleUponUnlock = false;
    m_documentAllowedToRelockWithoutUserGesture = m_element->document();
}

void PointerLockController::didNotAcquirePointerLock()
{
    enqueueEvent(eventNames().pointerlockerrorEvent, m_element.get());
    clearElement();
    m_unlockPending = false;
}

void PointerLockController::didLosePointerLock()
{
    if (!m_unlockPending)
        m_documentAllowedToRelockWithoutUserGesture = nullptr;

    enqueueEvent(eventNames().pointerlockchangeEvent, m_element ? &m_element->document() : m_documentOfRemovedElementWhileWaitingForUnlock.get());
    clearElement();
    m_unlockPending = false;
    m_documentOfRemovedElementWhileWaitingForUnlock = nullptr;
    if (m_forceCursorVisibleUponUnlock) {
        m_forceCursorVisibleUponUnlock = false;
        m_page.chrome().client().setCursorHiddenUntilMouseMoves(false);
    }
}

void PointerLockController::dispatchLockedMouseEvent(const PlatformMouseEvent& event, const AtomString& eventType)
{
    if (!m_element || !m_element->document().frame())
        return;

    Ref protectedElement { *m_element };
    protectedElement->dispatchMouseEvent(event, eventType, event.clickCount());

    // Create click events
    if (eventType == eventNames().mouseupEvent)
        protectedElement->dispatchMouseEvent(event, eventNames().clickEvent, event.clickCount());
}

void PointerLockController::dispatchLockedWheelEvent(const PlatformWheelEvent& event)
{
    if (!m_element || !m_element->document().frame())
        return;

    OptionSet<EventHandling> defaultHandling;
    m_element->dispatchWheelEvent(event, defaultHandling);
}

void PointerLockController::clearElement()
{
    m_lockPending = false;
    m_element = nullptr;
}

void PointerLockController::enqueueEvent(const AtomString& type, Element* element)
{
    if (element)
        enqueueEvent(type, &element->document());
}

void PointerLockController::enqueueEvent(const AtomString& type, Document* document)
{
    // FIXME: Spec doesn't specify which task source use.
    if (RefPtr protectedDocument = document)
        protectedDocument->queueTaskToDispatchEvent(TaskSource::UserInteraction, Event::create(type, Event::CanBubble::Yes, Event::IsCancelable::No));
}

} // namespace WebCore

#endif // ENABLE(POINTER_LOCK)
