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>Reporting of performance timeline events, as specified in 028 * https://w3c.github.io/performance-timeline/#dom-performanceobserver.</B></SPAN> 029 * 030 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE> 031 */ 032@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION}) 033@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE") 034public class PerformanceTimeline 035{ 036 // ******************************************************************************************** 037 // ******************************************************************************************** 038 // Class Header Stuff 039 // ******************************************************************************************** 040 // ******************************************************************************************** 041 042 043 // No Pubic Constructors 044 private PerformanceTimeline () { } 045 046 // These two Vector's are used by all the "Methods" exported by this class. java.lang.reflect 047 // is used to generate the JSON String's. It saves thousands of lines of Auto-Generated Code. 048 private static final Map<String, Vector<String>> parameterNames = new HashMap<>(); 049 private static final Map<String, Vector<Class<?>>> parameterTypes = new HashMap<>(); 050 051 // Some Methods do not take any parameters - for instance all the "enable()" and "disable()" 052 // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now, 053 // offically, two empty-vectors. One for String's, and the other for Classes. 054 055 private static final Vector<String> EMPTY_VEC_STR = new Vector<>(); 056 private static final Vector<Class<?>> EMPTY_VEC_CLASS = new Vector<>(); 057 058 static 059 { 060 for (Method m : PerformanceTimeline.class.getMethods()) 061 { 062 // This doesn't work! The parameter names are all "arg0" ... "argN" 063 // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter! 064 // 065 // Vector<String> parameterNamesList = new Vector<>(); -- NOPE! 066 067 Vector<Class<?>> parameterTypesList = new Vector<>(); 068 069 for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType()); 070 071 parameterTypes.put( 072 m.getName(), 073 (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS 074 ); 075 } 076 } 077 078 static 079 { 080 Vector<String> v = null; 081 082 v = new Vector<String>(1); 083 parameterNames.put("enable", v); 084 Collections.addAll(v, new String[] 085 { "eventTypes", }); 086 } 087 088 089 // ******************************************************************************************** 090 // ******************************************************************************************** 091 // Types - Static Inner Classes 092 // ******************************************************************************************** 093 // ******************************************************************************************** 094 095 /** See https://github.com/WICG/LargestContentfulPaint and largest_contentful_paint.idl */ 096 public static class LargestContentfulPaint 097 extends BaseType 098 implements java.io.Serializable 099 { 100 /** For Object Serialization. java.io.Serializable */ 101 protected static final long serialVersionUID = 1; 102 103 public boolean[] optionals() 104 { return new boolean[] { false, false, false, true, true, true, }; } 105 106 /** <CODE>[No Description Provided by Google]</CODE> */ 107 public final Number renderTime; 108 109 /** <CODE>[No Description Provided by Google]</CODE> */ 110 public final Number loadTime; 111 112 /** The number of pixels being painted. */ 113 public final Number size; 114 115 /** 116 * The id attribute of the element, if available. 117 * <BR /><B CLASS=Opt>OPTIONAL</B> 118 */ 119 public final String elementId; 120 121 /** 122 * The URL of the image (may be trimmed). 123 * <BR /><B CLASS=Opt>OPTIONAL</B> 124 */ 125 public final String url; 126 127 /** 128 * <CODE>[No Description Provided by Google]</CODE> 129 * <BR /><B CLASS=Opt>OPTIONAL</B> 130 */ 131 public final Integer nodeId; 132 133 /** 134 * Constructor 135 * 136 * @param renderTime - 137 * 138 * @param loadTime - 139 * 140 * @param size The number of pixels being painted. 141 * 142 * @param elementId The id attribute of the element, if available. 143 * <BR /><B CLASS=Opt>OPTIONAL</B> 144 * 145 * @param url The URL of the image (may be trimmed). 146 * <BR /><B CLASS=Opt>OPTIONAL</B> 147 * 148 * @param nodeId - 149 * <BR /><B CLASS=Opt>OPTIONAL</B> 150 */ 151 public LargestContentfulPaint( 152 Number renderTime, Number loadTime, Number size, String elementId, String url, 153 Integer nodeId 154 ) 155 { 156 // Exception-Check(s) to ensure that if any parameters which are not declared as 157 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 158 159 if (renderTime == null) THROWS.throwNPE("renderTime"); 160 if (loadTime == null) THROWS.throwNPE("loadTime"); 161 if (size == null) THROWS.throwNPE("size"); 162 163 this.renderTime = renderTime; 164 this.loadTime = loadTime; 165 this.size = size; 166 this.elementId = elementId; 167 this.url = url; 168 this.nodeId = nodeId; 169 } 170 171 /** 172 * JSON Object Constructor 173 * @param jo A Json-Object having data about an instance of {@code 'LargestContentfulPaint'}. 174 */ 175 public LargestContentfulPaint (JsonObject jo) 176 { 177 this.renderTime = ReadNumberJSON.get(jo, "renderTime", false, true); 178 this.loadTime = ReadNumberJSON.get(jo, "loadTime", false, true); 179 this.size = ReadNumberJSON.get(jo, "size", false, true); 180 this.elementId = ReadJSON.getString(jo, "elementId", true, false); 181 this.url = ReadJSON.getString(jo, "url", true, false); 182 this.nodeId = ReadBoxedJSON.getInteger(jo, "nodeId", true); 183 } 184 185 186 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 187 public boolean equals(Object other) 188 { 189 if (this == other) return true; 190 if (other == null) return false; 191 if (other.getClass() != this.getClass()) return false; 192 193 LargestContentfulPaint o = (LargestContentfulPaint) other; 194 195 return 196 Objects.equals(this.renderTime, o.renderTime) 197 && Objects.equals(this.loadTime, o.loadTime) 198 && Objects.equals(this.size, o.size) 199 && Objects.equals(this.elementId, o.elementId) 200 && Objects.equals(this.url, o.url) 201 && Objects.equals(this.nodeId, o.nodeId); 202 } 203 204 /** Generates a Hash-Code for {@code 'this'} instance */ 205 public int hashCode() 206 { 207 return 208 Objects.hashCode(this.renderTime) 209 + Objects.hashCode(this.loadTime) 210 + Objects.hashCode(this.size) 211 + Objects.hashCode(this.elementId) 212 + Objects.hashCode(this.url) 213 + Objects.hashCode(this.nodeId); 214 } 215 } 216 217 /** <CODE>[No Description Provided by Google]</CODE> */ 218 public static class LayoutShiftAttribution 219 extends BaseType 220 implements java.io.Serializable 221 { 222 /** For Object Serialization. java.io.Serializable */ 223 protected static final long serialVersionUID = 1; 224 225 public boolean[] optionals() 226 { return new boolean[] { false, false, true, }; } 227 228 /** <CODE>[No Description Provided by Google]</CODE> */ 229 public final DOM.Rect previousRect; 230 231 /** <CODE>[No Description Provided by Google]</CODE> */ 232 public final DOM.Rect currentRect; 233 234 /** 235 * <CODE>[No Description Provided by Google]</CODE> 236 * <BR /><B CLASS=Opt>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 CLASS=Opt>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" fields 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 /><B CLASS=Opt>OPTIONAL</B> 425 */ 426 public final Number duration; 427 428 /** 429 * <CODE>[No Description Provided by Google]</CODE> 430 * <BR /><B CLASS=Opt>OPTIONAL</B> 431 */ 432 public final PerformanceTimeline.LargestContentfulPaint lcpDetails; 433 434 /** 435 * <CODE>[No Description Provided by Google]</CODE> 436 * <BR /><B CLASS=Opt>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" fields 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 CLASS=Opt>OPTIONAL</B> 455 * 456 * @param lcpDetails - 457 * <BR /><B CLASS=Opt>OPTIONAL</B> 458 * 459 * @param layoutShiftDetails - 460 * <BR /><B CLASS=Opt>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) THROWS.throwNPE("frameId"); 472 if (type == null) THROWS.throwNPE("type"); 473 if (name == null) THROWS.throwNPE("name"); 474 if (time == null) THROWS.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 (this == other) return true; 505 if (other == null) return false; 506 if (other.getClass() != this.getClass()) return false; 507 508 TimelineEvent o = (TimelineEvent) other; 509 510 return 511 Objects.equals(this.frameId, o.frameId) 512 && Objects.equals(this.type, o.type) 513 && Objects.equals(this.name, o.name) 514 && Objects.equals(this.time, o.time) 515 && Objects.equals(this.duration, o.duration) 516 && Objects.equals(this.lcpDetails, o.lcpDetails) 517 && Objects.equals(this.layoutShiftDetails, o.layoutShiftDetails); 518 } 519 520 /** Generates a Hash-Code for {@code 'this'} instance */ 521 public int hashCode() 522 { 523 return 524 Objects.hashCode(this.frameId) 525 + Objects.hashCode(this.type) 526 + Objects.hashCode(this.name) 527 + Objects.hashCode(this.time) 528 + Objects.hashCode(this.duration) 529 + this.lcpDetails.hashCode() 530 + this.layoutShiftDetails.hashCode(); 531 } 532 } 533 534 /** Sent when a performance timeline event is added. See reportPerformanceTimeline method. */ 535 public static class timelineEventAdded 536 extends BrowserEvent 537 implements java.io.Serializable 538 { 539 /** For Object Serialization. java.io.Serializable */ 540 protected static final long serialVersionUID = 1; 541 542 public boolean[] optionals() 543 { return new boolean[] { false, }; } 544 545 /** <CODE>[No Description Provided by Google]</CODE> */ 546 public final PerformanceTimeline.TimelineEvent event; 547 548 /** 549 * Constructor 550 * 551 * @param event - 552 */ 553 public timelineEventAdded(PerformanceTimeline.TimelineEvent event) 554 { 555 super("PerformanceTimeline", "timelineEventAdded", 1); 556 557 // Exception-Check(s) to ensure that if any parameters which are not declared as 558 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 559 560 if (event == null) THROWS.throwNPE("event"); 561 562 this.event = event; 563 } 564 565 /** 566 * JSON Object Constructor 567 * @param jo A Json-Object having data about an instance of {@code 'timelineEventAdded'}. 568 */ 569 public timelineEventAdded (JsonObject jo) 570 { 571 super("PerformanceTimeline", "timelineEventAdded", 1); 572 573 this.event = ReadJSON.getObject(jo, "event", PerformanceTimeline.TimelineEvent.class, false, true); 574 } 575 576 577 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 578 public boolean equals(Object other) 579 { 580 if (this == other) return true; 581 if (other == null) return false; 582 if (other.getClass() != this.getClass()) return false; 583 584 timelineEventAdded o = (timelineEventAdded) other; 585 586 return 587 Objects.equals(this.event, o.event); 588 } 589 590 /** Generates a Hash-Code for {@code 'this'} instance */ 591 public int hashCode() 592 { 593 return 594 this.event.hashCode(); 595 } 596 } 597 598 599 // Counter for keeping the WebSocket Request ID's distinct. 600 private static int counter = 1; 601 602 /** 603 * Previously buffered events would be reported before method returns. 604 * See also: timelineEventAdded 605 * 606 * @param eventTypes 607 * The types of event to report, as specified in 608 * https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype 609 * The specified filter overrides any previous filters, passing empty 610 * filter disables recording. 611 * Note that not all types exposed to the web platform are currently supported. 612 * 613 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 614 * {@link Ret0}></CODE> 615 * 616 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 617 * browser receives the invocation-request. 618 * 619 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 620 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 621 * {@code >} to ensure the Browser Function has run to completion. 622 */ 623 public static Script<String, JsonObject, Ret0> enable(String[] eventTypes) 624 { 625 // Exception-Check(s) to ensure that if any parameters which are not declared as 626 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 627 628 if (eventTypes == null) THROWS.throwNPE("eventTypes"); 629 630 final int webSocketID = 37000000 + counter++; 631 final boolean[] optionals = { false, }; 632 633 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 634 String requestJSON = WriteJSON.get( 635 parameterTypes.get("enable"), 636 parameterNames.get("enable"), 637 optionals, webSocketID, 638 "PerformanceTimeline.enable", 639 (Object) eventTypes 640 ); 641 642 // This Remote Command does not have a Return-Value. 643 return new Script<> 644 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 645 } 646 647}