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) BRDPC.throwNPE("renderTime"); 159 if (loadTime == null) BRDPC.throwNPE("loadTime"); 160 if (size == null) BRDPC.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 (other == null) return false; 189 if (other.getClass() != this.getClass()) return false; 190 191 LargestContentfulPaint o = (LargestContentfulPaint) other; 192 193 return 194 Objects.equals(this.renderTime, o.renderTime) 195 && Objects.equals(this.loadTime, o.loadTime) 196 && Objects.equals(this.size, o.size) 197 && Objects.equals(this.elementId, o.elementId) 198 && Objects.equals(this.url, o.url) 199 && Objects.equals(this.nodeId, o.nodeId); 200 } 201 202 /** Generates a Hash-Code for {@code 'this'} instance */ 203 public int hashCode() 204 { 205 return 206 Objects.hashCode(this.renderTime) 207 + Objects.hashCode(this.loadTime) 208 + Objects.hashCode(this.size) 209 + Objects.hashCode(this.elementId) 210 + Objects.hashCode(this.url) 211 + Objects.hashCode(this.nodeId); 212 } 213 } 214 215 /** <CODE>[No Description Provided by Google]</CODE> */ 216 public static class LayoutShiftAttribution 217 extends BaseType 218 implements java.io.Serializable 219 { 220 /** For Object Serialization. java.io.Serializable */ 221 protected static final long serialVersionUID = 1; 222 223 public boolean[] optionals() 224 { return new boolean[] { false, false, true, }; } 225 226 /** <CODE>[No Description Provided by Google]</CODE> */ 227 public final DOM.Rect previousRect; 228 229 /** <CODE>[No Description Provided by Google]</CODE> */ 230 public final DOM.Rect currentRect; 231 232 /** 233 * <CODE>[No Description Provided by Google]</CODE> 234 * <BR /> 235 * <BR /><B>OPTIONAL</B> 236 */ 237 public final Integer nodeId; 238 239 /** 240 * Constructor 241 * 242 * @param previousRect - 243 * 244 * @param currentRect - 245 * 246 * @param nodeId - 247 * <BR /><B>OPTIONAL</B> 248 */ 249 public LayoutShiftAttribution 250 (DOM.Rect previousRect, DOM.Rect currentRect, Integer nodeId) 251 { 252 // Exception-Check(s) to ensure that if any parameters which are not declared as 253 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 254 255 if (previousRect == null) BRDPC.throwNPE("previousRect"); 256 if (currentRect == null) BRDPC.throwNPE("currentRect"); 257 258 this.previousRect = previousRect; 259 this.currentRect = currentRect; 260 this.nodeId = nodeId; 261 } 262 263 /** 264 * JSON Object Constructor 265 * @param jo A Json-Object having data about an instance of {@code 'LayoutShiftAttribution'}. 266 */ 267 public LayoutShiftAttribution (JsonObject jo) 268 { 269 this.previousRect = ReadJSON.getObject(jo, "previousRect", DOM.Rect.class, false, true); 270 this.currentRect = ReadJSON.getObject(jo, "currentRect", DOM.Rect.class, false, true); 271 this.nodeId = ReadBoxedJSON.getInteger(jo, "nodeId", true); 272 } 273 274 275 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 276 public boolean equals(Object other) 277 { 278 if (other == null) return false; 279 if (other.getClass() != this.getClass()) return false; 280 281 LayoutShiftAttribution o = (LayoutShiftAttribution) other; 282 283 return 284 Objects.equals(this.previousRect, o.previousRect) 285 && Objects.equals(this.currentRect, o.currentRect) 286 && Objects.equals(this.nodeId, o.nodeId); 287 } 288 289 /** Generates a Hash-Code for {@code 'this'} instance */ 290 public int hashCode() 291 { 292 return 293 this.previousRect.hashCode() 294 + this.currentRect.hashCode() 295 + Objects.hashCode(this.nodeId); 296 } 297 } 298 299 /** See https://wicg.github.io/layout-instability/#sec-layout-shift and layout_shift.idl */ 300 public static class LayoutShift 301 extends BaseType 302 implements java.io.Serializable 303 { 304 /** For Object Serialization. java.io.Serializable */ 305 protected static final long serialVersionUID = 1; 306 307 public boolean[] optionals() 308 { return new boolean[] { false, false, false, false, }; } 309 310 /** Score increment produced by this event. */ 311 public final Number value; 312 313 /** <CODE>[No Description Provided by Google]</CODE> */ 314 public final boolean hadRecentInput; 315 316 /** <CODE>[No Description Provided by Google]</CODE> */ 317 public final Number lastInputTime; 318 319 /** <CODE>[No Description Provided by Google]</CODE> */ 320 public final PerformanceTimeline.LayoutShiftAttribution[] sources; 321 322 /** 323 * Constructor 324 * 325 * @param value Score increment produced by this event. 326 * 327 * @param hadRecentInput - 328 * 329 * @param lastInputTime - 330 * 331 * @param sources - 332 */ 333 public LayoutShift( 334 Number value, boolean hadRecentInput, Number lastInputTime, 335 PerformanceTimeline.LayoutShiftAttribution[] sources 336 ) 337 { 338 // Exception-Check(s) to ensure that if any parameters which are not declared as 339 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 340 341 if (value == null) BRDPC.throwNPE("value"); 342 if (lastInputTime == null) BRDPC.throwNPE("lastInputTime"); 343 if (sources == null) BRDPC.throwNPE("sources"); 344 345 this.value = value; 346 this.hadRecentInput = hadRecentInput; 347 this.lastInputTime = lastInputTime; 348 this.sources = sources; 349 } 350 351 /** 352 * JSON Object Constructor 353 * @param jo A Json-Object having data about an instance of {@code 'LayoutShift'}. 354 */ 355 public LayoutShift (JsonObject jo) 356 { 357 this.value = ReadNumberJSON.get(jo, "value", false, true); 358 this.hadRecentInput = ReadPrimJSON.getBoolean(jo, "hadRecentInput"); 359 this.lastInputTime = ReadNumberJSON.get(jo, "lastInputTime", false, true); 360 this.sources = (jo.getJsonArray("sources") == null) 361 ? null 362 : RJArrDimN.objArr(jo.getJsonArray("sources"), null, 0, PerformanceTimeline.LayoutShiftAttribution[].class); 363 364 } 365 366 367 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 368 public boolean equals(Object other) 369 { 370 if (other == null) return false; 371 if (other.getClass() != this.getClass()) return false; 372 373 LayoutShift o = (LayoutShift) other; 374 375 return 376 Objects.equals(this.value, o.value) 377 && (this.hadRecentInput == o.hadRecentInput) 378 && Objects.equals(this.lastInputTime, o.lastInputTime) 379 && Arrays.deepEquals(this.sources, o.sources); 380 } 381 382 /** Generates a Hash-Code for {@code 'this'} instance */ 383 public int hashCode() 384 { 385 return 386 Objects.hashCode(this.value) 387 + (this.hadRecentInput ? 1 : 0) 388 + Objects.hashCode(this.lastInputTime) 389 + Arrays.deepHashCode(this.sources); 390 } 391 } 392 393 /** <CODE>[No Description Provided by Google]</CODE> */ 394 public static class TimelineEvent 395 extends BaseType 396 implements java.io.Serializable 397 { 398 /** For Object Serialization. java.io.Serializable */ 399 protected static final long serialVersionUID = 1; 400 401 public boolean[] optionals() 402 { return new boolean[] { false, false, false, false, true, true, true, }; } 403 404 /** Identifies the frame that this event is related to. Empty for non-frame targets. */ 405 public final String frameId; 406 407 /** 408 * The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype 409 * This determines which of the optional "details" fiedls is present. 410 */ 411 public final String type; 412 413 /** Name may be empty depending on the type. */ 414 public final String name; 415 416 /** Time in seconds since Epoch, monotonically increasing within document lifetime. */ 417 public final Number time; 418 419 /** 420 * Event duration, if applicable. 421 * <BR /> 422 * <BR /><B>OPTIONAL</B> 423 */ 424 public final Number duration; 425 426 /** 427 * <CODE>[No Description Provided by Google]</CODE> 428 * <BR /> 429 * <BR /><B>OPTIONAL</B> 430 */ 431 public final PerformanceTimeline.LargestContentfulPaint lcpDetails; 432 433 /** 434 * <CODE>[No Description Provided by Google]</CODE> 435 * <BR /> 436 * <BR /><B>OPTIONAL</B> 437 */ 438 public final PerformanceTimeline.LayoutShift layoutShiftDetails; 439 440 /** 441 * Constructor 442 * 443 * @param frameId Identifies the frame that this event is related to. Empty for non-frame targets. 444 * 445 * @param type 446 * The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype 447 * This determines which of the optional "details" fiedls is present. 448 * 449 * @param name Name may be empty depending on the type. 450 * 451 * @param time Time in seconds since Epoch, monotonically increasing within document lifetime. 452 * 453 * @param duration Event duration, if applicable. 454 * <BR /><B>OPTIONAL</B> 455 * 456 * @param lcpDetails - 457 * <BR /><B>OPTIONAL</B> 458 * 459 * @param layoutShiftDetails - 460 * <BR /><B>OPTIONAL</B> 461 */ 462 public TimelineEvent( 463 String frameId, String type, String name, Number time, Number duration, 464 PerformanceTimeline.LargestContentfulPaint lcpDetails, 465 PerformanceTimeline.LayoutShift layoutShiftDetails 466 ) 467 { 468 // Exception-Check(s) to ensure that if any parameters which are not declared as 469 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 470 471 if (frameId == null) BRDPC.throwNPE("frameId"); 472 if (type == null) BRDPC.throwNPE("type"); 473 if (name == null) BRDPC.throwNPE("name"); 474 if (time == null) BRDPC.throwNPE("time"); 475 476 this.frameId = frameId; 477 this.type = type; 478 this.name = name; 479 this.time = time; 480 this.duration = duration; 481 this.lcpDetails = lcpDetails; 482 this.layoutShiftDetails = layoutShiftDetails; 483 } 484 485 /** 486 * JSON Object Constructor 487 * @param jo A Json-Object having data about an instance of {@code 'TimelineEvent'}. 488 */ 489 public TimelineEvent (JsonObject jo) 490 { 491 this.frameId = ReadJSON.getString(jo, "frameId", false, true); 492 this.type = ReadJSON.getString(jo, "type", false, true); 493 this.name = ReadJSON.getString(jo, "name", false, true); 494 this.time = ReadNumberJSON.get(jo, "time", false, true); 495 this.duration = ReadNumberJSON.get(jo, "duration", true, false); 496 this.lcpDetails = ReadJSON.getObject(jo, "lcpDetails", PerformanceTimeline.LargestContentfulPaint.class, true, false); 497 this.layoutShiftDetails = ReadJSON.getObject(jo, "layoutShiftDetails", PerformanceTimeline.LayoutShift.class, true, false); 498 } 499 500 501 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 502 public boolean equals(Object other) 503 { 504 if (other == null) return false; 505 if (other.getClass() != this.getClass()) return false; 506 507 TimelineEvent o = (TimelineEvent) other; 508 509 return 510 Objects.equals(this.frameId, o.frameId) 511 && Objects.equals(this.type, o.type) 512 && Objects.equals(this.name, o.name) 513 && Objects.equals(this.time, o.time) 514 && Objects.equals(this.duration, o.duration) 515 && Objects.equals(this.lcpDetails, o.lcpDetails) 516 && Objects.equals(this.layoutShiftDetails, o.layoutShiftDetails); 517 } 518 519 /** Generates a Hash-Code for {@code 'this'} instance */ 520 public int hashCode() 521 { 522 return 523 Objects.hashCode(this.frameId) 524 + Objects.hashCode(this.type) 525 + Objects.hashCode(this.name) 526 + Objects.hashCode(this.time) 527 + Objects.hashCode(this.duration) 528 + this.lcpDetails.hashCode() 529 + this.layoutShiftDetails.hashCode(); 530 } 531 } 532 533 /** Sent when a performance timeline event is added. See reportPerformanceTimeline method. */ 534 public static class timelineEventAdded 535 extends BrowserEvent 536 implements java.io.Serializable 537 { 538 /** For Object Serialization. java.io.Serializable */ 539 protected static final long serialVersionUID = 1; 540 541 public boolean[] optionals() 542 { return new boolean[] { false, }; } 543 544 /** <CODE>[No Description Provided by Google]</CODE> */ 545 public final PerformanceTimeline.TimelineEvent event; 546 547 /** 548 * Constructor 549 * 550 * @param event - 551 */ 552 public timelineEventAdded(PerformanceTimeline.TimelineEvent event) 553 { 554 super("PerformanceTimeline", "timelineEventAdded", 1); 555 556 // Exception-Check(s) to ensure that if any parameters which are not declared as 557 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 558 559 if (event == null) BRDPC.throwNPE("event"); 560 561 this.event = event; 562 } 563 564 /** 565 * JSON Object Constructor 566 * @param jo A Json-Object having data about an instance of {@code 'timelineEventAdded'}. 567 */ 568 public timelineEventAdded (JsonObject jo) 569 { 570 super("PerformanceTimeline", "timelineEventAdded", 1); 571 572 this.event = ReadJSON.getObject(jo, "event", PerformanceTimeline.TimelineEvent.class, false, true); 573 } 574 575 576 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 577 public boolean equals(Object other) 578 { 579 if (other == null) return false; 580 if (other.getClass() != this.getClass()) return false; 581 582 timelineEventAdded o = (timelineEventAdded) other; 583 584 return 585 Objects.equals(this.event, o.event); 586 } 587 588 /** Generates a Hash-Code for {@code 'this'} instance */ 589 public int hashCode() 590 { 591 return 592 this.event.hashCode(); 593 } 594 } 595 596 597 // Counter for keeping the WebSocket Request ID's distinct. 598 private static int counter = 1; 599 600 /** 601 * Previously buffered events would be reported before method returns. 602 * See also: timelineEventAdded 603 * 604 * @param eventTypes 605 * The types of event to report, as specified in 606 * https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype 607 * The specified filter overrides any previous filters, passing empty 608 * filter disables recording. 609 * Note that not all types exposed to the web platform are currently supported. 610 * 611 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 612 * {@link Ret0}></CODE> 613 * 614 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 615 * browser receives the invocation-request. 616 * 617 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 618 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 619 * {@code >} to ensure the Browser Function has run to completion. 620 */ 621 public static Script<String, JsonObject, Ret0> enable(String[] eventTypes) 622 { 623 // Exception-Check(s) to ensure that if any parameters which are not declared as 624 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 625 626 if (eventTypes == null) BRDPC.throwNPE("eventTypes"); 627 628 final int webSocketID = 34000000 + counter++; 629 final boolean[] optionals = { false, }; 630 631 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 632 String requestJSON = WriteJSON.get( 633 parameterTypes.get("enable"), 634 parameterNames.get("enable"), 635 optionals, webSocketID, 636 "PerformanceTimeline.enable", 637 (Object) eventTypes 638 ); 639 640 // This Remote Command does not have a Return-Value. 641 return new Script<> 642 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 643 } 644 645}