/*
 * Copyright 2009, The Android Open Source Project
 *
 * 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.
 */

#include "config.h"
#include "GeolocationPermissions.h"

#include "WebViewCore.h"

#include <DOMWindow.h>
#include <Frame.h>
#include <Geolocation.h>
#include <Navigator.h>
#include <SQLiteDatabase.h>
#include <SQLiteFileSystem.h>
#include <SQLiteStatement.h>
#include <SQLiteTransaction.h>
#include <text/CString.h>

using namespace WebCore;

namespace android {

GeolocationPermissions::PermissionsMap GeolocationPermissions::s_permanentPermissions;
GeolocationPermissions::GeolocationPermissionsVector GeolocationPermissions::s_instances;
bool GeolocationPermissions::s_alwaysDeny = false;
bool GeolocationPermissions::s_permanentPermissionsLoaded = false;
bool GeolocationPermissions::s_permanentPermissionsModified = false;
String GeolocationPermissions::s_databasePath;

static const char* databaseName = "GeolocationPermissions.db";

GeolocationPermissions::GeolocationPermissions(WebViewCore* webViewCore)
    : m_webViewCore(webViewCore)
    , m_timer(this, &GeolocationPermissions::timerFired)

{
    ASSERT(m_webViewCore);
    maybeLoadPermanentPermissions();
    s_instances.append(this);
}

GeolocationPermissions::~GeolocationPermissions()
{
    size_t index = s_instances.find(this);
    s_instances.remove(index);
}

void GeolocationPermissions::queryPermissionState(Frame* frame)
{
    ASSERT(s_permanentPermissionsLoaded);

    // We use SecurityOrigin::toString to key the map. Note that testing
    // the SecurityOrigin pointer for equality is insufficient.
    String originString = frame->document()->securityOrigin()->toString();

    // If we've been told to always deny requests, do so.
    if (s_alwaysDeny) {
        makeAsynchronousCallbackToGeolocation(originString, false);
        return;
    }

    // See if we have a record for this origin in the permanent permissions.
    // These take precedence over temporary permissions so that changes made
    // from the browser settings work as intended.
    PermissionsMap::const_iterator iter = s_permanentPermissions.find(originString);
    PermissionsMap::const_iterator end = s_permanentPermissions.end();
    if (iter != end) {
        bool allow = iter->second;
        makeAsynchronousCallbackToGeolocation(originString, allow);
        return;
    }

    // Check the temporary permisions.
    iter = m_temporaryPermissions.find(originString);
    end = m_temporaryPermissions.end();
    if (iter != end) {
        bool allow = iter->second;
        makeAsynchronousCallbackToGeolocation(originString, allow);
        return;
    }

    // If there's no pending request, prompt the user.
    if (nextOriginInQueue().isEmpty()) {
        // Although multiple tabs may request permissions for the same origin
        // simultaneously, the routing in WebViewCore/CallbackProxy ensures that
        // the result of the request will make it back to this object, so
        // there's no need for a globally unique ID for the request.
        m_webViewCore->geolocationPermissionsShowPrompt(originString);
    }

    // Add this request to the queue so we can track which frames requested it.
    if (m_queuedOrigins.find(originString) == WTF::notFound) {
        m_queuedOrigins.append(originString);
        FrameSet frameSet;
        frameSet.add(frame);
        m_queuedOriginsToFramesMap.add(originString, frameSet);
    } else {
        ASSERT(m_queuedOriginsToFramesMap.contains(originString));
        m_queuedOriginsToFramesMap.find(originString)->second.add(frame);
    }
}

void GeolocationPermissions::cancelPermissionStateQuery(WebCore::Frame* frame)
{
    // We cancel any queued request for the given frame. There can be at most
    // one of these, since each frame maps to a single origin. We only cancel
    // the request if this frame is the only one reqesting permission for this
    // origin.
    //
    // We can use the origin string to avoid searching the map.
    String originString = frame->document()->securityOrigin()->toString();
    size_t index = m_queuedOrigins.find(originString);
    if (index == WTF::notFound)
        return;

    ASSERT(m_queuedOriginsToFramesMap.contains(originString));
    OriginToFramesMap::iterator iter = m_queuedOriginsToFramesMap.find(originString);
    ASSERT(iter->second.contains(frame));
    iter->second.remove(frame);
    if (!iter->second.isEmpty())
        return;

    m_queuedOrigins.remove(index);
    m_queuedOriginsToFramesMap.remove(iter);

    // If this is the origin currently being shown, cancel the prompt
    // and show the next in the queue, if present.
    if (index == 0) {
        m_webViewCore->geolocationPermissionsHidePrompt();
        if (!nextOriginInQueue().isEmpty())
            m_webViewCore->geolocationPermissionsShowPrompt(nextOriginInQueue());
    }
}

void GeolocationPermissions::makeAsynchronousCallbackToGeolocation(String origin, bool allow)
{
    m_callbackData.origin = origin;
    m_callbackData.allow = allow;
    m_timer.startOneShot(0);
}

void GeolocationPermissions::providePermissionState(String origin, bool allow, bool remember)
{
    ASSERT(s_permanentPermissionsLoaded);

    // It's possible that this method is called with an origin that doesn't
    // match m_originInProgress. This can occur if this object is reset
    // while a permission result is in the process of being marshalled back to
    // the WebCore thread from the browser. In this case, we simply ignore the
    // call.
    if (origin != nextOriginInQueue())
        return;

    maybeCallbackFrames(origin, allow);
    recordPermissionState(origin, allow, remember);

    // If the permissions are set to be remembered, cancel any queued requests
    // for this domain in other tabs.
    if (remember)
        cancelPendingRequestsInOtherTabs(origin);

    // Clear the origin from the queue.
    ASSERT(!m_queuedOrigins.isEmpty());
    m_queuedOrigins.remove(0);
    ASSERT(m_queuedOriginsToFramesMap.contains(origin));
    m_queuedOriginsToFramesMap.remove(origin);

    // If there are other requests queued, start the next one.
    if (!nextOriginInQueue().isEmpty())
        m_webViewCore->geolocationPermissionsShowPrompt(nextOriginInQueue());
}

void GeolocationPermissions::recordPermissionState(String origin, bool allow, bool remember)
{
    if (remember) {
        s_permanentPermissions.set(origin, allow);
        s_permanentPermissionsModified = true;
    } else {
        // It's possible that another tab recorded a permanent permission for
        // this origin while our request was in progress, but we record it
        // anyway.
        m_temporaryPermissions.set(origin, allow);
    }
}

void GeolocationPermissions::cancelPendingRequestsInOtherTabs(String origin)
{
    for (GeolocationPermissionsVector::const_iterator iter = s_instances.begin();
         iter != s_instances.end();
         ++iter)
        (*iter)->cancelPendingRequests(origin);
}

void GeolocationPermissions::cancelPendingRequests(String origin)
{
    size_t index = m_queuedOrigins.find(origin);

    // Don't cancel the request if it's currently being shown, in which case
    // it's at index 0.
    if (index == WTF::notFound || !index)
        return;

    // Get the permission from the permanent list.
    ASSERT(s_permanentPermissions.contains(origin));
    PermissionsMap::const_iterator iter = s_permanentPermissions.find(origin);
    bool allow = iter->second;

    maybeCallbackFrames(origin, allow);

    m_queuedOrigins.remove(index);
    ASSERT(m_queuedOriginsToFramesMap.contains(origin));
    m_queuedOriginsToFramesMap.remove(origin);
}

void GeolocationPermissions::timerFired(Timer<GeolocationPermissions>* timer)
{
    ASSERT_UNUSED(timer, timer == &m_timer);
    maybeCallbackFrames(m_callbackData.origin, m_callbackData.allow);
}

void GeolocationPermissions::resetTemporaryPermissionStates()
{
    ASSERT(s_permanentPermissionsLoaded);
    m_queuedOrigins.clear();
    m_queuedOriginsToFramesMap.clear();
    m_temporaryPermissions.clear();
    // If any permission results are being marshalled back to this thread, this
    // will render them inefective.
    m_timer.stop();

    m_webViewCore->geolocationPermissionsHidePrompt();
}

const WTF::String& GeolocationPermissions::nextOriginInQueue()
{
    static const String emptyString = "";
    return m_queuedOrigins.isEmpty() ? emptyString : m_queuedOrigins[0];
}

void GeolocationPermissions::maybeCallbackFrames(String origin, bool allow)
{
    // We can't track which frame issued the request, as frames can be deleted
    // or have their contents replaced. Even uniqueChildName is not unique when
    // frames are dynamically deleted and created. Instead, we simply call back
    // to the Geolocation object in all frames from the correct origin.
    for (Frame* frame = m_webViewCore->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
        if (origin == frame->document()->securityOrigin()->toString()) {
            // If the page has changed, it may no longer have a Geolocation
            // object.
            Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation();
            if (geolocation)
                geolocation->setIsAllowed(allow);
        }
    }
}

GeolocationPermissions::OriginSet GeolocationPermissions::getOrigins()
{
    maybeLoadPermanentPermissions();
    OriginSet origins;
    PermissionsMap::const_iterator end = s_permanentPermissions.end();
    for (PermissionsMap::const_iterator iter = s_permanentPermissions.begin(); iter != end; ++iter)
        origins.add(iter->first);
    return origins;
}

bool GeolocationPermissions::getAllowed(String origin)
{
    maybeLoadPermanentPermissions();
    bool allowed = false;
    PermissionsMap::const_iterator iter = s_permanentPermissions.find(origin);
    PermissionsMap::const_iterator end = s_permanentPermissions.end();
    if (iter != end)
        allowed = iter->second;
    return allowed;
}

void GeolocationPermissions::clear(String origin)
{
    maybeLoadPermanentPermissions();
    PermissionsMap::iterator iter = s_permanentPermissions.find(origin);
    if (iter != s_permanentPermissions.end()) {
        s_permanentPermissions.remove(iter);
        s_permanentPermissionsModified = true;
    }
}

void GeolocationPermissions::allow(String origin)
{
    maybeLoadPermanentPermissions();
    // We replace any existing permanent permission.
    s_permanentPermissions.set(origin, true);
    s_permanentPermissionsModified = true;
}

void GeolocationPermissions::clearAll()
{
    maybeLoadPermanentPermissions();
    s_permanentPermissions.clear();
    s_permanentPermissionsModified = true;
}

void GeolocationPermissions::maybeLoadPermanentPermissions()
{
    if (s_permanentPermissionsLoaded)
        return;
    s_permanentPermissionsLoaded = true;

    SQLiteDatabase database;
    if (!openDatabase(&database))
        return;

    // Create the table here, such that even if we've just created the DB, the
    // commands below should succeed.
    if (!database.executeCommand("CREATE TABLE IF NOT EXISTS Permissions (origin TEXT UNIQUE NOT NULL, allow INTEGER NOT NULL)")) {
        database.close();
        return;
    }

    SQLiteStatement statement(database, "SELECT * FROM Permissions");
    if (statement.prepare() != SQLResultOk) {
        database.close();
        return;
    }

    ASSERT(s_permanentPermissions.size() == 0);
    while (statement.step() == SQLResultRow)
        s_permanentPermissions.set(statement.getColumnText(0), statement.getColumnInt64(1));

    database.close();
}

void GeolocationPermissions::maybeStorePermanentPermissions()
{
    // If the permanent permissions haven't been modified, there's no need to
    // save them to the DB. (If we haven't even loaded them, writing them now
    // would overwrite the stored permissions with the empty set.)
    if (!s_permanentPermissionsModified)
        return;

    SQLiteDatabase database;
    if (!openDatabase(&database))
        return;

    SQLiteTransaction transaction(database);

    // The number of entries should be small enough that it's not worth trying
    // to perform a diff. Simply clear the table and repopulate it.
    if (!database.executeCommand("DELETE FROM Permissions")) {
        database.close();
        return;
    }

    PermissionsMap::const_iterator end = s_permanentPermissions.end();
    for (PermissionsMap::const_iterator iter = s_permanentPermissions.begin(); iter != end; ++iter) {
         SQLiteStatement statement(database, "INSERT INTO Permissions (origin, allow) VALUES (?, ?)");
         if (statement.prepare() != SQLResultOk)
             continue;
         statement.bindText(1, iter->first);
         statement.bindInt64(2, iter->second);
         statement.executeCommand();
    }

    transaction.commit();
    database.close();

    s_permanentPermissionsModified = false;
}

void GeolocationPermissions::setDatabasePath(String path)
{
    // Take the first non-empty value.
    if (s_databasePath.length() > 0)
        return;
    s_databasePath = path;
}

bool GeolocationPermissions::openDatabase(SQLiteDatabase* database)
{
    ASSERT(database);
    String filename = SQLiteFileSystem::appendDatabaseFileNameToPath(s_databasePath, databaseName);
    if (!database->open(filename))
        return false;
    if (chmod(filename.utf8().data(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) {
        database->close();
        return false;
    }
    return true;
}

void GeolocationPermissions::setAlwaysDeny(bool deny)
{
    s_alwaysDeny = deny;
}

}  // namespace android
