001package Torello.Browser.BrowserAPI;
002
003import java.util.*;
004import javax.json.*;
005import javax.json.stream.*;
006import java.io.*;
007
008import java.lang.reflect.Method;
009import java.lang.reflect.Parameter;
010import java.util.function.Function;
011
012import Torello.Browser.BrowserEvent;
013import Torello.Browser.JavaScriptAPI.*;
014import Torello.Browser.helper.*;
015
016import Torello.Java.Additional.*;
017import Torello.Java.JSON.*;
018
019import static Torello.Java.JSON.JFlag.*;
020
021import Torello.Java.StrCmpr;
022import Torello.JavaDoc.StaticFunctional;
023import Torello.JavaDoc.JDHeaderBackgroundImg;
024import Torello.JavaDoc.Excuse;
025
026/**
027 * <SPAN CLASS=COPIEDJDK><B>A domain for letting clients substitute browser's network layer with client code.</B></SPAN>
028 * 
029 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE>
030 */
031@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION})
032@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE")
033public class Fetch
034{
035    // ********************************************************************************************
036    // ********************************************************************************************
037    // Class Header Stuff
038    // ********************************************************************************************
039    // ********************************************************************************************
040
041
042    // No Pubic Constructors
043    private Fetch () { }
044
045    // These two Vector's are used by all the "Methods" exported by this class.  java.lang.reflect
046    // is used to generate the JSON String's.  It saves thousands of lines of Auto-Generated Code.
047    private static final Map<String, Vector<String>>    parameterNames = new HashMap<>();
048    private static final Map<String, Vector<Class<?>>>  parameterTypes = new HashMap<>();
049
050    // Some Methods do not take any parameters - for instance all the "enable()" and "disable()"
051    // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now,
052    // offically, two empty-vectors.  One for String's, and the other for Classes.
053
054    private static final Vector<String>     EMPTY_VEC_STR = new Vector<>();
055    private static final Vector<Class<?>>   EMPTY_VEC_CLASS = new Vector<>();
056
057    static
058    {
059        for (Method m : Fetch.class.getMethods())
060        {
061            // This doesn't work!  The parameter names are all "arg0" ... "argN"
062            // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter!
063            //
064            // Vector<String> parameterNamesList = new Vector<>(); -- NOPE!
065
066            Vector<Class<?>> parameterTypesList = new Vector<>();
067        
068            for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType());
069
070            parameterTypes.put(
071                m.getName(),
072                (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS
073            );
074        }
075    }
076
077    static
078    {
079        Vector<String> v = null;
080
081        parameterNames.put("disable", EMPTY_VEC_STR);
082
083        v = new Vector<String>(2);
084        parameterNames.put("enable", v);
085        Collections.addAll(v, new String[]
086        { "patterns", "handleAuthRequests", });
087
088        v = new Vector<String>(2);
089        parameterNames.put("failRequest", v);
090        Collections.addAll(v, new String[]
091        { "requestId", "errorReason", });
092
093        v = new Vector<String>(6);
094        parameterNames.put("fulfillRequest", v);
095        Collections.addAll(v, new String[]
096        { "requestId", "responseCode", "responseHeaders", "binaryResponseHeaders", "body", "responsePhrase", });
097
098        v = new Vector<String>(6);
099        parameterNames.put("continueRequest", v);
100        Collections.addAll(v, new String[]
101        { "requestId", "url", "method", "postData", "headers", "interceptResponse", });
102
103        v = new Vector<String>(2);
104        parameterNames.put("continueWithAuth", v);
105        Collections.addAll(v, new String[]
106        { "requestId", "authChallengeResponse", });
107
108        v = new Vector<String>(5);
109        parameterNames.put("continueResponse", v);
110        Collections.addAll(v, new String[]
111        { "requestId", "responseCode", "responsePhrase", "responseHeaders", "binaryResponseHeaders", });
112
113        v = new Vector<String>(1);
114        parameterNames.put("getResponseBody", v);
115        Collections.addAll(v, new String[]
116        { "requestId", });
117
118        v = new Vector<String>(1);
119        parameterNames.put("takeResponseBodyAsStream", v);
120        Collections.addAll(v, new String[]
121        { "requestId", });
122    }
123
124
125    // ********************************************************************************************
126    // ********************************************************************************************
127    // Types - Static Inner Classes
128    // ********************************************************************************************
129    // ********************************************************************************************
130
131    // public static class RequestId => String
132    
133    /**
134     * Stages of the request to handle. Request will intercept before the request is
135     * sent. Response will intercept after the response is received (but before response
136     * body is received).
137     */
138    public static final String[] RequestStage =
139    { "Request", "Response", };
140    
141    /** <CODE>[No Description Provided by Google]</CODE> */
142    public static class RequestPattern
143        extends BaseType
144        implements java.io.Serializable
145    {
146        /** For Object Serialization.  java.io.Serializable */
147        protected static final long serialVersionUID = 1;
148        
149        public boolean[] optionals()
150        { return new boolean[] { true, true, true, }; }
151        
152        /**
153         * Wildcards ({@code '*'} -&gt; zero or more, {@code '?'} -&gt; exactly one) are allowed. Escape character is
154         * backslash. Omitting is equivalent to {@code "*"}.
155         * <BR /><B CLASS=Opt>OPTIONAL</B>
156         */
157        public final String urlPattern;
158        
159        /**
160         * If set, only requests for matching resource types will be intercepted.
161         * <BR /><B CLASS=Opt>OPTIONAL</B>
162         */
163        public final String resourceType;
164        
165        /**
166         * Stage at which to begin intercepting requests. Default is Request.
167         * <BR /><B CLASS=Opt>OPTIONAL</B>
168         */
169        public final String requestStage;
170        
171        /**
172         * Constructor
173         *
174         * @param urlPattern 
175         * Wildcards ({@code '*'} -&gt; zero or more, {@code '?'} -&gt; exactly one) are allowed. Escape character is
176         * backslash. Omitting is equivalent to {@code "*"}.
177         * <BR /><B CLASS=Opt>OPTIONAL</B>
178         * 
179         * @param resourceType If set, only requests for matching resource types will be intercepted.
180         * <BR /><B CLASS=Opt>OPTIONAL</B>
181         * 
182         * @param requestStage Stage at which to begin intercepting requests. Default is Request.
183         * <BR /><B CLASS=Opt>OPTIONAL</B>
184         */
185        public RequestPattern(String urlPattern, String resourceType, String requestStage)
186        {
187            // Exception-Check(s) to ensure that if any parameters which must adhere to a
188            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
189            
190            THROWS.checkIAE("resourceType", resourceType, "Network.ResourceType", Network.ResourceType);
191            THROWS.checkIAE("requestStage", requestStage, "Fetch.RequestStage", Fetch.RequestStage);
192            
193            this.urlPattern    = urlPattern;
194            this.resourceType  = resourceType;
195            this.requestStage  = requestStage;
196        }
197        
198        /**
199         * JSON Object Constructor
200         * @param jo A Json-Object having data about an instance of {@code 'RequestPattern'}.
201         */
202        public RequestPattern (JsonObject jo)
203        {
204            this.urlPattern    = ReadJSON.getString(jo, "urlPattern", true, false);
205            this.resourceType  = ReadJSON.getString(jo, "resourceType", true, false);
206            this.requestStage  = ReadJSON.getString(jo, "requestStage", true, false);
207        }
208        
209        
210        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
211        public boolean equals(Object other)
212        {
213            if (this == other)                       return true;
214            if (other == null)                       return false;
215            if (other.getClass() != this.getClass()) return false;
216        
217            RequestPattern o = (RequestPattern) other;
218        
219            return
220                    Objects.equals(this.urlPattern, o.urlPattern)
221                &&  Objects.equals(this.resourceType, o.resourceType)
222                &&  Objects.equals(this.requestStage, o.requestStage);
223        }
224        
225        /** Generates a Hash-Code for {@code 'this'} instance */
226        public int hashCode()
227        {
228            return
229                    Objects.hashCode(this.urlPattern)
230                +   Objects.hashCode(this.resourceType)
231                +   Objects.hashCode(this.requestStage);
232        }
233    }
234    
235    /** Response HTTP header entry */
236    public static class HeaderEntry
237        extends BaseType
238        implements java.io.Serializable
239    {
240        /** For Object Serialization.  java.io.Serializable */
241        protected static final long serialVersionUID = 1;
242        
243        public boolean[] optionals()
244        { return new boolean[] { false, false, }; }
245        
246        /** <CODE>[No Description Provided by Google]</CODE> */
247        public final String name;
248        
249        /** <CODE>[No Description Provided by Google]</CODE> */
250        public final String value;
251        
252        /**
253         * Constructor
254         *
255         * @param name -
256         * 
257         * @param value -
258         */
259        public HeaderEntry(String name, String value)
260        {
261            // Exception-Check(s) to ensure that if any parameters which are not declared as
262            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
263            
264            if (name == null)  THROWS.throwNPE("name");
265            if (value == null) THROWS.throwNPE("value");
266            
267            this.name   = name;
268            this.value  = value;
269        }
270        
271        /**
272         * JSON Object Constructor
273         * @param jo A Json-Object having data about an instance of {@code 'HeaderEntry'}.
274         */
275        public HeaderEntry (JsonObject jo)
276        {
277            this.name   = ReadJSON.getString(jo, "name", false, true);
278            this.value  = ReadJSON.getString(jo, "value", false, true);
279        }
280        
281        
282        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
283        public boolean equals(Object other)
284        {
285            if (this == other)                       return true;
286            if (other == null)                       return false;
287            if (other.getClass() != this.getClass()) return false;
288        
289            HeaderEntry o = (HeaderEntry) other;
290        
291            return
292                    Objects.equals(this.name, o.name)
293                &&  Objects.equals(this.value, o.value);
294        }
295        
296        /** Generates a Hash-Code for {@code 'this'} instance */
297        public int hashCode()
298        {
299            return
300                    Objects.hashCode(this.name)
301                +   Objects.hashCode(this.value);
302        }
303    }
304    
305    /** Authorization challenge for HTTP status code 401 or 407. */
306    public static class AuthChallenge
307        extends BaseType
308        implements java.io.Serializable
309    {
310        /** For Object Serialization.  java.io.Serializable */
311        protected static final long serialVersionUID = 1;
312        
313        public boolean[] optionals()
314        { return new boolean[] { true, false, false, false, }; }
315        
316        /**
317         * Source of the authentication challenge.
318         * <BR /><B CLASS=Opt>OPTIONAL</B>
319         */
320        public final String source;
321        
322        /** Origin of the challenger. */
323        public final String origin;
324        
325        /** The authentication scheme used, such as basic or digest */
326        public final String scheme;
327        
328        /** The realm of the challenge. May be empty. */
329        public final String realm;
330        
331        /**
332         * Constructor
333         *
334         * @param source Source of the authentication challenge.
335         * <BR />Acceptable Values: ["Server", "Proxy"]
336         * <BR /><B CLASS=Opt>OPTIONAL</B>
337         * 
338         * @param origin Origin of the challenger.
339         * 
340         * @param scheme The authentication scheme used, such as basic or digest
341         * 
342         * @param realm The realm of the challenge. May be empty.
343         */
344        public AuthChallenge(String source, String origin, String scheme, String realm)
345        {
346            // Exception-Check(s) to ensure that if any parameters which are not declared as
347            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
348            
349            if (origin == null) THROWS.throwNPE("origin");
350            if (scheme == null) THROWS.throwNPE("scheme");
351            if (realm == null)  THROWS.throwNPE("realm");
352            
353            // Exception-Check(s) to ensure that if any parameters which must adhere to a
354            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
355            
356            THROWS.checkIAE(
357                "source", source,
358                "Server", "Proxy"
359            );
360            
361            this.source  = source;
362            this.origin  = origin;
363            this.scheme  = scheme;
364            this.realm   = realm;
365        }
366        
367        /**
368         * JSON Object Constructor
369         * @param jo A Json-Object having data about an instance of {@code 'AuthChallenge'}.
370         */
371        public AuthChallenge (JsonObject jo)
372        {
373            this.source  = ReadJSON.getString(jo, "source", true, false);
374            this.origin  = ReadJSON.getString(jo, "origin", false, true);
375            this.scheme  = ReadJSON.getString(jo, "scheme", false, true);
376            this.realm   = ReadJSON.getString(jo, "realm", false, true);
377        }
378        
379        
380        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
381        public boolean equals(Object other)
382        {
383            if (this == other)                       return true;
384            if (other == null)                       return false;
385            if (other.getClass() != this.getClass()) return false;
386        
387            AuthChallenge o = (AuthChallenge) other;
388        
389            return
390                    Objects.equals(this.source, o.source)
391                &&  Objects.equals(this.origin, o.origin)
392                &&  Objects.equals(this.scheme, o.scheme)
393                &&  Objects.equals(this.realm, o.realm);
394        }
395        
396        /** Generates a Hash-Code for {@code 'this'} instance */
397        public int hashCode()
398        {
399            return
400                    Objects.hashCode(this.source)
401                +   Objects.hashCode(this.origin)
402                +   Objects.hashCode(this.scheme)
403                +   Objects.hashCode(this.realm);
404        }
405    }
406    
407    /** Response to an AuthChallenge. */
408    public static class AuthChallengeResponse
409        extends BaseType
410        implements java.io.Serializable
411    {
412        /** For Object Serialization.  java.io.Serializable */
413        protected static final long serialVersionUID = 1;
414        
415        public boolean[] optionals()
416        { return new boolean[] { false, true, true, }; }
417        
418        /**
419         * The decision on what to do in response to the authorization challenge.  Default means
420         * deferring to the default behavior of the net stack, which will likely either the Cancel
421         * authentication or display a popup dialog box.
422         */
423        public final String response;
424        
425        /**
426         * The username to provide, possibly empty. Should only be set if response is
427         * ProvideCredentials.
428         * <BR /><B CLASS=Opt>OPTIONAL</B>
429         */
430        public final String username;
431        
432        /**
433         * The password to provide, possibly empty. Should only be set if response is
434         * ProvideCredentials.
435         * <BR /><B CLASS=Opt>OPTIONAL</B>
436         */
437        public final String password;
438        
439        /**
440         * Constructor
441         *
442         * @param response 
443         * The decision on what to do in response to the authorization challenge.  Default means
444         * deferring to the default behavior of the net stack, which will likely either the Cancel
445         * authentication or display a popup dialog box.
446         * <BR />Acceptable Values: ["Default", "CancelAuth", "ProvideCredentials"]
447         * 
448         * @param username 
449         * The username to provide, possibly empty. Should only be set if response is
450         * ProvideCredentials.
451         * <BR /><B CLASS=Opt>OPTIONAL</B>
452         * 
453         * @param password 
454         * The password to provide, possibly empty. Should only be set if response is
455         * ProvideCredentials.
456         * <BR /><B CLASS=Opt>OPTIONAL</B>
457         */
458        public AuthChallengeResponse(String response, String username, String password)
459        {
460            // Exception-Check(s) to ensure that if any parameters which are not declared as
461            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
462            
463            if (response == null) THROWS.throwNPE("response");
464            
465            // Exception-Check(s) to ensure that if any parameters which must adhere to a
466            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
467            
468            THROWS.checkIAE(
469                "response", response,
470                "Default", "CancelAuth", "ProvideCredentials"
471            );
472            
473            this.response  = response;
474            this.username  = username;
475            this.password  = password;
476        }
477        
478        /**
479         * JSON Object Constructor
480         * @param jo A Json-Object having data about an instance of {@code 'AuthChallengeResponse'}.
481         */
482        public AuthChallengeResponse (JsonObject jo)
483        {
484            this.response  = ReadJSON.getString(jo, "response", false, true);
485            this.username  = ReadJSON.getString(jo, "username", true, false);
486            this.password  = ReadJSON.getString(jo, "password", true, false);
487        }
488        
489        
490        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
491        public boolean equals(Object other)
492        {
493            if (this == other)                       return true;
494            if (other == null)                       return false;
495            if (other.getClass() != this.getClass()) return false;
496        
497            AuthChallengeResponse o = (AuthChallengeResponse) other;
498        
499            return
500                    Objects.equals(this.response, o.response)
501                &&  Objects.equals(this.username, o.username)
502                &&  Objects.equals(this.password, o.password);
503        }
504        
505        /** Generates a Hash-Code for {@code 'this'} instance */
506        public int hashCode()
507        {
508            return
509                    Objects.hashCode(this.response)
510                +   Objects.hashCode(this.username)
511                +   Objects.hashCode(this.password);
512        }
513    }
514    
515    /**
516     * Issued when the domain is enabled and the request URL matches the
517     * specified filter. The request is paused until the client responds
518     * with one of continueRequest, failRequest or fulfillRequest.
519     * The stage of the request can be determined by presence of responseErrorReason
520     * and responseStatusCode -- the request is at the response stage if either
521     * of these fields is present and in the request stage otherwise.
522     * Redirect responses and subsequent requests are reported similarly to regular
523     * responses and requests. Redirect responses may be distinguished by the value
524     * of {@code responseStatusCode} (which is one of 301, 302, 303, 307, 308) along with
525     * presence of the {@code location} header. Requests resulting from a redirect will
526     * have {@code redirectedRequestId} field set.
527     */
528    public static class requestPaused
529        extends BrowserEvent
530        implements java.io.Serializable
531    {
532        /** For Object Serialization.  java.io.Serializable */
533        protected static final long serialVersionUID = 1;
534        
535        public boolean[] optionals()
536        { return new boolean[] { false, false, false, false, true, true, true, true, true, true, }; }
537        
538        /** Each request the page makes will have a unique id. */
539        public final String requestId;
540        
541        /** The details of the request. */
542        public final Network.Request request;
543        
544        /** The id of the frame that initiated the request. */
545        public final String frameId;
546        
547        /** How the requested resource will be used. */
548        public final String resourceType;
549        
550        /**
551         * Response error if intercepted at response stage.
552         * <BR /><B CLASS=Opt>OPTIONAL</B>
553         */
554        public final String responseErrorReason;
555        
556        /**
557         * Response code if intercepted at response stage.
558         * <BR /><B CLASS=Opt>OPTIONAL</B>
559         */
560        public final Integer responseStatusCode;
561        
562        /**
563         * Response status text if intercepted at response stage.
564         * <BR /><B CLASS=Opt>OPTIONAL</B>
565         */
566        public final String responseStatusText;
567        
568        /**
569         * Response headers if intercepted at the response stage.
570         * <BR /><B CLASS=Opt>OPTIONAL</B>
571         */
572        public final Fetch.HeaderEntry[] responseHeaders;
573        
574        /**
575         * If the intercepted request had a corresponding Network.requestWillBeSent event fired for it,
576         * then this networkId will be the same as the requestId present in the requestWillBeSent event.
577         * <BR /><B CLASS=Opt>OPTIONAL</B>
578         */
579        public final String networkId;
580        
581        /**
582         * If the request is due to a redirect response from the server, the id of the request that
583         * has caused the redirect.
584         * <BR /><B CLASS=Opt>OPTIONAL</B>
585        <B CLASS=Exp>EXPERIMENTAL</B>
586         */
587        public final String redirectedRequestId;
588        
589        /**
590         * Constructor
591         *
592         * @param requestId Each request the page makes will have a unique id.
593         * 
594         * @param request The details of the request.
595         * 
596         * @param frameId The id of the frame that initiated the request.
597         * 
598         * @param resourceType How the requested resource will be used.
599         * 
600         * @param responseErrorReason Response error if intercepted at response stage.
601         * <BR /><B CLASS=Opt>OPTIONAL</B>
602         * 
603         * @param responseStatusCode Response code if intercepted at response stage.
604         * <BR /><B CLASS=Opt>OPTIONAL</B>
605         * 
606         * @param responseStatusText Response status text if intercepted at response stage.
607         * <BR /><B CLASS=Opt>OPTIONAL</B>
608         * 
609         * @param responseHeaders Response headers if intercepted at the response stage.
610         * <BR /><B CLASS=Opt>OPTIONAL</B>
611         * 
612         * @param networkId 
613         * If the intercepted request had a corresponding Network.requestWillBeSent event fired for it,
614         * then this networkId will be the same as the requestId present in the requestWillBeSent event.
615         * <BR /><B CLASS=Opt>OPTIONAL</B>
616         * 
617         * @param redirectedRequestId 
618         * If the request is due to a redirect response from the server, the id of the request that
619         * has caused the redirect.
620         * <BR /><B CLASS=Opt>OPTIONAL</B><B CLASS=Exp>EXPERIMENTAL</B>
621         */
622        public requestPaused(
623                String requestId, Network.Request request, String frameId, String resourceType, 
624                String responseErrorReason, Integer responseStatusCode, String responseStatusText, 
625                Fetch.HeaderEntry[] responseHeaders, String networkId, String redirectedRequestId
626            )
627        {
628            super("Fetch", "requestPaused", 10);
629            
630            // Exception-Check(s) to ensure that if any parameters which are not declared as
631            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
632            
633            if (requestId == null)    THROWS.throwNPE("requestId");
634            if (request == null)      THROWS.throwNPE("request");
635            if (frameId == null)      THROWS.throwNPE("frameId");
636            if (resourceType == null) THROWS.throwNPE("resourceType");
637            
638            // Exception-Check(s) to ensure that if any parameters which must adhere to a
639            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
640            
641            THROWS.checkIAE("resourceType", resourceType, "Network.ResourceType", Network.ResourceType);
642            THROWS.checkIAE("responseErrorReason", responseErrorReason, "Network.ErrorReason", Network.ErrorReason);
643            
644            this.requestId            = requestId;
645            this.request              = request;
646            this.frameId              = frameId;
647            this.resourceType         = resourceType;
648            this.responseErrorReason  = responseErrorReason;
649            this.responseStatusCode   = responseStatusCode;
650            this.responseStatusText   = responseStatusText;
651            this.responseHeaders      = responseHeaders;
652            this.networkId            = networkId;
653            this.redirectedRequestId  = redirectedRequestId;
654        }
655        
656        /**
657         * JSON Object Constructor
658         * @param jo A Json-Object having data about an instance of {@code 'requestPaused'}.
659         */
660        public requestPaused (JsonObject jo)
661        {
662            super("Fetch", "requestPaused", 10);
663        
664            this.requestId            = ReadJSON.getString(jo, "requestId", false, true);
665            this.request              = ReadJSON.getObject(jo, "request", Network.Request.class, false, true);
666            this.frameId              = ReadJSON.getString(jo, "frameId", false, true);
667            this.resourceType         = ReadJSON.getString(jo, "resourceType", false, true);
668            this.responseErrorReason  = ReadJSON.getString(jo, "responseErrorReason", true, false);
669            this.responseStatusCode   = ReadBoxedJSON.getInteger(jo, "responseStatusCode", true);
670            this.responseStatusText   = ReadJSON.getString(jo, "responseStatusText", true, false);
671            this.responseHeaders = (jo.getJsonArray("responseHeaders") == null)
672                ? null
673                : RJArrIntoStream.objArr(jo.getJsonArray("responseHeaders"), null, 0, Fetch.HeaderEntry.class).toArray(Fetch.HeaderEntry[]::new);
674        
675            this.networkId            = ReadJSON.getString(jo, "networkId", true, false);
676            this.redirectedRequestId  = ReadJSON.getString(jo, "redirectedRequestId", true, false);
677        }
678        
679        
680        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
681        public boolean equals(Object other)
682        {
683            if (this == other)                       return true;
684            if (other == null)                       return false;
685            if (other.getClass() != this.getClass()) return false;
686        
687            requestPaused o = (requestPaused) other;
688        
689            return
690                    Objects.equals(this.requestId, o.requestId)
691                &&  Objects.equals(this.request, o.request)
692                &&  Objects.equals(this.frameId, o.frameId)
693                &&  Objects.equals(this.resourceType, o.resourceType)
694                &&  Objects.equals(this.responseErrorReason, o.responseErrorReason)
695                &&  Objects.equals(this.responseStatusCode, o.responseStatusCode)
696                &&  Objects.equals(this.responseStatusText, o.responseStatusText)
697                &&  Arrays.deepEquals(this.responseHeaders, o.responseHeaders)
698                &&  Objects.equals(this.networkId, o.networkId)
699                &&  Objects.equals(this.redirectedRequestId, o.redirectedRequestId);
700        }
701        
702        /** Generates a Hash-Code for {@code 'this'} instance */
703        public int hashCode()
704        {
705            return
706                    Objects.hashCode(this.requestId)
707                +   this.request.hashCode()
708                +   Objects.hashCode(this.frameId)
709                +   Objects.hashCode(this.resourceType)
710                +   Objects.hashCode(this.responseErrorReason)
711                +   Objects.hashCode(this.responseStatusCode)
712                +   Objects.hashCode(this.responseStatusText)
713                +   Arrays.deepHashCode(this.responseHeaders)
714                +   Objects.hashCode(this.networkId)
715                +   Objects.hashCode(this.redirectedRequestId);
716        }
717    }
718    
719    /**
720     * Issued when the domain is enabled with handleAuthRequests set to true.
721     * The request is paused until client responds with continueWithAuth.
722     */
723    public static class authRequired
724        extends BrowserEvent
725        implements java.io.Serializable
726    {
727        /** For Object Serialization.  java.io.Serializable */
728        protected static final long serialVersionUID = 1;
729        
730        public boolean[] optionals()
731        { return new boolean[] { false, false, false, false, false, }; }
732        
733        /** Each request the page makes will have a unique id. */
734        public final String requestId;
735        
736        /** The details of the request. */
737        public final Network.Request request;
738        
739        /** The id of the frame that initiated the request. */
740        public final String frameId;
741        
742        /** How the requested resource will be used. */
743        public final String resourceType;
744        
745        /**
746         * Details of the Authorization Challenge encountered.
747         * If this is set, client should respond with continueRequest that
748         * contains AuthChallengeResponse.
749         */
750        public final Fetch.AuthChallenge authChallenge;
751        
752        /**
753         * Constructor
754         *
755         * @param requestId Each request the page makes will have a unique id.
756         * 
757         * @param request The details of the request.
758         * 
759         * @param frameId The id of the frame that initiated the request.
760         * 
761         * @param resourceType How the requested resource will be used.
762         * 
763         * @param authChallenge 
764         * Details of the Authorization Challenge encountered.
765         * If this is set, client should respond with continueRequest that
766         * contains AuthChallengeResponse.
767         */
768        public authRequired(
769                String requestId, Network.Request request, String frameId, String resourceType, 
770                Fetch.AuthChallenge authChallenge
771            )
772        {
773            super("Fetch", "authRequired", 5);
774            
775            // Exception-Check(s) to ensure that if any parameters which are not declared as
776            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
777            
778            if (requestId == null)     THROWS.throwNPE("requestId");
779            if (request == null)       THROWS.throwNPE("request");
780            if (frameId == null)       THROWS.throwNPE("frameId");
781            if (resourceType == null)  THROWS.throwNPE("resourceType");
782            if (authChallenge == null) THROWS.throwNPE("authChallenge");
783            
784            // Exception-Check(s) to ensure that if any parameters which must adhere to a
785            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
786            
787            THROWS.checkIAE("resourceType", resourceType, "Network.ResourceType", Network.ResourceType);
788            
789            this.requestId      = requestId;
790            this.request        = request;
791            this.frameId        = frameId;
792            this.resourceType   = resourceType;
793            this.authChallenge  = authChallenge;
794        }
795        
796        /**
797         * JSON Object Constructor
798         * @param jo A Json-Object having data about an instance of {@code 'authRequired'}.
799         */
800        public authRequired (JsonObject jo)
801        {
802            super("Fetch", "authRequired", 5);
803        
804            this.requestId      = ReadJSON.getString(jo, "requestId", false, true);
805            this.request        = ReadJSON.getObject(jo, "request", Network.Request.class, false, true);
806            this.frameId        = ReadJSON.getString(jo, "frameId", false, true);
807            this.resourceType   = ReadJSON.getString(jo, "resourceType", false, true);
808            this.authChallenge  = ReadJSON.getObject(jo, "authChallenge", Fetch.AuthChallenge.class, false, true);
809        }
810        
811        
812        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
813        public boolean equals(Object other)
814        {
815            if (this == other)                       return true;
816            if (other == null)                       return false;
817            if (other.getClass() != this.getClass()) return false;
818        
819            authRequired o = (authRequired) other;
820        
821            return
822                    Objects.equals(this.requestId, o.requestId)
823                &&  Objects.equals(this.request, o.request)
824                &&  Objects.equals(this.frameId, o.frameId)
825                &&  Objects.equals(this.resourceType, o.resourceType)
826                &&  Objects.equals(this.authChallenge, o.authChallenge);
827        }
828        
829        /** Generates a Hash-Code for {@code 'this'} instance */
830        public int hashCode()
831        {
832            return
833                    Objects.hashCode(this.requestId)
834                +   this.request.hashCode()
835                +   Objects.hashCode(this.frameId)
836                +   Objects.hashCode(this.resourceType)
837                +   this.authChallenge.hashCode();
838        }
839    }
840    
841    
842    // Counter for keeping the WebSocket Request ID's distinct.
843    private static int counter = 1;
844    
845    /**
846     * Disables the fetch domain.
847     * 
848     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
849     * {@link Ret0}&gt;</CODE>
850     *
851     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
852     * browser receives the invocation-request.
853     *
854     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
855     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
856     * {@code >} to ensure the Browser Function has run to completion.
857     */
858    public static Script<String, JsonObject, Ret0> disable()
859    {
860        final int          webSocketID = 45000000 + counter++;
861        final boolean[]    optionals   = new boolean[0];
862        
863        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
864        String requestJSON = WriteJSON.get(
865            parameterTypes.get("disable"),
866            parameterNames.get("disable"),
867            optionals, webSocketID,
868            "Fetch.disable"
869        );
870        
871        // This Remote Command does not have a Return-Value.
872        return new Script<>
873            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
874    }
875    
876    /**
877     * Enables issuing of requestPaused events. A request will be paused until client
878     * calls one of failRequest, fulfillRequest or continueRequest/continueWithAuth.
879     * 
880     * @param patterns 
881     * If specified, only requests matching any of these patterns will produce
882     * fetchRequested event and will be paused until clients response. If not set,
883     * all requests will be affected.
884     * <BR /><B CLASS=Opt>OPTIONAL</B>
885     * 
886     * @param handleAuthRequests 
887     * If true, authRequired events will be issued and requests will be paused
888     * expecting a call to continueWithAuth.
889     * <BR /><B CLASS=Opt>OPTIONAL</B>
890     * 
891     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
892     * {@link Ret0}&gt;</CODE>
893     *
894     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
895     * browser receives the invocation-request.
896     *
897     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
898     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
899     * {@code >} to ensure the Browser Function has run to completion.
900     */
901    public static Script<String, JsonObject, Ret0> enable
902        (Fetch.RequestPattern[] patterns, Boolean handleAuthRequests)
903    {
904        final int       webSocketID = 45001000 + counter++;
905        final boolean[] optionals   = { true, true, };
906        
907        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
908        String requestJSON = WriteJSON.get(
909            parameterTypes.get("enable"),
910            parameterNames.get("enable"),
911            optionals, webSocketID,
912            "Fetch.enable",
913            patterns, handleAuthRequests
914        );
915        
916        // This Remote Command does not have a Return-Value.
917        return new Script<>
918            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
919    }
920    
921    /**
922     * Causes the request to fail with specified reason.
923     * 
924     * @param requestId An id the client received in requestPaused event.
925     * 
926     * @param errorReason Causes the request to fail with the given reason.
927     * 
928     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
929     * {@link Ret0}&gt;</CODE>
930     *
931     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
932     * browser receives the invocation-request.
933     *
934     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
935     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
936     * {@code >} to ensure the Browser Function has run to completion.
937     */
938    public static Script<String, JsonObject, Ret0> failRequest
939        (String requestId, String errorReason)
940    {
941        // Exception-Check(s) to ensure that if any parameters which are not declared as
942        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
943        
944        if (requestId == null)   THROWS.throwNPE("requestId");
945        if (errorReason == null) THROWS.throwNPE("errorReason");
946        
947        // Exception-Check(s) to ensure that if any parameters which must adhere to a
948        // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
949        
950        THROWS.checkIAE("errorReason", errorReason, "Network.ErrorReason", Network.ErrorReason);
951        
952        final int       webSocketID = 45002000 + counter++;
953        final boolean[] optionals   = { false, false, };
954        
955        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
956        String requestJSON = WriteJSON.get(
957            parameterTypes.get("failRequest"),
958            parameterNames.get("failRequest"),
959            optionals, webSocketID,
960            "Fetch.failRequest",
961            requestId, errorReason
962        );
963        
964        // This Remote Command does not have a Return-Value.
965        return new Script<>
966            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
967    }
968    
969    /**
970     * Provides response to the request.
971     * 
972     * @param requestId An id the client received in requestPaused event.
973     * 
974     * @param responseCode An HTTP response code.
975     * 
976     * @param responseHeaders Response headers.
977     * <BR /><B CLASS=Opt>OPTIONAL</B>
978     * 
979     * @param binaryResponseHeaders 
980     * Alternative way of specifying response headers as a \0-separated
981     * series of name: value pairs. Prefer the above method unless you
982     * need to represent some non-UTF8 values that can't be transmitted
983     * over the protocol as text. (Encoded as a base64 string when passed over JSON)
984     * <BR /><B CLASS=Opt>OPTIONAL</B>
985     * 
986     * @param body 
987     * A response body. If absent, original response body will be used if
988     * the request is intercepted at the response stage and empty body
989     * will be used if the request is intercepted at the request stage. (Encoded as a base64 string when passed over JSON)
990     * <BR /><B CLASS=Opt>OPTIONAL</B>
991     * 
992     * @param responsePhrase 
993     * A textual representation of responseCode.
994     * If absent, a standard phrase matching responseCode is used.
995     * <BR /><B CLASS=Opt>OPTIONAL</B>
996     * 
997     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
998     * {@link Ret0}&gt;</CODE>
999     *
1000     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
1001     * browser receives the invocation-request.
1002     *
1003     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
1004     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
1005     * {@code >} to ensure the Browser Function has run to completion.
1006     */
1007    public static Script<String, JsonObject, Ret0> fulfillRequest(
1008            String requestId, int responseCode, Fetch.HeaderEntry[] responseHeaders, 
1009            String binaryResponseHeaders, String body, String responsePhrase
1010        )
1011    {
1012        // Exception-Check(s) to ensure that if any parameters which are not declared as
1013        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1014        
1015        if (requestId == null) THROWS.throwNPE("requestId");
1016        
1017        final int       webSocketID = 45003000 + counter++;
1018        final boolean[] optionals   = { false, false, true, true, true, true, };
1019        
1020        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1021        String requestJSON = WriteJSON.get(
1022            parameterTypes.get("fulfillRequest"),
1023            parameterNames.get("fulfillRequest"),
1024            optionals, webSocketID,
1025            "Fetch.fulfillRequest",
1026            requestId, responseCode, responseHeaders, binaryResponseHeaders, body, responsePhrase
1027        );
1028        
1029        // This Remote Command does not have a Return-Value.
1030        return new Script<>
1031            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
1032    }
1033    
1034    /**
1035     * Continues the request, optionally modifying some of its parameters.
1036     * 
1037     * @param requestId An id the client received in requestPaused event.
1038     * 
1039     * @param url If set, the request url will be modified in a way that's not observable by page.
1040     * <BR /><B CLASS=Opt>OPTIONAL</B>
1041     * 
1042     * @param method If set, the request method is overridden.
1043     * <BR /><B CLASS=Opt>OPTIONAL</B>
1044     * 
1045     * @param postData If set, overrides the post data in the request. (Encoded as a base64 string when passed over JSON)
1046     * <BR /><B CLASS=Opt>OPTIONAL</B>
1047     * 
1048     * @param headers 
1049     * If set, overrides the request headers. Note that the overrides do not
1050     * extend to subsequent redirect hops, if a redirect happens. Another override
1051     * may be applied to a different request produced by a redirect.
1052     * <BR /><B CLASS=Opt>OPTIONAL</B>
1053     * 
1054     * @param interceptResponse If set, overrides response interception behavior for this request.
1055     * <BR /><B CLASS=Opt>OPTIONAL</B><B CLASS=Exp>EXPERIMENTAL</B>
1056     * 
1057     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
1058     * {@link Ret0}&gt;</CODE>
1059     *
1060     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
1061     * browser receives the invocation-request.
1062     *
1063     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
1064     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
1065     * {@code >} to ensure the Browser Function has run to completion.
1066     */
1067    public static Script<String, JsonObject, Ret0> continueRequest(
1068            String requestId, String url, String method, String postData, 
1069            Fetch.HeaderEntry[] headers, Boolean interceptResponse
1070        )
1071    {
1072        // Exception-Check(s) to ensure that if any parameters which are not declared as
1073        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1074        
1075        if (requestId == null) THROWS.throwNPE("requestId");
1076        
1077        final int       webSocketID = 45004000 + counter++;
1078        final boolean[] optionals   = { false, true, true, true, true, true, };
1079        
1080        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1081        String requestJSON = WriteJSON.get(
1082            parameterTypes.get("continueRequest"),
1083            parameterNames.get("continueRequest"),
1084            optionals, webSocketID,
1085            "Fetch.continueRequest",
1086            requestId, url, method, postData, headers, interceptResponse
1087        );
1088        
1089        // This Remote Command does not have a Return-Value.
1090        return new Script<>
1091            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
1092    }
1093    
1094    /**
1095     * Continues a request supplying authChallengeResponse following authRequired event.
1096     * 
1097     * @param requestId An id the client received in authRequired event.
1098     * 
1099     * @param authChallengeResponse Response to  with an authChallenge.
1100     * 
1101     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
1102     * {@link Ret0}&gt;</CODE>
1103     *
1104     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
1105     * browser receives the invocation-request.
1106     *
1107     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
1108     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
1109     * {@code >} to ensure the Browser Function has run to completion.
1110     */
1111    public static Script<String, JsonObject, Ret0> continueWithAuth
1112        (String requestId, Fetch.AuthChallengeResponse authChallengeResponse)
1113    {
1114        // Exception-Check(s) to ensure that if any parameters which are not declared as
1115        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1116        
1117        if (requestId == null)             THROWS.throwNPE("requestId");
1118        if (authChallengeResponse == null) THROWS.throwNPE("authChallengeResponse");
1119        
1120        final int       webSocketID = 45005000 + counter++;
1121        final boolean[] optionals   = { false, false, };
1122        
1123        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1124        String requestJSON = WriteJSON.get(
1125            parameterTypes.get("continueWithAuth"),
1126            parameterNames.get("continueWithAuth"),
1127            optionals, webSocketID,
1128            "Fetch.continueWithAuth",
1129            requestId, authChallengeResponse
1130        );
1131        
1132        // This Remote Command does not have a Return-Value.
1133        return new Script<>
1134            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
1135    }
1136    
1137    /**
1138     * Continues loading of the paused response, optionally modifying the
1139     * response headers. If either responseCode or headers are modified, all of them
1140     * must be present.
1141     * <BR /><B CLASS=Exp-Top>EXPERIMENTAL</B>
1142     * 
1143     * @param requestId An id the client received in requestPaused event.
1144     * 
1145     * @param responseCode An HTTP response code. If absent, original response code will be used.
1146     * <BR /><B CLASS=Opt>OPTIONAL</B>
1147     * 
1148     * @param responsePhrase 
1149     * A textual representation of responseCode.
1150     * If absent, a standard phrase matching responseCode is used.
1151     * <BR /><B CLASS=Opt>OPTIONAL</B>
1152     * 
1153     * @param responseHeaders Response headers. If absent, original response headers will be used.
1154     * <BR /><B CLASS=Opt>OPTIONAL</B>
1155     * 
1156     * @param binaryResponseHeaders 
1157     * Alternative way of specifying response headers as a \0-separated
1158     * series of name: value pairs. Prefer the above method unless you
1159     * need to represent some non-UTF8 values that can't be transmitted
1160     * over the protocol as text. (Encoded as a base64 string when passed over JSON)
1161     * <BR /><B CLASS=Opt>OPTIONAL</B>
1162     * 
1163     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
1164     * {@link Ret0}&gt;</CODE>
1165     *
1166     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
1167     * browser receives the invocation-request.
1168     *
1169     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
1170     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
1171     * {@code >} to ensure the Browser Function has run to completion.
1172     */
1173    public static Script<String, JsonObject, Ret0> continueResponse(
1174            String requestId, Integer responseCode, String responsePhrase, 
1175            Fetch.HeaderEntry[] responseHeaders, String binaryResponseHeaders
1176        )
1177    {
1178        // Exception-Check(s) to ensure that if any parameters which are not declared as
1179        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1180        
1181        if (requestId == null) THROWS.throwNPE("requestId");
1182        
1183        final int       webSocketID = 45006000 + counter++;
1184        final boolean[] optionals   = { false, true, true, true, true, };
1185        
1186        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1187        String requestJSON = WriteJSON.get(
1188            parameterTypes.get("continueResponse"),
1189            parameterNames.get("continueResponse"),
1190            optionals, webSocketID,
1191            "Fetch.continueResponse",
1192            requestId, responseCode, responsePhrase, responseHeaders, binaryResponseHeaders
1193        );
1194        
1195        // This Remote Command does not have a Return-Value.
1196        return new Script<>
1197            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
1198    }
1199    
1200    /**
1201     * Causes the body of the response to be received from the server and
1202     * returned as a single string. May only be issued for a request that
1203     * is paused in the Response stage and is mutually exclusive with
1204     * takeResponseBodyForInterceptionAsStream. Calling other methods that
1205     * affect the request or disabling fetch domain before body is received
1206     * results in an undefined behavior.
1207     * Note that the response body is not available for redirects. Requests
1208     * paused in the _redirect received_ state may be differentiated by
1209     * {@code responseCode} and presence of {@code location} response header, see
1210     * comments to {@code requestPaused} for details.
1211     * 
1212     * @param requestId Identifier for the intercepted request to get body for.
1213     * 
1214     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
1215     * {@link Ret2}&gt;</CODE>
1216     *
1217     * <BR /><BR />This {@link Script} may be <B STYLE='color:red'>executed</B> (using 
1218     * {@link Script#exec()}), and a {@link Promise} returned.
1219     *
1220     * <BR /><BR />When the {@code Promise} is <B STYLE='color: red'>awaited</B>
1221     * (using {@link Promise#await()}), the {@code Ret2} will subsequently
1222     * be returned from that call.
1223     * 
1224     * <BR /><BR />The <B STYLE='color: red'>returned</B> values are encapsulated
1225     * in an instance of <B>{@link Ret2}</B>
1226     *
1227     * <BR /><BR /><UL CLASS=JDUL>
1228     * <LI><CODE><B>Ret2.a:</B> String (<B>body</B>)</CODE>
1229     *     <BR />Response body.
1230     *     <BR /><BR /></LI>
1231     * <LI><CODE><B>Ret2.b:</B> Boolean (<B>base64Encoded</B>)</CODE>
1232     *     <BR />True, if content was sent as base64.
1233     *     </LI>
1234     * </UL>
1235     */
1236    public static Script<String, JsonObject, Ret2<String, Boolean>> getResponseBody
1237        (String requestId)
1238    {
1239        // Exception-Check(s) to ensure that if any parameters which are not declared as
1240        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1241        
1242        if (requestId == null) THROWS.throwNPE("requestId");
1243        
1244        final int       webSocketID = 45007000 + counter++;
1245        final boolean[] optionals   = { false, };
1246        
1247        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1248        String requestJSON = WriteJSON.get(
1249            parameterTypes.get("getResponseBody"),
1250            parameterNames.get("getResponseBody"),
1251            optionals, webSocketID,
1252            "Fetch.getResponseBody",
1253            requestId
1254        );
1255        
1256        // 'JSON Binding' ... Converts Browser Response-JSON into Java-Type 'Ret2'
1257        Function<JsonObject, Ret2<String, Boolean>>
1258            responseProcessor = (JsonObject jo) -> new Ret2<>(
1259                ReadJSON.getString(jo, "body", false, true),
1260                ReadBoxedJSON.getBoolean(jo, "base64Encoded", true)
1261            );
1262        
1263        return new Script<>(webSocketID, requestJSON, responseProcessor);
1264    }
1265    
1266    /**
1267     * Returns a handle to the stream representing the response body.
1268     * The request must be paused in the HeadersReceived stage.
1269     * Note that after this command the request can't be continued
1270     * as is -- client either needs to cancel it or to provide the
1271     * response body.
1272     * The stream only supports sequential read, IO.read will fail if the position
1273     * is specified.
1274     * This method is mutually exclusive with getResponseBody.
1275     * Calling other methods that affect the request or disabling fetch
1276     * domain before body is received results in an undefined behavior.
1277     * 
1278     * @param requestId -
1279     * 
1280     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
1281     * String&gt;</CODE>
1282     * 
1283     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
1284     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
1285     * String&gt;</CODE> will be returned.
1286     *
1287     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
1288     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
1289      * may be retrieved.</I>
1290     *
1291     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
1292     * <BR /><BR /><UL CLASS=JDUL>
1293     * <LI><CODE>String (<B>stream</B></CODE>)
1294     *     <BR />-
1295     * </LI>
1296     * </UL> */
1297    public static Script<String, JsonObject, String> takeResponseBodyAsStream(String requestId)
1298    {
1299        // Exception-Check(s) to ensure that if any parameters which are not declared as
1300        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1301        
1302        if (requestId == null) THROWS.throwNPE("requestId");
1303        
1304        final int       webSocketID = 45008000 + counter++;
1305        final boolean[] optionals   = { false, };
1306        
1307        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1308        String requestJSON = WriteJSON.get(
1309            parameterTypes.get("takeResponseBodyAsStream"),
1310            parameterNames.get("takeResponseBodyAsStream"),
1311            optionals, webSocketID,
1312            "Fetch.takeResponseBodyAsStream",
1313            requestId
1314        );
1315        
1316        // 'JSON Binding' ... Converts Browser Response-JSON to 'String'
1317        Function<JsonObject, String> responseProcessor = (JsonObject jo) ->
1318            ReadJSON.getString(jo, "stream", false, true);
1319        
1320        return new Script<>(webSocketID, requestJSON, responseProcessor);
1321    }
1322    
1323}