001package Torello.Browser; 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.Java.Additional.*; 013import Torello.Java.JSON.*; 014 015import static Torello.Java.JSON.JFlag.*; 016 017import Torello.Java.StrCmpr; 018import Torello.JavaDoc.StaticFunctional; 019import Torello.JavaDoc.JDHeaderBackgroundImg; 020import Torello.JavaDoc.Excuse; 021 022/** 023 * <SPAN CLASS=COPIEDJDK><B>Reporting of performance timeline events, as specified in 024 * https://w3c.github.io/performance-timeline/#dom-performanceobserver.</B></SPAN> 025 * 026 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE> 027 */ 028@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION}) 029@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE") 030public class PerformanceTimeline 031{ 032 // ******************************************************************************************** 033 // ******************************************************************************************** 034 // Class Header Stuff 035 // ******************************************************************************************** 036 // ******************************************************************************************** 037 038 039 // No Pubic Constructors 040 private PerformanceTimeline () { } 041 042 // These two Vector's are used by all the "Methods" exported by this class. java.lang.reflect 043 // is used to generate the JSON String's. It saves thousands of lines of Auto-Generated Code. 044 private static final Map<String, Vector<String>> parameterNames = new HashMap<>(); 045 private static final Map<String, Vector<Class<?>>> parameterTypes = new HashMap<>(); 046 047 // Some Methods do not take any parameters - for instance all the "enable()" and "disable()" 048 // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now, 049 // offically, two empty-vectors. One for String's, and the other for Classes. 050 051 private static final Vector<String> EMPTY_VEC_STR = new Vector<>(); 052 private static final Vector<Class<?>> EMPTY_VEC_CLASS = new Vector<>(); 053 054 static 055 { 056 for (Method m : PerformanceTimeline.class.getMethods()) 057 { 058 // This doesn't work! The parameter names are all "arg0" ... "argN" 059 // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter! 060 // 061 // Vector<String> parameterNamesList = new Vector<>(); -- NOPE! 062 063 Vector<Class<?>> parameterTypesList = new Vector<>(); 064 065 for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType()); 066 067 parameterTypes.put( 068 m.getName(), 069 (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS 070 ); 071 } 072 } 073 074 static 075 { 076 Vector<String> v = null; 077 078 v = new Vector<String>(1); 079 parameterNames.put("enable", v); 080 Collections.addAll(v, new String[] 081 { "eventTypes", }); 082 } 083 084 085 // ******************************************************************************************** 086 // ******************************************************************************************** 087 // Types - Static Inner Classes 088 // ******************************************************************************************** 089 // ******************************************************************************************** 090 091 /** See https://github.com/WICG/LargestContentfulPaint and largest_contentful_paint.idl */ 092 public static class LargestContentfulPaint 093 extends BaseType 094 implements java.io.Serializable 095 { 096 /** For Object Serialization. java.io.Serializable */ 097 protected static final long serialVersionUID = 1; 098 099 public boolean[] optionals() 100 { return new boolean[] { false, false, false, true, true, true, }; } 101 102 /** <CODE>[No Description Provided by Google]</CODE> */ 103 public final Number renderTime; 104 105 /** <CODE>[No Description Provided by Google]</CODE> */ 106 public final Number loadTime; 107 108 /** The number of pixels being painted. */ 109 public final Number size; 110 111 /** 112 * The id attribute of the element, if available. 113 * <BR /> 114 * <BR /><B>OPTIONAL</B> 115 */ 116 public final String elementId; 117 118 /** 119 * The URL of the image (may be trimmed). 120 * <BR /> 121 * <BR /><B>OPTIONAL</B> 122 */ 123 public final String url; 124 125 /** 126 * <CODE>[No Description Provided by Google]</CODE> 127 * <BR /> 128 * <BR /><B>OPTIONAL</B> 129 */ 130 public final Integer nodeId; 131 132 /** 133 * Constructor 134 * 135 * @param renderTime - 136 * 137 * @param loadTime - 138 * 139 * @param size The number of pixels being painted. 140 * 141 * @param elementId The id attribute of the element, if available. 142 * <BR /><B>OPTIONAL</B> 143 * 144 * @param url The URL of the image (may be trimmed). 145 * <BR /><B>OPTIONAL</B> 146 * 147 * @param nodeId - 148 * <BR /><B>OPTIONAL</B> 149 */ 150 public LargestContentfulPaint( 151 Number renderTime, Number loadTime, Number size, String elementId, String url, 152 Integer nodeId 153 ) 154 { 155 // Exception-Check(s) to ensure that if any parameters which are not declared as 156 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 157 158 if (renderTime == null) THROWS.throwNPE("renderTime"); 159 if (loadTime == null) THROWS.throwNPE("loadTime"); 160 if (size == null) THROWS.throwNPE("size"); 161 162 this.renderTime = renderTime; 163 this.loadTime = loadTime; 164 this.size = size; 165 this.elementId = elementId; 166 this.url = url; 167 this.nodeId = nodeId; 168 } 169 170 /** 171 * JSON Object Constructor 172 * @param jo A Json-Object having data about an instance of {@code 'LargestContentfulPaint'}. 173 */ 174 public LargestContentfulPaint (JsonObject jo) 175 { 176 this.renderTime = ReadNumberJSON.get(jo, "renderTime", false, true); 177 this.loadTime = ReadNumberJSON.get(jo, "loadTime", false, true); 178 this.size = ReadNumberJSON.get(jo, "size", false, true); 179 this.elementId = ReadJSON.getString(jo, "elementId", true, false); 180 this.url = ReadJSON.getString(jo, "url", true, false); 181 this.nodeId = ReadBoxedJSON.getInteger(jo, "nodeId", true); 182 } 183 184 185 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 186 public boolean equals(Object other) 187 { 188 if (this == other) return true; 189 if (other == null) return false; 190 if (other.getClass() != this.getClass()) return false; 191 192 LargestContentfulPaint o = (LargestContentfulPaint) other; 193 194 return 195 Objects.equals(this.renderTime, o.renderTime) 196 && Objects.equals(this.loadTime, o.loadTime) 197 && Objects.equals(this.size, o.size) 198 && Objects.equals(this.elementId, o.elementId) 199 && Objects.equals(this.url, o.url) 200 && Objects.equals(this.nodeId, o.nodeId); 201 } 202 203 /** Generates a Hash-Code for {@code 'this'} instance */ 204 public int hashCode() 205 { 206 return 207 Objects.hashCode(this.renderTime) 208 + Objects.hashCode(this.loadTime) 209 + Objects.hashCode(this.size) 210 + Objects.hashCode(this.elementId) 211 + Objects.hashCode(this.url) 212 + Objects.hashCode(this.nodeId); 213 } 214 } 215 216 /** <CODE>[No Description Provided by Google]</CODE> */ 217 public static class LayoutShiftAttribution 218 extends BaseType 219 implements java.io.Serializable 220 { 221 /** For Object Serialization. java.io.Serializable */ 222 protected static final long serialVersionUID = 1; 223 224 public boolean[] optionals() 225 { return new boolean[] { false, false, true, }; } 226 227 /** <CODE>[No Description Provided by Google]</CODE> */ 228 public final DOM.Rect previousRect; 229 230 /** <CODE>[No Description Provided by Google]</CODE> */ 231 public final DOM.Rect currentRect; 232 233 /** 234 * <CODE>[No Description Provided by Google]</CODE> 235 * <BR /> 236 * <BR /><B>OPTIONAL</B> 237 */ 238 public final Integer nodeId; 239 240 /** 241 * Constructor 242 * 243 * @param previousRect - 244 * 245 * @param currentRect - 246 * 247 * @param nodeId - 248 * <BR /><B>OPTIONAL</B> 249 */ 250 public LayoutShiftAttribution 251 (DOM.Rect previousRect, DOM.Rect currentRect, Integer nodeId) 252 { 253 // Exception-Check(s) to ensure that if any parameters which are not declared as 254 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 255 256 if (previousRect == null) THROWS.throwNPE("previousRect"); 257 if (currentRect == null) THROWS.throwNPE("currentRect"); 258 259 this.previousRect = previousRect; 260 this.currentRect = currentRect; 261 this.nodeId = nodeId; 262 } 263 264 /** 265 * JSON Object Constructor 266 * @param jo A Json-Object having data about an instance of {@code 'LayoutShiftAttribution'}. 267 */ 268 public LayoutShiftAttribution (JsonObject jo) 269 { 270 this.previousRect = ReadJSON.getObject(jo, "previousRect", DOM.Rect.class, false, true); 271 this.currentRect = ReadJSON.getObject(jo, "currentRect", DOM.Rect.class, false, true); 272 this.nodeId = ReadBoxedJSON.getInteger(jo, "nodeId", true); 273 } 274 275 276 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 277 public boolean equals(Object other) 278 { 279 if (this == other) return true; 280 if (other == null) return false; 281 if (other.getClass() != this.getClass()) return false; 282 283 LayoutShiftAttribution o = (LayoutShiftAttribution) other; 284 285 return 286 Objects.equals(this.previousRect, o.previousRect) 287 && Objects.equals(this.currentRect, o.currentRect) 288 && Objects.equals(this.nodeId, o.nodeId); 289 } 290 291 /** Generates a Hash-Code for {@code 'this'} instance */ 292 public int hashCode() 293 { 294 return 295 this.previousRect.hashCode() 296 + this.currentRect.hashCode() 297 + Objects.hashCode(this.nodeId); 298 } 299 } 300 301 /** See https://wicg.github.io/layout-instability/#sec-layout-shift and layout_shift.idl */ 302 public static class LayoutShift 303 extends BaseType 304 implements java.io.Serializable 305 { 306 /** For Object Serialization. java.io.Serializable */ 307 protected static final long serialVersionUID = 1; 308 309 public boolean[] optionals() 310 { return new boolean[] { false, false, false, false, }; } 311 312 /** Score increment produced by this event. */ 313 public final Number value; 314 315 /** <CODE>[No Description Provided by Google]</CODE> */ 316 public final boolean hadRecentInput; 317 318 /** <CODE>[No Description Provided by Google]</CODE> */ 319 public final Number lastInputTime; 320 321 /** <CODE>[No Description Provided by Google]</CODE> */ 322 public final PerformanceTimeline.LayoutShiftAttribution[] sources; 323 324 /** 325 * Constructor 326 * 327 * @param value Score increment produced by this event. 328 * 329 * @param hadRecentInput - 330 * 331 * @param lastInputTime - 332 * 333 * @param sources - 334 */ 335 public LayoutShift( 336 Number value, boolean hadRecentInput, Number lastInputTime, 337 PerformanceTimeline.LayoutShiftAttribution[] sources 338 ) 339 { 340 // Exception-Check(s) to ensure that if any parameters which are not declared as 341 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 342 343 if (value == null) THROWS.throwNPE("value"); 344 if (lastInputTime == null) THROWS.throwNPE("lastInputTime"); 345 if (sources == null) THROWS.throwNPE("sources"); 346 347 this.value = value; 348 this.hadRecentInput = hadRecentInput; 349 this.lastInputTime = lastInputTime; 350 this.sources = sources; 351 } 352 353 /** 354 * JSON Object Constructor 355 * @param jo A Json-Object having data about an instance of {@code 'LayoutShift'}. 356 */ 357 public LayoutShift (JsonObject jo) 358 { 359 this.value = ReadNumberJSON.get(jo, "value", false, true); 360 this.hadRecentInput = ReadPrimJSON.getBoolean(jo, "hadRecentInput"); 361 this.lastInputTime = ReadNumberJSON.get(jo, "lastInputTime", false, true); 362 this.sources = (jo.getJsonArray("sources") == null) 363 ? null 364 : RJArrIntoStream.objArr(jo.getJsonArray("sources"), null, 0, PerformanceTimeline.LayoutShiftAttribution.class).toArray(PerformanceTimeline.LayoutShiftAttribution[]::new); 365 366 } 367 368 369 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 370 public boolean equals(Object other) 371 { 372 if (this == other) return true; 373 if (other == null) return false; 374 if (other.getClass() != this.getClass()) return false; 375 376 LayoutShift o = (LayoutShift) other; 377 378 return 379 Objects.equals(this.value, o.value) 380 && (this.hadRecentInput == o.hadRecentInput) 381 && Objects.equals(this.lastInputTime, o.lastInputTime) 382 && Arrays.deepEquals(this.sources, o.sources); 383 } 384 385 /** Generates a Hash-Code for {@code 'this'} instance */ 386 public int hashCode() 387 { 388 return 389 Objects.hashCode(this.value) 390 + (this.hadRecentInput ? 1 : 0) 391 + Objects.hashCode(this.lastInputTime) 392 + Arrays.deepHashCode(this.sources); 393 } 394 } 395 396 /** <CODE>[No Description Provided by Google]</CODE> */ 397 public static class TimelineEvent 398 extends BaseType 399 implements java.io.Serializable 400 { 401 /** For Object Serialization. java.io.Serializable */ 402 protected static final long serialVersionUID = 1; 403 404 public boolean[] optionals() 405 { return new boolean[] { false, false, false, false, true, true, true, }; } 406 407 /** Identifies the frame that this event is related to. Empty for non-frame targets. */ 408 public final String frameId; 409 410 /** 411 * The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype 412 * This determines which of the optional "details" fiedls is present. 413 */ 414 public final String type; 415 416 /** Name may be empty depending on the type. */ 417 public final String name; 418 419 /** Time in seconds since Epoch, monotonically increasing within document lifetime. */ 420 public final Number time; 421 422 /** 423 * Event duration, if applicable. 424 * <BR /> 425 * <BR /><B>OPTIONAL</B> 426 */ 427 public final Number duration; 428 429 /** 430 * <CODE>[No Description Provided by Google]</CODE> 431 * <BR /> 432 * <BR /><B>OPTIONAL</B> 433 */ 434 public final PerformanceTimeline.LargestContentfulPaint lcpDetails; 435 436 /** 437 * <CODE>[No Description Provided by Google]</CODE> 438 * <BR /> 439 * <BR /><B>OPTIONAL</B> 440 */ 441 public final PerformanceTimeline.LayoutShift layoutShiftDetails; 442 443 /** 444 * Constructor 445 * 446 * @param frameId Identifies the frame that this event is related to. Empty for non-frame targets. 447 * 448 * @param type 449 * The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype 450 * This determines which of the optional "details" fiedls is present. 451 * 452 * @param name Name may be empty depending on the type. 453 * 454 * @param time Time in seconds since Epoch, monotonically increasing within document lifetime. 455 * 456 * @param duration Event duration, if applicable. 457 * <BR /><B>OPTIONAL</B> 458 * 459 * @param lcpDetails - 460 * <BR /><B>OPTIONAL</B> 461 * 462 * @param layoutShiftDetails - 463 * <BR /><B>OPTIONAL</B> 464 */ 465 public TimelineEvent( 466 String frameId, String type, String name, Number time, Number duration, 467 PerformanceTimeline.LargestContentfulPaint lcpDetails, 468 PerformanceTimeline.LayoutShift layoutShiftDetails 469 ) 470 { 471 // Exception-Check(s) to ensure that if any parameters which are not declared as 472 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 473 474 if (frameId == null) THROWS.throwNPE("frameId"); 475 if (type == null) THROWS.throwNPE("type"); 476 if (name == null) THROWS.throwNPE("name"); 477 if (time == null) THROWS.throwNPE("time"); 478 479 this.frameId = frameId; 480 this.type = type; 481 this.name = name; 482 this.time = time; 483 this.duration = duration; 484 this.lcpDetails = lcpDetails; 485 this.layoutShiftDetails = layoutShiftDetails; 486 } 487 488 /** 489 * JSON Object Constructor 490 * @param jo A Json-Object having data about an instance of {@code 'TimelineEvent'}. 491 */ 492 public TimelineEvent (JsonObject jo) 493 { 494 this.frameId = ReadJSON.getString(jo, "frameId", false, true); 495 this.type = ReadJSON.getString(jo, "type", false, true); 496 this.name = ReadJSON.getString(jo, "name", false, true); 497 this.time = ReadNumberJSON.get(jo, "time", false, true); 498 this.duration = ReadNumberJSON.get(jo, "duration", true, false); 499 this.lcpDetails = ReadJSON.getObject(jo, "lcpDetails", PerformanceTimeline.LargestContentfulPaint.class, true, false); 500 this.layoutShiftDetails = ReadJSON.getObject(jo, "layoutShiftDetails", PerformanceTimeline.LayoutShift.class, true, false); 501 } 502 503 504 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 505 public boolean equals(Object other) 506 { 507 if (this == other) return true; 508 if (other == null) return false; 509 if (other.getClass() != this.getClass()) return false; 510 511 TimelineEvent o = (TimelineEvent) other; 512 513 return 514 Objects.equals(this.frameId, o.frameId) 515 && Objects.equals(this.type, o.type) 516 && Objects.equals(this.name, o.name) 517 && Objects.equals(this.time, o.time) 518 && Objects.equals(this.duration, o.duration) 519 && Objects.equals(this.lcpDetails, o.lcpDetails) 520 && Objects.equals(this.layoutShiftDetails, o.layoutShiftDetails); 521 } 522 523 /** Generates a Hash-Code for {@code 'this'} instance */ 524 public int hashCode() 525 { 526 return 527 Objects.hashCode(this.frameId) 528 + Objects.hashCode(this.type) 529 + Objects.hashCode(this.name) 530 + Objects.hashCode(this.time) 531 + Objects.hashCode(this.duration) 532 + this.lcpDetails.hashCode() 533 + this.layoutShiftDetails.hashCode(); 534 } 535 } 536 537 /** Sent when a performance timeline event is added. See reportPerformanceTimeline method. */ 538 public static class timelineEventAdded 539 extends BrowserEvent 540 implements java.io.Serializable 541 { 542 /** For Object Serialization. java.io.Serializable */ 543 protected static final long serialVersionUID = 1; 544 545 public boolean[] optionals() 546 { return new boolean[] { false, }; } 547 548 /** <CODE>[No Description Provided by Google]</CODE> */ 549 public final PerformanceTimeline.TimelineEvent event; 550 551 /** 552 * Constructor 553 * 554 * @param event - 555 */ 556 public timelineEventAdded(PerformanceTimeline.TimelineEvent event) 557 { 558 super("PerformanceTimeline", "timelineEventAdded", 1); 559 560 // Exception-Check(s) to ensure that if any parameters which are not declared as 561 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 562 563 if (event == null) THROWS.throwNPE("event"); 564 565 this.event = event; 566 } 567 568 /** 569 * JSON Object Constructor 570 * @param jo A Json-Object having data about an instance of {@code 'timelineEventAdded'}. 571 */ 572 public timelineEventAdded (JsonObject jo) 573 { 574 super("PerformanceTimeline", "timelineEventAdded", 1); 575 576 this.event = ReadJSON.getObject(jo, "event", PerformanceTimeline.TimelineEvent.class, false, true); 577 } 578 579 580 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 581 public boolean equals(Object other) 582 { 583 if (this == other) return true; 584 if (other == null) return false; 585 if (other.getClass() != this.getClass()) return false; 586 587 timelineEventAdded o = (timelineEventAdded) other; 588 589 return 590 Objects.equals(this.event, o.event); 591 } 592 593 /** Generates a Hash-Code for {@code 'this'} instance */ 594 public int hashCode() 595 { 596 return 597 this.event.hashCode(); 598 } 599 } 600 601 602 // Counter for keeping the WebSocket Request ID's distinct. 603 private static int counter = 1; 604 605 /** 606 * Previously buffered events would be reported before method returns. 607 * See also: timelineEventAdded 608 * 609 * @param eventTypes 610 * The types of event to report, as specified in 611 * https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype 612 * The specified filter overrides any previous filters, passing empty 613 * filter disables recording. 614 * Note that not all types exposed to the web platform are currently supported. 615 * 616 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 617 * {@link Ret0}></CODE> 618 * 619 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 620 * browser receives the invocation-request. 621 * 622 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 623 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 624 * {@code >} to ensure the Browser Function has run to completion. 625 */ 626 public static Script<String, JsonObject, Ret0> enable(String[] eventTypes) 627 { 628 // Exception-Check(s) to ensure that if any parameters which are not declared as 629 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 630 631 if (eventTypes == null) THROWS.throwNPE("eventTypes"); 632 633 final int webSocketID = 34000000 + counter++; 634 final boolean[] optionals = { false, }; 635 636 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 637 String requestJSON = WriteJSON.get( 638 parameterTypes.get("enable"), 639 parameterNames.get("enable"), 640 optionals, webSocketID, 641 "PerformanceTimeline.enable", 642 (Object) eventTypes 643 ); 644 645 // This Remote Command does not have a Return-Value. 646 return new Script<> 647 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 648 } 649 650}