home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libmocha / lm_applt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  10.0 KB  |  368 lines

  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.  * JS reflection of applets in the current document
  21.  */
  22.  
  23. /* Please leave outside of ifdef for windows precompiled headers */
  24. #include "lm.h"
  25.  
  26. #ifdef JAVA
  27.  
  28. #include "xp.h"
  29. #include "layout.h"
  30. #include "java.h"
  31. #include "lj.h"        /* for LJ_InvokeMethod */
  32. #define IMPLEMENT_netscape_applet_MozillaAppletContext
  33. #define IMPLEMENT_netscape_applet_EmbeddedObjectNatives
  34. #ifdef XP_MAC
  35. #include "n_applet_MozillaAppletContext.h"
  36. #include "n_a_EmbeddedObjectNatives.h"
  37. #else
  38. #include "netscape_applet_MozillaAppletContext.h"
  39. #include "netscape_applet_EmbeddedObjectNatives.h"
  40. #endif
  41. #include "jsjava.h"
  42. #include "jsobj.h"
  43. #include "prlog.h"
  44.  
  45. extern PRLogModuleInfo* Moja;
  46. #define debug    PR_LOG_DEBUG
  47. #define warn    PR_LOG_WARN
  48.  
  49. JSClass *lm_java_clasp = NULL;
  50.  
  51. enum applet_array_slot {
  52.     APPLET_ARRAY_LENGTH = -1
  53. };
  54.  
  55. static JSPropertySpec applet_array_props[] = {
  56.     {lm_length_str, APPLET_ARRAY_LENGTH,
  57.             JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT},
  58.     {0}
  59. };
  60.  
  61. extern JSClass lm_applet_array_class;
  62.  
  63. PR_STATIC_CALLBACK(JSBool)
  64. applet_array_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
  65. {
  66.     JSObjectArray *array;
  67.     MochaDecoder *decoder;
  68.     MWContext *context;
  69.     jsint count, slot;
  70.     LO_JavaAppStruct *applet_data;
  71.     int32 active_layer_id;
  72.  
  73.     if (!JSVAL_IS_INT(id))
  74.     return JS_TRUE;
  75.  
  76.     slot = JSVAL_TO_INT(id);
  77.  
  78.     array = JS_GetInstancePrivate(cx, obj, &lm_applet_array_class, NULL);
  79.     if (!array)
  80.     return JS_TRUE;
  81.     decoder = array->decoder;
  82.     context = decoder->window_context;
  83.  
  84.     if (!context) 
  85.     return JS_TRUE;
  86.  
  87.     if (LM_MOJA_OK != ET_InitMoja(context))
  88.     return JS_FALSE;
  89.  
  90.     LO_LockLayout();
  91.  
  92.     switch (slot) {
  93.       case APPLET_ARRAY_LENGTH:
  94.     active_layer_id = LM_GetActiveLayer(context);
  95.     LM_SetActiveLayer(context, array->layer_id);
  96.     count = LO_EnumerateApplets(context, array->layer_id);
  97.     LM_SetActiveLayer(context, active_layer_id);
  98.     if (count > array->length)
  99.         array->length = count;
  100.         *vp = INT_TO_JSVAL(array->length);
  101.     break;
  102.  
  103.       default:
  104.     if (slot < 0) {
  105.         /* Don't mess with user-defined or method properties. */
  106.         LO_UnlockLayout();
  107.         return JS_TRUE;
  108.     }
  109.     applet_data = LO_GetAppletByIndex(context, array->layer_id, 
  110.                                           (uint)slot);
  111.     if (applet_data) {
  112.             JSObject *mo = LM_ReflectApplet(context, applet_data, NULL,
  113.                         array->layer_id, (uint)slot);
  114.  
  115.             if (!mo) {
  116.                 JS_ReportError(cx,
  117.                  "unable to reflect applet \"%s\", index %d - not loaded yet?",
  118.                  applet_data->attr_name, (uint) slot);
  119.                 goto err;
  120.             }
  121.             *vp = OBJECT_TO_JSVAL(mo);
  122.  
  123.             if (slot >= array->length)
  124.                 array->length = slot + 1;
  125.     } else {
  126.             JS_ReportError(cx, "no applet with index %d\n");
  127.         goto err;
  128.         }
  129.     break;
  130.     }
  131.     LO_UnlockLayout();
  132.     return JS_TRUE;
  133.   err:
  134.     LO_UnlockLayout();
  135.     return JS_FALSE;
  136. }
  137.  
  138. PR_STATIC_CALLBACK(void)
  139. applet_array_finalize(JSContext *cx, JSObject *obj)
  140. {
  141.     JSObjectArray *array;
  142.  
  143.     array = JS_GetPrivate(cx, obj);
  144.     if (!array)
  145.     return;
  146.     DROP_BACK_COUNT(array->decoder);
  147.     JS_free(cx, array);
  148. }
  149.  
  150. JSClass lm_applet_array_class = {
  151.     "AppletArray", JSCLASS_HAS_PRIVATE,
  152.     JS_PropertyStub, JS_PropertyStub,
  153.     applet_array_getProperty, applet_array_getProperty, JS_EnumerateStub,
  154.     JS_ResolveStub, JS_ConvertStub, applet_array_finalize
  155. };
  156.  
  157. JSObject *
  158. lm_GetAppletArray(MochaDecoder *decoder, JSObject *document)
  159. {
  160.     JSContext *cx = decoder->js_context;
  161.     JSObject *obj;
  162.     JSObjectArray *array;
  163.     JSDocument *doc;
  164.  
  165.     doc = JS_GetPrivate(cx, document);
  166.     if (!doc)
  167.     return NULL;
  168.  
  169.     obj = doc->applets;
  170.     if (obj)
  171.     return obj;
  172.  
  173.     array = JS_malloc(cx, sizeof *array);
  174.     if (!array)
  175.         return NULL;
  176.     array->decoder = NULL;  /* in case of error below */
  177.  
  178.     obj = JS_NewObject(cx, &lm_applet_array_class, NULL, document);
  179.     if (!obj || !JS_SetPrivate(cx, obj, array)) {
  180.     JS_free(cx, array);    
  181.     return NULL;
  182.     }
  183.  
  184.     if (!JS_DefineProperties(cx, obj, applet_array_props))
  185.     return NULL;
  186.  
  187.     array->decoder = HOLD_BACK_COUNT(decoder);
  188.     array->length = 0;
  189.     array->layer_id = doc->layer_id;
  190.     doc->applets = obj;
  191.  
  192.     return obj;
  193. }
  194.  
  195. static JSObject *
  196. lm_ReallyReflectApplet(MWContext *context, LO_JavaAppStruct *lo_applet,
  197.                        int32 layer_id, uint32 index)
  198. {
  199.     JSObject *obj;
  200.     MochaDecoder *decoder;
  201.     JSContext *cx;
  202.     LJAppletData *ad;
  203.     jref japplet;
  204.     lo_TopState *top_state;
  205.     PRHashTable *map;
  206.  
  207.     PR_LOG(Moja, debug, ("really reflect applet 0x%x\n", lo_applet));
  208.  
  209.      obj = lo_applet->mocha_object;
  210.      if (obj)
  211.         return obj;
  212.  
  213.     decoder = LM_GetMochaDecoder(context);
  214.     if (!decoder)
  215.     return NULL;
  216.     cx = decoder->js_context;
  217.  
  218.     top_state = lo_GetMochaTopState(context);
  219.     if (top_state->resize_reload) {
  220.         map = lm_GetIdToObjectMap(decoder);
  221.         if (map)
  222.             obj = (JSObject *)PR_HashTableLookup(map,
  223.                              LM_GET_MAPPING_KEY(LM_APPLETS, layer_id, index));
  224.  
  225.         if (obj) {
  226.             lo_applet->mocha_object = obj;
  227.             return obj;
  228.         }
  229.     }
  230.  
  231.     /* set the element to something bad if we can't get the java obj */
  232.     if (!JSJ_IsEnabled()) {
  233.         PR_LOG(Moja, debug, ("reflected applet 0x%x as null\n",
  234.                              lo_applet));
  235.         return lo_applet->mocha_object = lm_DummyObject;
  236.     }
  237.  
  238.     ad = (LJAppletData *) lo_applet->session_data;
  239.  
  240.     if (ad) {
  241.         /* MozillaAppletContext.reflectApplet gets the java applet
  242.          * object out of a hash table given the AppletData pointer
  243.          * as an integer */
  244.     if (ad->selector_type != LO_JAVA_SELECTOR_APPLET)
  245.         japplet = LJ_InvokeMethod(classEmbeddedObjectNatives,
  246.         methodID_netscape_applet_EmbeddedObjectNatives_reflectObject,
  247.         ad->docID, ad);
  248.     else
  249.         japplet = LJ_InvokeMethod(classMozillaAppletContext,
  250.         methodID_netscape_applet_MozillaAppletContext_reflectApplet_1,
  251.         ad->docID, ad);
  252.  
  253.         obj = js_ReflectJObjectToJSObject(decoder->js_context,
  254.                                             (HObject *)japplet);
  255.  
  256.         map = lm_GetIdToObjectMap(decoder);
  257.         if (map)
  258.             PR_HashTableAdd(map, 
  259.                             LM_GET_MAPPING_KEY(LM_APPLETS, layer_id, index),
  260.                             obj);
  261.  
  262.         /*
  263.           lj_mozilla_ee->js_context = saved_context;
  264.           */
  265.  
  266.         PR_LOG(Moja, debug, ("reflected applet 0x%x (java 0x%x) to 0x%x ok\n",
  267.                              lo_applet, japplet, obj));
  268.  
  269.         if (obj)
  270.         lm_java_clasp = JS_GetClass(obj);
  271.     return lo_applet->mocha_object = obj;
  272.     } else {
  273.         PR_LOG(Moja, warn, ("failed to reflect applet 0x%x\n", lo_applet));
  274.         return NULL;
  275.     }
  276. }
  277.  
  278.  
  279. /* XXX what happens if this is called before java starts up?
  280.  * or if java is disabled? */
  281.  
  282. JSObject *
  283. LM_ReflectApplet(MWContext *context, LO_JavaAppStruct *applet_data,
  284.                  PA_Tag * tag, int32 layer_id, uint index)
  285. {
  286.     JSObject *obj, *array_obj, *outer_obj, *document;
  287.     MochaDecoder *decoder;
  288.     JSContext *cx;
  289.     char *name;
  290.  
  291.     obj = applet_data->mocha_object;
  292.     if (obj)
  293.         return obj;
  294.  
  295.     decoder = LM_GetMochaDecoder(context);
  296.     if (!decoder)
  297.         return NULL;
  298.     cx = decoder->js_context;
  299.  
  300.     /* get the name */
  301.     if (applet_data->attr_name) {
  302.         name = JS_strdup(cx, (char *) applet_data->attr_name);
  303.     } else {
  304.         name = 0;
  305.     }
  306.  
  307.     /* Get the document object that will hold this applet */
  308.     document = lm_GetDocumentFromLayerId(decoder, layer_id);
  309.     if (!document)
  310.         goto out;
  311.  
  312.     array_obj = lm_GetAppletArray(decoder, document);
  313.     if (!array_obj) {
  314.         obj = 0;
  315.         goto out;
  316.     }
  317.  
  318.     /* XXX should pass thru ReallyReflectApplet to whatever calls NewObject */
  319.     outer_obj = lm_GetOuterObject(decoder);
  320.  
  321.     /* this function does the real work */
  322.     obj = lm_ReallyReflectApplet(context, applet_data, layer_id, index);
  323.  
  324.     if (!obj)
  325.         /* reflection failed.  this usually means that javascript tried
  326.          * to talk to the applet before it was ready.  there's not much
  327.          * we can do about it */
  328.         goto out;
  329.  
  330.     /* put it in the applet array */
  331.     if (!lm_AddObjectToArray(cx, array_obj, name, index, obj)) {
  332.     obj = NULL;
  333.     goto out;
  334.     }
  335.  
  336.     /* put it in the document scope */
  337.     if (name) {
  338.         if (!JS_DefineProperty(cx, outer_obj, name, OBJECT_TO_JSVAL(obj),
  339.                    NULL, NULL, 
  340.                 JSPROP_ENUMERATE | JSPROP_READONLY)) {
  341.             PR_LOG(Moja, warn, ("failed to define applet 0x%x as %s\n",
  342.                                 applet_data, name));
  343.         /* XXX remove it altogether? */
  344.         }
  345.     JS_free(cx, name);
  346.     }
  347.  
  348.     /* cache it in layout data structure XXX lm_ReallyReflectApplet did this */
  349.     XP_ASSERT(applet_data->mocha_object == obj);
  350.  
  351.   out:
  352.     LM_PutMochaDecoder(decoder);
  353.     return obj;
  354. }
  355.  
  356. PRIVATE JSObject *
  357. LM_ReflectNamedApplet(MWContext *context, lo_NameList *name_rec, 
  358.                       int32 layer_id, uint index)
  359. {
  360.     return NULL;
  361. }
  362.  
  363. #else
  364.  
  365. void *lm_java_clasp = NULL;
  366.  
  367. #endif /* JAVA */
  368.