// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_PROXY_H__
#define V8_PROXY_H__

#include <v8.h>
#include "v8_index.h"
#include "v8_custom.h"
#include "V8Utilities.h"
#include "Node.h"
#include "NodeFilter.h"
#include "PlatformString.h"  // for WebCore::String
#include "ScriptSourceCode.h"  // for WebCore::ScriptSourceCode
#include "SecurityOrigin.h"  // for WebCore::SecurityOrigin
#include "V8DOMMap.h"
#include <wtf/Assertions.h>
#include <wtf/PassRefPtr.h> // so generated bindings don't have to
#include <wtf/Vector.h>

#if defined(ENABLE_DOM_STATS_COUNTERS) && PLATFORM(CHROMIUM)
#include "ChromiumBridge.h"
#define INC_STATS(name) ChromiumBridge::incrementStatsCounter(name)
#else
#define INC_STATS(name)
#endif

// FIXME: Remove the following hack when we replace all references to GetDOMObjectMap.
#define GetDOMObjectMap getDOMObjectMap

namespace WebCore {

class CSSStyleDeclaration;
class DOMImplementation;
class Element;
class Event;
class EventListener;
class Frame;
class HTMLCollection;
class HTMLOptionsCollection;
class HTMLElement;
class HTMLDocument;
class MediaList;
class NamedNodeMap;
class Node;
class NodeList;
class Screen;
class String;
class StyleSheet;
class SVGElement;
class DOMWindow;
class Document;
class EventTarget;
class Event;
class EventListener;
class Navigator;
class MimeType;
class MimeTypeArray;
class Plugin;
class PluginArray;
class StyleSheetList;
class CSSValue;
class CSSRule;
class CSSRuleList;
class CSSValueList;
class NodeFilter;
class ScriptExecutionContext;

#if ENABLE(SVG)
class SVGElementInstance;
#endif

class V8EventListener;
class V8ObjectEventListener;

// This is a container for V8EventListener objects that also does some
// caching to speed up finding entries by v8::Object.
class V8EventListenerList {
 public:
  static const size_t kMaxKeyNameLength = 254;
  // The name should be distinct from any other V8EventListenerList
  // within the same process, and <= kMaxKeyNameLength characters.
  explicit V8EventListenerList(const char* name);
  ~V8EventListenerList();

  typedef Vector<V8EventListener*>::iterator iterator;
  V8EventListenerList::iterator begin();
  iterator end();

  // In addition to adding the listener to this list, this also caches the
  // V8EventListener as a hidden property on its wrapped v8 listener object,
  // so we can quickly look it up later.
  void add(V8EventListener*);
  void remove(V8EventListener*);
  V8EventListener* find(v8::Local<v8::Object>, bool isInline);
  void clear();

