/* * MIT License * * Copyright (c) 2017 Serge Zaitsev, (c) 2019 Tauri Apps * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef WEBVIEW_H #define WEBVIEW_H #ifdef __cplusplus extern "C" { #endif #ifdef WEBVIEW_STATIC #define WEBVIEW_API static #else #define WEBVIEW_API extern #endif #include #include #include #include struct webview; typedef void (*webview_external_invoke_cb_t)(struct webview *w, const char *arg); struct webview { const char *url; const char *title; int width; int height; int resizable; int debug; webview_external_invoke_cb_t external_invoke_cb; struct webview_priv priv; void *userdata; }; enum webview_dialog_type { WEBVIEW_DIALOG_TYPE_OPEN = 0, WEBVIEW_DIALOG_TYPE_SAVE = 1, WEBVIEW_DIALOG_TYPE_ALERT = 2 }; #define WEBVIEW_DIALOG_FLAG_FILE (0 << 0) #define WEBVIEW_DIALOG_FLAG_DIRECTORY (1 << 0) #define WEBVIEW_DIALOG_FLAG_INFO (1 << 1) #define WEBVIEW_DIALOG_FLAG_WARNING (2 << 1) #define WEBVIEW_DIALOG_FLAG_ERROR (3 << 1) #define WEBVIEW_DIALOG_FLAG_ALERT_MASK (3 << 1) typedef void (*webview_dispatch_fn)(struct webview *w, void *arg); struct webview_dispatch_arg { webview_dispatch_fn fn; struct webview *w; void *arg; }; #define DEFAULT_URL \ "data:text/" \ "html,%3C%21DOCTYPE%20html%3E%0A%3Chtml%20lang=%22en%22%3E%0A%3Chead%3E%" \ "3Cmeta%20charset=%22utf-8%22%3E%3Cmeta%20http-equiv=%22X-UA-Compatible%22%" \ "20content=%22IE=edge%22%3E%3C%2Fhead%3E%0A%3Cbody%3E%3Cdiv%20id=%22app%22%" \ "3E%3C%2Fdiv%3E%3Cscript%20type=%22text%2Fjavascript%22%3E%3C%2Fscript%3E%" \ "3C%2Fbody%3E%0A%3C%2Fhtml%3E" #define CSS_INJECT_FUNCTION \ "(function(e){var " \ "t=document.createElement('style'),d=document.head||document." \ "getElementsByTagName('head')[0];t.setAttribute('type','text/" \ "css'),t.styleSheet?t.styleSheet.cssText=e:t.appendChild(document." \ "createTextNode(e)),d.appendChild(t)})" static const char *webview_check_url(const char *url) { if (url == NULL || strlen(url) == 0) { return DEFAULT_URL; } return url; } WEBVIEW_API int webview(const char *title, const char *url, int width, int height, int resizable); WEBVIEW_API int webview_init(struct webview *w); WEBVIEW_API int webview_loop(struct webview *w, int blocking); WEBVIEW_API int webview_eval(struct webview *w, const char *js); WEBVIEW_API int webview_inject_css(struct webview *w, const char *css); WEBVIEW_API void webview_set_title(struct webview *w, const char *title); WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen); WEBVIEW_API void webview_set_color(struct webview *w, uint8_t r, uint8_t g, uint8_t b, uint8_t a); WEBVIEW_API void webview_dialog(struct webview *w, enum webview_dialog_type dlgtype, int flags, const char *title, const char *arg, char *result, size_t resultsz); WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn, void *arg); WEBVIEW_API void webview_terminate(struct webview *w); WEBVIEW_API void webview_exit(struct webview *w); WEBVIEW_API void webview_debug(const char *format, ...); WEBVIEW_API void webview_print_log(const char *s); #ifdef WEBVIEW_IMPLEMENTATION #undef WEBVIEW_IMPLEMENTATION WEBVIEW_API int webview(const char *title, const char *url, int width, int height, int resizable) { struct webview webview; memset(&webview, 0, sizeof(webview)); webview.title = title; webview.url = url; webview.width = width; webview.height = height; webview.resizable = resizable; int r = webview_init(&webview); if (r != 0) { return r; } while (webview_loop(&webview, 1) == 0) { } webview_exit(&webview); return 0; } WEBVIEW_API void webview_debug(const char *format, ...) { char buf[4096]; va_list ap; va_start(ap, format); vsnprintf(buf, sizeof(buf), format, ap); webview_print_log(buf); va_end(ap); } static int webview_js_encode(const char *s, char *esc, size_t n) { int r = 1; /* At least one byte for trailing zero */ for (; *s; s++) { const unsigned char c = *s; if (c >= 0x20 && c < 0x80 && strchr("<>\\'\"", c) == NULL) { if (n > 0) { *esc++ = c; n--; } r++; } else { if (n > 0) { snprintf(esc, n, "\\x%02x", (int)c); esc += 4; n -= 4; } r += 4; } } return r; } WEBVIEW_API int webview_inject_css(struct webview *w, const char *css) { int n = webview_js_encode(css, NULL, 0); char *esc = (char *)calloc(1, sizeof(CSS_INJECT_FUNCTION) + n + 4); if (esc == NULL) { return -1; } char *js = (char *)calloc(1, n); webview_js_encode(css, js, n); snprintf(esc, sizeof(CSS_INJECT_FUNCTION) + n + 4, "%s(\"%s\")", CSS_INJECT_FUNCTION, js); int r = webview_eval(w, esc); free(js); free(esc); return r; } #endif /* WEBVIEW_IMPLEMENTATION */ #ifdef __cplusplus } #endif #endif /* WEBVIEW_H */