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

  1. /* -*- Mode: C++; tab-width: 4; 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.  * JS reflection of the Navigator Session History.
  20.  *
  21.  * Brendan Eich, 9/8/95
  22.  */
  23. #include "lm.h"
  24. #include "shist.h"
  25. #include "structs.h"
  26.  
  27. enum hist_slot {
  28.     HIST_LENGTH     = -1,
  29.     HIST_CURRENT    = -2,
  30.     HIST_PREVIOUS   = -3,
  31.     HIST_NEXT       = -4
  32. };
  33.  
  34. static JSPropertySpec hist_props[] = {
  35.     {lm_length_str,     HIST_LENGTH,    JSPROP_ENUMERATE|JSPROP_READONLY},
  36.     {"current",         HIST_CURRENT,   JSPROP_ENUMERATE|JSPROP_READONLY},
  37.     {"previous",        HIST_PREVIOUS,  JSPROP_ENUMERATE|JSPROP_READONLY},
  38.     {"next",            HIST_NEXT,      JSPROP_ENUMERATE|JSPROP_READONLY},
  39.     {0}
  40. };
  41.  
  42. typedef struct JSHistory {
  43.     MochaDecoder    *decoder;
  44.     JSObject     *object;
  45. } JSHistory;
  46.  
  47. /*
  48.  * DO NOT REMOVE: 
  49.  *   forward decl of hist_go and early def of hist_forward to work
  50.  *   around a Win16 compiler bug! 
  51.  */
  52. JSBool PR_CALLBACK
  53. hist_go(JSContext *cx, JSObject *obj, unsigned int argc, jsval *argv, jsval *rval);
  54.  
  55. PR_STATIC_CALLBACK(JSBool)
  56. hist_forward(JSContext *cx, JSObject *obj, unsigned int argc, jsval *argv, jsval *rval)
  57. {
  58.     jsval plus_one;
  59.  
  60.     plus_one = INT_TO_JSVAL(1);
  61.     return hist_go(cx, obj, 1, &plus_one, rval);
  62. }
  63.  
  64. extern JSClass lm_hist_class;
  65.  
  66. PR_STATIC_CALLBACK(JSBool)
  67. hist_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
  68. {
  69.     JSHistory *hist;
  70.     MochaDecoder *decoder;
  71.     MWContext *context;
  72.     History_entry *he, *he2;
  73.     JSString *str;
  74.     XP_List *histlist;
  75.     jsint slot;
  76.  
  77.     if (!JSVAL_IS_INT(id))
  78.     return JS_TRUE;
  79.  
  80.     slot = JSVAL_TO_INT(id);
  81.  
  82.     hist = JS_GetInstancePrivate(cx, obj, &lm_hist_class, NULL);
  83.     if (!hist)
  84.     return JS_TRUE;
  85.     decoder = hist->decoder;
  86.     context = decoder->window_context;
  87.     if (!context)
  88.     return JS_TRUE;
  89.  
  90.     str = JSVAL_TO_STRING(JS_GetEmptyStringValue(cx));
  91.     switch (slot) {
  92.       case HIST_LENGTH:
  93.     histlist = SHIST_GetList(context);
  94.     *vp = INT_TO_JSVAL(XP_ListCount(histlist));
  95.     return JS_TRUE;
  96.  
  97.       case HIST_CURRENT:
  98.     if (!lm_CanAccessTarget(cx, JSTARGET_UNIVERSAL_BROWSER_READ))
  99.         break;
  100.     he = SHIST_GetCurrent(&context->hist);
  101.     if (he && he->address)
  102.         str = JS_NewStringCopyZ(cx, he->address);
  103.     break;
  104.  
  105.       case HIST_PREVIOUS:
  106.     if (!lm_CanAccessTarget(cx, JSTARGET_UNIVERSAL_BROWSER_READ))
  107.         break;
  108.     he2 = SHIST_GetPrevious(context);
  109.     if (he2 && he2->address)
  110.         str = JS_NewStringCopyZ(cx, he2->address);
  111.     break;
  112.  
  113.       case HIST_NEXT:
  114.     if (!lm_CanAccessTarget(cx, JSTARGET_UNIVERSAL_BROWSER_READ))
  115.         break;
  116.     he2 = SHIST_GetNext(context);
  117.     if (he2 && he2->address)
  118.         str = JS_NewStringCopyZ(cx, he2->address);
  119.     break;
  120.  
  121.       default:
  122.     if (slot < 0) {
  123.         /* Don't mess with user-defined or method properties. */
  124.         return JS_TRUE;
  125.     }
  126.     if (lm_CanAccessTarget(cx, JSTARGET_UNIVERSAL_BROWSER_READ)) {
  127.         /* Access granted against potential privacy attack */
  128.         he = SHIST_GetObjectNum(&context->hist, 1 + slot);
  129.         if (he && he->address) {
  130.         str = JS_NewStringCopyZ(cx, he->address);
  131.         }
  132.     }
  133.     break;
  134.     }
  135.  
  136.     /* Common tail code for string-type properties. */
  137.     if (!str)
  138.     return JS_FALSE;
  139.     *vp = STRING_TO_JSVAL(str);
  140.     return JS_TRUE;
  141. }
  142.  
  143. PR_STATIC_CALLBACK(void)
  144. hist_finalize(JSContext *cx, JSObject *obj)
  145. {
  146.     JSHistory *hist;
  147.  
  148.     hist = JS_GetPrivate(cx, obj);
  149.     if (!hist)
  150.     return;
  151.     DROP_BACK_COUNT(hist->decoder);
  152.     XP_DELETE(hist);
  153. }
  154.  
  155. JSClass lm_hist_class = {
  156.     "History", JSCLASS_HAS_PRIVATE,
  157.     JS_PropertyStub, JS_PropertyStub, hist_getProperty, hist_getProperty,
  158.     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, hist_finalize
  159. };
  160.  
  161. JSBool PR_CALLBACK
  162. hist_go(JSContext *cx, JSObject *obj,
  163.     unsigned int argc, jsval *argv, jsval *rval)
  164. {
  165.     JSHistory *hist;
  166.     MochaDecoder *decoder;
  167.     MWContext *context;
  168.     History_entry *he;
  169.     int index, delta;
  170.     XP_List *histlist;
  171.     URL_Struct *url_struct;
  172.  
  173.     if (!JS_InstanceOf(cx, obj, &lm_hist_class, argv))
  174.         return JS_FALSE;
  175.     hist = JS_GetPrivate(cx, obj);
  176.     if (!hist)
  177.     return JS_TRUE;
  178.     decoder = hist->decoder;
  179.     context = decoder->window_context;
  180.     if (!context)
  181.     return JS_TRUE;
  182.     he = SHIST_GetCurrent(&context->hist);
  183.  
  184.     if (JSVAL_IS_INT(argv[0])) {
  185.     index = SHIST_GetIndex(&context->hist, he);
  186.     delta = JSVAL_TO_INT(argv[0]);
  187.     index += delta;
  188.     he = SHIST_GetObjectNum(&context->hist, index);
  189.     }
  190.     else if (JSVAL_IS_STRING(argv[0])) {
  191.     char * argv_str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
  192.     histlist = SHIST_GetList(context);
  193.     if (histlist)
  194.         histlist = histlist->next;
  195.  
  196.     for (index = XP_ListCount(histlist); index > 0; index--) {
  197.         he = SHIST_GetObjectNum(&context->hist, index);
  198.         if (XP_STRSTR(he->address, argv_str) ||
  199.         XP_STRSTR(he->title, argv_str)) {
  200.         goto out;
  201.         }
  202.     }
  203.     he = 0;
  204.     }
  205.     else {
  206.     he = 0;
  207.     }
  208.  
  209.     if (!he)
  210.     return JS_TRUE;
  211. out:
  212.     url_struct = SHIST_CreateURLStructFromHistoryEntry(context, he);
  213.     if (!url_struct) {
  214.     JS_ReportOutOfMemory(cx);
  215.     return JS_FALSE;
  216.     }
  217.     return lm_GetURL(cx, decoder, url_struct);
  218. }
  219.  
  220. PR_STATIC_CALLBACK(JSBool)
  221. hist_back(JSContext *cx, JSObject *obj,
  222.       unsigned int argc, jsval *argv, jsval *rval)
  223. {
  224.     jsval minus_one;
  225.  
  226.     minus_one = INT_TO_JSVAL(-1);
  227.     return hist_go(cx, obj, 1, &minus_one, rval);
  228. }
  229.  
  230. PR_STATIC_CALLBACK(JSBool)
  231. hist_toString(JSContext *cx, JSObject *obj,
  232.           unsigned int argc, jsval *argv, jsval *rval)
  233. {
  234.     JSHistory *hist;
  235.     MochaDecoder *decoder;
  236.     MWContext *context;
  237.     XP_List *histlist;
  238.     History_entry *he;
  239.     char *bytes;
  240.     JSString *str;
  241.  
  242.     if (!JS_InstanceOf(cx, obj, &lm_hist_class, argv))
  243.         return JS_FALSE;
  244.  
  245.     hist = JS_GetPrivate(cx, obj);
  246.     if (!hist)
  247.     return JS_TRUE;
  248.     decoder = hist->decoder;
  249.     context = decoder->window_context;
  250.     if (!context)
  251.     return JS_TRUE;
  252.     histlist = SHIST_GetList(context);
  253.  
  254.     /* only build a string if we have permission */
  255.     if (!lm_CanAccessTarget(cx, JSTARGET_UNIVERSAL_BROWSER_READ))
  256.     return JS_TRUE;
  257.  
  258.     bytes = 0;
  259.     StrAllocCopy(bytes, "<TITLE>Window History</TITLE>"
  260.               "<TABLE BORDER=0 ALIGN=center VALIGN=top HSPACE=8>");
  261.     while ((he = XP_ListNextObject(histlist)) != 0) {
  262.     StrAllocCat(bytes, "<TR><TD VALIGN=top><STRONG>");
  263.     StrAllocCat(bytes, he->title);
  264.     StrAllocCat(bytes, "</STRONG></TD><TD> </TD>"
  265.              "<TD VALIGN=top><A HREF=\"");
  266.     StrAllocCat(bytes, he->address);
  267.     StrAllocCat(bytes, "\">");
  268.     StrAllocCat(bytes, he->address);
  269.     StrAllocCat(bytes, "</A></TD></TR>");
  270.     }
  271.     StrAllocCat(bytes, "</TABLE>");
  272.     if (!bytes) {
  273.     JS_ReportOutOfMemory(cx);
  274.     return JS_FALSE;
  275.     }
  276.  
  277.     str = JS_NewString(cx, bytes, XP_STRLEN(bytes));
  278.     if (!str)
  279.     return JS_FALSE;
  280.     *rval = STRING_TO_JSVAL(str);
  281.     return JS_TRUE;
  282. }
  283.  
  284. static JSFunctionSpec hist_methods[] = {
  285.     {"go",              hist_go,                1},
  286.     {"back",            hist_back,              0},
  287.     {"forward",         hist_forward,           0},
  288.     {lm_toString_str,   hist_toString,         1},
  289.     {0}
  290. };
  291.  
  292. /* XXX avoid ntypes.h History typedef name clash */
  293. PR_STATIC_CALLBACK(JSBool)
  294. History_ctor(JSContext *cx, JSObject *obj,
  295.          uint argc, jsval *argv, jsval *rval)
  296. {
  297.     return JS_TRUE;
  298. }
  299.  
  300.  
  301. JSObject *
  302. lm_DefineHistory(MochaDecoder *decoder)
  303. {
  304.     JSObject *obj;
  305.     JSContext *cx;
  306.     JSHistory *hist;
  307.  
  308.     obj = decoder->history;
  309.     if (obj)
  310.     return obj;
  311.  
  312.     cx = decoder->js_context;
  313.     hist = JS_malloc(cx, sizeof *hist);
  314.     if (!hist)
  315.     return NULL;
  316.     XP_BZERO(hist, sizeof *hist);
  317.  
  318.     obj = JS_InitClass(cx, decoder->window_object, NULL, &lm_hist_class,
  319.                History_ctor, 0, hist_props, hist_methods, NULL, NULL);
  320.     if (!obj || !JS_SetPrivate(cx, obj, hist)) {
  321.     JS_free(cx, hist);
  322.     return NULL;
  323.     }
  324.  
  325.     if (!JS_DefineProperty(cx, decoder->window_object, "history",
  326.                OBJECT_TO_JSVAL(obj), NULL, NULL,
  327.                JSPROP_ENUMERATE|JSPROP_READONLY)) {
  328.     return NULL;
  329.     }
  330.  
  331.     hist->object = obj;
  332.     hist->decoder = HOLD_BACK_COUNT(decoder);
  333.     decoder->history = obj;
  334.     return obj;
  335. }
  336.