 private:
   v8::Handle<v8::String> getKey(bool isInline);
   v8::Persistent<v8::String> m_inlineKey;
   v8::Persistent<v8::String> m_nonInlineKey;
   Vector<V8EventListener*> m_list;
};


// TODO(fqian): use standard logging facilities in WebCore.
void log_info(Frame* frame, const String& msg, const String& url);


#ifndef NDEBUG

#define GlobalHandleTypeList(V) \
  V(PROXY)                      \
  V(NPOBJECT)                   \
  V(SCHEDULED_ACTION)           \
  V(EVENT_LISTENER)             \
  V(NODE_FILTER)                \
  V(SCRIPTINSTANCE)             \
  V(SCRIPTVALUE)


// Host information of persistent handles.
enum GlobalHandleType {
#define ENUM(name) name,
  GlobalHandleTypeList(ENUM)
#undef ENUM
};


class GlobalHandleInfo {
 public:
  GlobalHandleInfo(void* host, GlobalHandleType type)
      : host_(host), type_(type) { }
  void* host_;
  GlobalHandleType type_;
};

#endif  // NDEBUG

// The following Batch structs and methods are used for setting multiple
// properties on an ObjectTemplate, used from the generated bindings
// initialization (ConfigureXXXTemplate).  This greatly reduces the binary
// size by moving from code driven setup to data table driven setup.

// BatchedAttribute translates into calls to SetAccessor() on either the
// instance or the prototype ObjectTemplate, based on |on_proto|.
struct BatchedAttribute {
  const char* const name;
  v8::AccessorGetter getter;
  v8::AccessorSetter setter;
  V8ClassIndex::V8WrapperType data;
  v8::AccessControl settings;
  v8::PropertyAttribute attribute;
  bool on_proto;
};

void BatchConfigureAttributes(v8::Handle<v8::ObjectTemplate> inst,
                              v8::Handle<v8::ObjectTemplate> proto,
                              const BatchedAttribute* attrs,
                              size_t num_attrs);

// BatchedConstant translates into calls to Set() for setting up an object's
// constants.  It sets the constant on both the FunctionTemplate |desc| and the
// ObjectTemplate |proto|.  PropertyAttributes is always ReadOnly.
struct BatchedConstant {
  const char* const name;
  int value;
};

void BatchConfigureConstants(v8::Handle<v8::FunctionTemplate> desc,
                             v8::Handle<v8::ObjectTemplate> proto,
                             const BatchedConstant* consts,
                             size_t num_consts);

const int kMaxRecursionDepth = 20;

// Information about an extension that is registered for use with V8. If scheme
// is non-empty, it contains the URL scheme the extension should be used with.
// Otherwise, the extension is used with all schemes.
struct V8ExtensionInfo {
  String scheme;
  v8::Extension* extension;
};
typedef WTF::Vector<V8ExtensionInfo> V8ExtensionList;

class V8Proxy {
 public:
  // The types of javascript errors that can be thrown.
  enum ErrorType {
    RANGE_ERROR,
    REFERENCE_ERROR,
    SYNTAX_ERROR,
    TYPE_ERROR,
    GENERAL_ERROR
  };

  explicit V8Proxy(Frame* frame)
      : m_frame(frame), m_event_listeners("m_event_listeners"),
        m_xhr_listeners("m_xhr_listeners"), m_inlineCode(false),
        m_timerCallback(false), m_recursion(0) { }

  ~V8Proxy();

  Frame* frame() { return m_frame; }

  // Clear page-specific data, but keep the global object identify.
  void clearForNavigation();

  // Clear page-specific data before shutting down the proxy object.
  void clearForClose();

  // Update document object of the frame.
  void updateDocument();

  // Update the security origin of a document
  // (e.g., after setting docoument.domain).
  void updateSecurityOrigin();

  // Destroy the global object.
  void DestroyGlobal();

  // TODO(mpcomplete): Need comment.  User Gesture related.
  bool inlineCode() const { return m_inlineCode; }
  void setInlineCode(bool value) { m_inlineCode = value; }

  bool timerCallback() const { return m_timerCallback; }
  void setTimerCallback(bool value) { m_timerCallback = value; }

  // Has the context for this proxy been initialized?
  bool ContextInitialized();

  // Disconnects the proxy from its owner frame,
  // and clears all timeouts on the DOM window.
  void disconnectFrame();

  bool isEnabled();

  // Find/Create/Remove event listener wrappers.
  PassRefPtr<V8EventListener> FindV8EventListener(v8::Local<v8::Value> listener,
                                       bool html);
  PassRefPtr<V8EventListener> FindOrCreateV8EventListener(v8::Local<v8::Value> listener,
                                               bool html);

  PassRefPtr<V8EventListener> FindObjectEventListener(v8::Local<v8::Value> listener,
                                        bool html);
  PassRefPtr<V8EventListener> FindOrCreateObjectEventListener(v8::Local<v8::Value> listener,
                                                bool html);

  void RemoveV8EventListener(V8EventListener* listener);
  void RemoveObjectEventListener(V8ObjectEventListener* listener);

  // Protect/Unprotect JS wrappers of a DOM object.
  static void GCProtect(void* dom_object);
  static void GCUnprotect(void* dom_object);

