1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host;
16
17 import java.nio.charset.StandardCharsets;
18 import java.util.Arrays;
19 import java.util.Base64;
20
21 import org.apache.commons.lang3.StringUtils;
22 import org.htmlunit.Page;
23 import org.htmlunit.WebWindow;
24 import org.htmlunit.corejs.javascript.Context;
25 import org.htmlunit.corejs.javascript.Function;
26 import org.htmlunit.corejs.javascript.FunctionObject;
27 import org.htmlunit.corejs.javascript.Scriptable;
28 import org.htmlunit.javascript.HtmlUnitScriptable;
29 import org.htmlunit.javascript.JavaScriptEngine;
30 import org.htmlunit.javascript.background.BackgroundJavaScriptFactory;
31 import org.htmlunit.javascript.background.JavaScriptJob;
32
33
34
35
36
37
38
39
40 public final class WindowOrWorkerGlobalScopeMixin {
41
42
43
44
45
46
47
48 private static final int MIN_TIMER_DELAY = 1;
49
50 private WindowOrWorkerGlobalScopeMixin() {
51 super();
52 }
53
54
55
56
57
58
59
60 public static String atob(final String encodedData, final HtmlUnitScriptable scriptable) {
61 final String withoutWhitespace = StringUtils.replaceChars(encodedData, " \t\r\n\u000c", "");
62 final byte[] bytes = withoutWhitespace.getBytes(StandardCharsets.ISO_8859_1);
63 try {
64 return new String(Base64.getDecoder().decode(bytes), StandardCharsets.ISO_8859_1);
65 }
66 catch (final IllegalArgumentException e) {
67 throw JavaScriptEngine.asJavaScriptException(
68 scriptable,
69 "Failed to execute atob(): " + e.getMessage(),
70 org.htmlunit.javascript.host.dom.DOMException.INVALID_CHARACTER_ERR);
71 }
72 }
73
74
75
76
77
78
79
80 public static String btoa(final String stringToEncode, final HtmlUnitScriptable scriptable) {
81 final int l = stringToEncode.length();
82 for (int i = 0; i < l; i++) {
83 if (stringToEncode.charAt(i) > 255) {
84 throw JavaScriptEngine.asJavaScriptException(
85 scriptable,
86 "Function btoa supports only latin1 characters",
87 org.htmlunit.javascript.host.dom.DOMException.INVALID_CHARACTER_ERR);
88 }
89 }
90
91 final byte[] bytes = stringToEncode.getBytes(StandardCharsets.ISO_8859_1);
92 try {
93 return new String(Base64.getEncoder().encode(bytes), StandardCharsets.UTF_8);
94 }
95 catch (final IllegalArgumentException e) {
96 throw JavaScriptEngine.asJavaScriptException(
97 scriptable,
98 "Failed to execute btoa(): " + e.getMessage(),
99 org.htmlunit.javascript.host.dom.DOMException.INVALID_CHARACTER_ERR);
100 }
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 public static Object setTimeout(final Context context, final Scriptable thisObj,
118 final Object[] args, final Function function) {
119 if (args.length < 1) {
120 throw JavaScriptEngine.typeError("Function not provided");
121 }
122
123 final int timeout = JavaScriptEngine.toInt32((args.length > 1) ? args[1] : JavaScriptEngine.UNDEFINED);
124 final Object[] params = (args.length > 2)
125 ? Arrays.copyOfRange(args, 2, args.length)
126 : JavaScriptEngine.EMPTY_ARGS;
127 return setTimeoutIntervalImpl((Window) thisObj, args[0], timeout, true, params);
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141 public static Object setInterval(final Context context, final Scriptable thisObj,
142 final Object[] args, final Function function) {
143 if (args.length < 1) {
144 throw JavaScriptEngine.typeError("Function not provided");
145 }
146
147 final int timeout = JavaScriptEngine.toInt32((args.length > 1) ? args[1] : JavaScriptEngine.UNDEFINED);
148 final Object[] params = (args.length > 2)
149 ? Arrays.copyOfRange(args, 2, args.length)
150 : JavaScriptEngine.EMPTY_ARGS;
151 return setTimeoutIntervalImpl((Window) thisObj, args[0], timeout, false, params);
152 }
153
154 private static int setTimeoutIntervalImpl(final Window window, final Object code,
155 int timeout, final boolean isTimeout, final Object[] params) {
156 if (timeout < MIN_TIMER_DELAY) {
157 timeout = MIN_TIMER_DELAY;
158 }
159
160 final WebWindow webWindow = window.getWebWindow();
161 final Page page = (Page) window.getDomNodeOrNull();
162 Integer period = null;
163 if (!isTimeout) {
164 period = timeout;
165 }
166
167 if (code instanceof String) {
168 final String s = (String) code;
169 final String description = "window.set"
170 + (isTimeout ? "Timeout" : "Interval")
171 + "(" + s + ", " + timeout + ")";
172 final JavaScriptJob job = BackgroundJavaScriptFactory.theFactory().
173 createJavaScriptJob(timeout, period, description, webWindow, s);
174 return webWindow.getJobManager().addJob(job, page);
175 }
176
177 if (code instanceof Function) {
178 final Function f = (Function) code;
179 final String functionName;
180 if (f instanceof FunctionObject) {
181 functionName = ((FunctionObject) f).getFunctionName();
182 }
183 else {
184 functionName = String.valueOf(f);
185 }
186
187 final String description = "window.set"
188 + (isTimeout ? "Timeout" : "Interval")
189 + "(" + functionName + ", " + timeout + ")";
190 final JavaScriptJob job = BackgroundJavaScriptFactory.theFactory().
191 createJavaScriptJob(timeout, period, description, webWindow, f, params);
192 return webWindow.getJobManager().addJob(job, page);
193 }
194
195 throw JavaScriptEngine.reportRuntimeError("Unknown type for function.");
196 }
197 }