mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
[mujs] window.open
This commit is contained in:
parent
6762dd3146
commit
247df89310
@ -48,135 +48,6 @@
|
||||
|
||||
static JSClassID js_window_class_id;
|
||||
|
||||
/* @window_funcs{"open"} */
|
||||
JSValue
|
||||
js_window_open(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
#ifdef ECMASCRIPT_DEBUG
|
||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||
#endif
|
||||
struct view_state *vs;
|
||||
struct document_view *doc_view;
|
||||
struct session *ses;
|
||||
const char *frame = NULL;
|
||||
char *url, *url2;
|
||||
struct uri *uri;
|
||||
static time_t ratelimit_start;
|
||||
static int ratelimit_count;
|
||||
|
||||
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
||||
vs = interpreter->vs;
|
||||
doc_view = vs->doc_view;
|
||||
ses = doc_view->session;
|
||||
|
||||
if (get_opt_bool("ecmascript.block_window_opening", ses)) {
|
||||
#ifdef CONFIG_LEDS
|
||||
set_led_value(ses->status.popup_led, 'P');
|
||||
#endif
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
if (argc < 1) return JS_UNDEFINED;
|
||||
|
||||
/* Ratelimit window opening. Recursive window.open() is very nice.
|
||||
* We permit at most 20 tabs in 2 seconds. The ratelimiter is very
|
||||
* rough but shall suffice against the usual cases. */
|
||||
if (!ratelimit_start || time(NULL) - ratelimit_start > 2) {
|
||||
ratelimit_start = time(NULL);
|
||||
ratelimit_count = 0;
|
||||
} else {
|
||||
ratelimit_count++;
|
||||
if (ratelimit_count > 20) {
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
const char *str;
|
||||
size_t len;
|
||||
|
||||
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
||||
|
||||
if (!str) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
url = stracpy(str);
|
||||
JS_FreeCString(ctx, str);
|
||||
|
||||
if (!url) {
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
trim_chars(url, ' ', 0);
|
||||
url2 = join_urls(doc_view->document->uri, url);
|
||||
mem_free(url);
|
||||
|
||||
if (!url2) {
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
size_t len2;
|
||||
frame = JS_ToCStringLen(ctx, &len2, argv[1]);
|
||||
|
||||
if (!frame) {
|
||||
mem_free(url2);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Support for window naming and perhaps some window features? */
|
||||
|
||||
uri = get_uri(url2, URI_NONE);
|
||||
mem_free(url2);
|
||||
if (!uri) {
|
||||
if (frame) JS_FreeCString(ctx, frame);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
JSValue ret;
|
||||
|
||||
if (frame && *frame && c_strcasecmp(frame, "_blank")) {
|
||||
struct delayed_open *deo = (struct delayed_open *)mem_calloc(1, sizeof(*deo));
|
||||
|
||||
if (deo) {
|
||||
deo->ses = ses;
|
||||
deo->uri = get_uri_reference(uri);
|
||||
deo->target = stracpy(frame);
|
||||
register_bottom_half(delayed_goto_uri_frame, deo);
|
||||
ret = JS_TRUE;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_cmd_opt_bool("no-connect")
|
||||
&& !get_cmd_opt_bool("no-home")
|
||||
&& !get_cmd_opt_bool("anonymous")
|
||||
&& can_open_in_new(ses->tab->term)) {
|
||||
open_uri_in_new_window(ses, uri, NULL, ENV_ANY,
|
||||
CACHE_MODE_NORMAL, TASK_NONE);
|
||||
ret = JS_TRUE;
|
||||
} else {
|
||||
/* When opening a new tab, we might get rerendered, losing our
|
||||
* context and triggerring a disaster, so postpone that. */
|
||||
struct delayed_open *deo = (struct delayed_open *)mem_calloc(1, sizeof(*deo));
|
||||
|
||||
if (deo) {
|
||||
deo->ses = ses;
|
||||
deo->uri = get_uri_reference(uri);
|
||||
register_bottom_half(delayed_open, deo);
|
||||
ret = JS_TRUE;
|
||||
} else {
|
||||
ret = JS_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
done_uri(uri);
|
||||
if (frame) JS_FreeCString(ctx, frame);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* @window_funcs{"setTimeout"} */
|
||||
JSValue
|
||||
js_window_setTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
@ -409,6 +280,137 @@ mjs_window_alert(js_State *J)
|
||||
js_pushundefined(J);
|
||||
}
|
||||
|
||||
static void
|
||||
mjs_window_open(js_State *J)
|
||||
{
|
||||
#ifdef ECMASCRIPT_DEBUG
|
||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||
#endif
|
||||
struct view_state *vs;
|
||||
struct document_view *doc_view;
|
||||
struct session *ses;
|
||||
const char *frame = NULL;
|
||||
char *url, *url2;
|
||||
struct uri *uri;
|
||||
static time_t ratelimit_start;
|
||||
static int ratelimit_count;
|
||||
|
||||
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)js_getcontext(J);
|
||||
vs = interpreter->vs;
|
||||
doc_view = vs->doc_view;
|
||||
ses = doc_view->session;
|
||||
|
||||
if (get_opt_bool("ecmascript.block_window_opening", ses)) {
|
||||
#ifdef CONFIG_LEDS
|
||||
set_led_value(ses->status.popup_led, 'P');
|
||||
#endif
|
||||
js_pushundefined(J);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ratelimit window opening. Recursive window.open() is very nice.
|
||||
* We permit at most 20 tabs in 2 seconds. The ratelimiter is very
|
||||
* rough but shall suffice against the usual cases. */
|
||||
if (!ratelimit_start || time(NULL) - ratelimit_start > 2) {
|
||||
ratelimit_start = time(NULL);
|
||||
ratelimit_count = 0;
|
||||
} else {
|
||||
ratelimit_count++;
|
||||
if (ratelimit_count > 20) {
|
||||
js_pushundefined(J);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const char *str;
|
||||
str = js_tostring(J, 1);
|
||||
|
||||
if (!str) {
|
||||
js_pushundefined(J);
|
||||
return;
|
||||
}
|
||||
|
||||
url = stracpy(str);
|
||||
|
||||
if (!url) {
|
||||
js_pushundefined(J);
|
||||
return;
|
||||
}
|
||||
trim_chars(url, ' ', 0);
|
||||
url2 = join_urls(doc_view->document->uri, url);
|
||||
mem_free(url);
|
||||
|
||||
if (!url2) {
|
||||
js_pushundefined(J);
|
||||
return;
|
||||
}
|
||||
|
||||
if (true) {
|
||||
frame = js_tostring(J, 2);
|
||||
|
||||
if (!frame) {
|
||||
mem_free(url2);
|
||||
js_pushundefined(J);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Support for window naming and perhaps some window features? */
|
||||
|
||||
uri = get_uri(url2, URI_NONE);
|
||||
mem_free(url2);
|
||||
if (!uri) {
|
||||
js_pushundefined(J);
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (frame && *frame && c_strcasecmp(frame, "_blank")) {
|
||||
struct delayed_open *deo = (struct delayed_open *)mem_calloc(1, sizeof(*deo));
|
||||
|
||||
if (deo) {
|
||||
deo->ses = ses;
|
||||
deo->uri = get_uri_reference(uri);
|
||||
deo->target = stracpy(frame);
|
||||
register_bottom_half(delayed_goto_uri_frame, deo);
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_cmd_opt_bool("no-connect")
|
||||
&& !get_cmd_opt_bool("no-home")
|
||||
&& !get_cmd_opt_bool("anonymous")
|
||||
&& can_open_in_new(ses->tab->term)) {
|
||||
open_uri_in_new_window(ses, uri, NULL, ENV_ANY,
|
||||
CACHE_MODE_NORMAL, TASK_NONE);
|
||||
ret = 1;
|
||||
} else {
|
||||
/* When opening a new tab, we might get rerendered, losing our
|
||||
* context and triggerring a disaster, so postpone that. */
|
||||
struct delayed_open *deo = (struct delayed_open *)mem_calloc(1, sizeof(*deo));
|
||||
|
||||
if (deo) {
|
||||
deo->ses = ses;
|
||||
deo->uri = get_uri_reference(uri);
|
||||
register_bottom_half(delayed_open, deo);
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
done_uri(uri);
|
||||
|
||||
if (ret == -1) {
|
||||
js_pushundefined(J);
|
||||
return;
|
||||
}
|
||||
js_pushboolean(J, ret);
|
||||
}
|
||||
|
||||
static void
|
||||
mjs_window_toString(js_State *J)
|
||||
{
|
||||
@ -424,6 +426,7 @@ mjs_window_init(js_State *J)
|
||||
js_newobject(J);
|
||||
{
|
||||
addmethod(J, "window.alert", mjs_window_alert, 1);
|
||||
addmethod(J, "window.open", mjs_window_open, 3);
|
||||
addmethod(J, "window.toString", mjs_window_toString, 0);
|
||||
|
||||
addproperty(J, "closed", mjs_window_get_property_closed, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user