/*
 * Copyright (C) 2018-2019 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:
 * 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 "JSRemoteDOMWindow.h"

#include "JSDOMExceptionHandling.h"
#include "JSDOMWindowCustom.h"
#include "WebCoreJSClientData.h"

namespace WebCore {
using namespace JSC;

bool JSRemoteDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
{
    if (Optional<unsigned> index = parseIndex(propertyName))
        return getOwnPropertySlotByIndex(object, state, index.value(), slot);

    auto* thisObject = jsCast<JSRemoteDOMWindow*>(object);
    return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(thisObject, thisObject->wrapped(), *state, propertyName, slot, String());
}

bool JSRemoteDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
{
    VM& vm = state->vm();
    auto* thisObject = jsCast<JSRemoteDOMWindow*>(object);

    // Indexed getters take precendence over regular properties, so caching would be invalid.
    slot.disableCaching();

    // FIXME: Add support for indexed properties.

    return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(thisObject, thisObject->wrapped(), *state, Identifier::from(vm, index), slot, String());
}

bool JSRemoteDOMWindow::put(JSCell* cell, ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
{
    VM& vm = state->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    auto* thisObject = jsCast<JSRemoteDOMWindow*>(cell);
    if (!thisObject->wrapped().frame())
        return false;

    String errorMessage;

    // We only allow setting "location" attribute cross-origin.
    if (propertyName == static_cast<JSVMClientData*>(vm.clientData)->builtinNames().locationPublicName()) {
        bool putResult = false;
        if (lookupPut(state, propertyName, thisObject, value, *s_info.staticPropHashTable, slot, putResult))
            return putResult;
        return false;
    }
    throwSecurityError(*state, scope, errorMessage);
    return false;
}

bool JSRemoteDOMWindow::putByIndex(JSCell*, ExecState*, unsigned, JSValue, bool)
{
    return false;
}

bool JSRemoteDOMWindow::deleteProperty(JSCell*, ExecState* state, PropertyName)
{
    VM& vm = state->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    throwSecurityError(*state, scope, String());
    return false;
}

bool JSRemoteDOMWindow::deletePropertyByIndex(JSCell*, ExecState* state, unsigned)
{
    VM& vm = state->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    throwSecurityError(*state, scope, String());
    return false;
}

void JSRemoteDOMWindow::getOwnPropertyNames(JSObject*, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
    // FIXME: Add scoped children indexes.

    if (mode.includeDontEnumProperties())
        addCrossOriginOwnPropertyNames<CrossOriginObject::Window>(*exec, propertyNames);
}

bool JSRemoteDOMWindow::defineOwnProperty(JSC::JSObject*, JSC::ExecState* state, JSC::PropertyName, const JSC::PropertyDescriptor&, bool)
{
    VM& vm = state->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    throwSecurityError(*state, scope, String());
    return false;
}

JSValue JSRemoteDOMWindow::getPrototype(JSObject*, ExecState*)
{
    return jsNull();
}

bool JSRemoteDOMWindow::preventExtensions(JSObject*, ExecState* exec)
{
    auto scope = DECLARE_THROW_SCOPE(exec->vm());
    throwTypeError(exec, scope, "Cannot prevent extensions on this object"_s);
    return false;
}

String JSRemoteDOMWindow::toStringName(const JSObject*, ExecState*)
{
    return "Object"_s;
}

} // namepace WebCore
