/* Binding to generate window interface * * Copyright 2012 Vincent Sanders * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * Released under the terms of the MIT License, * http://www.opensource.org/licenses/mit-license */ webidlfile "html.idl"; webidlfile "dom.idl"; webidlfile "console.idl"; hdrcomment "Copyright 2012 Vincent Sanders "; hdrcomment "This file is part of NetSurf, http://www.netsurf-browser.org/"; hdrcomment "Released under the terms of the MIT License,"; hdrcomment " http://www.opensource.org/licenses/mit-license"; preamble %{ #include #include "utils/config.h" #include "utils/log.h" #include "utils/corestrings.h" #include "render/html_internal.h" #include "javascript/jsapi.h" #include "console.h" #include "navigator.h" #include "event.h" #include "node.h" #include "htmlcollection.h" #include "nodelist.h" #include "htmldocument.h" #include "text.h" #include "comment.h" #include "htmlelement.h" #include "window.h" #include "location.h" struct browser_window *jsapi_get_browser_window(JSContext *cx); %} prologue %{ struct browser_window *jsapi_get_browser_window(JSContext *cx) { struct jsclass_private *private; private = JS_GetInstancePrivate(cx, JS_GetGlobalObject(cx), &JSClass_Window, NULL); if (private != NULL) { return private->bw; } return NULL; } static bool init_user_prototypes(JSContext *cx, struct jsclass_private *private, JSObject *parent) { /* Initialises all the user javascript classes to make their * prototypes available. */ /** @todo should we be managing these prototype objects ourselves */ private->prototype_Document = jsapi_InitClass_Document(cx, parent); if (private->prototype_Document == NULL) { return false; } private->prototype_Navigator = jsapi_InitClass_Navigator(cx, parent); if (private->prototype_Navigator == NULL) { return false; } private->prototype_Location = jsapi_InitClass_Location(cx, parent); if (private->prototype_Location == NULL) { return false; } private->prototype_Console = jsapi_InitClass_Console(cx, parent); if (private->prototype_Console == NULL) { return false; } private->prototype_HTMLElement = jsapi_InitClass_HTMLElement(cx, parent); if (private->prototype_HTMLElement == NULL) { return false; } private->prototype_HTMLCollection = jsapi_InitClass_HTMLCollection(cx, parent); if (private->prototype_HTMLCollection == NULL) { return false; } private->prototype_NodeList = jsapi_InitClass_NodeList(cx, parent); if (private->prototype_NodeList == NULL) { return false; } private->prototype_Text = jsapi_InitClass_Text(cx, parent); if (private->prototype_Text == NULL) { return false; } private->prototype_Comment = jsapi_InitClass_Comment(cx, parent); if (private->prototype_Comment == NULL) { return false; } private->prototype_Node = jsapi_InitClass_Node(cx, parent); if (private->prototype_Node == NULL) { return false; } private->prototype_Event = jsapi_InitClass_Event(cx, parent); if (private->prototype_Event == NULL) { return false; } return true; } %} binding window { type js_libdom; /* the binding type */ interface Window; /* Web IDL interface to generate */ private "struct browser_window *" bw; private "struct html_content *" htmlc; /* prototypes held in this object */ internal "JSObject *" prototype_Document; internal "JSObject *" prototype_Navigator; internal "JSObject *" prototype_Location; internal "JSObject *" prototype_Console; internal "JSObject *" prototype_HTMLElement; internal "JSObject *" prototype_HTMLCollection; internal "JSObject *" prototype_NodeList; internal "JSObject *" prototype_Text; internal "JSObject *" prototype_Comment; internal "JSObject *" prototype_Node; internal "JSObject *" prototype_Event; /** document instantiated on first use */ property unshared document; /** navigator instantiated on first use */ property unshared navigator; /** console instantiated on first use */ property unshared console; /** location is unshared */ property unshared location; /** @todo instantiate forms, history etc. attributes */ /* events through a single interface */ property unshared type EventHandler; } api mark %{ if (private != NULL) { if (private->prototype_Document != NULL) { JSAPI_GCMARK(private->prototype_Document); } if (private->prototype_Navigator != NULL) { JSAPI_GCMARK(private->prototype_Navigator); } if (private->prototype_Location != NULL) { JSAPI_GCMARK(private->prototype_Location); } if (private->prototype_Console != NULL) { JSAPI_GCMARK(private->prototype_Console); } if (private->prototype_HTMLElement != NULL) { JSAPI_GCMARK(private->prototype_HTMLElement); } if (private->prototype_HTMLCollection != NULL) { JSAPI_GCMARK(private->prototype_HTMLCollection); } if (private->prototype_NodeList != NULL) { JSAPI_GCMARK(private->prototype_NodeList); } if (private->prototype_Text != NULL) { JSAPI_GCMARK(private->prototype_Text); } if (private->prototype_Comment != NULL) { JSAPI_GCMARK(private->prototype_Comment); } if (private->prototype_Node != NULL) { JSAPI_GCMARK(private->prototype_Node); } if (private->prototype_Event != NULL) { JSAPI_GCMARK(private->prototype_Event); } } %} api global %{ %} api init %{ prototype = JS_NewCompartmentAndGlobalObject(cx, &JSClass_Window, NULL); if (prototype == NULL) { return NULL; } /** @todo reconsider global object handling. future * editions of spidermonkey appear to be removing the * idea of a global so we probably need to handle * global object references internally */ /* set the contexts global */ JS_SetGlobalObject(cx, prototype); /* Populate the global object with the standard globals, like * Object and Array. */ if (!JS_InitStandardClasses(cx, prototype)) { return NULL; } /* add functions to prototype */ if (!JS_DefineFunctions(cx, prototype, jsclass_functions)) { return NULL; } /* add properties to prototype */ if (!JS_DefineProperties(cx, prototype, jsclass_properties)) return NULL; /* as the global just got changed, force a GC run */ JS_GC(cx); %} api new %{ /* @todo sort out windows that are not globals */ assert(parent == NULL); /* the window object is the global so its prototype *is* the instance */ newobject = prototype; if (init_user_prototypes(cx, private, prototype) == false) { /* prototype initialisation failed */ free(private); return NULL; } LOG("Created new window object %p", newobject); %} getter document %{ if (!JSVAL_IS_VOID(JSAPI_PROP_RVAL(cx, vp))) { /* already created - return it */ return JS_TRUE; } /* instantiate the subclasses off the window global */ jsret = jsapi_new_Document(cx, NULL, NULL, (dom_document *)dom_node_ref(private->htmlc->document), private->htmlc); %} getter navigator %{ if (!JSVAL_IS_VOID(JSAPI_PROP_RVAL(cx, vp))) { /* already created - return it */ return JS_TRUE; } jsret = jsapi_new_Navigator(cx, NULL, NULL); %} getter console %{ if (!JSVAL_IS_VOID(JSAPI_PROP_RVAL(cx, vp))) { /* already created - return it */ return JS_TRUE; } jsret = jsapi_new_Console(cx, NULL, NULL); %} operation confirm %{ warn_user(message, NULL); %} operation alert %{ warn_user(message, NULL); %} operation prompt %{ warn_user(message, NULL); %} /* boolean dispatchEvent(Event event); */ operation dispatchEvent %{ /* this implementation is unique to the window object as it is * not a "real" dom node. */ /* caution, this must match the struct generated from event.bnd */ struct { dom_event *event; } *event_private; dom_string *type_dom = NULL; dom_exception exc; jsval eventval = JSVAL_VOID; jsval event_argv[1]; jsval event_rval; event_private = JS_GetInstancePrivate(cx, event, &JSClass_Event, NULL); if (event_private->event == NULL) { /** @todo type error? */ jsret = JS_FALSE; } else { exc = dom_event_get_type(event_private->event, &type_dom); if (exc == DOM_NO_ERR) { if (dom_string_isequal(type_dom, corestring_dom_load)) { JS_GetProperty(cx, JSAPI_THIS_OBJECT(cx, vp), "onload", &eventval); } if (!JSVAL_IS_VOID(eventval)) { event_argv[0] = eventval; jsret = JS_CallFunctionValue(cx, NULL, eventval, 1, event_argv, &event_rval); } } } %} getter location %{ if (!JSVAL_IS_VOID(JSAPI_PROP_RVAL(cx, vp))) { /* already created - return it */ return JS_TRUE; } /* should get the docuemnts location jsval loc; JS_GetProperty(cx, private->document, "location", &loc); jsret = JSVAL_TO_OBJECT(loc); */ jsret = jsapi_new_Location(cx, NULL, NULL, llcache_handle_get_url(private->htmlc->base.llcache)); %} getter window %{ jsret = obj; %} getter self %{ jsret = obj; %} /* very iffy implementation */ getter top %{ jsret = obj; %} getter EventHandler %{ /* this implementation is unique to the window object as it is * not a dom node. */ JSLOG("propname[%d]=\"%s\"", tinyid, jsclass_properties[tinyid].name); %} setter EventHandler %{ /* this implementation is unique to the window object as it is * not a dom node. */ JSLOG("propname[%d]=\"%s\"", tinyid, jsclass_properties[tinyid].name); %}