mirror of
https://github.com/rkd77/elinks.git
synced 2024-11-04 08:17:17 -05:00
[mujs] window.open
This commit is contained in:
parent
6762dd3146
commit
247df89310
@ -48,135 +48,6 @@
|
|||||||
|
|
||||||
static JSClassID js_window_class_id;
|
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"} */
|
/* @window_funcs{"setTimeout"} */
|
||||||
JSValue
|
JSValue
|
||||||
js_window_setTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
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);
|
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
|
static void
|
||||||
mjs_window_toString(js_State *J)
|
mjs_window_toString(js_State *J)
|
||||||
{
|
{
|
||||||
@ -424,6 +426,7 @@ mjs_window_init(js_State *J)
|
|||||||
js_newobject(J);
|
js_newobject(J);
|
||||||
{
|
{
|
||||||
addmethod(J, "window.alert", mjs_window_alert, 1);
|
addmethod(J, "window.alert", mjs_window_alert, 1);
|
||||||
|
addmethod(J, "window.open", mjs_window_open, 3);
|
||||||
addmethod(J, "window.toString", mjs_window_toString, 0);
|
addmethod(J, "window.toString", mjs_window_toString, 0);
|
||||||
|
|
||||||
addproperty(J, "closed", mjs_window_get_property_closed, NULL);
|
addproperty(J, "closed", mjs_window_get_property_closed, NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user