/*
 * Copyright (C) 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:
 * 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 COMPUTER, INC. ``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 COMPUTER, INC. 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 "PageCache.h"

#include "ApplicationCacheHost.h"
#include "BackForwardController.h"
#include "MemoryCache.h"
#include "CachedPage.h"
#include "DOMWindow.h"
#include "DeviceMotionController.h"
#include "DeviceOrientationController.h"
#include "Document.h"
#include "DocumentLoader.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
#include "FrameLoaderStateMachine.h"
#include "HistoryItem.h"
#include "Logging.h"
#include "Page.h"
#include "Settings.h"
#include "SharedWorkerRepository.h"
#include "SystemTime.h"
#include <wtf/CurrentTime.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringConcatenate.h>

using namespace std;

namespace WebCore {

static const double autoreleaseInterval = 3;

#ifndef NDEBUG

static String& pageCacheLogPrefix(int indentLevel)
{
    static int previousIndent = -1;
    DEFINE_STATIC_LOCAL(String, prefix, ());
    
    if (indentLevel != previousIndent) {    
        previousIndent = indentLevel;
        prefix.truncate(0);
        for (int i = 0; i < previousIndent; ++i)
            prefix += "    ";
    }
    
    return prefix;
}

static void pageCacheLog(const String& prefix, const String& message)
{
    LOG(PageCache, "%s%s", prefix.utf8().data(), message.utf8().data());
}
    
#define PCLOG(...) pageCacheLog(pageCacheLogPrefix(indentLevel), makeString(__VA_ARGS__))
    
static bool logCanCacheFrameDecision(Frame* frame, int indentLevel)
{
    // Only bother logging for frames that have actually loaded and have content.
    if (frame->loader()->stateMachine()->creatingInitialEmptyDocument())
        return false;
    KURL currentURL = frame->loader()->documentLoader() ? frame->loader()->documentLoader()->url() : KURL();
    if (currentURL.isEmpty())
        return false;
    
    PCLOG("+---");
    KURL newURL = frame->loader()->provisionalDocumentLoader() ? frame->loader()->provisionalDocumentLoader()->url() : KURL();
    if (!newURL.isEmpty())
        PCLOG(" Determining if frame can be cached navigating from (", currentURL.string(), ") to (", newURL.string(), "):");
    else
        PCLOG(" Determining if subframe with URL (", currentURL.string(), ") can be cached:");
    
    bool cannotCache = false;
    
    do {
        if (!frame->loader()->documentLoader()) {
            PCLOG("   -There is no DocumentLoader object");
            cannotCache = true;
            break;
        }
        if (!frame->loader()->documentLoader()->mainDocumentError().isNull()) {
            PCLOG("   -Main document has an error");
            cannotCache = true;
        }
        if (frame->loader()->subframeLoader()->containsPlugins()) {
            PCLOG("   -Frame contains plugins");
            cannotCache = true;
        }
        if (frame->document()->url().protocolIs("https")) {
            PCLOG("   -Frame is HTTPS");
            cannotCache = true;
        }
        if (frame->domWindow() && frame->domWindow()->hasEventListeners(eventNames().unloadEvent)) {
            PCLOG("   -Frame has an unload event listener");
            cannotCache = true;
        }
#if ENABLE(DATABASE)
        if (frame->document()->hasOpenDatabases()) {
            PCLOG("   -Frame has open database handles");
            cannotCache = true;
        }
#endif
#if ENABLE(SHARED_WORKERS)
        if (SharedWorkerRepository::hasSharedWorkers(frame->document())) {
            PCLOG("   -Frame has associated SharedWorkers");
            cannotCache = true;
        }
#endif
        if (frame->document()->usingGeolocation()) {
            PCLOG("   -Frame uses Geolocation");
            cannotCache = true;
        }
        if (!frame->loader()->history()->currentItem()) {
            PCLOG("   -No current history item");
            cannotCache = true;
        }
        if (frame->loader()->quickRedirectComing()) {
            PCLOG("   -Quick redirect is coming");
            cannotCache = true;
        }
        if (frame->loader()->documentLoader()->isLoadingInAPISense()) {
            PCLOG("   -DocumentLoader is still loading in API sense");
            cannotCache = true;
        }
        if (frame->loader()->documentLoader()->isStopping()) {
            PCLOG("   -DocumentLoader is in the middle of stopping");
            cannotCache = true;
        }
        if (!frame->document()->canSuspendActiveDOMObjects()) {
            PCLOG("   -The document cannot suspect its active DOM Objects");
            cannotCache = true;
        }
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
        if (!frame->loader()->documentLoader()->applicationCacheHost()->canCacheInPageCache()) {
            PCLOG("   -The DocumentLoader uses an application cache");
            cannotCache = true;
        }
#endif
        if (!frame->loader()->client()->canCachePage()) {
            PCLOG("   -The client says this frame cannot be cached");
            cannotCache = true; 
        }
    } while (false);
    
    for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
        if (!logCanCacheFrameDecision(child, indentLevel + 1))
            cannotCache = true;
    
    PCLOG(cannotCache ? " Frame CANNOT be cached" : " Frame CAN be cached");
    PCLOG("+---");
    
    return !cannotCache;
}
    
static void logCanCachePageDecision(Page* page)
{
    // Only bother logging for main frames that have actually loaded and have content.
    if (page->mainFrame()->loader()->stateMachine()->creatingInitialEmptyDocument())
        return;
    KURL currentURL = page->mainFrame()->loader()->documentLoader() ? page->mainFrame()->loader()->documentLoader()->url() : KURL();
    if (currentURL.isEmpty())
        return;
    
    int indentLevel = 0;    
    PCLOG("--------\n Determining if page can be cached:");
    
    bool cannotCache = !logCanCacheFrameDecision(page->mainFrame(), 1);
    
    FrameLoadType loadType = page->mainFrame()->loader()->loadType();
    if (!page->backForward()->isActive()) {
        PCLOG("   -The back/forward list is disabled or has 0 capacity");
        cannotCache = true;
    }
    if (!page->settings()->usesPageCache()) {
        PCLOG("   -Page settings says b/f cache disabled");
        cannotCache = true;
    }
#if ENABLE(DEVICE_ORIENTATION)
    if (page->deviceMotionController() && page->deviceMotionController()->isActive()) {
        PCLOG("   -Page is using DeviceMotion");
        cannotCache = true;
    }
    if (page->deviceOrientationController() && page->deviceOrientationController()->isActive()) {
        PCLOG("   -Page is using DeviceOrientation");
        cannotCache = true;
    }
#endif
    if (loadType == FrameLoadTypeReload) {
        PCLOG("   -Load type is: Reload");
        cannotCache = true;
    }
    if (loadType == FrameLoadTypeReloadFromOrigin) {
        PCLOG("   -Load type is: Reload from origin");
        cannotCache = true;
    }
    if (loadType == FrameLoadTypeSame) {
        PCLOG("   -Load type is: Same");
        cannotCache = true;
    }
    
    PCLOG(cannotCache ? " Page CANNOT be cached\n--------" : " Page CAN be cached\n--------");
}

#endif 

PageCache* pageCache()
{
    static PageCache* staticPageCache = new PageCache;
    return staticPageCache;
}

PageCache::PageCache()
    : m_capacity(0)
    , m_size(0)
    , m_head(0)
    , m_tail(0)
    , m_autoreleaseTimer(this, &PageCache::releaseAutoreleasedPagesNowOrReschedule)
{
}
    
bool PageCache::canCachePageContainingThisFrame(Frame* frame)
{
    for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
        if (!canCachePageContainingThisFrame(child))
            return false;
    }
    
    return frame->loader()->documentLoader()
        && frame->loader()->documentLoader()->mainDocumentError().isNull()
        // Do not cache error pages (these can be recognized as pages with substitute data or unreachable URLs).
        && !(frame->loader()->documentLoader()->substituteData().isValid() && !frame->loader()->documentLoader()->substituteData().failingURL().isEmpty())
        // FIXME: If we ever change this so that frames with plug-ins will be cached,
        // we need to make sure that we don't cache frames that have outstanding NPObjects
        // (objects created by the plug-in). Since there is no way to pause/resume a Netscape plug-in,
        // they would need to be destroyed and then recreated, and there is no way that we can recreate
        // the right NPObjects. See <rdar://problem/5197041> for more information.
        && !frame->loader()->subframeLoader()->containsPlugins()
        && !frame->document()->url().protocolIs("https")
        && (!frame->domWindow() || !frame->domWindow()->hasEventListeners(eventNames().unloadEvent))
#if ENABLE(DATABASE)
        && !frame->document()->hasOpenDatabases()
#endif
#if ENABLE(SHARED_WORKERS)
        && !SharedWorkerRepository::hasSharedWorkers(frame->document())
#endif
        && !frame->document()->usingGeolocation()
        && frame->loader()->history()->currentItem()
        && !frame->loader()->quickRedirectComing()
        && !frame->loader()->documentLoader()->isLoadingInAPISense()
        && !frame->loader()->documentLoader()->isStopping()
        && frame->document()->canSuspendActiveDOMObjects()
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
        // FIXME: We should investigating caching frames that have an associated
        // application cache. <rdar://problem/5917899> tracks that work.
        && frame->loader()->documentLoader()->applicationCacheHost()->canCacheInPageCache()
#endif
#if ENABLE(WML)
        && !frame->document()->containsWMLContent()
        && !frame->document()->isWMLDocument()
#endif
        && frame->loader()->client()->canCachePage();
}
    
bool PageCache::canCache(Page* page)
{
    if (!page)
        return false;
    
#ifndef NDEBUG
    logCanCachePageDecision(page);
#endif
    
    // Cache the page, if possible.
    // Don't write to the cache if in the middle of a redirect, since we will want to
    // store the final page we end up on.
    // No point writing to the cache on a reload or loadSame, since we will just write
    // over it again when we leave that page.
    // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they
    // are the most interesting pages on the web, and often those that would benefit the most from caching!
    FrameLoadType loadType = page->mainFrame()->loader()->loadType();
    
    return canCachePageContainingThisFrame(page->mainFrame())
        && page->backForward()->isActive()
        && page->settings()->usesPageCache()
#if ENABLE(DEVICE_ORIENTATION)
        && !(page->deviceMotionController() && page->deviceMotionController()->isActive())
        && !(page->deviceOrientationController() && page->deviceOrientationController()->isActive())
#endif
        && loadType != FrameLoadTypeReload
        && loadType != FrameLoadTypeReloadFromOrigin
        && loadType != FrameLoadTypeSame;
}

void PageCache::setCapacity(int capacity)
{
    ASSERT(capacity >= 0);
    m_capacity = max(capacity, 0);

    prune();
}

int PageCache::frameCount() const
{
    int frameCount = 0;
    for (HistoryItem* current = m_head; current; current = current->m_next) {
        ++frameCount;
        ASSERT(current->m_cachedPage);
        frameCount += current->m_cachedPage ? current->m_cachedPage->cachedMainFrame()->descendantFrameCount() : 0;
    }
    
    return frameCount;
}

int PageCache::autoreleasedPageCount() const
{
    return m_autoreleaseSet.size();
}

void PageCache::markPagesForVistedLinkStyleRecalc()
{
    for (HistoryItem* current = m_head; current; current = current->m_next)
        current->m_cachedPage->markForVistedLinkStyleRecalc();
}

void PageCache::add(PassRefPtr<HistoryItem> prpItem, Page* page)
{
    ASSERT(prpItem);
    ASSERT(page);
    ASSERT(canCache(page));
    
    HistoryItem* item = prpItem.releaseRef(); // Balanced in remove().

    // Remove stale cache entry if necessary.
    if (item->m_cachedPage)
        remove(item);

    item->m_cachedPage = CachedPage::create(page);
    addToLRUList(item);
    ++m_size;
    
    prune();
}

CachedPage* PageCache::get(HistoryItem* item)
{
    if (!item)
        return 0;

    if (CachedPage* cachedPage = item->m_cachedPage.get()) {
        // FIXME: 1800 should not be hardcoded, it should come from
        // WebKitBackForwardCacheExpirationIntervalKey in WebKit.
        // Or we should remove WebKitBackForwardCacheExpirationIntervalKey.
        if (currentTime() - cachedPage->timeStamp() <= 1800)
            return cachedPage;
        
        LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", item->url().string().ascii().data());
        pageCache()->remove(item);
    }
    return 0;
}

void PageCache::remove(HistoryItem* item)
{
    // Safely ignore attempts to remove items not in the cache.
    if (!item || !item->m_cachedPage)
        return;

    autorelease(item->m_cachedPage.release());
    removeFromLRUList(item);
    --m_size;

    item->deref(); // Balanced in add().
}

void PageCache::prune()
{
    while (m_size > m_capacity) {
        ASSERT(m_tail && m_tail->m_cachedPage);
        remove(m_tail);
    }
}

void PageCache::addToLRUList(HistoryItem* item)
{
    item->m_next = m_head;
    item->m_prev = 0;

    if (m_head) {
        ASSERT(m_tail);
        m_head->m_prev = item;
    } else {
        ASSERT(!m_tail);
        m_tail = item;
    }

    m_head = item;
}

void PageCache::removeFromLRUList(HistoryItem* item)
{
    if (!item->m_next) {
        ASSERT(item == m_tail);
        m_tail = item->m_prev;
    } else {
        ASSERT(item != m_tail);
        item->m_next->m_prev = item->m_prev;
    }

    if (!item->m_prev) {
        ASSERT(item == m_head);
        m_head = item->m_next;
    } else {
        ASSERT(item != m_head);
        item->m_prev->m_next = item->m_next;
    }
}

void PageCache::releaseAutoreleasedPagesNowOrReschedule(Timer<PageCache>* timer)
{
    double loadDelta = currentTime() - FrameLoader::timeOfLastCompletedLoad();
    float userDelta = userIdleTime();
    
    // FIXME: <rdar://problem/5211190> This limit of 42 risks growing the page cache far beyond its nominal capacity.
    if ((userDelta < 0.5 || loadDelta < 1.25) && m_autoreleaseSet.size() < 42) {
        LOG(PageCache, "WebCorePageCache: Postponing releaseAutoreleasedPagesNowOrReschedule() - %f since last load, %f since last input, %i objects pending release", loadDelta, userDelta, m_autoreleaseSet.size());
        timer->startOneShot(autoreleaseInterval);
        return;
    }

    LOG(PageCache, "WebCorePageCache: Releasing page caches - %f seconds since last load, %f since last input, %i objects pending release", loadDelta, userDelta, m_autoreleaseSet.size());
    releaseAutoreleasedPagesNow();
}

void PageCache::releaseAutoreleasedPagesNow()
{
    m_autoreleaseTimer.stop();

    // Postpone dead pruning until all our resources have gone dead.
    memoryCache()->setPruneEnabled(false);

    CachedPageSet tmp;
    tmp.swap(m_autoreleaseSet);

    CachedPageSet::iterator end = tmp.end();
    for (CachedPageSet::iterator it = tmp.begin(); it != end; ++it)
        (*it)->destroy();

    // Now do the prune.
    memoryCache()->setPruneEnabled(true);
    memoryCache()->prune();
}

void PageCache::autorelease(PassRefPtr<CachedPage> page)
{
    ASSERT(page);
    ASSERT(!m_autoreleaseSet.contains(page.get()));
    m_autoreleaseSet.add(page);
    if (!m_autoreleaseTimer.isActive())
        m_autoreleaseTimer.startOneShot(autoreleaseInterval);
}

} // namespace WebCore
