/*
 * Copyright (C) 2009 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 "bindings/v8/DateExtension.h"

#include "RuntimeEnabledFeatures.h"
#include "bindings/v8/V8Binding.h"
#include "bindings/v8/V8HiddenPropertyName.h"
#include "bindings/v8/V8ScriptRunner.h"

namespace WebCore {

DateExtension* DateExtension::extension;

static const char* dateExtensionName = "v8/DateExtension";
static const char* dateExtensionScript =
    "(function () {"
    "  var counter;"
    "  var orig_getTime;"
    "  function getTimeOverride() {"
    "    if (++counter > 1000)"
    "      OnSleepDetected();"
    "    return orig_getTime.call(this);"
    "  };"
    "  function enableSleepDetection(enable) {"
    "    if (enable) {"
    "      counter = 0;"
    "      orig_getTime = Date.prototype.getTime;"
    "      Date.prototype.getTime = getTimeOverride;"
    "    } else {"
    "      Date.prototype.getTime = orig_getTime;"
    "    }"
    "  };"
    "  native function Setup();"
    "  native function OnSleepDetected();"
    "  Setup(Date, enableSleepDetection);"
    "})()";

DateExtension::DateExtension() : v8::Extension(dateExtensionName, dateExtensionScript)
{
}

DateExtension* DateExtension::get()
{
    if (!RuntimeEnabledFeatures::dateExtensionEnabled())
        return 0;
    if (!extension)
        extension = new DateExtension();
    return extension;
}

void DateExtension::setAllowSleep(bool allow, v8::Isolate* isolate)
{
    v8::Local<v8::Value> result = v8::Context::GetCurrent()->Global()->Get(v8::String::NewSymbol("Date"));
    if (result.IsEmpty() || !result->IsObject())
        return;

    v8::Handle<v8::Object> dateObject = v8::Handle<v8::Object>::Cast(result);
    if (dateObject.IsEmpty())
        return;

    v8::Local<v8::Value> sleepFunctionHandle = dateObject->GetHiddenValue(V8HiddenPropertyName::sleepFunction(isolate));
    if (sleepFunctionHandle.IsEmpty() || !sleepFunctionHandle->IsFunction())
        return;

    v8::Handle<v8::Value> argv[1];
    argv[0] = v8::Boolean::New(!allow);
    V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(sleepFunctionHandle), v8::Object::New(), WTF_ARRAY_LENGTH(argv), argv, isolate);
}

v8::Handle<v8::FunctionTemplate> DateExtension::GetNativeFunction(v8::Handle<v8::String> name)
{
    if (name->Equals(v8::String::NewSymbol("Setup")))
        return v8::FunctionTemplate::New(Setup);
    if (name->Equals(v8::String::NewSymbol("OnSleepDetected")))
        return v8::FunctionTemplate::New(OnSleepDetected);

    return v8::Handle<v8::FunctionTemplate>();
}

void DateExtension::Setup(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    if (args.Length() != 2 || !args[0]->IsObject() || !args[1]->IsFunction())
        return;

    v8::Handle<v8::Object> dateObject = v8::Handle<v8::Object>::Cast(args[0]);
    v8::Handle<v8::Function> enableSleepDetectionFunction = v8::Handle<v8::Function>::Cast(args[1]);

    dateObject->SetHiddenValue(V8HiddenPropertyName::sleepFunction(args.GetIsolate()), enableSleepDetectionFunction);
    return;
}

void DateExtension::OnSleepDetected(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    throwError(v8GeneralError, "Too much time spent in unload handler.", args.GetIsolate());
}

}  // namespace WebCore