  // Create a lazy event listener.
  PassRefPtr<EventListener> createInlineEventListener(
      const String& functionName, const String& code, Node* node);
#if ENABLE(SVG)
  PassRefPtr<EventListener> createSVGEventHandler(
      const String& functionName, const String& code, Node* node);

  static void SetSVGContext(void* object, SVGElement* context);
  static SVGElement* GetSVGContext(void* object);
#endif

  void setEventHandlerLineno(int lineno) { m_handlerLineno = lineno; }
  void finishedWithEvent(Event* event) { }

  // Evaluate JavaScript in a new context. The script gets its own global scope
  // and its own prototypes for intrinsic JavaScript objects (String, Array,
  // and so-on). It shares the wrappers for all DOM nodes and DOM constructors.
  void evaluateInNewContext(const Vector<ScriptSourceCode>& sources);

  // Evaluate a script file in the current execution environment.
  // The caller must hold an execution context.
  // If cannot evalute the script, it returns an error.
  v8::Local<v8::Value> evaluate(const ScriptSourceCode& source,
                                Node* node);

  // Run an already compiled script.
  v8::Local<v8::Value> RunScript(v8::Handle<v8::Script> script,
                                 bool inline_code);

  // Call the function with the given receiver and arguments.
  v8::Local<v8::Value> CallFunction(v8::Handle<v8::Function> function,
                                    v8::Handle<v8::Object> receiver,
                                    int argc,
                                    v8::Handle<v8::Value> argv[]);

  // Returns the dom constructor function for the given node type.
  v8::Local<v8::Function> GetConstructor(V8ClassIndex::V8WrapperType type);

  // To create JS Wrapper objects, we create a cache of a 'boiler plate'
  // object, and then simply Clone that object each time we need a new one.
  // This is faster than going through the full object creation process.
  v8::Local<v8::Object> CreateWrapperFromCache(V8ClassIndex::V8WrapperType type);

  // Returns the window object of the currently executing context.
  static DOMWindow* retrieveWindow();
  // Returns the window object associated with a context.
  static DOMWindow* retrieveWindow(v8::Handle<v8::Context> context);
  // Returns V8Proxy object of the currently executing context.
  static V8Proxy* retrieve();
  // Returns V8Proxy object associated with a frame.
  static V8Proxy* retrieve(Frame* frame);
  // Returns V8Proxy object associated with a script execution context.
  static V8Proxy* retrieve(ScriptExecutionContext* context);

  // Returns the frame object of the window object associated
  // with the currently executing context.
  static Frame* retrieveFrame();
  // Returns the frame object of the window object associated with
  // a context.
  static Frame* retrieveFrame(v8::Handle<v8::Context> context);
  // Returns the frame that started JS execution.
  // NOTE: cannot declare retrieveActiveFrame as inline function,
  // VS complains at linking time.
  static Frame* retrieveActiveFrame();

  // Returns V8 Context of a frame. If none exists, creates
  // a new context.  It is potentially slow and consumes memory.
  static v8::Local<v8::Context> GetContext(Frame* frame);
  static v8::Local<v8::Context> GetCurrentContext();

  // If the current context causes out of memory, JavaScript setting
  // is disabled and it returns true.
  static bool HandleOutOfMemory();

  // Check if the active execution context can access the target frame.
  static bool CanAccessFrame(Frame* target, bool report_error);

  // Check if it is safe to access the given node from the
  // current security context.
  static bool CheckNodeSecurity(Node* node);

  static v8::Handle<v8::Value> CheckNewLegal(const v8::Arguments& args);

  // Create a V8 wrapper for a C pointer
  static v8::Handle<v8::Value> WrapCPointer(void* cptr) {
    // Represent void* as int
    int addr = reinterpret_cast<int>(cptr);
    ASSERT((addr & 0x01) == 0);  // the address must be aligned.
    return v8::Integer::New(addr >> 1);
  }

