/*
 * 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"
#include "ContextFeaturesClientImpl.h"

#include "WebDocument.h"
#include "WebFrameImpl.h"
#include "WebPermissionClient.h"
#include "core/dom/Document.h"
#include "platform/weborigin/SecurityOrigin.h"

using namespace WebCore;

namespace blink {

class ContextFeaturesCache : public DocumentSupplement {
public:
    class Entry {
    public:
        enum Value {
            IsEnabled,
            IsDisabled,
            NeedsRefresh
        };

        Entry()
            : m_value(NeedsRefresh)
            , m_defaultValue(false)
        { }

        bool isEnabled() const
        {
            ASSERT(m_value != NeedsRefresh);
            return m_value == IsEnabled;
        }

        void set(bool value, bool defaultValue)
        {
            m_value = value ? IsEnabled : IsDisabled;
            m_defaultValue = defaultValue;
        }

        bool needsRefresh(bool defaultValue) const
        {
            return m_value == NeedsRefresh || m_defaultValue != defaultValue;
        }

    private:
        Value m_value;
        bool m_defaultValue; // Needs to be traked as a part of the signature since it can be changed dynamically.
    };

    static const char* supplementName();
    static ContextFeaturesCache* from(Document*);

    Entry& entryFor(ContextFeatures::FeatureType type)
    {
        size_t index = static_cast<size_t>(type);
        ASSERT_WITH_SECURITY_IMPLICATION(index < ContextFeatures::FeatureTypeSize);
        return m_entries[index];
    }

    void validateAgainst(Document*);

private:
    String m_domain;
    Entry m_entries[ContextFeatures::FeatureTypeSize];
};

const char* ContextFeaturesCache::supplementName()
{
    return "ContextFeaturesCache";
}

ContextFeaturesCache* ContextFeaturesCache::from(Document* document)
{
    ContextFeaturesCache* cache = static_cast<ContextFeaturesCache*>(DocumentSupplement::from(document, supplementName()));
    if (!cache) {
        cache = new ContextFeaturesCache();
        DocumentSupplement::provideTo(document, supplementName(), adoptPtr(cache));
    }

    return cache;
}

void ContextFeaturesCache::validateAgainst(Document* document)
{
    String currentDomain = document->securityOrigin()->domain();
    if (currentDomain == m_domain)
        return;
    m_domain = currentDomain;
    for (size_t i = 0; i < ContextFeatures::FeatureTypeSize; ++i)
        m_entries[i] = Entry();
}

bool ContextFeaturesClientImpl::isEnabled(Document* document, ContextFeatures::FeatureType type, bool defaultValue)
{
    ContextFeaturesCache::Entry& cache = ContextFeaturesCache::from(document)->entryFor(type);
    if (cache.needsRefresh(defaultValue))
        cache.set(askIfIsEnabled(document, type, defaultValue), defaultValue);
    return cache.isEnabled();
}

void ContextFeaturesClientImpl::urlDidChange(Document* document)
{
    ContextFeaturesCache::from(document)->validateAgainst(document);
}

bool ContextFeaturesClientImpl::askIfIsEnabled(Document* document, ContextFeatures::FeatureType type, bool defaultValue)
{
    if (!m_client)
        return defaultValue;

#if defined(WEBPERMISSIONCLIENT_USES_FRAME_FOR_ALL_METHODS)
    WebFrameImpl* frame = WebFrameImpl::fromFrame(document->frame());
    if (!frame)
        return defaultValue;

    if (frame->permissionClient()) {
        switch (type) {
        case ContextFeatures::StyleScoped:
            return frame->permissionClient()->allowWebComponents(frame, defaultValue);
        case ContextFeatures::MutationEvents:
            return frame->permissionClient()->allowMutationEvents(frame, defaultValue);
        case ContextFeatures::PushState:
            return frame->permissionClient()->allowPushState(frame);
        default:
            return defaultValue;
        }
    }
#endif

    switch (type) {
#if defined(WEBPERMISSIONCLIENT_USES_FRAME_FOR_ALL_METHODS)
    case ContextFeatures::StyleScoped:
        return m_client->allowWebComponents(frame, defaultValue);
    case ContextFeatures::MutationEvents:
        return m_client->allowMutationEvents(frame, defaultValue);
    case ContextFeatures::PushState:
        return m_client->allowPushState(frame);
#else
    case ContextFeatures::StyleScoped:
        return m_client->allowWebComponents(WebDocument(document), defaultValue);
    case ContextFeatures::MutationEvents:
        return m_client->allowMutationEvents(WebDocument(document), defaultValue);
    case ContextFeatures::PushState:
        return m_client->allowPushState(WebDocument(document));
#endif
    default:
        return defaultValue;
    }
}

} // namespace blink