  // Take C pointer out of a v8 wrapper
  template <class C>
  static C* ExtractCPointer(v8::Handle<v8::Value> obj) {
    return static_cast<C*>(ExtractCPointerImpl(obj));
  }

  static v8::Handle<v8::Script> CompileScript(v8::Handle<v8::String> code,
                                              const String& fileName,
                                              int baseLine);

#ifndef NDEBUG
  // Checks if a v8 value can be a DOM wrapper
  static bool MaybeDOMWrapper(v8::Handle<v8::Value> value);
#endif

  // Sets contents of a DOM wrapper.
  static void SetDOMWrapper(v8::Handle<v8::Object> obj, int type, void* ptr);

  static v8::Handle<v8::Object> LookupDOMWrapper(
    V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> value);

  // A helper function extract native object pointer from a DOM wrapper
  // and cast to the specified type.
  template <class C>
  static C* DOMWrapperToNative(v8::Handle<v8::Value> object) {
    ASSERT(MaybeDOMWrapper(object));
    v8::Handle<v8::Value> ptr =
      v8::Handle<v8::Object>::Cast(object)->GetInternalField(
          V8Custom::kDOMWrapperObjectIndex);
    return ExtractCPointer<C>(ptr);
  }

  // A help function extract a node type pointer from a DOM wrapper.
  // Wrapped pointer must be cast to Node* first.
  template <class C>
  static C* DOMWrapperToNode(v8::Handle<v8::Value> value) {
    ASSERT(MaybeDOMWrapper(value));

    v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);

    ASSERT(GetDOMWrapperType(object) == V8ClassIndex::NODE);

    v8::Handle<v8::Value> wrapper =
       object->GetInternalField(V8Custom::kDOMWrapperObjectIndex);
    return static_cast<C*>(ExtractCPointer<Node>(wrapper));
  }

  template<typename T>
  static v8::Handle<v8::Value> ToV8Object(V8ClassIndex::V8WrapperType type, PassRefPtr<T> imp)
  {
    return ToV8Object(type, imp.get());
  }
  static v8::Handle<v8::Value> ToV8Object(V8ClassIndex::V8WrapperType type,
                                          void* imp);
  // Fast-path for Node objects.
  static v8::Handle<v8::Value> NodeToV8Object(Node* node);

  template <class C>
  static C* ToNativeObject(V8ClassIndex::V8WrapperType type,
                           v8::Handle<v8::Value> object) {
    return static_cast<C*>(ToNativeObjectImpl(type, object));
  }

  static V8ClassIndex::V8WrapperType GetDOMWrapperType(
      v8::Handle<v8::Object> object);

  // If the exception code is different from zero, a DOM exception is
  // schedule to be thrown.
  static void SetDOMException(int exception_code);

  // Schedule an error object to be thrown.
  static v8::Handle<v8::Value> ThrowError(ErrorType type, const char* message);

  // Create an instance of a function descriptor and set to the global object
  // as a named property. Used by v8_test_shell.
  static void BindJSObjectToWindow(Frame* frame,
                                   const char* name,
                                   int type,
                                   v8::Handle<v8::FunctionTemplate> desc,
                                   void* imp);

  static v8::Handle<v8::Value> EventToV8Object(Event* event);
  static Event* ToNativeEvent(v8::Handle<v8::Value> jsevent) {
    if (!IsDOMEventWrapper(jsevent)) return 0;
    return DOMWrapperToNative<Event>(jsevent);
  }

  static v8::Handle<v8::Value> EventTargetToV8Object(EventTarget* target);
  // Wrap and unwrap JS event listeners
  static v8::Handle<v8::Value> EventListenerToV8Object(EventListener* target);

  // DOMImplementation is a singleton and it is handled in a special
  // way.  A wrapper is generated per document and stored in an
  // internal field of the document.
  static v8::Handle<v8::Value> DOMImplementationToV8Object(
      DOMImplementation* impl);

  // Wrap JS node filter in C++
  static PassRefPtr<NodeFilter> ToNativeNodeFilter(v8::Handle<v8::Value> filter);

  static v8::Persistent<v8::FunctionTemplate> GetTemplate(
      V8ClassIndex::V8WrapperType type);

  template <int tag, typename T>
    static v8::Handle<v8::Value> ConstructDOMObject(const v8::Arguments& args);

  // Checks whether a DOM object has a JS wrapper.
  static bool DOMObjectHasJSWrapper(void* obj);
  // Set JS wrapper of a DOM object, the caller in charge of increase ref.
  static void SetJSWrapperForDOMObject(void* obj,
                                       v8::Persistent<v8::Object> wrapper);
  static void SetJSWrapperForActiveDOMObject(void* obj,
                                             v8::Persistent<v8::Object> wrapper);
  static void SetJSWrapperForDOMNode(Node* node,
                                     v8::Persistent<v8::Object> wrapper);

  // Process any pending JavaScript console messages.
  static void ProcessConsoleMessages();

#ifndef NDEBUG
  // For debugging and leak detection purpose
  static void RegisterGlobalHandle(GlobalHandleType type,
                                   void* host,
                                   v8::Persistent<v8::Value> handle);
  static void UnregisterGlobalHandle(void* host,
                                     v8::Persistent<v8::Value> handle);
#endif

  // Check whether a V8 value is a wrapper of type |classType|.
  static bool IsWrapperOfType(v8::Handle<v8::Value> obj,
                              V8ClassIndex::V8WrapperType classType);

  // Function for retrieving the line number and source name for the top
  // JavaScript stack frame.
  static int GetSourceLineNumber();
  static String GetSourceName();


  // Returns a local handle of the context.
  v8::Local<v8::Context> GetContext() {
    return v8::Local<v8::Context>::New(m_context);
  }

  // Registers an extension to be available on webpages with a particular scheme
  // If the scheme argument is empty, the extension is available on all pages.
  // Will only affect v8 contexts initialized after this call. Takes ownership
  // of the v8::Extension object passed.
  static void RegisterExtension(v8::Extension* extension,
                                const String& schemeRestriction);

 private:
  v8::Persistent<v8::Context> createNewContext(v8::Handle<v8::Object> global);
  void InitContextIfNeeded();
  void DisconnectEventListeners();
  void SetSecurityToken();
  void ClearDocumentWrapper();
  void UpdateDocumentWrapper(v8::Handle<v8::Value> wrapper);
  // Dispose global handles of m_contexts and friends.
  void DisposeContextHandles();

  static bool CanAccessPrivate(DOMWindow* target);

  // Check whether a V8 value is a DOM Event wrapper
  static bool IsDOMEventWrapper(v8::Handle<v8::Value> obj);

  static void* ToNativeObjectImpl(V8ClassIndex::V8WrapperType type,
                                  v8::Handle<v8::Value> object);

  // Take C pointer out of a v8 wrapper
  static void* ExtractCPointerImpl(v8::Handle<v8::Value> obj) {
    ASSERT(obj->IsNumber());
    int addr = obj->Int32Value();
    return reinterpret_cast<void*>(addr << 1);
  }


  static v8::Handle<v8::Value> StyleSheetToV8Object(StyleSheet* sheet);
  static v8::Handle<v8::Value> CSSValueToV8Object(CSSValue* value);
  static v8::Handle<v8::Value> CSSRuleToV8Object(CSSRule* rule);
  // Returns the JS wrapper of a window object, initializes the environment
  // of the window frame if needed.
  static v8::Handle<v8::Value> WindowToV8Object(DOMWindow* window);

#if ENABLE(SVG)
  static v8::Handle<v8::Value> SVGElementInstanceToV8Object(
      SVGElementInstance* instance);
  static v8::Handle<v8::Value> SVGObjectWithContextToV8Object(
      V8ClassIndex::V8WrapperType type, void* object);
#endif

  // Set hidden references in a DOMWindow object of a frame.
  static void SetHiddenWindowReference(Frame* frame,
                                       const int internal_index,
                                       v8::Handle<v8::Object> jsobj);

  static V8ClassIndex::V8WrapperType GetHTMLElementType(HTMLElement* elm);

  // The first parameter, desc_type, specifies the function descriptor
  // used to create JS object. The second parameter, cptr_type, specifies
  // the type of third parameter, impl, for type casting.
  // For example, a HTML element has HTMLELEMENT desc_type, but always
  // use NODE as cptr_type. JS wrapper stores cptr_type and impl as
  // internal fields.
  static v8::Local<v8::Object> InstantiateV8Object(
      V8ClassIndex::V8WrapperType desc_type,
      V8ClassIndex::V8WrapperType cptr_type,
      void* impl);

  static const char* GetRangeExceptionName(int exception_code);
  static const char* GetEventExceptionName(int exception_code);
  static const char* GetXMLHttpRequestExceptionName(int exception_code);
  static const char* GetDOMExceptionName(int exception_code);

#if ENABLE(XPATH)
  static const char* GetXPathExceptionName(int exception_code);
#endif

#if ENABLE(SVG)
  static V8ClassIndex::V8WrapperType GetSVGElementType(SVGElement* elm);
  static const char* GetSVGExceptionName(int exception_code);
#endif

  // Create and populate the utility context.
  static void CreateUtilityContext();

  // Returns a local handle of the utility context.
  static v8::Local<v8::Context> GetUtilityContext() {
    if (m_utilityContext.IsEmpty()) {
      CreateUtilityContext();
    }
    return v8::Local<v8::Context>::New(m_utilityContext);
  }

  Frame* m_frame;

  v8::Persistent<v8::Context> m_context;
  // For each possible type of wrapper, we keep a boilerplate object.
  // The boilerplate is used to create additional wrappers of the same type.
  // We keep a single persistent handle to an array of the activated
  // boilerplates.
  v8::Persistent<v8::Array> m_wrapper_boilerplates;
  v8::Persistent<v8::Value> m_object_prototype;

  v8::Persistent<v8::Object> m_global;
  v8::Persistent<v8::Value> m_document;

  // Utility context holding JavaScript functions used internally.
  static v8::Persistent<v8::Context> m_utilityContext;

  int m_handlerLineno;

  // A list of event listeners created for this frame,
  // the list gets cleared when removing all timeouts.
  V8EventListenerList m_event_listeners;

  // A list of event listeners create for XMLHttpRequest object for this frame,
  // the list gets cleared when removing all timeouts.
  V8EventListenerList m_xhr_listeners;

  // True for <a href="javascript:foo()"> and false for <script>foo()</script>.
  // Only valid during execution.
  bool m_inlineCode;

  // True when executing from within a timer callback.  Only valid during
  // execution.
  bool m_timerCallback;

  // Track the recursion depth to be able to avoid too deep recursion. The V8
  // engine allows much more recursion than KJS does so we need to guard against
  // excessive recursion in the binding layer.
  int m_recursion;

  // List of extensions registered with the context.
  static V8ExtensionList m_extensions;
};

template <int tag, typename T>
v8::Handle<v8::Value> V8Proxy::ConstructDOMObject(const v8::Arguments& args) {
  if (!args.IsConstructCall()) {
    V8Proxy::ThrowError(V8Proxy::TYPE_ERROR,
        "DOM object constructor cannot be called as a function.");
    return v8::Undefined();
  }


  // Note: it's OK to let this RefPtr go out of scope because we also call
  // SetDOMWrapper(), which effectively holds a reference to obj.
  RefPtr<T> obj = T::create();
  V8Proxy::SetDOMWrapper(args.Holder(), tag, obj.get());
  obj->ref();
  V8Proxy::SetJSWrapperForDOMObject(
      obj.get(), v8::Persistent<v8::Object>::New(args.Holder()));
  return args.Holder();
}

}  // namespace WebCore

#endif  // V8_PROXY_H__
