diff --git a/README.md b/README.md index 07437e0..8343608 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Python CDP -#### Currently supports CDP [r1179426][2] (Chrome 117). +#### Currently supports CDP [r1429850][2]. Python CDP Generator (shortened to PyCDP) is a library that provides Python wrappers for the types, commands, and events specified in the [Chrome @@ -151,7 +151,7 @@ PyCDP is licensed under the MIT License.
[1]: https://chromedevtools.github.io/devtools-protocol/ -[2]: https://github.com/ChromeDevTools/devtools-protocol/tree/39e36261937bf39dced789dd7ff19df6933d56d8 +[2]: https://github.com/ChromeDevTools/devtools-protocol/tree/e1bdcc8cda9709838002a1516058ec8b266cbe88 [3]: docs/getting_started.rst [4]: https://github.com/hyperiongray/trio-chrome-devtools-protocol [5]: https://python-poetry.org/docs/ diff --git a/docs/api/animation.rst b/docs/api/animation.rst index 9ab7262..91628c1 100644 --- a/docs/api/animation.rst +++ b/docs/api/animation.rst @@ -22,6 +22,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: ViewOrScrollTimeline + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: AnimationEffect :members: :undoc-members: @@ -90,3 +95,8 @@ you use the event's attributes. :members: :undoc-members: :exclude-members: from_json, to_json + +.. autoclass:: AnimationUpdated + :members: + :undoc-members: + :exclude-members: from_json, to_json diff --git a/docs/api/audits.rst b/docs/api/audits.rst index 2f85f59..a63bbf5 100644 --- a/docs/api/audits.rst +++ b/docs/api/audits.rst @@ -49,6 +49,16 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: InsightType + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: CookieIssueInsight + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: CookieIssueDetails :members: :undoc-members: @@ -134,6 +144,16 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: SharedDictionaryError + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: SRIMessageSignatureError + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: AttributionReportingIssueDetails :members: :undoc-members: @@ -149,6 +169,16 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: SharedDictionaryIssueDetails + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: SRIMessageSignatureIssueDetails + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: GenericIssueErrorType :members: :undoc-members: @@ -169,6 +199,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: CookieDeprecationMetadataIssueDetails + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: ClientHintIssueReason :members: :undoc-members: @@ -204,6 +239,26 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: PartitioningBlobURLInfo + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: PartitioningBlobURLIssueDetails + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: SelectElementAccessibilityIssueReason + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: SelectElementAccessibilityIssueDetails + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: StyleSheetLoadingIssueReason :members: :undoc-members: @@ -214,6 +269,16 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: PropertyRuleIssueReason + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: PropertyRuleIssueDetails + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: InspectorIssueCode :members: :undoc-members: diff --git a/docs/api/autofill.rst b/docs/api/autofill.rst index 73de6a3..64036b8 100644 --- a/docs/api/autofill.rst +++ b/docs/api/autofill.rst @@ -29,11 +29,31 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: AddressFields + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: Address :members: :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: AddressUI + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: FillingStrategy + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: FilledField + :members: + :undoc-members: + :exclude-members: from_json, to_json + Commands -------- @@ -46,6 +66,10 @@ commands, and ``z`` is the return type you should pay attention to. For more information, see :ref:`Getting Started: Commands `. +.. autofunction:: disable + +.. autofunction:: enable + .. autofunction:: set_addresses .. autofunction:: trigger @@ -53,4 +77,11 @@ to. For more information, see Events ------ -*There are no events in this module.* +Generally, you do not need to instantiate CDP events +yourself. Instead, the API creates events for you and then +you use the event's attributes. + +.. autoclass:: AddressFormFilled + :members: + :undoc-members: + :exclude-members: from_json, to_json diff --git a/docs/api/database.rst b/docs/api/bluetooth_emulation.rst similarity index 71% rename from docs/api/database.rst rename to docs/api/bluetooth_emulation.rst index 21c374b..765f8e3 100644 --- a/docs/api/database.rst +++ b/docs/api/bluetooth_emulation.rst @@ -1,9 +1,12 @@ -Database -======== +BluetoothEmulation +================== + +This domain allows configuring virtual Bluetooth devices to test +the web-bluetooth API. *This CDP domain is experimental.* -.. module:: cdp.database +.. module:: cdp.bluetooth_emulation * Types_ * Commands_ @@ -17,17 +20,22 @@ yourself. Instead, the API creates objects for you as return values from commands, and then you can use those objects as arguments to other commands. -.. autoclass:: DatabaseId +.. autoclass:: CentralState + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: ManufacturerData :members: :undoc-members: :exclude-members: from_json, to_json -.. autoclass:: Database +.. autoclass:: ScanRecord :members: :undoc-members: :exclude-members: from_json, to_json -.. autoclass:: Error +.. autoclass:: ScanEntry :members: :undoc-members: :exclude-members: from_json, to_json @@ -48,18 +56,13 @@ to. For more information, see .. autofunction:: enable -.. autofunction:: execute_sql +.. autofunction:: set_simulated_central_state -.. autofunction:: get_database_table_names +.. autofunction:: simulate_advertisement + +.. autofunction:: simulate_preconnected_peripheral Events ------ -Generally, you do not need to instantiate CDP events -yourself. Instead, the API creates events for you and then -you use the event's attributes. - -.. autoclass:: AddDatabase - :members: - :undoc-members: - :exclude-members: from_json, to_json +*There are no events in this module.* diff --git a/docs/api/css.rst b/docs/api/css.rst index 85ca375..0c92b6d 100644 --- a/docs/api/css.rst +++ b/docs/api/css.rst @@ -39,11 +39,21 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: CSSAnimationStyle + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: InheritedStyleEntry :members: :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: InheritedAnimatedStyleEntry + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: InheritedPseudoElementMatches :members: :undoc-members: @@ -149,6 +159,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: CSSStartingStyle + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: CSSLayerData :members: :undoc-members: @@ -174,7 +189,7 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json -.. autoclass:: CSSPositionFallbackRule +.. autoclass:: CSSPositionTryRule :members: :undoc-members: :exclude-members: from_json, to_json @@ -184,6 +199,41 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: CSSPropertyRegistration + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: CSSFontPaletteValuesRule + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: CSSPropertyRule + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: CSSFunctionParameter + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: CSSFunctionConditionNode + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: CSSFunctionNode + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: CSSFunctionRule + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: CSSKeyframeRule :members: :undoc-members: @@ -218,6 +268,10 @@ to. For more information, see .. autofunction:: force_pseudo_state +.. autofunction:: force_starting_style + +.. autofunction:: get_animated_styles_for_node + .. autofunction:: get_background_colors .. autofunction:: get_computed_style_for_node @@ -226,6 +280,10 @@ to. For more information, see .. autofunction:: get_layers_for_node +.. autofunction:: get_location_for_selector + +.. autofunction:: get_longhand_properties + .. autofunction:: get_matched_styles_for_node .. autofunction:: get_media_queries @@ -234,6 +292,8 @@ to. For more information, see .. autofunction:: get_style_sheet_text +.. autofunction:: resolve_values + .. autofunction:: set_container_query_text .. autofunction:: set_effective_property_value_for_node @@ -244,6 +304,8 @@ to. For more information, see .. autofunction:: set_media_text +.. autofunction:: set_property_rule_property_name + .. autofunction:: set_rule_selector .. autofunction:: set_scope_text @@ -264,6 +326,8 @@ to. For more information, see .. autofunction:: track_computed_style_updates +.. autofunction:: track_computed_style_updates_for_node + Events ------ @@ -295,3 +359,8 @@ you use the event's attributes. :members: :undoc-members: :exclude-members: from_json, to_json + +.. autoclass:: ComputedStyleUpdated + :members: + :undoc-members: + :exclude-members: from_json, to_json diff --git a/docs/api/debugger.rst b/docs/api/debugger.rst index 42984e3..1ff47e2 100644 --- a/docs/api/debugger.rst +++ b/docs/api/debugger.rst @@ -78,6 +78,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: ResolvedBreakpoint + :members: + :undoc-members: + :exclude-members: from_json, to_json + Commands -------- @@ -124,6 +129,8 @@ to. For more information, see .. autofunction:: set_async_call_stack_depth +.. autofunction:: set_blackbox_execution_contexts + .. autofunction:: set_blackbox_patterns .. autofunction:: set_blackboxed_ranges diff --git a/docs/api/dom.rst b/docs/api/dom.rst index 748e90e..544e221 100644 --- a/docs/api/dom.rst +++ b/docs/api/dom.rst @@ -63,11 +63,21 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: ScrollOrientation + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: Node :members: :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: DetachedElementInfo + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: RGBA :members: :undoc-members: @@ -124,6 +134,8 @@ to. For more information, see .. autofunction:: focus +.. autofunction:: get_anchor_element + .. autofunction:: get_attributes .. autofunction:: get_box_model @@ -132,8 +144,12 @@ to. For more information, see .. autofunction:: get_content_quads +.. autofunction:: get_detached_dom_nodes + .. autofunction:: get_document +.. autofunction:: get_element_by_relation + .. autofunction:: get_file_info .. autofunction:: get_flattened_document @@ -270,6 +286,11 @@ you use the event's attributes. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: ScrollableFlagUpdated + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: PseudoElementRemoved :members: :undoc-members: diff --git a/docs/api/emulation.rst b/docs/api/emulation.rst index 019e50d..a9578ae 100644 --- a/docs/api/emulation.rst +++ b/docs/api/emulation.rst @@ -17,6 +17,11 @@ yourself. Instead, the API creates objects for you as return values from commands, and then you can use those objects as arguments to other commands. +.. autoclass:: SafeAreaInsets + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: ScreenOrientation :members: :undoc-members: @@ -27,6 +32,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: DevicePosture + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: MediaFeature :members: :undoc-members: @@ -47,6 +57,51 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: SensorType + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: SensorMetadata + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: SensorReadingSingle + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: SensorReadingXYZ + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: SensorReadingQuaternion + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: SensorReading + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: PressureSource + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: PressureState + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: PressureMetadata + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: DisabledImageType :members: :undoc-members: @@ -68,10 +123,14 @@ to. For more information, see .. autofunction:: clear_device_metrics_override +.. autofunction:: clear_device_posture_override + .. autofunction:: clear_geolocation_override .. autofunction:: clear_idle_override +.. autofunction:: get_overridden_sensor_information + .. autofunction:: reset_page_scale_factor .. autofunction:: set_auto_dark_mode_override @@ -84,6 +143,8 @@ to. For more information, see .. autofunction:: set_device_metrics_override +.. autofunction:: set_device_posture_override + .. autofunction:: set_disabled_image_types .. autofunction:: set_document_cookie_disabled @@ -108,10 +169,20 @@ to. For more information, see .. autofunction:: set_page_scale_factor +.. autofunction:: set_pressure_source_override_enabled + +.. autofunction:: set_pressure_state_override + +.. autofunction:: set_safe_area_insets_override + .. autofunction:: set_script_execution_disabled .. autofunction:: set_scrollbars_hidden +.. autofunction:: set_sensor_override_enabled + +.. autofunction:: set_sensor_override_readings + .. autofunction:: set_timezone_override .. autofunction:: set_touch_emulation_enabled diff --git a/docs/api/event_breakpoints.rst b/docs/api/event_breakpoints.rst index af20be4..590f351 100644 --- a/docs/api/event_breakpoints.rst +++ b/docs/api/event_breakpoints.rst @@ -1,10 +1,9 @@ EventBreakpoints ================ -EventBreakpoints permits setting breakpoints on particular operations and -events in targets that run JavaScript but do not have a DOM. -JavaScript execution will stop on these operations as if there was a regular -breakpoint set. +EventBreakpoints permits setting JavaScript breakpoints on operations and events +occurring in native code invoked from JavaScript. Once breakpoint is hit, it is +reported through Debugger domain, similarly to regular breakpoints being hit. *This CDP domain is experimental.* @@ -31,6 +30,8 @@ commands, and ``z`` is the return type you should pay attention to. For more information, see :ref:`Getting Started: Commands `. +.. autofunction:: disable + .. autofunction:: remove_instrumentation_breakpoint .. autofunction:: set_instrumentation_breakpoint diff --git a/docs/api/extensions.rst b/docs/api/extensions.rst new file mode 100644 index 0000000..ef7538d --- /dev/null +++ b/docs/api/extensions.rst @@ -0,0 +1,54 @@ +Extensions +========== + +Defines commands and events for browser extensions. + +*This CDP domain is experimental.* + +.. module:: cdp.extensions + +* Types_ +* Commands_ +* Events_ + +Types +----- + +Generally, you do not need to instantiate CDP types +yourself. Instead, the API creates objects for you as return +values from commands, and then you can use those objects as +arguments to other commands. + +.. autoclass:: StorageArea + :members: + :undoc-members: + :exclude-members: from_json, to_json + +Commands +-------- + +Each command is a generator function. The return +type ``Generator[x, y, z]`` indicates that the generator +*yields* arguments of type ``x``, it must be resumed with +an argument of type ``y``, and it returns type ``z``. In +this library, types ``x`` and ``y`` are the same for all +commands, and ``z`` is the return type you should pay attention +to. For more information, see +:ref:`Getting Started: Commands `. + +.. autofunction:: clear_storage_items + +.. autofunction:: get_storage_items + +.. autofunction:: load_unpacked + +.. autofunction:: remove_storage_items + +.. autofunction:: set_storage_items + +.. autofunction:: uninstall + +Events +------ + +*There are no events in this module.* diff --git a/docs/api/fed_cm.rst b/docs/api/fed_cm.rst index 70ba519..ce2a1c0 100644 --- a/docs/api/fed_cm.rst +++ b/docs/api/fed_cm.rst @@ -29,6 +29,16 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: DialogButton + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AccountUrlType + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: Account :members: :undoc-members: @@ -46,12 +56,16 @@ commands, and ``z`` is the return type you should pay attention to. For more information, see :ref:`Getting Started: Commands `. +.. autofunction:: click_dialog_button + .. autofunction:: disable .. autofunction:: dismiss_dialog .. autofunction:: enable +.. autofunction:: open_url + .. autofunction:: reset_cooldown .. autofunction:: select_account @@ -67,3 +81,8 @@ you use the event's attributes. :members: :undoc-members: :exclude-members: from_json, to_json + +.. autoclass:: DialogClosed + :members: + :undoc-members: + :exclude-members: from_json, to_json diff --git a/docs/api/file_system.rst b/docs/api/file_system.rst new file mode 100644 index 0000000..bc38fab --- /dev/null +++ b/docs/api/file_system.rst @@ -0,0 +1,52 @@ +FileSystem +========== + +*This CDP domain is experimental.* + +.. module:: cdp.file_system + +* Types_ +* Commands_ +* Events_ + +Types +----- + +Generally, you do not need to instantiate CDP types +yourself. Instead, the API creates objects for you as return +values from commands, and then you can use those objects as +arguments to other commands. + +.. autoclass:: File + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: Directory + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: BucketFileSystemLocator + :members: + :undoc-members: + :exclude-members: from_json, to_json + +Commands +-------- + +Each command is a generator function. The return +type ``Generator[x, y, z]`` indicates that the generator +*yields* arguments of type ``x``, it must be resumed with +an argument of type ``y``, and it returns type ``z``. In +this library, types ``x`` and ``y`` are the same for all +commands, and ``z`` is the return type you should pay attention +to. For more information, see +:ref:`Getting Started: Commands `. + +.. autofunction:: get_directory + +Events +------ + +*There are no events in this module.* diff --git a/docs/api/memory.rst b/docs/api/memory.rst index 8730cd3..cdc347c 100644 --- a/docs/api/memory.rst +++ b/docs/api/memory.rst @@ -37,6 +37,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: DOMCounter + :members: + :undoc-members: + :exclude-members: from_json, to_json + Commands -------- @@ -57,6 +62,8 @@ to. For more information, see .. autofunction:: get_dom_counters +.. autofunction:: get_dom_counters_for_leak_detection + .. autofunction:: get_sampling_profile .. autofunction:: prepare_for_leak_detection diff --git a/docs/api/network.rst b/docs/api/network.rst index 23fa448..9e1079f 100644 --- a/docs/api/network.rst +++ b/docs/api/network.rst @@ -148,6 +148,16 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: ServiceWorkerRouterSource + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: ServiceWorkerRouterInfo + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: Response :members: :undoc-members: @@ -178,6 +188,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: CookiePartitionKey + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: Cookie :members: :undoc-members: @@ -193,12 +208,22 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: CookieExemptionReason + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: BlockedSetCookieWithReason :members: :undoc-members: :exclude-members: from_json, to_json -.. autoclass:: BlockedCookieWithReason +.. autoclass:: ExemptedSetCookieWithReason + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AssociatedCookie :members: :undoc-members: :exclude-members: from_json, to_json @@ -258,6 +283,16 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: DirectSocketDnsQueryType + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: DirectTCPSocketOptions + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: PrivateNetworkRequestPolicy :members: :undoc-members: @@ -411,6 +446,8 @@ to. For more information, see .. autofunction:: set_cookie +.. autofunction:: set_cookie_controls + .. autofunction:: set_cookies .. autofunction:: set_extra_http_headers @@ -419,6 +456,8 @@ to. For more information, see .. autofunction:: set_user_agent_override +.. autofunction:: stream_resource_content + .. autofunction:: take_response_body_for_interception_as_stream Events @@ -528,6 +567,26 @@ you use the event's attributes. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: DirectTCPSocketCreated + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: DirectTCPSocketOpened + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: DirectTCPSocketAborted + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: DirectTCPSocketClosed + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: RequestWillBeSentExtraInfo :members: :undoc-members: @@ -538,11 +597,21 @@ you use the event's attributes. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: ResponseReceivedEarlyHints + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: TrustTokenOperationDone :members: :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: PolicyUpdated + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: SubresourceWebBundleMetadataReceived :members: :undoc-members: diff --git a/docs/api/overlay.rst b/docs/api/overlay.rst index 2e89767..accba4b 100644 --- a/docs/api/overlay.rst +++ b/docs/api/overlay.rst @@ -89,6 +89,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: WindowControlsOverlayConfig + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: ContainerQueryHighlightConfig :members: :undoc-members: @@ -182,6 +187,8 @@ to. For more information, see .. autofunction:: set_show_web_vitals +.. autofunction:: set_show_window_controls_overlay + Events ------ diff --git a/docs/api/page.rst b/docs/api/page.rst index 87371f1..db038b6 100644 --- a/docs/api/page.rst +++ b/docs/api/page.rst @@ -107,6 +107,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: SecurityOriginDetails + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: Frame :members: :undoc-members: @@ -222,6 +227,61 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: FileFilter + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: FileHandler + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: ImageResource + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: LaunchHandler + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: ProtocolHandler + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: RelatedApplication + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: ScopeExtension + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: Screenshot + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: ShareTarget + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: Shortcut + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: WebAppManifest + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: AutoResponseMode :members: :undoc-members: @@ -242,6 +302,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: BackForwardCacheBlockingDetails + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: BackForwardCacheNotRestoredExplanation :members: :undoc-members: @@ -304,8 +369,6 @@ to. For more information, see .. autofunction:: get_app_manifest -.. autofunction:: get_cookies - .. autofunction:: get_frame_tree .. autofunction:: get_installability_errors @@ -418,6 +481,11 @@ you use the event's attributes. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: FrameSubtreeWillBeDetached + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: FrameNavigated :members: :undoc-members: @@ -433,6 +501,11 @@ you use the event's attributes. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: FrameStartedNavigating + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: FrameRequestedNavigation :members: :undoc-members: diff --git a/docs/api/preload.rst b/docs/api/preload.rst index bec744a..64dfc81 100644 --- a/docs/api/preload.rst +++ b/docs/api/preload.rst @@ -52,6 +52,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: PreloadPipelineId + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: PrerenderFinalStatus :members: :undoc-members: @@ -67,6 +72,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: PrerenderMismatchedHeaders + :members: + :undoc-members: + :exclude-members: from_json, to_json + Commands -------- @@ -100,11 +110,6 @@ you use the event's attributes. :undoc-members: :exclude-members: from_json, to_json -.. autoclass:: PrerenderAttemptCompleted - :members: - :undoc-members: - :exclude-members: from_json, to_json - .. autoclass:: PreloadEnabledStateUpdated :members: :undoc-members: diff --git a/docs/api/pwa.rst b/docs/api/pwa.rst new file mode 100644 index 0000000..6f8cec2 --- /dev/null +++ b/docs/api/pwa.rst @@ -0,0 +1,66 @@ +PWA +=== + +This domain allows interacting with the browser to control PWAs. + +*This CDP domain is experimental.* + +.. module:: cdp.pwa + +* Types_ +* Commands_ +* Events_ + +Types +----- + +Generally, you do not need to instantiate CDP types +yourself. Instead, the API creates objects for you as return +values from commands, and then you can use those objects as +arguments to other commands. + +.. autoclass:: FileHandlerAccept + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: FileHandler + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: DisplayMode + :members: + :undoc-members: + :exclude-members: from_json, to_json + +Commands +-------- + +Each command is a generator function. The return +type ``Generator[x, y, z]`` indicates that the generator +*yields* arguments of type ``x``, it must be resumed with +an argument of type ``y``, and it returns type ``z``. In +this library, types ``x`` and ``y`` are the same for all +commands, and ``z`` is the return type you should pay attention +to. For more information, see +:ref:`Getting Started: Commands `. + +.. autofunction:: change_app_user_settings + +.. autofunction:: get_os_app_state + +.. autofunction:: install + +.. autofunction:: launch + +.. autofunction:: launch_files_in_app + +.. autofunction:: open_current_page_in_app + +.. autofunction:: uninstall + +Events +------ + +*There are no events in this module.* diff --git a/docs/api/storage.rst b/docs/api/storage.rst index b9de833..4e0dba2 100644 --- a/docs/api/storage.rst +++ b/docs/api/storage.rst @@ -37,17 +37,22 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: InterestGroupAuctionId + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: InterestGroupAccessType :members: :undoc-members: :exclude-members: from_json, to_json -.. autoclass:: InterestGroupAd +.. autoclass:: InterestGroupAuctionEventType :members: :undoc-members: :exclude-members: from_json, to_json -.. autoclass:: InterestGroupDetails +.. autoclass:: InterestGroupAuctionFetchType :members: :undoc-members: :exclude-members: from_json, to_json @@ -122,11 +127,51 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: AttributionReportingFilterConfig + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingFilterPair + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: AttributionReportingAggregationKeysEntry :members: :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: AttributionReportingEventReportWindows + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingTriggerSpec + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingTriggerDataMatching + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingAggregatableDebugReportingData + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingAggregatableDebugReportingConfig + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionScopesData + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: AttributionReportingSourceRegistration :members: :undoc-members: @@ -137,6 +182,56 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: AttributionReportingSourceRegistrationTimeConfig + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingAggregatableValueDictEntry + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingAggregatableValueEntry + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingEventTriggerData + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingAggregatableTriggerData + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingAggregatableDedupKey + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingTriggerRegistration + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingEventLevelResult + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingAggregatableResult + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: RelatedWebsiteSet + :members: + :undoc-members: + :exclude-members: from_json, to_json + Commands -------- @@ -163,10 +258,14 @@ to. For more information, see .. autofunction:: delete_storage_bucket +.. autofunction:: get_affected_urls_for_third_party_cookie_metadata + .. autofunction:: get_cookies .. autofunction:: get_interest_group_details +.. autofunction:: get_related_website_sets + .. autofunction:: get_shared_storage_entries .. autofunction:: get_shared_storage_metadata @@ -183,12 +282,16 @@ to. For more information, see .. autofunction:: run_bounce_tracking_mitigations +.. autofunction:: send_pending_attribution_reports + .. autofunction:: set_attribution_reporting_local_testing_mode .. autofunction:: set_attribution_reporting_tracking .. autofunction:: set_cookies +.. autofunction:: set_interest_group_auction_tracking + .. autofunction:: set_interest_group_tracking .. autofunction:: set_shared_storage_entry @@ -245,6 +348,16 @@ you use the event's attributes. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: InterestGroupAuctionEventOccurred + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: InterestGroupAuctionNetworkRequestCreated + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: SharedStorageAccessed :members: :undoc-members: @@ -264,3 +377,8 @@ you use the event's attributes. :members: :undoc-members: :exclude-members: from_json, to_json + +.. autoclass:: AttributionReportingTriggerRegistered + :members: + :undoc-members: + :exclude-members: from_json, to_json diff --git a/docs/api/target.rst b/docs/api/target.rst index 38edd3b..2f3c345 100644 --- a/docs/api/target.rst +++ b/docs/api/target.rst @@ -47,6 +47,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: WindowState + :members: + :undoc-members: + :exclude-members: from_json, to_json + Commands -------- diff --git a/docs/api/tracing.rst b/docs/api/tracing.rst index fd134ba..ea7a0e5 100644 --- a/docs/api/tracing.rst +++ b/docs/api/tracing.rst @@ -1,8 +1,6 @@ Tracing ======= -*This CDP domain is experimental.* - .. module:: cdp.tracing * Types_ diff --git a/docs/api/web_authn.rst b/docs/api/web_authn.rst index cc38dd3..2299ff0 100644 --- a/docs/api/web_authn.rst +++ b/docs/api/web_authn.rst @@ -82,6 +82,8 @@ to. For more information, see .. autofunction:: set_automatic_presence_simulation +.. autofunction:: set_credential_properties + .. autofunction:: set_response_override_bits .. autofunction:: set_user_verified @@ -98,6 +100,16 @@ you use the event's attributes. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: CredentialDeleted + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: CredentialUpdated + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: CredentialAsserted :members: :undoc-members: diff --git a/pycdp/asyncio.py b/pycdp/asyncio.py index 52e942f..fe17e0e 100644 --- a/pycdp/asyncio.py +++ b/pycdp/asyncio.py @@ -68,7 +68,7 @@ class CDPBase(LoggerMixin): ''' Contains shared functionality between the CDP connection and session. ''' - def __init__(self, ws: ClientWebSocketResponse=None, session_id=None, target_id=None): + def __init__(self, ws: t.Optional[ClientWebSocketResponse]=None, session_id=None, target_id=None): super().__init__() self._listeners: t.Dict[type, t.Set[CDPEventListener]] = defaultdict(set) self._id_iter = itertools.count() diff --git a/pycdp/browser.py b/pycdp/browser.py index bab421d..999961c 100644 --- a/pycdp/browser.py +++ b/pycdp/browser.py @@ -15,17 +15,17 @@ def __init__( self, *, binary: str, - profile: str=None, + profile: t.Optional[str]=None, keep_profile: bool=True, headless: bool=False, - locale: str=None, - timezone: str=None, - proxy: str=None, - window_width: int=None, - window_height: int=None, - initial_url: str=None, + locale: t.Optional[str]=None, + timezone: t.Optional[str]=None, + proxy: t.Optional[str]=None, + window_width: t.Optional[int]=None, + window_height: t.Optional[int]=None, + initial_url: t.Optional[str]=None, extensions: t.List[str]=[], - args: t.List[str]=None, + args: t.Optional[t.List[str]]=None, log: bool=True ): super().__init__() diff --git a/pycdp/cdp/__init__.py b/pycdp/cdp/__init__.py index 4a47920..29e56ca 100644 --- a/pycdp/cdp/__init__.py +++ b/pycdp/cdp/__init__.py @@ -3,4 +3,4 @@ # This file is generated from the CDP specification. If you need to make # changes, edit the generator and regenerate all of the modules. -from . import (accessibility, animation, audits, autofill, background_service, browser, css, cache_storage, cast, console, dom, dom_debugger, dom_snapshot, dom_storage, database, debugger, device_access, device_orientation, emulation, event_breakpoints, fed_cm, fetch, headless_experimental, heap_profiler, io, indexed_db, input_, inspector, layer_tree, log, media, memory, network, overlay, page, performance, performance_timeline, preload, profiler, runtime, schema, security, service_worker, storage, system_info, target, tethering, tracing, web_audio, web_authn) \ No newline at end of file +from . import (accessibility, animation, audits, autofill, background_service, bluetooth_emulation, browser, css, cache_storage, cast, console, dom, dom_debugger, dom_snapshot, dom_storage, debugger, device_access, device_orientation, emulation, event_breakpoints, extensions, fed_cm, fetch, file_system, headless_experimental, heap_profiler, io, indexed_db, input_, inspector, layer_tree, log, media, memory, network, overlay, pwa, page, performance, performance_timeline, preload, profiler, runtime, schema, security, service_worker, storage, system_info, target, tethering, tracing, web_audio, web_authn) \ No newline at end of file diff --git a/pycdp/cdp/accessibility.py b/pycdp/cdp/accessibility.py index a824182..e52c63a 100644 --- a/pycdp/cdp/accessibility.py +++ b/pycdp/cdp/accessibility.py @@ -269,6 +269,7 @@ class AXPropertyName(enum.Enum): - from 'checked' to 'selected': states which apply to widgets - from 'activedescendant' to 'owns' - relationships between elements other than parent/child/sibling. ''' + ACTIONS = "actions" BUSY = "busy" DISABLED = "disabled" EDITABLE = "editable" @@ -308,6 +309,7 @@ class AXPropertyName(enum.Enum): FLOWTO = "flowto" LABELLEDBY = "labelledby" OWNS = "owns" + URL = "url" def to_json(self) -> str: return self.value @@ -473,7 +475,7 @@ def get_full_ax_tree( **EXPERIMENTAL** :param depth: *(Optional)* The maximum depth at which descendants of the root node should be retrieved. If omitted, the full tree is returned. - :param frame_id: *(Optional)* The frame for whose document the AX tree should be retrieved. If omited, the root frame is used. + :param frame_id: *(Optional)* The frame for whose document the AX tree should be retrieved. If omitted, the root frame is used. :returns: ''' params: T_JSON_DICT = dict() @@ -579,7 +581,7 @@ def query_ax_tree( ''' Query a DOM node's accessibility subtree for accessible name and role. This command computes the name and role for all nodes in the subtree, including those that are - ignored for accessibility, and returns those that mactch the specified name and role. If no DOM + ignored for accessibility, and returns those that match the specified name and role. If no DOM node is specified, or the DOM node does not exist, the command returns an error. If neither ``accessibleName`` or ``role`` is specified, it returns all the accessibility nodes in the subtree. diff --git a/pycdp/cdp/animation.py b/pycdp/cdp/animation.py index a967832..b55c197 100644 --- a/pycdp/cdp/animation.py +++ b/pycdp/cdp/animation.py @@ -36,6 +36,9 @@ class Animation: playback_rate: float #: ``Animation``'s start time. + #: Milliseconds for time based animations and + #: percentage [0 - 100] for scroll driven animations + #: (i.e. when viewOrScrollTimeline exists). start_time: float #: ``Animation``'s current time. @@ -51,6 +54,9 @@ class Animation: #: animation/transition. css_id: typing.Optional[str] = None + #: View or scroll timeline + view_or_scroll_timeline: typing.Optional[ViewOrScrollTimeline] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['id'] = self.id_ @@ -65,6 +71,8 @@ def to_json(self) -> T_JSON_DICT: json['source'] = self.source.to_json() if self.css_id is not None: json['cssId'] = self.css_id + if self.view_or_scroll_timeline is not None: + json['viewOrScrollTimeline'] = self.view_or_scroll_timeline.to_json() return json @classmethod @@ -80,6 +88,55 @@ def from_json(cls, json: T_JSON_DICT) -> Animation: type_=str(json['type']), source=AnimationEffect.from_json(json['source']) if json.get('source', None) is not None else None, css_id=str(json['cssId']) if json.get('cssId', None) is not None else None, + view_or_scroll_timeline=ViewOrScrollTimeline.from_json(json['viewOrScrollTimeline']) if json.get('viewOrScrollTimeline', None) is not None else None, + ) + + +@dataclass +class ViewOrScrollTimeline: + ''' + Timeline instance + ''' + #: Orientation of the scroll + axis: dom.ScrollOrientation + + #: Scroll container node + source_node_id: typing.Optional[dom.BackendNodeId] = None + + #: Represents the starting scroll position of the timeline + #: as a length offset in pixels from scroll origin. + start_offset: typing.Optional[float] = None + + #: Represents the ending scroll position of the timeline + #: as a length offset in pixels from scroll origin. + end_offset: typing.Optional[float] = None + + #: The element whose principal box's visibility in the + #: scrollport defined the progress of the timeline. + #: Does not exist for animations with ScrollTimeline + subject_node_id: typing.Optional[dom.BackendNodeId] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['axis'] = self.axis.to_json() + if self.source_node_id is not None: + json['sourceNodeId'] = self.source_node_id.to_json() + if self.start_offset is not None: + json['startOffset'] = self.start_offset + if self.end_offset is not None: + json['endOffset'] = self.end_offset + if self.subject_node_id is not None: + json['subjectNodeId'] = self.subject_node_id.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ViewOrScrollTimeline: + return cls( + axis=dom.ScrollOrientation.from_json(json['axis']), + source_node_id=dom.BackendNodeId.from_json(json['sourceNodeId']) if json.get('sourceNodeId', None) is not None else None, + start_offset=float(json['startOffset']) if json.get('startOffset', None) is not None else None, + end_offset=float(json['endOffset']) if json.get('endOffset', None) is not None else None, + subject_node_id=dom.BackendNodeId.from_json(json['subjectNodeId']) if json.get('subjectNodeId', None) is not None else None, ) @@ -101,6 +158,9 @@ class AnimationEffect: iterations: float #: ``AnimationEffect``'s iteration duration. + #: Milliseconds for time based animations and + #: percentage [0 - 100] for scroll driven animations + #: (i.e. when viewOrScrollTimeline exists). duration: float #: ``AnimationEffect``'s playback direction. @@ -415,3 +475,19 @@ def from_json(cls, json: T_JSON_DICT) -> AnimationStarted: return cls( animation=Animation.from_json(json['animation']) ) + + +@event_class('Animation.animationUpdated') +@dataclass +class AnimationUpdated: + ''' + Event for animation that has been updated. + ''' + #: Animation that was updated. + animation: Animation + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AnimationUpdated: + return cls( + animation=Animation.from_json(json['animation']) + ) diff --git a/pycdp/cdp/audits.py b/pycdp/cdp/audits.py index 2e63492..dd9ecd8 100644 --- a/pycdp/cdp/audits.py +++ b/pycdp/cdp/audits.py @@ -50,23 +50,23 @@ class AffectedRequest: ''' Information about a request that is affected by an inspector issue. ''' - #: The unique request id. - request_id: network.RequestId + url: str - url: typing.Optional[str] = None + #: The unique request id. + request_id: typing.Optional[network.RequestId] = None def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() - json['requestId'] = self.request_id.to_json() - if self.url is not None: - json['url'] = self.url + json['url'] = self.url + if self.request_id is not None: + json['requestId'] = self.request_id.to_json() return json @classmethod def from_json(cls, json: T_JSON_DICT) -> AffectedRequest: return cls( - request_id=network.RequestId.from_json(json['requestId']), - url=str(json['url']) if json.get('url', None) is not None else None, + url=str(json['url']), + request_id=network.RequestId.from_json(json['requestId']) if json.get('requestId', None) is not None else None, ) @@ -98,6 +98,9 @@ class CookieExclusionReason(enum.Enum): EXCLUDE_SAME_PARTY_CROSS_PARTY_CONTEXT = "ExcludeSamePartyCrossPartyContext" EXCLUDE_DOMAIN_NON_ASCII = "ExcludeDomainNonASCII" EXCLUDE_THIRD_PARTY_COOKIE_BLOCKED_IN_FIRST_PARTY_SET = "ExcludeThirdPartyCookieBlockedInFirstPartySet" + EXCLUDE_THIRD_PARTY_PHASEOUT = "ExcludeThirdPartyPhaseout" + EXCLUDE_PORT_MISMATCH = "ExcludePortMismatch" + EXCLUDE_SCHEME_MISMATCH = "ExcludeSchemeMismatch" def to_json(self) -> str: return self.value @@ -119,6 +122,9 @@ class CookieWarningReason(enum.Enum): WARN_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE = "WarnAttributeValueExceedsMaxSize" WARN_DOMAIN_NON_ASCII = "WarnDomainNonASCII" WARN_THIRD_PARTY_PHASEOUT = "WarnThirdPartyPhaseout" + WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION = "WarnCrossSiteRedirectDowngradeChangesInclusion" + WARN_DEPRECATION_TRIAL_METADATA = "WarnDeprecationTrialMetadata" + WARN_THIRD_PARTY_COOKIE_HEURISTIC = "WarnThirdPartyCookieHeuristic" def to_json(self) -> str: return self.value @@ -140,6 +146,47 @@ def from_json(cls, json: str) -> CookieOperation: return cls(json) +class InsightType(enum.Enum): + ''' + Represents the category of insight that a cookie issue falls under. + ''' + GIT_HUB_RESOURCE = "GitHubResource" + GRACE_PERIOD = "GracePeriod" + HEURISTICS = "Heuristics" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> InsightType: + return cls(json) + + +@dataclass +class CookieIssueInsight: + ''' + Information about the suggested solution to a cookie issue. + ''' + type_: InsightType + + #: Link to table entry in third-party cookie migration readiness list. + table_entry_url: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['type'] = self.type_.to_json() + if self.table_entry_url is not None: + json['tableEntryUrl'] = self.table_entry_url + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CookieIssueInsight: + return cls( + type_=InsightType.from_json(json['type']), + table_entry_url=str(json['tableEntryUrl']) if json.get('tableEntryUrl', None) is not None else None, + ) + + @dataclass class CookieIssueDetails: ''' @@ -169,6 +216,9 @@ class CookieIssueDetails: request: typing.Optional[AffectedRequest] = None + #: The recommended solution to the issue. + insight: typing.Optional[CookieIssueInsight] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['cookieWarningReasons'] = [i.to_json() for i in self.cookie_warning_reasons] @@ -184,6 +234,8 @@ def to_json(self) -> T_JSON_DICT: json['cookieUrl'] = self.cookie_url if self.request is not None: json['request'] = self.request.to_json() + if self.insight is not None: + json['insight'] = self.insight.to_json() return json @classmethod @@ -197,6 +249,7 @@ def from_json(cls, json: T_JSON_DICT) -> CookieIssueDetails: site_for_cookies=str(json['siteForCookies']) if json.get('siteForCookies', None) is not None else None, cookie_url=str(json['cookieUrl']) if json.get('cookieUrl', None) is not None else None, request=AffectedRequest.from_json(json['request']) if json.get('request', None) is not None else None, + insight=CookieIssueInsight.from_json(json['insight']) if json.get('insight', None) is not None else None, ) @@ -226,6 +279,7 @@ class MixedContentResourceType(enum.Enum): FRAME = "Frame" IMAGE = "Image" IMPORT = "Import" + JSON = "JSON" MANIFEST = "Manifest" PING = "Ping" PLUGIN_DATA = "PluginData" @@ -235,6 +289,7 @@ class MixedContentResourceType(enum.Enum): SCRIPT = "Script" SERVICE_WORKER = "ServiceWorker" SHARED_WORKER = "SharedWorker" + SPECULATION_RULES = "SpeculationRules" STYLESHEET = "Stylesheet" TRACK = "Track" VIDEO = "Video" @@ -308,7 +363,10 @@ class BlockedByResponseReason(enum.Enum): COOP_SANDBOXED_I_FRAME_CANNOT_NAVIGATE_TO_COOP_PAGE = "CoopSandboxedIFrameCannotNavigateToCoopPage" CORP_NOT_SAME_ORIGIN = "CorpNotSameOrigin" CORP_NOT_SAME_ORIGIN_AFTER_DEFAULTED_TO_SAME_ORIGIN_BY_COEP = "CorpNotSameOriginAfterDefaultedToSameOriginByCoep" + CORP_NOT_SAME_ORIGIN_AFTER_DEFAULTED_TO_SAME_ORIGIN_BY_DIP = "CorpNotSameOriginAfterDefaultedToSameOriginByDip" + CORP_NOT_SAME_ORIGIN_AFTER_DEFAULTED_TO_SAME_ORIGIN_BY_COEP_AND_DIP = "CorpNotSameOriginAfterDefaultedToSameOriginByCoepAndDip" CORP_NOT_SAME_SITE = "CorpNotSameSite" + SRI_MESSAGE_SIGNATURE_MISMATCH = "SRIMessageSignatureMismatch" def to_json(self) -> str: return self.value @@ -409,6 +467,7 @@ class ContentSecurityPolicyViolationType(enum.Enum): K_INLINE_VIOLATION = "kInlineViolation" K_EVAL_VIOLATION = "kEvalViolation" K_URL_VIOLATION = "kURLViolation" + K_SRI_VIOLATION = "kSRIViolation" K_TRUSTED_TYPES_SINK_VIOLATION = "kTrustedTypesSinkViolation" K_TRUSTED_TYPES_POLICY_VIOLATION = "kTrustedTypesPolicyViolation" K_WASM_EVAL_VIOLATION = "kWasmEvalViolation" @@ -640,6 +699,12 @@ class AttributionReportingIssueType(enum.Enum): WEB_AND_OS_HEADERS = "WebAndOsHeaders" NO_WEB_OR_OS_SUPPORT = "NoWebOrOsSupport" NAVIGATION_REGISTRATION_WITHOUT_TRANSIENT_USER_ACTIVATION = "NavigationRegistrationWithoutTransientUserActivation" + INVALID_INFO_HEADER = "InvalidInfoHeader" + NO_REGISTER_SOURCE_HEADER = "NoRegisterSourceHeader" + NO_REGISTER_TRIGGER_HEADER = "NoRegisterTriggerHeader" + NO_REGISTER_OS_SOURCE_HEADER = "NoRegisterOsSourceHeader" + NO_REGISTER_OS_TRIGGER_HEADER = "NoRegisterOsTriggerHeader" + NAVIGATION_REGISTRATION_UNIQUE_SCOPE_ALREADY_SET = "NavigationRegistrationUniqueScopeAlreadySet" def to_json(self) -> str: return self.value @@ -649,6 +714,69 @@ def from_json(cls, json: str) -> AttributionReportingIssueType: return cls(json) +class SharedDictionaryError(enum.Enum): + USE_ERROR_CROSS_ORIGIN_NO_CORS_REQUEST = "UseErrorCrossOriginNoCorsRequest" + USE_ERROR_DICTIONARY_LOAD_FAILURE = "UseErrorDictionaryLoadFailure" + USE_ERROR_MATCHING_DICTIONARY_NOT_USED = "UseErrorMatchingDictionaryNotUsed" + USE_ERROR_UNEXPECTED_CONTENT_DICTIONARY_HEADER = "UseErrorUnexpectedContentDictionaryHeader" + WRITE_ERROR_COSS_ORIGIN_NO_CORS_REQUEST = "WriteErrorCossOriginNoCorsRequest" + WRITE_ERROR_DISALLOWED_BY_SETTINGS = "WriteErrorDisallowedBySettings" + WRITE_ERROR_EXPIRED_RESPONSE = "WriteErrorExpiredResponse" + WRITE_ERROR_FEATURE_DISABLED = "WriteErrorFeatureDisabled" + WRITE_ERROR_INSUFFICIENT_RESOURCES = "WriteErrorInsufficientResources" + WRITE_ERROR_INVALID_MATCH_FIELD = "WriteErrorInvalidMatchField" + WRITE_ERROR_INVALID_STRUCTURED_HEADER = "WriteErrorInvalidStructuredHeader" + WRITE_ERROR_NAVIGATION_REQUEST = "WriteErrorNavigationRequest" + WRITE_ERROR_NO_MATCH_FIELD = "WriteErrorNoMatchField" + WRITE_ERROR_NON_LIST_MATCH_DEST_FIELD = "WriteErrorNonListMatchDestField" + WRITE_ERROR_NON_SECURE_CONTEXT = "WriteErrorNonSecureContext" + WRITE_ERROR_NON_STRING_ID_FIELD = "WriteErrorNonStringIdField" + WRITE_ERROR_NON_STRING_IN_MATCH_DEST_LIST = "WriteErrorNonStringInMatchDestList" + WRITE_ERROR_NON_STRING_MATCH_FIELD = "WriteErrorNonStringMatchField" + WRITE_ERROR_NON_TOKEN_TYPE_FIELD = "WriteErrorNonTokenTypeField" + WRITE_ERROR_REQUEST_ABORTED = "WriteErrorRequestAborted" + WRITE_ERROR_SHUTTING_DOWN = "WriteErrorShuttingDown" + WRITE_ERROR_TOO_LONG_ID_FIELD = "WriteErrorTooLongIdField" + WRITE_ERROR_UNSUPPORTED_TYPE = "WriteErrorUnsupportedType" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> SharedDictionaryError: + return cls(json) + + +class SRIMessageSignatureError(enum.Enum): + MISSING_SIGNATURE_HEADER = "MissingSignatureHeader" + MISSING_SIGNATURE_INPUT_HEADER = "MissingSignatureInputHeader" + INVALID_SIGNATURE_HEADER = "InvalidSignatureHeader" + INVALID_SIGNATURE_INPUT_HEADER = "InvalidSignatureInputHeader" + SIGNATURE_HEADER_VALUE_IS_NOT_BYTE_SEQUENCE = "SignatureHeaderValueIsNotByteSequence" + SIGNATURE_HEADER_VALUE_IS_PARAMETERIZED = "SignatureHeaderValueIsParameterized" + SIGNATURE_HEADER_VALUE_IS_INCORRECT_LENGTH = "SignatureHeaderValueIsIncorrectLength" + SIGNATURE_INPUT_HEADER_MISSING_LABEL = "SignatureInputHeaderMissingLabel" + SIGNATURE_INPUT_HEADER_VALUE_NOT_INNER_LIST = "SignatureInputHeaderValueNotInnerList" + SIGNATURE_INPUT_HEADER_VALUE_MISSING_COMPONENTS = "SignatureInputHeaderValueMissingComponents" + SIGNATURE_INPUT_HEADER_INVALID_COMPONENT_TYPE = "SignatureInputHeaderInvalidComponentType" + SIGNATURE_INPUT_HEADER_INVALID_COMPONENT_NAME = "SignatureInputHeaderInvalidComponentName" + SIGNATURE_INPUT_HEADER_INVALID_HEADER_COMPONENT_PARAMETER = "SignatureInputHeaderInvalidHeaderComponentParameter" + SIGNATURE_INPUT_HEADER_INVALID_DERIVED_COMPONENT_PARAMETER = "SignatureInputHeaderInvalidDerivedComponentParameter" + SIGNATURE_INPUT_HEADER_KEY_ID_LENGTH = "SignatureInputHeaderKeyIdLength" + SIGNATURE_INPUT_HEADER_INVALID_PARAMETER = "SignatureInputHeaderInvalidParameter" + SIGNATURE_INPUT_HEADER_MISSING_REQUIRED_PARAMETERS = "SignatureInputHeaderMissingRequiredParameters" + VALIDATION_FAILED_SIGNATURE_EXPIRED = "ValidationFailedSignatureExpired" + VALIDATION_FAILED_INVALID_LENGTH = "ValidationFailedInvalidLength" + VALIDATION_FAILED_SIGNATURE_MISMATCH = "ValidationFailedSignatureMismatch" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> SRIMessageSignatureError: + return cls(json) + + @dataclass class AttributionReportingIssueDetails: ''' @@ -743,8 +871,47 @@ def from_json(cls, json: T_JSON_DICT) -> NavigatorUserAgentIssueDetails: ) +@dataclass +class SharedDictionaryIssueDetails: + shared_dictionary_error: SharedDictionaryError + + request: AffectedRequest + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['sharedDictionaryError'] = self.shared_dictionary_error.to_json() + json['request'] = self.request.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> SharedDictionaryIssueDetails: + return cls( + shared_dictionary_error=SharedDictionaryError.from_json(json['sharedDictionaryError']), + request=AffectedRequest.from_json(json['request']), + ) + + +@dataclass +class SRIMessageSignatureIssueDetails: + error: SRIMessageSignatureError + + request: AffectedRequest + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['error'] = self.error.to_json() + json['request'] = self.request.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> SRIMessageSignatureIssueDetails: + return cls( + error=SRIMessageSignatureError.from_json(json['error']), + request=AffectedRequest.from_json(json['request']), + ) + + class GenericIssueErrorType(enum.Enum): - CROSS_ORIGIN_PORTAL_POST_MESSAGE_ERROR = "CrossOriginPortalPostMessageError" FORM_LABEL_FOR_NAME_ERROR = "FormLabelForNameError" FORM_DUPLICATE_ID_FOR_INPUT_ERROR = "FormDuplicateIdForInputError" FORM_INPUT_WITH_NO_LABEL_ERROR = "FormInputWithNoLabelError" @@ -858,6 +1025,41 @@ def from_json(cls, json: T_JSON_DICT) -> BounceTrackingIssueDetails: ) +@dataclass +class CookieDeprecationMetadataIssueDetails: + ''' + This issue warns about third-party sites that are accessing cookies on the + current page, and have been permitted due to having a global metadata grant. + Note that in this context 'site' means eTLD+1. For example, if the URL + ``https://example.test:80/web_page`` was accessing cookies, the site reported + would be ``example.test``. + ''' + allowed_sites: typing.List[str] + + opt_out_percentage: float + + is_opt_out_top_level: bool + + operation: CookieOperation + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['allowedSites'] = [i for i in self.allowed_sites] + json['optOutPercentage'] = self.opt_out_percentage + json['isOptOutTopLevel'] = self.is_opt_out_top_level + json['operation'] = self.operation.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CookieDeprecationMetadataIssueDetails: + return cls( + allowed_sites=[str(i) for i in json['allowedSites']], + opt_out_percentage=float(json['optOutPercentage']), + is_opt_out_top_level=bool(json['isOptOutTopLevel']), + operation=CookieOperation.from_json(json['operation']), + ) + + class ClientHintIssueReason(enum.Enum): META_TAG_ALLOW_LIST_INVALID_ORIGIN = "MetaTagAllowListInvalidOrigin" META_TAG_MODIFIED_HTML = "MetaTagModifiedHTML" @@ -910,7 +1112,9 @@ class FederatedAuthRequestIssueReason(enum.Enum): CLIENT_METADATA_NO_RESPONSE = "ClientMetadataNoResponse" CLIENT_METADATA_INVALID_RESPONSE = "ClientMetadataInvalidResponse" CLIENT_METADATA_INVALID_CONTENT_TYPE = "ClientMetadataInvalidContentType" + IDP_NOT_POTENTIALLY_TRUSTWORTHY = "IdpNotPotentiallyTrustworthy" DISABLED_IN_SETTINGS = "DisabledInSettings" + DISABLED_IN_FLAGS = "DisabledInFlags" ERROR_FETCHING_SIGNIN = "ErrorFetchingSignin" INVALID_SIGNIN_RESPONSE = "InvalidSigninResponse" ACCOUNTS_HTTP_NOT_FOUND = "AccountsHttpNotFound" @@ -921,6 +1125,8 @@ class FederatedAuthRequestIssueReason(enum.Enum): ID_TOKEN_HTTP_NOT_FOUND = "IdTokenHttpNotFound" ID_TOKEN_NO_RESPONSE = "IdTokenNoResponse" ID_TOKEN_INVALID_RESPONSE = "IdTokenInvalidResponse" + ID_TOKEN_IDP_ERROR_RESPONSE = "IdTokenIdpErrorResponse" + ID_TOKEN_CROSS_SITE_IDP_ERROR_RESPONSE = "IdTokenCrossSiteIdpErrorResponse" ID_TOKEN_INVALID_REQUEST = "IdTokenInvalidRequest" ID_TOKEN_INVALID_CONTENT_TYPE = "IdTokenInvalidContentType" ERROR_ID_TOKEN = "ErrorIdToken" @@ -928,6 +1134,14 @@ class FederatedAuthRequestIssueReason(enum.Enum): RP_PAGE_NOT_VISIBLE = "RpPageNotVisible" SILENT_MEDIATION_FAILURE = "SilentMediationFailure" THIRD_PARTY_COOKIES_BLOCKED = "ThirdPartyCookiesBlocked" + NOT_SIGNED_IN_WITH_IDP = "NotSignedInWithIdp" + MISSING_TRANSIENT_USER_ACTIVATION = "MissingTransientUserActivation" + REPLACED_BY_ACTIVE_MODE = "ReplacedByActiveMode" + INVALID_FIELDS_SPECIFIED = "InvalidFieldsSpecified" + RELYING_PARTY_ORIGIN_IS_OPAQUE = "RelyingPartyOriginIsOpaque" + TYPE_NOT_MATCHING = "TypeNotMatching" + UI_DISMISSED_NO_EMBARGO = "UiDismissedNoEmbargo" + CORS_ERROR = "CorsError" def to_json(self) -> str: return self.value @@ -1028,6 +1242,82 @@ def from_json(cls, json: T_JSON_DICT) -> FailedRequestInfo: ) +class PartitioningBlobURLInfo(enum.Enum): + BLOCKED_CROSS_PARTITION_FETCHING = "BlockedCrossPartitionFetching" + ENFORCE_NOOPENER_FOR_NAVIGATION = "EnforceNoopenerForNavigation" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> PartitioningBlobURLInfo: + return cls(json) + + +@dataclass +class PartitioningBlobURLIssueDetails: + #: The BlobURL that failed to load. + url: str + + #: Additional information about the Partitioning Blob URL issue. + partitioning_blob_url_info: PartitioningBlobURLInfo + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['url'] = self.url + json['partitioningBlobURLInfo'] = self.partitioning_blob_url_info.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> PartitioningBlobURLIssueDetails: + return cls( + url=str(json['url']), + partitioning_blob_url_info=PartitioningBlobURLInfo.from_json(json['partitioningBlobURLInfo']), + ) + + +class SelectElementAccessibilityIssueReason(enum.Enum): + DISALLOWED_SELECT_CHILD = "DisallowedSelectChild" + DISALLOWED_OPT_GROUP_CHILD = "DisallowedOptGroupChild" + NON_PHRASING_CONTENT_OPTION_CHILD = "NonPhrasingContentOptionChild" + INTERACTIVE_CONTENT_OPTION_CHILD = "InteractiveContentOptionChild" + INTERACTIVE_CONTENT_LEGEND_CHILD = "InteractiveContentLegendChild" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> SelectElementAccessibilityIssueReason: + return cls(json) + + +@dataclass +class SelectElementAccessibilityIssueDetails: + ''' + This issue warns about errors in the select element content model. + ''' + node_id: dom.BackendNodeId + + select_element_accessibility_issue_reason: SelectElementAccessibilityIssueReason + + has_disallowed_attributes: bool + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['nodeId'] = self.node_id.to_json() + json['selectElementAccessibilityIssueReason'] = self.select_element_accessibility_issue_reason.to_json() + json['hasDisallowedAttributes'] = self.has_disallowed_attributes + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> SelectElementAccessibilityIssueDetails: + return cls( + node_id=dom.BackendNodeId.from_json(json['nodeId']), + select_element_accessibility_issue_reason=SelectElementAccessibilityIssueReason.from_json(json['selectElementAccessibilityIssueReason']), + has_disallowed_attributes=bool(json['hasDisallowedAttributes']), + ) + + class StyleSheetLoadingIssueReason(enum.Enum): LATE_IMPORT_RULE = "LateImportRule" REQUEST_FAILED = "RequestFailed" @@ -1071,6 +1361,52 @@ def from_json(cls, json: T_JSON_DICT) -> StylesheetLoadingIssueDetails: ) +class PropertyRuleIssueReason(enum.Enum): + INVALID_SYNTAX = "InvalidSyntax" + INVALID_INITIAL_VALUE = "InvalidInitialValue" + INVALID_INHERITS = "InvalidInherits" + INVALID_NAME = "InvalidName" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> PropertyRuleIssueReason: + return cls(json) + + +@dataclass +class PropertyRuleIssueDetails: + ''' + This issue warns about errors in property rules that lead to property + registrations being ignored. + ''' + #: Source code position of the property rule. + source_code_location: SourceCodeLocation + + #: Reason why the property rule was discarded. + property_rule_issue_reason: PropertyRuleIssueReason + + #: The value of the property rule property that failed to parse + property_value: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['sourceCodeLocation'] = self.source_code_location.to_json() + json['propertyRuleIssueReason'] = self.property_rule_issue_reason.to_json() + if self.property_value is not None: + json['propertyValue'] = self.property_value + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> PropertyRuleIssueDetails: + return cls( + source_code_location=SourceCodeLocation.from_json(json['sourceCodeLocation']), + property_rule_issue_reason=PropertyRuleIssueReason.from_json(json['propertyRuleIssueReason']), + property_value=str(json['propertyValue']) if json.get('propertyValue', None) is not None else None, + ) + + class InspectorIssueCode(enum.Enum): ''' A unique identifier for the type of issue. Each type may use one of the @@ -1087,14 +1423,20 @@ class InspectorIssueCode(enum.Enum): CORS_ISSUE = "CorsIssue" ATTRIBUTION_REPORTING_ISSUE = "AttributionReportingIssue" QUIRKS_MODE_ISSUE = "QuirksModeIssue" + PARTITIONING_BLOB_URL_ISSUE = "PartitioningBlobURLIssue" NAVIGATOR_USER_AGENT_ISSUE = "NavigatorUserAgentIssue" GENERIC_ISSUE = "GenericIssue" DEPRECATION_ISSUE = "DeprecationIssue" CLIENT_HINT_ISSUE = "ClientHintIssue" FEDERATED_AUTH_REQUEST_ISSUE = "FederatedAuthRequestIssue" BOUNCE_TRACKING_ISSUE = "BounceTrackingIssue" + COOKIE_DEPRECATION_METADATA_ISSUE = "CookieDeprecationMetadataIssue" STYLESHEET_LOADING_ISSUE = "StylesheetLoadingIssue" FEDERATED_AUTH_USER_INFO_REQUEST_ISSUE = "FederatedAuthUserInfoRequestIssue" + PROPERTY_RULE_ISSUE = "PropertyRuleIssue" + SHARED_DICTIONARY_ISSUE = "SharedDictionaryIssue" + SELECT_ELEMENT_ACCESSIBILITY_ISSUE = "SelectElementAccessibilityIssue" + SRI_MESSAGE_SIGNATURE_ISSUE = "SRIMessageSignatureIssue" def to_json(self) -> str: return self.value @@ -1131,6 +1473,8 @@ class InspectorIssueDetails: quirks_mode_issue_details: typing.Optional[QuirksModeIssueDetails] = None + partitioning_blob_url_issue_details: typing.Optional[PartitioningBlobURLIssueDetails] = None + navigator_user_agent_issue_details: typing.Optional[NavigatorUserAgentIssueDetails] = None generic_issue_details: typing.Optional[GenericIssueDetails] = None @@ -1143,10 +1487,20 @@ class InspectorIssueDetails: bounce_tracking_issue_details: typing.Optional[BounceTrackingIssueDetails] = None + cookie_deprecation_metadata_issue_details: typing.Optional[CookieDeprecationMetadataIssueDetails] = None + stylesheet_loading_issue_details: typing.Optional[StylesheetLoadingIssueDetails] = None + property_rule_issue_details: typing.Optional[PropertyRuleIssueDetails] = None + federated_auth_user_info_request_issue_details: typing.Optional[FederatedAuthUserInfoRequestIssueDetails] = None + shared_dictionary_issue_details: typing.Optional[SharedDictionaryIssueDetails] = None + + select_element_accessibility_issue_details: typing.Optional[SelectElementAccessibilityIssueDetails] = None + + sri_message_signature_issue_details: typing.Optional[SRIMessageSignatureIssueDetails] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() if self.cookie_issue_details is not None: @@ -1169,6 +1523,8 @@ def to_json(self) -> T_JSON_DICT: json['attributionReportingIssueDetails'] = self.attribution_reporting_issue_details.to_json() if self.quirks_mode_issue_details is not None: json['quirksModeIssueDetails'] = self.quirks_mode_issue_details.to_json() + if self.partitioning_blob_url_issue_details is not None: + json['partitioningBlobURLIssueDetails'] = self.partitioning_blob_url_issue_details.to_json() if self.navigator_user_agent_issue_details is not None: json['navigatorUserAgentIssueDetails'] = self.navigator_user_agent_issue_details.to_json() if self.generic_issue_details is not None: @@ -1181,10 +1537,20 @@ def to_json(self) -> T_JSON_DICT: json['federatedAuthRequestIssueDetails'] = self.federated_auth_request_issue_details.to_json() if self.bounce_tracking_issue_details is not None: json['bounceTrackingIssueDetails'] = self.bounce_tracking_issue_details.to_json() + if self.cookie_deprecation_metadata_issue_details is not None: + json['cookieDeprecationMetadataIssueDetails'] = self.cookie_deprecation_metadata_issue_details.to_json() if self.stylesheet_loading_issue_details is not None: json['stylesheetLoadingIssueDetails'] = self.stylesheet_loading_issue_details.to_json() + if self.property_rule_issue_details is not None: + json['propertyRuleIssueDetails'] = self.property_rule_issue_details.to_json() if self.federated_auth_user_info_request_issue_details is not None: json['federatedAuthUserInfoRequestIssueDetails'] = self.federated_auth_user_info_request_issue_details.to_json() + if self.shared_dictionary_issue_details is not None: + json['sharedDictionaryIssueDetails'] = self.shared_dictionary_issue_details.to_json() + if self.select_element_accessibility_issue_details is not None: + json['selectElementAccessibilityIssueDetails'] = self.select_element_accessibility_issue_details.to_json() + if self.sri_message_signature_issue_details is not None: + json['sriMessageSignatureIssueDetails'] = self.sri_message_signature_issue_details.to_json() return json @classmethod @@ -1200,14 +1566,20 @@ def from_json(cls, json: T_JSON_DICT) -> InspectorIssueDetails: cors_issue_details=CorsIssueDetails.from_json(json['corsIssueDetails']) if json.get('corsIssueDetails', None) is not None else None, attribution_reporting_issue_details=AttributionReportingIssueDetails.from_json(json['attributionReportingIssueDetails']) if json.get('attributionReportingIssueDetails', None) is not None else None, quirks_mode_issue_details=QuirksModeIssueDetails.from_json(json['quirksModeIssueDetails']) if json.get('quirksModeIssueDetails', None) is not None else None, + partitioning_blob_url_issue_details=PartitioningBlobURLIssueDetails.from_json(json['partitioningBlobURLIssueDetails']) if json.get('partitioningBlobURLIssueDetails', None) is not None else None, navigator_user_agent_issue_details=NavigatorUserAgentIssueDetails.from_json(json['navigatorUserAgentIssueDetails']) if json.get('navigatorUserAgentIssueDetails', None) is not None else None, generic_issue_details=GenericIssueDetails.from_json(json['genericIssueDetails']) if json.get('genericIssueDetails', None) is not None else None, deprecation_issue_details=DeprecationIssueDetails.from_json(json['deprecationIssueDetails']) if json.get('deprecationIssueDetails', None) is not None else None, client_hint_issue_details=ClientHintIssueDetails.from_json(json['clientHintIssueDetails']) if json.get('clientHintIssueDetails', None) is not None else None, federated_auth_request_issue_details=FederatedAuthRequestIssueDetails.from_json(json['federatedAuthRequestIssueDetails']) if json.get('federatedAuthRequestIssueDetails', None) is not None else None, bounce_tracking_issue_details=BounceTrackingIssueDetails.from_json(json['bounceTrackingIssueDetails']) if json.get('bounceTrackingIssueDetails', None) is not None else None, + cookie_deprecation_metadata_issue_details=CookieDeprecationMetadataIssueDetails.from_json(json['cookieDeprecationMetadataIssueDetails']) if json.get('cookieDeprecationMetadataIssueDetails', None) is not None else None, stylesheet_loading_issue_details=StylesheetLoadingIssueDetails.from_json(json['stylesheetLoadingIssueDetails']) if json.get('stylesheetLoadingIssueDetails', None) is not None else None, + property_rule_issue_details=PropertyRuleIssueDetails.from_json(json['propertyRuleIssueDetails']) if json.get('propertyRuleIssueDetails', None) is not None else None, federated_auth_user_info_request_issue_details=FederatedAuthUserInfoRequestIssueDetails.from_json(json['federatedAuthUserInfoRequestIssueDetails']) if json.get('federatedAuthUserInfoRequestIssueDetails', None) is not None else None, + shared_dictionary_issue_details=SharedDictionaryIssueDetails.from_json(json['sharedDictionaryIssueDetails']) if json.get('sharedDictionaryIssueDetails', None) is not None else None, + select_element_accessibility_issue_details=SelectElementAccessibilityIssueDetails.from_json(json['selectElementAccessibilityIssueDetails']) if json.get('selectElementAccessibilityIssueDetails', None) is not None else None, + sri_message_signature_issue_details=SRIMessageSignatureIssueDetails.from_json(json['sriMessageSignatureIssueDetails']) if json.get('sriMessageSignatureIssueDetails', None) is not None else None, ) diff --git a/pycdp/cdp/autofill.py b/pycdp/cdp/autofill.py index dad677b..1355fa4 100644 --- a/pycdp/cdp/autofill.py +++ b/pycdp/cdp/autofill.py @@ -57,7 +57,7 @@ class AddressField: #: address field name, for example GIVEN_NAME. name: str - #: address field name, for example Jon Doe. + #: address field value, for example Jon Doe. value: str def to_json(self) -> T_JSON_DICT: @@ -74,9 +74,28 @@ def from_json(cls, json: T_JSON_DICT) -> AddressField: ) +@dataclass +class AddressFields: + ''' + A list of address fields. + ''' + fields: typing.List[AddressField] + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['fields'] = [i.to_json() for i in self.fields] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AddressFields: + return cls( + fields=[AddressField.from_json(i) for i in json['fields']], + ) + + @dataclass class Address: - #: fields and values defining a test address. + #: fields and values defining an address. fields: typing.List[AddressField] def to_json(self) -> T_JSON_DICT: @@ -91,6 +110,99 @@ def from_json(cls, json: T_JSON_DICT) -> Address: ) +@dataclass +class AddressUI: + ''' + Defines how an address can be displayed like in chrome://settings/addresses. + Address UI is a two dimensional array, each inner array is an "address information line", and when rendered in a UI surface should be displayed as such. + The following address UI for instance: + [[{name: "GIVE_NAME", value: "Jon"}, {name: "FAMILY_NAME", value: "Doe"}], [{name: "CITY", value: "Munich"}, {name: "ZIP", value: "81456"}]] + should allow the receiver to render: + Jon Doe + Munich 81456 + ''' + #: A two dimension array containing the representation of values from an address profile. + address_fields: typing.List[AddressFields] + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['addressFields'] = [i.to_json() for i in self.address_fields] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AddressUI: + return cls( + address_fields=[AddressFields.from_json(i) for i in json['addressFields']], + ) + + +class FillingStrategy(enum.Enum): + ''' + Specified whether a filled field was done so by using the html autocomplete attribute or autofill heuristics. + ''' + AUTOCOMPLETE_ATTRIBUTE = "autocompleteAttribute" + AUTOFILL_INFERRED = "autofillInferred" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> FillingStrategy: + return cls(json) + + +@dataclass +class FilledField: + #: The type of the field, e.g text, password etc. + html_type: str + + #: the html id + id_: str + + #: the html name + name: str + + #: the field value + value: str + + #: The actual field type, e.g FAMILY_NAME + autofill_type: str + + #: The filling strategy + filling_strategy: FillingStrategy + + #: The frame the field belongs to + frame_id: page.FrameId + + #: The form field's DOM node + field_id: dom.BackendNodeId + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['htmlType'] = self.html_type + json['id'] = self.id_ + json['name'] = self.name + json['value'] = self.value + json['autofillType'] = self.autofill_type + json['fillingStrategy'] = self.filling_strategy.to_json() + json['frameId'] = self.frame_id.to_json() + json['fieldId'] = self.field_id.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> FilledField: + return cls( + html_type=str(json['htmlType']), + id_=str(json['id']), + name=str(json['name']), + value=str(json['value']), + autofill_type=str(json['autofillType']), + filling_strategy=FillingStrategy.from_json(json['fillingStrategy']), + frame_id=page.FrameId.from_json(json['frameId']), + field_id=dom.BackendNodeId.from_json(json['fieldId']), + ) + + def trigger( field_id: dom.BackendNodeId, card: CreditCard, @@ -131,3 +243,43 @@ def set_addresses( 'params': params, } json = yield cmd_dict + + +def disable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Disables autofill domain notifications. + ''' + cmd_dict: T_JSON_DICT = { + 'method': 'Autofill.disable', + } + json = yield cmd_dict + + +def enable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Enables autofill domain notifications. + ''' + cmd_dict: T_JSON_DICT = { + 'method': 'Autofill.enable', + } + json = yield cmd_dict + + +@event_class('Autofill.addressFormFilled') +@dataclass +class AddressFormFilled: + ''' + Emitted when an address form is filled. + ''' + #: Information about the fields that were filled + filled_fields: typing.List[FilledField] + #: An UI representation of the address used to fill the form. + #: Consists of a 2D array where each child represents an address/profile line. + address_ui: AddressUI + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AddressFormFilled: + return cls( + filled_fields=[FilledField.from_json(i) for i in json['filledFields']], + address_ui=AddressUI.from_json(json['addressUi']) + ) diff --git a/pycdp/cdp/bluetooth_emulation.py b/pycdp/cdp/bluetooth_emulation.py new file mode 100644 index 0000000..f307f15 --- /dev/null +++ b/pycdp/cdp/bluetooth_emulation.py @@ -0,0 +1,218 @@ +# DO NOT EDIT THIS FILE! +# +# This file is generated from the CDP specification. If you need to make +# changes, edit the generator and regenerate all of the modules. +# +# CDP domain: BluetoothEmulation (experimental) + +from __future__ import annotations +import enum +import typing +from dataclasses import dataclass +from .util import event_class, T_JSON_DICT + + +class CentralState(enum.Enum): + ''' + Indicates the various states of Central. + ''' + ABSENT = "absent" + POWERED_OFF = "powered-off" + POWERED_ON = "powered-on" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> CentralState: + return cls(json) + + +@dataclass +class ManufacturerData: + ''' + Stores the manufacturer data + ''' + #: Company identifier + #: https://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/company_identifiers/company_identifiers.yaml + #: https://usb.org/developers + key: int + + #: Manufacturer-specific data (Encoded as a base64 string when passed over JSON) + data: str + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['key'] = self.key + json['data'] = self.data + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ManufacturerData: + return cls( + key=int(json['key']), + data=str(json['data']), + ) + + +@dataclass +class ScanRecord: + ''' + Stores the byte data of the advertisement packet sent by a Bluetooth device. + ''' + name: typing.Optional[str] = None + + uuids: typing.Optional[typing.List[str]] = None + + #: Stores the external appearance description of the device. + appearance: typing.Optional[int] = None + + #: Stores the transmission power of a broadcasting device. + tx_power: typing.Optional[int] = None + + #: Key is the company identifier and the value is an array of bytes of + #: manufacturer specific data. + manufacturer_data: typing.Optional[typing.List[ManufacturerData]] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.name is not None: + json['name'] = self.name + if self.uuids is not None: + json['uuids'] = [i for i in self.uuids] + if self.appearance is not None: + json['appearance'] = self.appearance + if self.tx_power is not None: + json['txPower'] = self.tx_power + if self.manufacturer_data is not None: + json['manufacturerData'] = [i.to_json() for i in self.manufacturer_data] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ScanRecord: + return cls( + name=str(json['name']) if json.get('name', None) is not None else None, + uuids=[str(i) for i in json['uuids']] if json.get('uuids', None) is not None else None, + appearance=int(json['appearance']) if json.get('appearance', None) is not None else None, + tx_power=int(json['txPower']) if json.get('txPower', None) is not None else None, + manufacturer_data=[ManufacturerData.from_json(i) for i in json['manufacturerData']] if json.get('manufacturerData', None) is not None else None, + ) + + +@dataclass +class ScanEntry: + ''' + Stores the advertisement packet information that is sent by a Bluetooth device. + ''' + device_address: str + + rssi: int + + scan_record: ScanRecord + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['deviceAddress'] = self.device_address + json['rssi'] = self.rssi + json['scanRecord'] = self.scan_record.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ScanEntry: + return cls( + device_address=str(json['deviceAddress']), + rssi=int(json['rssi']), + scan_record=ScanRecord.from_json(json['scanRecord']), + ) + + +def enable( + state: CentralState, + le_supported: bool + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Enable the BluetoothEmulation domain. + + :param state: State of the simulated central. + :param le_supported: If the simulated central supports low-energy. + ''' + params: T_JSON_DICT = dict() + params['state'] = state.to_json() + params['leSupported'] = le_supported + cmd_dict: T_JSON_DICT = { + 'method': 'BluetoothEmulation.enable', + 'params': params, + } + json = yield cmd_dict + + +def set_simulated_central_state( + state: CentralState + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Set the state of the simulated central. + + :param state: State of the simulated central. + ''' + params: T_JSON_DICT = dict() + params['state'] = state.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'BluetoothEmulation.setSimulatedCentralState', + 'params': params, + } + json = yield cmd_dict + + +def disable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Disable the BluetoothEmulation domain. + ''' + cmd_dict: T_JSON_DICT = { + 'method': 'BluetoothEmulation.disable', + } + json = yield cmd_dict + + +def simulate_preconnected_peripheral( + address: str, + name: str, + manufacturer_data: typing.List[ManufacturerData], + known_service_uuids: typing.List[str] + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Simulates a peripheral with ``address``, ``name`` and ``knownServiceUuids`` + that has already been connected to the system. + + :param address: + :param name: + :param manufacturer_data: + :param known_service_uuids: + ''' + params: T_JSON_DICT = dict() + params['address'] = address + params['name'] = name + params['manufacturerData'] = [i.to_json() for i in manufacturer_data] + params['knownServiceUuids'] = [i for i in known_service_uuids] + cmd_dict: T_JSON_DICT = { + 'method': 'BluetoothEmulation.simulatePreconnectedPeripheral', + 'params': params, + } + json = yield cmd_dict + + +def simulate_advertisement( + entry: ScanEntry + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Simulates an advertisement packet described in ``entry`` being received by + the central. + + :param entry: + ''' + params: T_JSON_DICT = dict() + params['entry'] = entry.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'BluetoothEmulation.simulateAdvertisement', + 'params': params, + } + json = yield cmd_dict diff --git a/pycdp/cdp/browser.py b/pycdp/cdp/browser.py index 28bc1fb..51ab52b 100644 --- a/pycdp/cdp/browser.py +++ b/pycdp/cdp/browser.py @@ -102,17 +102,21 @@ def from_json(cls, json: T_JSON_DICT) -> Bounds: class PermissionType(enum.Enum): - ACCESSIBILITY_EVENTS = "accessibilityEvents" + AR = "ar" AUDIO_CAPTURE = "audioCapture" - BACKGROUND_SYNC = "backgroundSync" + AUTOMATIC_FULLSCREEN = "automaticFullscreen" BACKGROUND_FETCH = "backgroundFetch" + BACKGROUND_SYNC = "backgroundSync" + CAMERA_PAN_TILT_ZOOM = "cameraPanTiltZoom" + CAPTURED_SURFACE_CONTROL = "capturedSurfaceControl" CLIPBOARD_READ_WRITE = "clipboardReadWrite" CLIPBOARD_SANITIZED_WRITE = "clipboardSanitizedWrite" DISPLAY_CAPTURE = "displayCapture" DURABLE_STORAGE = "durableStorage" - FLASH = "flash" GEOLOCATION = "geolocation" + HAND_TRACKING = "handTracking" IDLE_DETECTION = "idleDetection" + KEYBOARD_LOCK = "keyboardLock" LOCAL_FONTS = "localFonts" MIDI = "midi" MIDI_SYSEX = "midiSysex" @@ -120,14 +124,19 @@ class PermissionType(enum.Enum): NOTIFICATIONS = "notifications" PAYMENT_HANDLER = "paymentHandler" PERIODIC_BACKGROUND_SYNC = "periodicBackgroundSync" + POINTER_LOCK = "pointerLock" PROTECTED_MEDIA_IDENTIFIER = "protectedMediaIdentifier" SENSORS = "sensors" + SMART_CARD = "smartCard" + SPEAKER_SELECTION = "speakerSelection" STORAGE_ACCESS = "storageAccess" TOP_LEVEL_STORAGE_ACCESS = "topLevelStorageAccess" VIDEO_CAPTURE = "videoCapture" - VIDEO_CAPTURE_PAN_TILT_ZOOM = "videoCapturePanTiltZoom" + VR = "vr" WAKE_LOCK_SCREEN = "wakeLockScreen" WAKE_LOCK_SYSTEM = "wakeLockSystem" + WEB_APP_INSTALLATION = "webAppInstallation" + WEB_PRINTING = "webPrinting" WINDOW_MANAGEMENT = "windowManagement" def to_json(self) -> str: @@ -155,7 +164,7 @@ def from_json(cls, json: str) -> PermissionSetting: class PermissionDescriptor: ''' Definition of PermissionDescriptor defined in the Permissions API: - https://w3c.github.io/permissions/#dictdef-permissiondescriptor. + https://w3c.github.io/permissions/#dom-permissiondescriptor. ''' #: Name of permission. #: See https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/permissions/permission_descriptor.idl for valid permission names. @@ -171,6 +180,9 @@ class PermissionDescriptor: #: For "clipboard" permission, may specify allowWithoutSanitization. allow_without_sanitization: typing.Optional[bool] = None + #: For "fullscreen" permission, must specify allowWithoutGesture:true. + allow_without_gesture: typing.Optional[bool] = None + #: For "camera" permission, may specify panTiltZoom. pan_tilt_zoom: typing.Optional[bool] = None @@ -183,6 +195,8 @@ def to_json(self) -> T_JSON_DICT: json['userVisibleOnly'] = self.user_visible_only if self.allow_without_sanitization is not None: json['allowWithoutSanitization'] = self.allow_without_sanitization + if self.allow_without_gesture is not None: + json['allowWithoutGesture'] = self.allow_without_gesture if self.pan_tilt_zoom is not None: json['panTiltZoom'] = self.pan_tilt_zoom return json @@ -194,6 +208,7 @@ def from_json(cls, json: T_JSON_DICT) -> PermissionDescriptor: sysex=bool(json['sysex']) if json.get('sysex', None) is not None else None, user_visible_only=bool(json['userVisibleOnly']) if json.get('userVisibleOnly', None) is not None else None, allow_without_sanitization=bool(json['allowWithoutSanitization']) if json.get('allowWithoutSanitization', None) is not None else None, + allow_without_gesture=bool(json['allowWithoutGesture']) if json.get('allowWithoutGesture', None) is not None else None, pan_tilt_zoom=bool(json['panTiltZoom']) if json.get('panTiltZoom', None) is not None else None, ) @@ -341,8 +356,6 @@ def reset_permissions( ''' Reset all permission management for all origins. - **EXPERIMENTAL** - :param browser_context_id: *(Optional)* BrowserContext to reset permissions. When omitted, default browser context is used. ''' params: T_JSON_DICT = dict() @@ -366,7 +379,7 @@ def set_download_behavior( **EXPERIMENTAL** - :param behavior: Whether to allow all or deny all download requests, or use default Chrome behavior if available (otherwise deny). ``allowAndName`` allows download and names files according to their dowmload guids. + :param behavior: Whether to allow all or deny all download requests, or use default Chrome behavior if available (otherwise deny). ``allowAndName`` allows download and names files according to their download guids. :param browser_context_id: *(Optional)* BrowserContext to set download behavior. When omitted, default browser context is used. :param download_path: *(Optional)* The default path to save downloaded files to. This is required if behavior is set to 'allow' or 'allowAndName'. :param events_enabled: *(Optional)* Whether to emit download events (defaults to false). diff --git a/pycdp/cdp/css.py b/pycdp/cdp/css.py index e6a5e0a..29ca421 100644 --- a/pycdp/cdp/css.py +++ b/pycdp/cdp/css.py @@ -77,6 +77,32 @@ def from_json(cls, json: T_JSON_DICT) -> PseudoElementMatches: ) +@dataclass +class CSSAnimationStyle: + ''' + CSS style coming from animations with the name of the animation. + ''' + #: The style coming from the animation. + style: CSSStyle + + #: The name of the animation. + name: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['style'] = self.style.to_json() + if self.name is not None: + json['name'] = self.name + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CSSAnimationStyle: + return cls( + style=CSSStyle.from_json(json['style']), + name=str(json['name']) if json.get('name', None) is not None else None, + ) + + @dataclass class InheritedStyleEntry: ''' @@ -103,6 +129,33 @@ def from_json(cls, json: T_JSON_DICT) -> InheritedStyleEntry: ) +@dataclass +class InheritedAnimatedStyleEntry: + ''' + Inherited CSS style collection for animated styles from ancestor node. + ''' + #: Styles coming from the animations of the ancestor, if any, in the style inheritance chain. + animation_styles: typing.Optional[typing.List[CSSAnimationStyle]] = None + + #: The style coming from the transitions of the ancestor, if any, in the style inheritance chain. + transitions_style: typing.Optional[CSSStyle] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.animation_styles is not None: + json['animationStyles'] = [i.to_json() for i in self.animation_styles] + if self.transitions_style is not None: + json['transitionsStyle'] = self.transitions_style.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> InheritedAnimatedStyleEntry: + return cls( + animation_styles=[CSSAnimationStyle.from_json(i) for i in json['animationStyles']] if json.get('animationStyles', None) is not None else None, + transitions_style=CSSStyle.from_json(json['transitionsStyle']) if json.get('transitionsStyle', None) is not None else None, + ) + + @dataclass class InheritedPseudoElementMatches: ''' @@ -249,7 +302,7 @@ class CSSStyleSheetHeader: frame_id: page.FrameId #: Stylesheet resource URL. Empty if this is a constructed stylesheet created using - #: new CSSStyleSheet() (but non-empty if this is a constructed sylesheet imported + #: new CSSStyleSheet() (but non-empty if this is a constructed stylesheet imported #: as a CSS module script). source_url: str @@ -397,6 +450,10 @@ class CSSRule: #: The array keeps the types of ancestor CSSRules from the innermost going outwards. rule_types: typing.Optional[typing.List[CSSRuleType]] = None + #: @starting-style CSS at-rule array. + #: The array enumerates @starting-style at-rules starting with the innermost one, going outwards. + starting_styles: typing.Optional[typing.List[CSSStartingStyle]] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['selectorList'] = self.selector_list.to_json() @@ -418,6 +475,8 @@ def to_json(self) -> T_JSON_DICT: json['scopes'] = [i.to_json() for i in self.scopes] if self.rule_types is not None: json['ruleTypes'] = [i.to_json() for i in self.rule_types] + if self.starting_styles is not None: + json['startingStyles'] = [i.to_json() for i in self.starting_styles] return json @classmethod @@ -434,6 +493,7 @@ def from_json(cls, json: T_JSON_DICT) -> CSSRule: layers=[CSSLayer.from_json(i) for i in json['layers']] if json.get('layers', None) is not None else None, scopes=[CSSScope.from_json(i) for i in json['scopes']] if json.get('scopes', None) is not None else None, rule_types=[CSSRuleType.from_json(i) for i in json['ruleTypes']] if json.get('ruleTypes', None) is not None else None, + starting_styles=[CSSStartingStyle.from_json(i) for i in json['startingStyles']] if json.get('startingStyles', None) is not None else None, ) @@ -448,6 +508,7 @@ class CSSRuleType(enum.Enum): LAYER_RULE = "LayerRule" SCOPE_RULE = "ScopeRule" STYLE_RULE = "StyleRule" + STARTING_STYLE_RULE = "StartingStyleRule" def to_json(self) -> str: return self.value @@ -834,6 +895,9 @@ class CSSContainerQuery: #: Optional logical axes queried for the container. logical_axes: typing.Optional[dom.LogicalAxes] = None + #: true if the query contains scroll-state() queries. + queries_scroll_state: typing.Optional[bool] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['text'] = self.text @@ -847,6 +911,8 @@ def to_json(self) -> T_JSON_DICT: json['physicalAxes'] = self.physical_axes.to_json() if self.logical_axes is not None: json['logicalAxes'] = self.logical_axes.to_json() + if self.queries_scroll_state is not None: + json['queriesScrollState'] = self.queries_scroll_state return json @classmethod @@ -858,6 +924,7 @@ def from_json(cls, json: T_JSON_DICT) -> CSSContainerQuery: name=str(json['name']) if json.get('name', None) is not None else None, physical_axes=dom.PhysicalAxes.from_json(json['physicalAxes']) if json.get('physicalAxes', None) is not None else None, logical_axes=dom.LogicalAxes.from_json(json['logicalAxes']) if json.get('logicalAxes', None) is not None else None, + queries_scroll_state=bool(json['queriesScrollState']) if json.get('queriesScrollState', None) is not None else None, ) @@ -965,6 +1032,34 @@ def from_json(cls, json: T_JSON_DICT) -> CSSLayer: ) +@dataclass +class CSSStartingStyle: + ''' + CSS Starting Style at-rule descriptor. + ''' + #: The associated rule header range in the enclosing stylesheet (if + #: available). + range_: typing.Optional[SourceRange] = None + + #: Identifier of the stylesheet containing this object (if exists). + style_sheet_id: typing.Optional[StyleSheetId] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.range_ is not None: + json['range'] = self.range_.to_json() + if self.style_sheet_id is not None: + json['styleSheetId'] = self.style_sheet_id.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CSSStartingStyle: + return cls( + range_=SourceRange.from_json(json['range']) if json.get('range', None) is not None else None, + style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None, + ) + + @dataclass class CSSLayerData: ''' @@ -1005,6 +1100,9 @@ class PlatformFontUsage: #: Font's family name reported by platform. family_name: str + #: Font's PostScript name reported by platform. + post_script_name: str + #: Indicates if the font was downloaded or resolved locally. is_custom_font: bool @@ -1014,6 +1112,7 @@ class PlatformFontUsage: def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['familyName'] = self.family_name + json['postScriptName'] = self.post_script_name json['isCustomFont'] = self.is_custom_font json['glyphCount'] = self.glyph_count return json @@ -1022,6 +1121,7 @@ def to_json(self) -> T_JSON_DICT: def from_json(cls, json: T_JSON_DICT) -> PlatformFontUsage: return cls( family_name=str(json['familyName']), + post_script_name=str(json['postScriptName']), is_custom_font=bool(json['isCustomFont']), glyph_count=float(json['glyphCount']), ) @@ -1167,26 +1267,43 @@ def from_json(cls, json: T_JSON_DICT) -> CSSTryRule: @dataclass -class CSSPositionFallbackRule: +class CSSPositionTryRule: ''' - CSS position-fallback rule representation. + CSS @position-try rule representation. ''' + #: The prelude dashed-ident name name: Value - #: List of keyframes. - try_rules: typing.List[CSSTryRule] + #: Parent stylesheet's origin. + origin: StyleSheetOrigin + + #: Associated style declaration. + style: CSSStyle + + active: bool + + #: The css style sheet identifier (absent for user agent stylesheet and user-specified + #: stylesheet rules) this rule came from. + style_sheet_id: typing.Optional[StyleSheetId] = None def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['name'] = self.name.to_json() - json['tryRules'] = [i.to_json() for i in self.try_rules] + json['origin'] = self.origin.to_json() + json['style'] = self.style.to_json() + json['active'] = self.active + if self.style_sheet_id is not None: + json['styleSheetId'] = self.style_sheet_id.to_json() return json @classmethod - def from_json(cls, json: T_JSON_DICT) -> CSSPositionFallbackRule: + def from_json(cls, json: T_JSON_DICT) -> CSSPositionTryRule: return cls( name=Value.from_json(json['name']), - try_rules=[CSSTryRule.from_json(i) for i in json['tryRules']], + origin=StyleSheetOrigin.from_json(json['origin']), + style=CSSStyle.from_json(json['style']), + active=bool(json['active']), + style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None, ) @@ -1215,6 +1332,249 @@ def from_json(cls, json: T_JSON_DICT) -> CSSKeyframesRule: ) +@dataclass +class CSSPropertyRegistration: + ''' + Representation of a custom property registration through CSS.registerProperty + ''' + property_name: str + + inherits: bool + + syntax: str + + initial_value: typing.Optional[Value] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['propertyName'] = self.property_name + json['inherits'] = self.inherits + json['syntax'] = self.syntax + if self.initial_value is not None: + json['initialValue'] = self.initial_value.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CSSPropertyRegistration: + return cls( + property_name=str(json['propertyName']), + inherits=bool(json['inherits']), + syntax=str(json['syntax']), + initial_value=Value.from_json(json['initialValue']) if json.get('initialValue', None) is not None else None, + ) + + +@dataclass +class CSSFontPaletteValuesRule: + ''' + CSS font-palette-values rule representation. + ''' + #: Parent stylesheet's origin. + origin: StyleSheetOrigin + + #: Associated font palette name. + font_palette_name: Value + + #: Associated style declaration. + style: CSSStyle + + #: The css style sheet identifier (absent for user agent stylesheet and user-specified + #: stylesheet rules) this rule came from. + style_sheet_id: typing.Optional[StyleSheetId] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['origin'] = self.origin.to_json() + json['fontPaletteName'] = self.font_palette_name.to_json() + json['style'] = self.style.to_json() + if self.style_sheet_id is not None: + json['styleSheetId'] = self.style_sheet_id.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CSSFontPaletteValuesRule: + return cls( + origin=StyleSheetOrigin.from_json(json['origin']), + font_palette_name=Value.from_json(json['fontPaletteName']), + style=CSSStyle.from_json(json['style']), + style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None, + ) + + +@dataclass +class CSSPropertyRule: + ''' + CSS property at-rule representation. + ''' + #: Parent stylesheet's origin. + origin: StyleSheetOrigin + + #: Associated property name. + property_name: Value + + #: Associated style declaration. + style: CSSStyle + + #: The css style sheet identifier (absent for user agent stylesheet and user-specified + #: stylesheet rules) this rule came from. + style_sheet_id: typing.Optional[StyleSheetId] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['origin'] = self.origin.to_json() + json['propertyName'] = self.property_name.to_json() + json['style'] = self.style.to_json() + if self.style_sheet_id is not None: + json['styleSheetId'] = self.style_sheet_id.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CSSPropertyRule: + return cls( + origin=StyleSheetOrigin.from_json(json['origin']), + property_name=Value.from_json(json['propertyName']), + style=CSSStyle.from_json(json['style']), + style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None, + ) + + +@dataclass +class CSSFunctionParameter: + ''' + CSS function argument representation. + ''' + #: The parameter name. + name: str + + #: The parameter type. + type_: str + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['name'] = self.name + json['type'] = self.type_ + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CSSFunctionParameter: + return cls( + name=str(json['name']), + type_=str(json['type']), + ) + + +@dataclass +class CSSFunctionConditionNode: + ''' + CSS function conditional block representation. + ''' + #: Block body. + children: typing.List[CSSFunctionNode] + + #: The condition text. + condition_text: str + + #: Media query for this conditional block. Only one type of condition should be set. + media: typing.Optional[CSSMedia] = None + + #: Container query for this conditional block. Only one type of condition should be set. + container_queries: typing.Optional[CSSContainerQuery] = None + + #: @supports CSS at-rule condition. Only one type of condition should be set. + supports: typing.Optional[CSSSupports] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['children'] = [i.to_json() for i in self.children] + json['conditionText'] = self.condition_text + if self.media is not None: + json['media'] = self.media.to_json() + if self.container_queries is not None: + json['containerQueries'] = self.container_queries.to_json() + if self.supports is not None: + json['supports'] = self.supports.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CSSFunctionConditionNode: + return cls( + children=[CSSFunctionNode.from_json(i) for i in json['children']], + condition_text=str(json['conditionText']), + media=CSSMedia.from_json(json['media']) if json.get('media', None) is not None else None, + container_queries=CSSContainerQuery.from_json(json['containerQueries']) if json.get('containerQueries', None) is not None else None, + supports=CSSSupports.from_json(json['supports']) if json.get('supports', None) is not None else None, + ) + + +@dataclass +class CSSFunctionNode: + ''' + Section of the body of a CSS function rule. + ''' + #: A conditional block. If set, style should not be set. + condition: typing.Optional[CSSFunctionConditionNode] = None + + #: Values set by this node. If set, condition should not be set. + style: typing.Optional[CSSStyle] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.condition is not None: + json['condition'] = self.condition.to_json() + if self.style is not None: + json['style'] = self.style.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CSSFunctionNode: + return cls( + condition=CSSFunctionConditionNode.from_json(json['condition']) if json.get('condition', None) is not None else None, + style=CSSStyle.from_json(json['style']) if json.get('style', None) is not None else None, + ) + + +@dataclass +class CSSFunctionRule: + ''' + CSS function at-rule representation. + ''' + #: Name of the function. + name: Value + + #: Parent stylesheet's origin. + origin: StyleSheetOrigin + + #: List of parameters. + parameters: typing.List[CSSFunctionParameter] + + #: Function body. + children: typing.List[CSSFunctionNode] + + #: The css style sheet identifier (absent for user agent stylesheet and user-specified + #: stylesheet rules) this rule came from. + style_sheet_id: typing.Optional[StyleSheetId] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['name'] = self.name.to_json() + json['origin'] = self.origin.to_json() + json['parameters'] = [i.to_json() for i in self.parameters] + json['children'] = [i.to_json() for i in self.children] + if self.style_sheet_id is not None: + json['styleSheetId'] = self.style_sheet_id.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CSSFunctionRule: + return cls( + name=Value.from_json(json['name']), + origin=StyleSheetOrigin.from_json(json['origin']), + parameters=[CSSFunctionParameter.from_json(i) for i in json['parameters']], + children=[CSSFunctionNode.from_json(i) for i in json['children']], + style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None, + ) + + @dataclass class CSSKeyframeRule: ''' @@ -1285,7 +1645,8 @@ def from_json(cls, json: T_JSON_DICT) -> StyleDeclarationEdit: def add_rule( style_sheet_id: StyleSheetId, rule_text: str, - location: SourceRange + location: SourceRange, + node_for_property_syntax_validation: typing.Optional[dom.NodeId] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,CSSRule]: ''' Inserts a new rule with the given ``ruleText`` in a stylesheet with given ``styleSheetId``, at the @@ -1294,12 +1655,15 @@ def add_rule( :param style_sheet_id: The css style sheet identifier where a new rule should be inserted. :param rule_text: The text of a new rule. :param location: Text position of a new rule in the target style sheet. + :param node_for_property_syntax_validation: **(EXPERIMENTAL)** *(Optional)* NodeId for the DOM node in whose context custom property declarations for registered properties should be validated. If omitted, declarations in the new rule text can only be validated statically, which may produce incorrect results if the declaration contains a var() for example. :returns: The newly created rule. ''' params: T_JSON_DICT = dict() params['styleSheetId'] = style_sheet_id.to_json() params['ruleText'] = rule_text params['location'] = location.to_json() + if node_for_property_syntax_validation is not None: + params['nodeForPropertySyntaxValidation'] = node_for_property_syntax_validation.to_json() cmd_dict: T_JSON_DICT = { 'method': 'CSS.addRule', 'params': params, @@ -1328,16 +1692,20 @@ def collect_class_names( def create_style_sheet( - frame_id: page.FrameId + frame_id: page.FrameId, + force: typing.Optional[bool] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,StyleSheetId]: ''' Creates a new special "via-inspector" stylesheet in the frame with given ``frameId``. :param frame_id: Identifier of the frame where "via-inspector" stylesheet should be created. + :param force: *(Optional)* If true, creates a new stylesheet for every call. If false, returns a stylesheet previously created by a call with force=false for the frame's document if it exists or creates a new stylesheet (default: false). :returns: Identifier of the created "via-inspector" stylesheet. ''' params: T_JSON_DICT = dict() params['frameId'] = frame_id.to_json() + if force is not None: + params['force'] = force cmd_dict: T_JSON_DICT = { 'method': 'CSS.createStyleSheet', 'params': params, @@ -1388,6 +1756,26 @@ def force_pseudo_state( json = yield cmd_dict +def force_starting_style( + node_id: dom.NodeId, + forced: bool + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Ensures that the given node is in its starting-style state. + + :param node_id: The element id for which to force the starting-style state. + :param forced: Boolean indicating if this is on or off. + ''' + params: T_JSON_DICT = dict() + params['nodeId'] = node_id.to_json() + params['forced'] = forced + cmd_dict: T_JSON_DICT = { + 'method': 'CSS.forceStartingStyle', + 'params': params, + } + json = yield cmd_dict + + def get_background_colors( node_id: dom.NodeId ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.Optional[typing.List[str]], typing.Optional[str], typing.Optional[str]]]: @@ -1432,6 +1820,67 @@ def get_computed_style_for_node( return [CSSComputedStyleProperty.from_json(i) for i in json['computedStyle']] +def resolve_values( + values: typing.List[str], + node_id: dom.NodeId, + property_name: typing.Optional[str] = None, + pseudo_type: typing.Optional[dom.PseudoType] = None, + pseudo_identifier: typing.Optional[str] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[str]]: + ''' + Resolve the specified values in the context of the provided element. + For example, a value of '1em' is evaluated according to the computed + 'font-size' of the element and a value 'calc(1px + 2px)' will be + resolved to '3px'. + + :param values: Substitution functions (var()/env()/attr()) and cascade-dependent keywords (revert/revert-layer) do not work. + :param node_id: Id of the node in whose context the expression is evaluated + :param property_name: *(Optional)* Only longhands and custom property names are accepted. + :param pseudo_type: **(EXPERIMENTAL)** *(Optional)* Pseudo element type, only works for pseudo elements that generate elements in the tree, such as ::before and ::after. + :param pseudo_identifier: **(EXPERIMENTAL)** *(Optional)* Pseudo element custom ident. + :returns: + ''' + params: T_JSON_DICT = dict() + params['values'] = [i for i in values] + params['nodeId'] = node_id.to_json() + if property_name is not None: + params['propertyName'] = property_name + if pseudo_type is not None: + params['pseudoType'] = pseudo_type.to_json() + if pseudo_identifier is not None: + params['pseudoIdentifier'] = pseudo_identifier + cmd_dict: T_JSON_DICT = { + 'method': 'CSS.resolveValues', + 'params': params, + } + json = yield cmd_dict + return [str(i) for i in json['results']] + + +def get_longhand_properties( + shorthand_name: str, + value: str + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[CSSProperty]]: + ''' + + + **EXPERIMENTAL** + + :param shorthand_name: + :param value: + :returns: + ''' + params: T_JSON_DICT = dict() + params['shorthandName'] = shorthand_name + params['value'] = value + cmd_dict: T_JSON_DICT = { + 'method': 'CSS.getLonghandProperties', + 'params': params, + } + json = yield cmd_dict + return [CSSProperty.from_json(i) for i in json['longhandProperties']] + + def get_inline_styles_for_node( node_id: dom.NodeId ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.Optional[CSSStyle], typing.Optional[CSSStyle]]]: @@ -1458,9 +1907,39 @@ def get_inline_styles_for_node( ) +def get_animated_styles_for_node( + node_id: dom.NodeId + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.Optional[typing.List[CSSAnimationStyle]], typing.Optional[CSSStyle], typing.Optional[typing.List[InheritedAnimatedStyleEntry]]]]: + ''' + Returns the styles coming from animations & transitions + including the animation & transition styles coming from inheritance chain. + + **EXPERIMENTAL** + + :param node_id: + :returns: A tuple with the following items: + + 0. **animationStyles** - *(Optional)* Styles coming from animations. + 1. **transitionsStyle** - *(Optional)* Style coming from transitions. + 2. **inherited** - *(Optional)* Inherited style entries for animationsStyle and transitionsStyle from the inheritance chain of the element. + ''' + params: T_JSON_DICT = dict() + params['nodeId'] = node_id.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'CSS.getAnimatedStylesForNode', + 'params': params, + } + json = yield cmd_dict + return ( + [CSSAnimationStyle.from_json(i) for i in json['animationStyles']] if json.get('animationStyles', None) is not None else None, + CSSStyle.from_json(json['transitionsStyle']) if json.get('transitionsStyle', None) is not None else None, + [InheritedAnimatedStyleEntry.from_json(i) for i in json['inherited']] if json.get('inherited', None) is not None else None + ) + + def get_matched_styles_for_node( node_id: dom.NodeId - ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.Optional[CSSStyle], typing.Optional[CSSStyle], typing.Optional[typing.List[RuleMatch]], typing.Optional[typing.List[PseudoElementMatches]], typing.Optional[typing.List[InheritedStyleEntry]], typing.Optional[typing.List[InheritedPseudoElementMatches]], typing.Optional[typing.List[CSSKeyframesRule]], typing.Optional[typing.List[CSSPositionFallbackRule]], typing.Optional[dom.NodeId]]]: + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.Optional[CSSStyle], typing.Optional[CSSStyle], typing.Optional[typing.List[RuleMatch]], typing.Optional[typing.List[PseudoElementMatches]], typing.Optional[typing.List[InheritedStyleEntry]], typing.Optional[typing.List[InheritedPseudoElementMatches]], typing.Optional[typing.List[CSSKeyframesRule]], typing.Optional[typing.List[CSSPositionTryRule]], typing.Optional[int], typing.Optional[typing.List[CSSPropertyRule]], typing.Optional[typing.List[CSSPropertyRegistration]], typing.Optional[CSSFontPaletteValuesRule], typing.Optional[dom.NodeId], typing.Optional[typing.List[CSSFunctionRule]]]]: ''' Returns requested styles for a DOM node identified by ``nodeId``. @@ -1474,8 +1953,13 @@ def get_matched_styles_for_node( 4. **inherited** - *(Optional)* A chain of inherited styles (from the immediate node parent up to the DOM tree root). 5. **inheritedPseudoElements** - *(Optional)* A chain of inherited pseudo element styles (from the immediate node parent up to the DOM tree root). 6. **cssKeyframesRules** - *(Optional)* A list of CSS keyframed animations matching this node. - 7. **cssPositionFallbackRules** - *(Optional)* A list of CSS position fallbacks matching this node. - 8. **parentLayoutNodeId** - *(Optional)* Id of the first parent element that does not have display: contents. + 7. **cssPositionTryRules** - *(Optional)* A list of CSS @position-try rules matching this node, based on the position-try-fallbacks property. + 8. **activePositionFallbackIndex** - *(Optional)* Index of the active fallback in the applied position-try-fallback property, will not be set if there is no active position-try fallback. + 9. **cssPropertyRules** - *(Optional)* A list of CSS at-property rules matching this node. + 10. **cssPropertyRegistrations** - *(Optional)* A list of CSS property registrations matching this node. + 11. **cssFontPaletteValuesRule** - *(Optional)* A font-palette-values rule matching this node. + 12. **parentLayoutNodeId** - *(Optional)* Id of the first parent element that does not have display: contents. + 13. **cssFunctionRules** - *(Optional)* A list of CSS at-function rules referenced by styles of this node. ''' params: T_JSON_DICT = dict() params['nodeId'] = node_id.to_json() @@ -1492,8 +1976,13 @@ def get_matched_styles_for_node( [InheritedStyleEntry.from_json(i) for i in json['inherited']] if json.get('inherited', None) is not None else None, [InheritedPseudoElementMatches.from_json(i) for i in json['inheritedPseudoElements']] if json.get('inheritedPseudoElements', None) is not None else None, [CSSKeyframesRule.from_json(i) for i in json['cssKeyframesRules']] if json.get('cssKeyframesRules', None) is not None else None, - [CSSPositionFallbackRule.from_json(i) for i in json['cssPositionFallbackRules']] if json.get('cssPositionFallbackRules', None) is not None else None, - dom.NodeId.from_json(json['parentLayoutNodeId']) if json.get('parentLayoutNodeId', None) is not None else None + [CSSPositionTryRule.from_json(i) for i in json['cssPositionTryRules']] if json.get('cssPositionTryRules', None) is not None else None, + int(json['activePositionFallbackIndex']) if json.get('activePositionFallbackIndex', None) is not None else None, + [CSSPropertyRule.from_json(i) for i in json['cssPropertyRules']] if json.get('cssPropertyRules', None) is not None else None, + [CSSPropertyRegistration.from_json(i) for i in json['cssPropertyRegistrations']] if json.get('cssPropertyRegistrations', None) is not None else None, + CSSFontPaletteValuesRule.from_json(json['cssFontPaletteValuesRule']) if json.get('cssFontPaletteValuesRule', None) is not None else None, + dom.NodeId.from_json(json['parentLayoutNodeId']) if json.get('parentLayoutNodeId', None) is not None else None, + [CSSFunctionRule.from_json(i) for i in json['cssFunctionRules']] if json.get('cssFunctionRules', None) is not None else None ) @@ -1573,6 +2062,56 @@ def get_layers_for_node( return CSSLayerData.from_json(json['rootLayer']) +def get_location_for_selector( + style_sheet_id: StyleSheetId, + selector_text: str + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[SourceRange]]: + ''' + Given a CSS selector text and a style sheet ID, getLocationForSelector + returns an array of locations of the CSS selector in the style sheet. + + **EXPERIMENTAL** + + :param style_sheet_id: + :param selector_text: + :returns: + ''' + params: T_JSON_DICT = dict() + params['styleSheetId'] = style_sheet_id.to_json() + params['selectorText'] = selector_text + cmd_dict: T_JSON_DICT = { + 'method': 'CSS.getLocationForSelector', + 'params': params, + } + json = yield cmd_dict + return [SourceRange.from_json(i) for i in json['ranges']] + + +def track_computed_style_updates_for_node( + node_id: typing.Optional[dom.NodeId] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Starts tracking the given node for the computed style updates + and whenever the computed style is updated for node, it queues + a ``computedStyleUpdated`` event with throttling. + There can only be 1 node tracked for computed style updates + so passing a new node id removes tracking from the previous node. + Pass ``undefined`` to disable tracking. + + **EXPERIMENTAL** + + :param node_id: *(Optional)* + ''' + params: T_JSON_DICT = dict() + if node_id is not None: + params['nodeId'] = node_id.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'CSS.trackComputedStyleUpdatesForNode', + 'params': params, + } + json = yield cmd_dict + + def track_computed_style_updates( properties_to_track: typing.List[CSSComputedStyleProperty] ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: @@ -1636,6 +2175,31 @@ def set_effective_property_value_for_node( json = yield cmd_dict +def set_property_rule_property_name( + style_sheet_id: StyleSheetId, + range_: SourceRange, + property_name: str + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,Value]: + ''' + Modifies the property rule property name. + + :param style_sheet_id: + :param range_: + :param property_name: + :returns: The resulting key text after modification. + ''' + params: T_JSON_DICT = dict() + params['styleSheetId'] = style_sheet_id.to_json() + params['range'] = range_.to_json() + params['propertyName'] = property_name + cmd_dict: T_JSON_DICT = { + 'method': 'CSS.setPropertyRulePropertyName', + 'params': params, + } + json = yield cmd_dict + return Value.from_json(json['propertyName']) + + def set_keyframe_key( style_sheet_id: StyleSheetId, range_: SourceRange, @@ -1815,16 +2379,20 @@ def set_style_sheet_text( def set_style_texts( - edits: typing.List[StyleDeclarationEdit] + edits: typing.List[StyleDeclarationEdit], + node_for_property_syntax_validation: typing.Optional[dom.NodeId] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[CSSStyle]]: ''' Applies specified style edits one after another in the given order. :param edits: + :param node_for_property_syntax_validation: **(EXPERIMENTAL)** *(Optional)* NodeId for the DOM node in whose context custom property declarations for registered properties should be validated. If omitted, declarations in the new rule text can only be validated statically, which may produce incorrect results if the declaration contains a var() for example. :returns: The resulting styles after modification. ''' params: T_JSON_DICT = dict() params['edits'] = [i.to_json() for i in edits] + if node_for_property_syntax_validation is not None: + params['nodeForPropertySyntaxValidation'] = node_for_property_syntax_validation.to_json() cmd_dict: T_JSON_DICT = { 'method': 'CSS.setStyleTexts', 'params': params, @@ -1974,3 +2542,21 @@ def from_json(cls, json: T_JSON_DICT) -> StyleSheetRemoved: return cls( style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) ) + + +@event_class('CSS.computedStyleUpdated') +@dataclass +class ComputedStyleUpdated: + ''' + **EXPERIMENTAL** + + + ''' + #: The node id that has updated computed styles. + node_id: dom.NodeId + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ComputedStyleUpdated: + return cls( + node_id=dom.NodeId.from_json(json['nodeId']) + ) diff --git a/pycdp/cdp/debugger.py b/pycdp/cdp/debugger.py index 068674a..74aacd5 100644 --- a/pycdp/cdp/debugger.py +++ b/pycdp/cdp/debugger.py @@ -359,6 +359,28 @@ def from_json(cls, json: T_JSON_DICT) -> DebugSymbols: ) +@dataclass +class ResolvedBreakpoint: + #: Breakpoint unique identifier. + breakpoint_id: BreakpointId + + #: Actual breakpoint location. + location: Location + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['breakpointId'] = self.breakpoint_id.to_json() + json['location'] = self.location.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ResolvedBreakpoint: + return cls( + breakpoint_id=BreakpointId.from_json(json['breakpointId']), + location=Location.from_json(json['location']), + ) + + def continue_to_location( location: Location, target_call_frames: typing.Optional[str] = None @@ -775,8 +797,30 @@ def set_async_call_stack_depth( json = yield cmd_dict +def set_blackbox_execution_contexts( + unique_ids: typing.List[str] + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Replace previous blackbox execution contexts with passed ones. Forces backend to skip + stepping/pausing in scripts in these execution contexts. VM will try to leave blackboxed script by + performing 'step in' several times, finally resorting to 'step out' if unsuccessful. + + **EXPERIMENTAL** + + :param unique_ids: Array of execution context unique ids for the debugger to ignore. + ''' + params: T_JSON_DICT = dict() + params['uniqueIds'] = [i for i in unique_ids] + cmd_dict: T_JSON_DICT = { + 'method': 'Debugger.setBlackboxExecutionContexts', + 'params': params, + } + json = yield cmd_dict + + def set_blackbox_patterns( - patterns: typing.List[str] + patterns: typing.List[str], + skip_anonymous: typing.Optional[bool] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in @@ -786,9 +830,12 @@ def set_blackbox_patterns( **EXPERIMENTAL** :param patterns: Array of regexps that will be used to check script url for blackbox state. + :param skip_anonymous: *(Optional)* If true, also ignore scripts with no source url. ''' params: T_JSON_DICT = dict() params['patterns'] = [i for i in patterns] + if skip_anonymous is not None: + params['skipAnonymous'] = skip_anonymous cmd_dict: T_JSON_DICT = { 'method': 'Debugger.setBlackboxPatterns', 'params': params, @@ -1142,11 +1189,13 @@ def step_over( json = yield cmd_dict +@deprecated(version="1.3") @event_class('Debugger.breakpointResolved') @dataclass class BreakpointResolved: ''' Fired when breakpoint is resolved to an actual script and location. + Deprecated in favor of ``resolvedBreakpoints`` in the ``scriptParsed`` event. ''' #: Breakpoint unique identifier. breakpoint_id: BreakpointId @@ -1232,6 +1281,8 @@ class ScriptFailedToParse: execution_context_id: runtime.ExecutionContextId #: Content hash of the script, SHA-256. hash_: str + #: For Wasm modules, the content of the ``build_id`` custom section. + build_id: str #: Embedder-specific auxiliary data likely matching {isDefault: boolean, type: 'default'``'isolated'``'worker', frameId: string} execution_context_aux_data: typing.Optional[dict] #: URL of source map associated with script (if any). @@ -1262,6 +1313,7 @@ def from_json(cls, json: T_JSON_DICT) -> ScriptFailedToParse: end_column=int(json['endColumn']), execution_context_id=runtime.ExecutionContextId.from_json(json['executionContextId']), hash_=str(json['hash']), + build_id=str(json['buildId']), execution_context_aux_data=dict(json['executionContextAuxData']) if json.get('executionContextAuxData', None) is not None else None, source_map_url=str(json['sourceMapURL']) if json.get('sourceMapURL', None) is not None else None, has_source_url=bool(json['hasSourceURL']) if json.get('hasSourceURL', None) is not None else None, @@ -1297,6 +1349,8 @@ class ScriptParsed: execution_context_id: runtime.ExecutionContextId #: Content hash of the script, SHA-256. hash_: str + #: For Wasm modules, the content of the ``build_id`` custom section. + build_id: str #: Embedder-specific auxiliary data likely matching {isDefault: boolean, type: 'default'``'isolated'``'worker', frameId: string} execution_context_aux_data: typing.Optional[dict] #: True, if this script is generated as a result of the live edit operation. @@ -1315,10 +1369,14 @@ class ScriptParsed: code_offset: typing.Optional[int] #: The language of the script. script_language: typing.Optional[ScriptLanguage] - #: If the scriptLanguage is WebASsembly, the source of debug symbols for the module. - debug_symbols: typing.Optional[DebugSymbols] + #: If the scriptLanguage is WebAssembly, the source of debug symbols for the module. + debug_symbols: typing.Optional[typing.List[DebugSymbols]] #: The name the embedder supplied for this script. embedder_name: typing.Optional[str] + #: The list of set breakpoints in this script if calls to ``setBreakpointByUrl`` + #: matches this script's URL or hash. Clients that use this list can ignore the + #: ``breakpointResolved`` event. They are equivalent. + resolved_breakpoints: typing.Optional[typing.List[ResolvedBreakpoint]] @classmethod def from_json(cls, json: T_JSON_DICT) -> ScriptParsed: @@ -1331,6 +1389,7 @@ def from_json(cls, json: T_JSON_DICT) -> ScriptParsed: end_column=int(json['endColumn']), execution_context_id=runtime.ExecutionContextId.from_json(json['executionContextId']), hash_=str(json['hash']), + build_id=str(json['buildId']), execution_context_aux_data=dict(json['executionContextAuxData']) if json.get('executionContextAuxData', None) is not None else None, is_live_edit=bool(json['isLiveEdit']) if json.get('isLiveEdit', None) is not None else None, source_map_url=str(json['sourceMapURL']) if json.get('sourceMapURL', None) is not None else None, @@ -1340,6 +1399,7 @@ def from_json(cls, json: T_JSON_DICT) -> ScriptParsed: stack_trace=runtime.StackTrace.from_json(json['stackTrace']) if json.get('stackTrace', None) is not None else None, code_offset=int(json['codeOffset']) if json.get('codeOffset', None) is not None else None, script_language=ScriptLanguage.from_json(json['scriptLanguage']) if json.get('scriptLanguage', None) is not None else None, - debug_symbols=DebugSymbols.from_json(json['debugSymbols']) if json.get('debugSymbols', None) is not None else None, - embedder_name=str(json['embedderName']) if json.get('embedderName', None) is not None else None + debug_symbols=[DebugSymbols.from_json(i) for i in json['debugSymbols']] if json.get('debugSymbols', None) is not None else None, + embedder_name=str(json['embedderName']) if json.get('embedderName', None) is not None else None, + resolved_breakpoints=[ResolvedBreakpoint.from_json(i) for i in json['resolvedBreakpoints']] if json.get('resolvedBreakpoints', None) is not None else None ) diff --git a/pycdp/cdp/dom.py b/pycdp/cdp/dom.py index e8ebf69..3d701e4 100644 --- a/pycdp/cdp/dom.py +++ b/pycdp/cdp/dom.py @@ -82,16 +82,23 @@ class PseudoType(enum.Enum): ''' FIRST_LINE = "first-line" FIRST_LETTER = "first-letter" + CHECKMARK = "checkmark" BEFORE = "before" AFTER = "after" + PICKER_ICON = "picker-icon" MARKER = "marker" BACKDROP = "backdrop" + COLUMN = "column" SELECTION = "selection" + SEARCH_TEXT = "search-text" TARGET_TEXT = "target-text" SPELLING_ERROR = "spelling-error" GRAMMAR_ERROR = "grammar-error" HIGHLIGHT = "highlight" FIRST_LINE_INHERITED = "first-line-inherited" + SCROLL_MARKER = "scroll-marker" + SCROLL_MARKER_GROUP = "scroll-marker-group" + SCROLL_BUTTON = "scroll-button" SCROLLBAR = "scrollbar" SCROLLBAR_THUMB = "scrollbar-thumb" SCROLLBAR_BUTTON = "scrollbar-button" @@ -105,6 +112,10 @@ class PseudoType(enum.Enum): VIEW_TRANSITION_IMAGE_PAIR = "view-transition-image-pair" VIEW_TRANSITION_OLD = "view-transition-old" VIEW_TRANSITION_NEW = "view-transition-new" + PLACEHOLDER = "placeholder" + FILE_SELECTOR_BUTTON = "file-selector-button" + DETAILS_CONTENT = "details-content" + PICKER = "picker" def to_json(self) -> str: return self.value @@ -178,6 +189,21 @@ def from_json(cls, json: str) -> LogicalAxes: return cls(json) +class ScrollOrientation(enum.Enum): + ''' + Physical scroll orientation + ''' + HORIZONTAL = "horizontal" + VERTICAL = "vertical" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> ScrollOrientation: + return cls(json) + + @dataclass class Node: ''' @@ -280,6 +306,8 @@ class Node: assigned_slot: typing.Optional[BackendNode] = None + is_scrollable: typing.Optional[bool] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['nodeId'] = self.node_id.to_json() @@ -338,6 +366,8 @@ def to_json(self) -> T_JSON_DICT: json['compatibilityMode'] = self.compatibility_mode.to_json() if self.assigned_slot is not None: json['assignedSlot'] = self.assigned_slot.to_json() + if self.is_scrollable is not None: + json['isScrollable'] = self.is_scrollable return json @classmethod @@ -374,6 +404,30 @@ def from_json(cls, json: T_JSON_DICT) -> Node: is_svg=bool(json['isSVG']) if json.get('isSVG', None) is not None else None, compatibility_mode=CompatibilityMode.from_json(json['compatibilityMode']) if json.get('compatibilityMode', None) is not None else None, assigned_slot=BackendNode.from_json(json['assignedSlot']) if json.get('assignedSlot', None) is not None else None, + is_scrollable=bool(json['isScrollable']) if json.get('isScrollable', None) is not None else None, + ) + + +@dataclass +class DetachedElementInfo: + ''' + A structure to hold the top-level node of a detached tree and an array of its retained descendants. + ''' + tree_node: Node + + retained_node_ids: typing.List[NodeId] + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['treeNode'] = self.tree_node.to_json() + json['retainedNodeIds'] = [i.to_json() for i in self.retained_node_ids] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> DetachedElementInfo: + return cls( + tree_node=Node.from_json(json['treeNode']), + retained_node_ids=[NodeId.from_json(i) for i in json['retainedNodeIds']], ) @@ -664,8 +718,6 @@ def scroll_into_view_if_needed( Note: exactly one between nodeId, backendNodeId and objectId should be passed to identify the node. - **EXPERIMENTAL** - :param node_id: *(Optional)* Identifier of the node. :param backend_node_id: *(Optional)* Identifier of the backend node. :param object_id: *(Optional)* JavaScript object id of the node wrapper. @@ -767,7 +819,7 @@ def get_attributes( ''' Returns attributes for the specified node. - :param node_id: Id of the node to retrieve attibutes for. + :param node_id: Id of the node to retrieve attributes for. :returns: An interleaved array of node attribute names and values. ''' params: T_JSON_DICT = dict() @@ -1240,6 +1292,30 @@ def get_top_layer_elements() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing. return [NodeId.from_json(i) for i in json['nodeIds']] +def get_element_by_relation( + node_id: NodeId, + relation: str + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,NodeId]: + ''' + Returns the NodeId of the matched element according to certain relations. + + **EXPERIMENTAL** + + :param node_id: Id of the node from which to query the relation. + :param relation: Type of relation to get. + :returns: NodeId of the element matching the queried relation. + ''' + params: T_JSON_DICT = dict() + params['nodeId'] = node_id.to_json() + params['relation'] = relation + cmd_dict: T_JSON_DICT = { + 'method': 'DOM.getElementByRelation', + 'params': params, + } + json = yield cmd_dict + return NodeId.from_json(json['nodeId']) + + def redo() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Re-does the last undone action. @@ -1508,6 +1584,21 @@ def get_file_info( return str(json['path']) +def get_detached_dom_nodes() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[DetachedElementInfo]]: + ''' + Returns list of detached nodes + + **EXPERIMENTAL** + + :returns: The list of detached nodes + ''' + cmd_dict: T_JSON_DICT = { + 'method': 'DOM.getDetachedDomNodes', + } + json = yield cmd_dict + return [DetachedElementInfo.from_json(i) for i in json['detachedNodes']] + + def set_inspected_node( node_id: NodeId ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: @@ -1633,13 +1724,15 @@ def get_container_for_node( node_id: NodeId, container_name: typing.Optional[str] = None, physical_axes: typing.Optional[PhysicalAxes] = None, - logical_axes: typing.Optional[LogicalAxes] = None + logical_axes: typing.Optional[LogicalAxes] = None, + queries_scroll_state: typing.Optional[bool] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Optional[NodeId]]: ''' Returns the query container of the given node based on container query - conditions: containerName, physical, and logical axes. If no axes are - provided, the style container is returned, which is the direct parent or the - closest element with a matching container-name. + conditions: containerName, physical and logical axes, and whether it queries + scroll-state. If no axes are provided and queriesScrollState is false, the + style container is returned, which is the direct parent or the closest + element with a matching container-name. **EXPERIMENTAL** @@ -1647,6 +1740,7 @@ def get_container_for_node( :param container_name: *(Optional)* :param physical_axes: *(Optional)* :param logical_axes: *(Optional)* + :param queries_scroll_state: *(Optional)* :returns: *(Optional)* The container node for the given node, or null if not found. ''' params: T_JSON_DICT = dict() @@ -1657,6 +1751,8 @@ def get_container_for_node( params['physicalAxes'] = physical_axes.to_json() if logical_axes is not None: params['logicalAxes'] = logical_axes.to_json() + if queries_scroll_state is not None: + params['queriesScrollState'] = queries_scroll_state cmd_dict: T_JSON_DICT = { 'method': 'DOM.getContainerForNode', 'params': params, @@ -1687,6 +1783,32 @@ def get_querying_descendants_for_container( return [NodeId.from_json(i) for i in json['nodeIds']] +def get_anchor_element( + node_id: NodeId, + anchor_specifier: typing.Optional[str] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,NodeId]: + ''' + Returns the target anchor element of the given anchor query according to + https://www.w3.org/TR/css-anchor-position-1/#target. + + **EXPERIMENTAL** + + :param node_id: Id of the positioned element from which to find the anchor. + :param anchor_specifier: *(Optional)* An optional anchor specifier, as defined in https://www.w3.org/TR/css-anchor-position-1/#anchor-specifier. If not provided, it will return the implicit anchor element for the given positioned element. + :returns: The anchor element of the given anchor query. + ''' + params: T_JSON_DICT = dict() + params['nodeId'] = node_id.to_json() + if anchor_specifier is not None: + params['anchorSpecifier'] = anchor_specifier + cmd_dict: T_JSON_DICT = { + 'method': 'DOM.getAnchorElement', + 'params': params, + } + json = yield cmd_dict + return NodeId.from_json(json['nodeId']) + + @event_class('DOM.attributeModified') @dataclass class AttributeModified: @@ -1899,6 +2021,27 @@ def from_json(cls, json: T_JSON_DICT) -> TopLayerElementsUpdated: ) +@event_class('DOM.scrollableFlagUpdated') +@dataclass +class ScrollableFlagUpdated: + ''' + **EXPERIMENTAL** + + Fired when a node's scrollability state changes. + ''' + #: The id of the node. + node_id: NodeId + #: If the node is scrollable. + is_scrollable: bool + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ScrollableFlagUpdated: + return cls( + node_id=NodeId.from_json(json['nodeId']), + is_scrollable=bool(json['isScrollable']) + ) + + @event_class('DOM.pseudoElementRemoved') @dataclass class PseudoElementRemoved: diff --git a/pycdp/cdp/dom_debugger.py b/pycdp/cdp/dom_debugger.py index 624776a..5a40a8d 100644 --- a/pycdp/cdp/dom_debugger.py +++ b/pycdp/cdp/dom_debugger.py @@ -13,6 +13,7 @@ from . import dom from . import runtime +from deprecated.sphinx import deprecated # type: ignore class DOMBreakpointType(enum.Enum): @@ -182,12 +183,15 @@ def remove_event_listener_breakpoint( json = yield cmd_dict +@deprecated(version="1.3") def remove_instrumentation_breakpoint( event_name: str ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Removes breakpoint on particular native event. + .. deprecated:: 1.3 + **EXPERIMENTAL** :param event_name: Instrumentation name to stop on. @@ -278,12 +282,15 @@ def set_event_listener_breakpoint( json = yield cmd_dict +@deprecated(version="1.3") def set_instrumentation_breakpoint( event_name: str ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Sets breakpoint on particular native event. + .. deprecated:: 1.3 + **EXPERIMENTAL** :param event_name: Instrumentation name to stop on. diff --git a/pycdp/cdp/emulation.py b/pycdp/cdp/emulation.py index b24dc28..2e3c00e 100644 --- a/pycdp/cdp/emulation.py +++ b/pycdp/cdp/emulation.py @@ -17,6 +17,66 @@ from deprecated.sphinx import deprecated # type: ignore +@dataclass +class SafeAreaInsets: + #: Overrides safe-area-inset-top. + top: typing.Optional[int] = None + + #: Overrides safe-area-max-inset-top. + top_max: typing.Optional[int] = None + + #: Overrides safe-area-inset-left. + left: typing.Optional[int] = None + + #: Overrides safe-area-max-inset-left. + left_max: typing.Optional[int] = None + + #: Overrides safe-area-inset-bottom. + bottom: typing.Optional[int] = None + + #: Overrides safe-area-max-inset-bottom. + bottom_max: typing.Optional[int] = None + + #: Overrides safe-area-inset-right. + right: typing.Optional[int] = None + + #: Overrides safe-area-max-inset-right. + right_max: typing.Optional[int] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.top is not None: + json['top'] = self.top + if self.top_max is not None: + json['topMax'] = self.top_max + if self.left is not None: + json['left'] = self.left + if self.left_max is not None: + json['leftMax'] = self.left_max + if self.bottom is not None: + json['bottom'] = self.bottom + if self.bottom_max is not None: + json['bottomMax'] = self.bottom_max + if self.right is not None: + json['right'] = self.right + if self.right_max is not None: + json['rightMax'] = self.right_max + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> SafeAreaInsets: + return cls( + top=int(json['top']) if json.get('top', None) is not None else None, + top_max=int(json['topMax']) if json.get('topMax', None) is not None else None, + left=int(json['left']) if json.get('left', None) is not None else None, + left_max=int(json['leftMax']) if json.get('leftMax', None) is not None else None, + bottom=int(json['bottom']) if json.get('bottom', None) is not None else None, + bottom_max=int(json['bottomMax']) if json.get('bottomMax', None) is not None else None, + right=int(json['right']) if json.get('right', None) is not None else None, + right_max=int(json['rightMax']) if json.get('rightMax', None) is not None else None, + ) + + @dataclass class ScreenOrientation: ''' @@ -72,6 +132,23 @@ def from_json(cls, json: T_JSON_DICT) -> DisplayFeature: ) +@dataclass +class DevicePosture: + #: Current posture of the device + type_: str + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['type'] = self.type_ + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> DevicePosture: + return cls( + type_=str(json['type']), + ) + + @dataclass class MediaFeature: name: str @@ -114,7 +191,7 @@ def from_json(cls, json: str) -> VirtualTimePolicy: @dataclass class UserAgentBrandVersion: ''' - Used to specify User Agent Cient Hints to emulate. See https://wicg.github.io/ua-client-hints + Used to specify User Agent Client Hints to emulate. See https://wicg.github.io/ua-client-hints ''' brand: str @@ -137,7 +214,7 @@ def from_json(cls, json: T_JSON_DICT) -> UserAgentBrandVersion: @dataclass class UserAgentMetadata: ''' - Used to specify User Agent Cient Hints to emulate. See https://wicg.github.io/ua-client-hints + Used to specify User Agent Client Hints to emulate. See https://wicg.github.io/ua-client-hints Missing optional values will be filled in by the target with what it would normally use. ''' platform: str @@ -197,6 +274,192 @@ def from_json(cls, json: T_JSON_DICT) -> UserAgentMetadata: ) +class SensorType(enum.Enum): + ''' + Used to specify sensor types to emulate. + See https://w3c.github.io/sensors/#automation for more information. + ''' + ABSOLUTE_ORIENTATION = "absolute-orientation" + ACCELEROMETER = "accelerometer" + AMBIENT_LIGHT = "ambient-light" + GRAVITY = "gravity" + GYROSCOPE = "gyroscope" + LINEAR_ACCELERATION = "linear-acceleration" + MAGNETOMETER = "magnetometer" + RELATIVE_ORIENTATION = "relative-orientation" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> SensorType: + return cls(json) + + +@dataclass +class SensorMetadata: + available: typing.Optional[bool] = None + + minimum_frequency: typing.Optional[float] = None + + maximum_frequency: typing.Optional[float] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.available is not None: + json['available'] = self.available + if self.minimum_frequency is not None: + json['minimumFrequency'] = self.minimum_frequency + if self.maximum_frequency is not None: + json['maximumFrequency'] = self.maximum_frequency + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> SensorMetadata: + return cls( + available=bool(json['available']) if json.get('available', None) is not None else None, + minimum_frequency=float(json['minimumFrequency']) if json.get('minimumFrequency', None) is not None else None, + maximum_frequency=float(json['maximumFrequency']) if json.get('maximumFrequency', None) is not None else None, + ) + + +@dataclass +class SensorReadingSingle: + value: float + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['value'] = self.value + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> SensorReadingSingle: + return cls( + value=float(json['value']), + ) + + +@dataclass +class SensorReadingXYZ: + x: float + + y: float + + z: float + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['x'] = self.x + json['y'] = self.y + json['z'] = self.z + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> SensorReadingXYZ: + return cls( + x=float(json['x']), + y=float(json['y']), + z=float(json['z']), + ) + + +@dataclass +class SensorReadingQuaternion: + x: float + + y: float + + z: float + + w: float + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['x'] = self.x + json['y'] = self.y + json['z'] = self.z + json['w'] = self.w + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> SensorReadingQuaternion: + return cls( + x=float(json['x']), + y=float(json['y']), + z=float(json['z']), + w=float(json['w']), + ) + + +@dataclass +class SensorReading: + single: typing.Optional[SensorReadingSingle] = None + + xyz: typing.Optional[SensorReadingXYZ] = None + + quaternion: typing.Optional[SensorReadingQuaternion] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.single is not None: + json['single'] = self.single.to_json() + if self.xyz is not None: + json['xyz'] = self.xyz.to_json() + if self.quaternion is not None: + json['quaternion'] = self.quaternion.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> SensorReading: + return cls( + single=SensorReadingSingle.from_json(json['single']) if json.get('single', None) is not None else None, + xyz=SensorReadingXYZ.from_json(json['xyz']) if json.get('xyz', None) is not None else None, + quaternion=SensorReadingQuaternion.from_json(json['quaternion']) if json.get('quaternion', None) is not None else None, + ) + + +class PressureSource(enum.Enum): + CPU = "cpu" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> PressureSource: + return cls(json) + + +class PressureState(enum.Enum): + NOMINAL = "nominal" + FAIR = "fair" + SERIOUS = "serious" + CRITICAL = "critical" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> PressureState: + return cls(json) + + +@dataclass +class PressureMetadata: + available: typing.Optional[bool] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.available is not None: + json['available'] = self.available + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> PressureMetadata: + return cls( + available=bool(json['available']) if json.get('available', None) is not None else None, + ) + + class DisabledImageType(enum.Enum): ''' Enum of image types that can be disabled. @@ -212,10 +475,13 @@ def from_json(cls, json: str) -> DisabledImageType: return cls(json) +@deprecated(version="1.3") def can_emulate() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,bool]: ''' Tells whether emulation is supported. + .. deprecated:: 1.3 + :returns: True if emulation is supported. ''' cmd_dict: T_JSON_DICT = { @@ -302,8 +568,6 @@ def set_cpu_throttling_rate( ''' Enables CPU throttling to emulate slow CPUs. - **EXPERIMENTAL** - :param rate: Throttling rate as a slowdown factor (1 is no throttle, 2 is 2x slowdown, etc). ''' params: T_JSON_DICT = dict() @@ -334,6 +598,26 @@ def set_default_background_color_override( json = yield cmd_dict +def set_safe_area_insets_override( + insets: SafeAreaInsets + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Overrides the values for env(safe-area-inset-*) and env(safe-area-max-inset-*). Unset values will cause the + respective variables to be undefined, even if previously overridden. + + **EXPERIMENTAL** + + :param insets: + ''' + params: T_JSON_DICT = dict() + params['insets'] = insets.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'Emulation.setSafeAreaInsetsOverride', + 'params': params, + } + json = yield cmd_dict + + def set_device_metrics_override( width: int, height: int, @@ -347,7 +631,8 @@ def set_device_metrics_override( dont_set_visible_size: typing.Optional[bool] = None, screen_orientation: typing.Optional[ScreenOrientation] = None, viewport: typing.Optional[page.Viewport] = None, - display_feature: typing.Optional[DisplayFeature] = None + display_feature: typing.Optional[DisplayFeature] = None, + device_posture: typing.Optional[DevicePosture] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Overrides the values of device screen dimensions (window.screen.width, window.screen.height, @@ -367,6 +652,7 @@ def set_device_metrics_override( :param screen_orientation: *(Optional)* Screen orientation override. :param viewport: **(EXPERIMENTAL)** *(Optional)* If set, the visible area of the page will be overridden to this viewport. This viewport change is not observed by the page, e.g. viewport-relative elements do not change positions. :param display_feature: **(EXPERIMENTAL)** *(Optional)* If set, the display feature of a multi-segment screen. If not set, multi-segment support is turned-off. + :param device_posture: **(DEPRECATED)** **(EXPERIMENTAL)** *(Optional)* If set, the posture of a foldable device. If not set the posture is set to continuous. Deprecated, use Emulation.setDevicePostureOverride. ''' params: T_JSON_DICT = dict() params['width'] = width @@ -391,6 +677,8 @@ def set_device_metrics_override( params['viewport'] = viewport.to_json() if display_feature is not None: params['displayFeature'] = display_feature.to_json() + if device_posture is not None: + params['devicePosture'] = device_posture.to_json() cmd_dict: T_JSON_DICT = { 'method': 'Emulation.setDeviceMetricsOverride', 'params': params, @@ -398,6 +686,41 @@ def set_device_metrics_override( json = yield cmd_dict +def set_device_posture_override( + posture: DevicePosture + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Start reporting the given posture value to the Device Posture API. + This override can also be set in setDeviceMetricsOverride(). + + **EXPERIMENTAL** + + :param posture: + ''' + params: T_JSON_DICT = dict() + params['posture'] = posture.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'Emulation.setDevicePostureOverride', + 'params': params, + } + json = yield cmd_dict + + +def clear_device_posture_override() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Clears a device posture override set with either setDeviceMetricsOverride() + or setDevicePostureOverride() and starts using posture information from the + platform again. + Does nothing if no override is set. + + **EXPERIMENTAL** + ''' + cmd_dict: T_JSON_DICT = { + 'method': 'Emulation.clearDevicePostureOverride', + } + json = yield cmd_dict + + def set_scrollbars_hidden( hidden: bool ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: @@ -487,8 +810,6 @@ def set_emulated_vision_deficiency( ''' Emulates the given vision deficiency. - **EXPERIMENTAL** - :param type_: Vision deficiency to emulate. Order: best-effort emulations come first, followed by any physiologically accurate emulations for medically recognized color vision deficiencies. ''' params: T_JSON_DICT = dict() @@ -527,6 +848,133 @@ def set_geolocation_override( json = yield cmd_dict +def get_overridden_sensor_information( + type_: SensorType + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,float]: + ''' + + + **EXPERIMENTAL** + + :param type_: + :returns: + ''' + params: T_JSON_DICT = dict() + params['type'] = type_.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'Emulation.getOverriddenSensorInformation', + 'params': params, + } + json = yield cmd_dict + return float(json['requestedSamplingFrequency']) + + +def set_sensor_override_enabled( + enabled: bool, + type_: SensorType, + metadata: typing.Optional[SensorMetadata] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Overrides a platform sensor of a given type. If ``enabled`` is true, calls to + Sensor.start() will use a virtual sensor as backend rather than fetching + data from a real hardware sensor. Otherwise, existing virtual + sensor-backend Sensor objects will fire an error event and new calls to + Sensor.start() will attempt to use a real sensor instead. + + **EXPERIMENTAL** + + :param enabled: + :param type_: + :param metadata: *(Optional)* + ''' + params: T_JSON_DICT = dict() + params['enabled'] = enabled + params['type'] = type_.to_json() + if metadata is not None: + params['metadata'] = metadata.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'Emulation.setSensorOverrideEnabled', + 'params': params, + } + json = yield cmd_dict + + +def set_sensor_override_readings( + type_: SensorType, + reading: SensorReading + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Updates the sensor readings reported by a sensor type previously overridden + by setSensorOverrideEnabled. + + **EXPERIMENTAL** + + :param type_: + :param reading: + ''' + params: T_JSON_DICT = dict() + params['type'] = type_.to_json() + params['reading'] = reading.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'Emulation.setSensorOverrideReadings', + 'params': params, + } + json = yield cmd_dict + + +def set_pressure_source_override_enabled( + enabled: bool, + source: PressureSource, + metadata: typing.Optional[PressureMetadata] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Overrides a pressure source of a given type, as used by the Compute + Pressure API, so that updates to PressureObserver.observe() are provided + via setPressureStateOverride instead of being retrieved from + platform-provided telemetry data. + + **EXPERIMENTAL** + + :param enabled: + :param source: + :param metadata: *(Optional)* + ''' + params: T_JSON_DICT = dict() + params['enabled'] = enabled + params['source'] = source.to_json() + if metadata is not None: + params['metadata'] = metadata.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'Emulation.setPressureSourceOverrideEnabled', + 'params': params, + } + json = yield cmd_dict + + +def set_pressure_state_override( + source: PressureSource, + state: PressureState + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Provides a given pressure state that will be processed and eventually be + delivered to PressureObserver users. ``source`` must have been previously + overridden by setPressureSourceOverrideEnabled. + + **EXPERIMENTAL** + + :param source: + :param state: + ''' + params: T_JSON_DICT = dict() + params['source'] = source.to_json() + params['state'] = state.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'Emulation.setPressureStateOverride', + 'params': params, + } + json = yield cmd_dict + + def set_idle_override( is_user_active: bool, is_screen_unlocked: bool @@ -534,8 +982,6 @@ def set_idle_override( ''' Overrides the Idle state. - **EXPERIMENTAL** - :param is_user_active: Mock isUserActive :param is_screen_unlocked: Mock isScreenUnlocked ''' @@ -552,8 +998,6 @@ def set_idle_override( def clear_idle_override() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Clears Idle state overrides. - - **EXPERIMENTAL** ''' cmd_dict: T_JSON_DICT = { 'method': 'Emulation.clearIdleOverride', @@ -700,9 +1144,7 @@ def set_timezone_override( ''' Overrides default host system timezone with the specified one. - **EXPERIMENTAL** - - :param timezone_id: The timezone identifier. If empty, disables the override and restores default host system timezone. + :param timezone_id: The timezone identifier. List of supported timezones: https://source.chromium.org/chromium/chromium/deps/icu.git/+/faee8bc70570192d82d2978a71e2a615788597d1:source/data/misc/metaZones.txt If empty, disables the override and restores default host system timezone. ''' params: T_JSON_DICT = dict() params['timezoneId'] = timezone_id @@ -786,9 +1228,10 @@ def set_user_agent_override( ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Allows overriding user agent with the given string. + ``userAgentMetadata`` must be set for Client Hint headers to be sent. :param user_agent: User agent to use. - :param accept_language: *(Optional)* Browser langugage to emulate. + :param accept_language: *(Optional)* Browser language to emulate. :param platform: *(Optional)* The platform navigator.platform should return. :param user_agent_metadata: **(EXPERIMENTAL)** *(Optional)* To be sent in Sec-CH-UA-* headers and returned in navigator.userAgentData ''' diff --git a/pycdp/cdp/event_breakpoints.py b/pycdp/cdp/event_breakpoints.py index 719ebd1..b2ace4e 100644 --- a/pycdp/cdp/event_breakpoints.py +++ b/pycdp/cdp/event_breakpoints.py @@ -44,3 +44,13 @@ def remove_instrumentation_breakpoint( 'params': params, } json = yield cmd_dict + + +def disable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Removes all breakpoints + ''' + cmd_dict: T_JSON_DICT = { + 'method': 'EventBreakpoints.disable', + } + json = yield cmd_dict diff --git a/pycdp/cdp/extensions.py b/pycdp/cdp/extensions.py new file mode 100644 index 0000000..55fcd53 --- /dev/null +++ b/pycdp/cdp/extensions.py @@ -0,0 +1,165 @@ +# DO NOT EDIT THIS FILE! +# +# This file is generated from the CDP specification. If you need to make +# changes, edit the generator and regenerate all of the modules. +# +# CDP domain: Extensions (experimental) + +from __future__ import annotations +import enum +import typing +from dataclasses import dataclass +from .util import event_class, T_JSON_DICT + + +class StorageArea(enum.Enum): + ''' + Storage areas. + ''' + SESSION = "session" + LOCAL = "local" + SYNC = "sync" + MANAGED = "managed" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> StorageArea: + return cls(json) + + +def load_unpacked( + path: str + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,str]: + ''' + Installs an unpacked extension from the filesystem similar to + --load-extension CLI flags. Returns extension ID once the extension + has been installed. Available if the client is connected using the + --remote-debugging-pipe flag and the --enable-unsafe-extension-debugging + flag is set. + + :param path: Absolute file path. + :returns: Extension id. + ''' + params: T_JSON_DICT = dict() + params['path'] = path + cmd_dict: T_JSON_DICT = { + 'method': 'Extensions.loadUnpacked', + 'params': params, + } + json = yield cmd_dict + return str(json['id']) + + +def uninstall( + id_: str + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Uninstalls an unpacked extension (others not supported) from the profile. + Available if the client is connected using the --remote-debugging-pipe flag + and the --enable-unsafe-extension-debugging. + + :param id_: Extension id. + ''' + params: T_JSON_DICT = dict() + params['id'] = id_ + cmd_dict: T_JSON_DICT = { + 'method': 'Extensions.uninstall', + 'params': params, + } + json = yield cmd_dict + + +def get_storage_items( + id_: str, + storage_area: StorageArea, + keys: typing.Optional[typing.List[str]] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,dict]: + ''' + Gets data from extension storage in the given ``storageArea``. If ``keys`` is + specified, these are used to filter the result. + + :param id_: ID of extension. + :param storage_area: StorageArea to retrieve data from. + :param keys: *(Optional)* Keys to retrieve. + :returns: + ''' + params: T_JSON_DICT = dict() + params['id'] = id_ + params['storageArea'] = storage_area.to_json() + if keys is not None: + params['keys'] = [i for i in keys] + cmd_dict: T_JSON_DICT = { + 'method': 'Extensions.getStorageItems', + 'params': params, + } + json = yield cmd_dict + return dict(json['data']) + + +def remove_storage_items( + id_: str, + storage_area: StorageArea, + keys: typing.List[str] + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Removes ``keys`` from extension storage in the given ``storageArea``. + + :param id_: ID of extension. + :param storage_area: StorageArea to remove data from. + :param keys: Keys to remove. + ''' + params: T_JSON_DICT = dict() + params['id'] = id_ + params['storageArea'] = storage_area.to_json() + params['keys'] = [i for i in keys] + cmd_dict: T_JSON_DICT = { + 'method': 'Extensions.removeStorageItems', + 'params': params, + } + json = yield cmd_dict + + +def clear_storage_items( + id_: str, + storage_area: StorageArea + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Clears extension storage in the given ``storageArea``. + + :param id_: ID of extension. + :param storage_area: StorageArea to remove data from. + ''' + params: T_JSON_DICT = dict() + params['id'] = id_ + params['storageArea'] = storage_area.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'Extensions.clearStorageItems', + 'params': params, + } + json = yield cmd_dict + + +def set_storage_items( + id_: str, + storage_area: StorageArea, + values: dict + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Sets ``values`` in extension storage in the given ``storageArea``. The provided ``values`` + will be merged with existing values in the storage area. + + :param id_: ID of extension. + :param storage_area: StorageArea to set data in. + :param values: Values to set. + ''' + params: T_JSON_DICT = dict() + params['id'] = id_ + params['storageArea'] = storage_area.to_json() + params['values'] = values + cmd_dict: T_JSON_DICT = { + 'method': 'Extensions.setStorageItems', + 'params': params, + } + json = yield cmd_dict diff --git a/pycdp/cdp/fed_cm.py b/pycdp/cdp/fed_cm.py index 8440c1b..d6ec340 100644 --- a/pycdp/cdp/fed_cm.py +++ b/pycdp/cdp/fed_cm.py @@ -30,10 +30,12 @@ def from_json(cls, json: str) -> LoginState: class DialogType(enum.Enum): ''' - Whether the dialog shown is an account chooser or an auto re-authentication dialog. + The types of FedCM dialogs. ''' ACCOUNT_CHOOSER = "AccountChooser" AUTO_REAUTHN = "AutoReauthn" + CONFIRM_IDP_LOGIN = "ConfirmIdpLogin" + ERROR = "Error" def to_json(self) -> str: return self.value @@ -43,6 +45,37 @@ def from_json(cls, json: str) -> DialogType: return cls(json) +class DialogButton(enum.Enum): + ''' + The buttons on the FedCM dialog. + ''' + CONFIRM_IDP_LOGIN_CONTINUE = "ConfirmIdpLoginContinue" + ERROR_GOT_IT = "ErrorGotIt" + ERROR_MORE_DETAILS = "ErrorMoreDetails" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> DialogButton: + return cls(json) + + +class AccountUrlType(enum.Enum): + ''' + The URLs that each account has + ''' + TERMS_OF_SERVICE = "TermsOfService" + PRIVACY_POLICY = "PrivacyPolicy" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> AccountUrlType: + return cls(json) + + @dataclass class Account: ''' @@ -60,7 +93,7 @@ class Account: idp_config_url: str - idp_signin_url: str + idp_login_url: str login_state: LoginState @@ -77,7 +110,7 @@ def to_json(self) -> T_JSON_DICT: json['givenName'] = self.given_name json['pictureUrl'] = self.picture_url json['idpConfigUrl'] = self.idp_config_url - json['idpSigninUrl'] = self.idp_signin_url + json['idpLoginUrl'] = self.idp_login_url json['loginState'] = self.login_state.to_json() if self.terms_of_service_url is not None: json['termsOfServiceUrl'] = self.terms_of_service_url @@ -94,7 +127,7 @@ def from_json(cls, json: T_JSON_DICT) -> Account: given_name=str(json['givenName']), picture_url=str(json['pictureUrl']), idp_config_url=str(json['idpConfigUrl']), - idp_signin_url=str(json['idpSigninUrl']), + idp_login_url=str(json['idpLoginUrl']), login_state=LoginState.from_json(json['loginState']), terms_of_service_url=str(json['termsOfServiceUrl']) if json.get('termsOfServiceUrl', None) is not None else None, privacy_policy_url=str(json['privacyPolicyUrl']) if json.get('privacyPolicyUrl', None) is not None else None, @@ -143,6 +176,45 @@ def select_account( json = yield cmd_dict +def click_dialog_button( + dialog_id: str, + dialog_button: DialogButton + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + :param dialog_id: + :param dialog_button: + ''' + params: T_JSON_DICT = dict() + params['dialogId'] = dialog_id + params['dialogButton'] = dialog_button.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'FedCm.clickDialogButton', + 'params': params, + } + json = yield cmd_dict + + +def open_url( + dialog_id: str, + account_index: int, + account_url_type: AccountUrlType + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + :param dialog_id: + :param account_index: + :param account_url_type: + ''' + params: T_JSON_DICT = dict() + params['dialogId'] = dialog_id + params['accountIndex'] = account_index + params['accountUrlType'] = account_url_type.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'FedCm.openUrl', + 'params': params, + } + json = yield cmd_dict + + def dismiss_dialog( dialog_id: str, trigger_cooldown: typing.Optional[bool] = None @@ -193,3 +265,19 @@ def from_json(cls, json: T_JSON_DICT) -> DialogShown: title=str(json['title']), subtitle=str(json['subtitle']) if json.get('subtitle', None) is not None else None ) + + +@event_class('FedCm.dialogClosed') +@dataclass +class DialogClosed: + ''' + Triggered when a dialog is closed, either by user action, JS abort, + or a command below. + ''' + dialog_id: str + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> DialogClosed: + return cls( + dialog_id=str(json['dialogId']) + ) diff --git a/pycdp/cdp/fetch.py b/pycdp/cdp/fetch.py index 56231a7..6280062 100644 --- a/pycdp/cdp/fetch.py +++ b/pycdp/cdp/fetch.py @@ -19,6 +19,8 @@ class RequestId(str): ''' Unique request identifier. + Note that this does not identify individual HTTP requests that are part of + a network request. ''' def to_json(self) -> str: return self diff --git a/pycdp/cdp/file_system.py b/pycdp/cdp/file_system.py new file mode 100644 index 0000000..398fac9 --- /dev/null +++ b/pycdp/cdp/file_system.py @@ -0,0 +1,115 @@ +# DO NOT EDIT THIS FILE! +# +# This file is generated from the CDP specification. If you need to make +# changes, edit the generator and regenerate all of the modules. +# +# CDP domain: FileSystem (experimental) + +from __future__ import annotations +import enum +import typing +from dataclasses import dataclass +from .util import event_class, T_JSON_DICT + +from . import network +from . import storage + + +@dataclass +class File: + name: str + + #: Timestamp + last_modified: network.TimeSinceEpoch + + #: Size in bytes + size: float + + type_: str + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['name'] = self.name + json['lastModified'] = self.last_modified.to_json() + json['size'] = self.size + json['type'] = self.type_ + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> File: + return cls( + name=str(json['name']), + last_modified=network.TimeSinceEpoch.from_json(json['lastModified']), + size=float(json['size']), + type_=str(json['type']), + ) + + +@dataclass +class Directory: + name: str + + nested_directories: typing.List[str] + + #: Files that are directly nested under this directory. + nested_files: typing.List[File] + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['name'] = self.name + json['nestedDirectories'] = [i for i in self.nested_directories] + json['nestedFiles'] = [i.to_json() for i in self.nested_files] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> Directory: + return cls( + name=str(json['name']), + nested_directories=[str(i) for i in json['nestedDirectories']], + nested_files=[File.from_json(i) for i in json['nestedFiles']], + ) + + +@dataclass +class BucketFileSystemLocator: + #: Storage key + storage_key: storage.SerializedStorageKey + + #: Path to the directory using each path component as an array item. + path_components: typing.List[str] + + #: Bucket name. Not passing a ``bucketName`` will retrieve the default Bucket. (https://developer.mozilla.org/en-US/docs/Web/API/Storage_API#storage_buckets) + bucket_name: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['storageKey'] = self.storage_key.to_json() + json['pathComponents'] = [i for i in self.path_components] + if self.bucket_name is not None: + json['bucketName'] = self.bucket_name + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> BucketFileSystemLocator: + return cls( + storage_key=storage.SerializedStorageKey.from_json(json['storageKey']), + path_components=[str(i) for i in json['pathComponents']], + bucket_name=str(json['bucketName']) if json.get('bucketName', None) is not None else None, + ) + + +def get_directory( + bucket_file_system_locator: BucketFileSystemLocator + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,Directory]: + ''' + :param bucket_file_system_locator: + :returns: Returns the directory object at the path. + ''' + params: T_JSON_DICT = dict() + params['bucketFileSystemLocator'] = bucket_file_system_locator.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'FileSystem.getDirectory', + 'params': params, + } + json = yield cmd_dict + return Directory.from_json(json['directory']) diff --git a/pycdp/cdp/input_.py b/pycdp/cdp/input_.py index e3ff0f6..3a0a971 100644 --- a/pycdp/cdp/input_.py +++ b/pycdp/cdp/input_.py @@ -37,10 +37,10 @@ class TouchPoint: tangential_pressure: typing.Optional[float] = None #: The plane angle between the Y-Z plane and the plane containing both the stylus axis and the Y axis, in degrees of the range [-90,90], a positive tiltX is to the right (default: 0) - tilt_x: typing.Optional[int] = None + tilt_x: typing.Optional[float] = None #: The plane angle between the X-Z plane and the plane containing both the stylus axis and the X axis, in degrees of the range [-90,90], a positive tiltY is towards the user (default: 0). - tilt_y: typing.Optional[int] = None + tilt_y: typing.Optional[float] = None #: The clockwise rotation of a pen stylus around its own major axis, in degrees in the range [0,359] (default: 0). twist: typing.Optional[int] = None @@ -82,8 +82,8 @@ def from_json(cls, json: T_JSON_DICT) -> TouchPoint: rotation_angle=float(json['rotationAngle']) if json.get('rotationAngle', None) is not None else None, force=float(json['force']) if json.get('force', None) is not None else None, tangential_pressure=float(json['tangentialPressure']) if json.get('tangentialPressure', None) is not None else None, - tilt_x=int(json['tiltX']) if json.get('tiltX', None) is not None else None, - tilt_y=int(json['tiltY']) if json.get('tiltY', None) is not None else None, + tilt_x=float(json['tiltX']) if json.get('tiltX', None) is not None else None, + tilt_y=float(json['tiltY']) if json.get('tiltY', None) is not None else None, twist=int(json['twist']) if json.get('twist', None) is not None else None, id_=float(json['id']) if json.get('id', None) is not None else None, ) @@ -329,7 +329,7 @@ def ime_set_composition( replacement_end: typing.Optional[int] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' - This method sets the current candidate text for ime. + This method sets the current candidate text for IME. Use imeCommitComposition to commit the final text. Use imeSetComposition with empty string as text to cancel composition. @@ -367,8 +367,8 @@ def dispatch_mouse_event( click_count: typing.Optional[int] = None, force: typing.Optional[float] = None, tangential_pressure: typing.Optional[float] = None, - tilt_x: typing.Optional[int] = None, - tilt_y: typing.Optional[int] = None, + tilt_x: typing.Optional[float] = None, + tilt_y: typing.Optional[float] = None, twist: typing.Optional[int] = None, delta_x: typing.Optional[float] = None, delta_y: typing.Optional[float] = None, @@ -387,8 +387,8 @@ def dispatch_mouse_event( :param click_count: *(Optional)* Number of times the mouse button was clicked (default: 0). :param force: **(EXPERIMENTAL)** *(Optional)* The normalized pressure, which has a range of [0,1] (default: 0). :param tangential_pressure: **(EXPERIMENTAL)** *(Optional)* The normalized tangential pressure, which has a range of [-1,1] (default: 0). - :param tilt_x: **(EXPERIMENTAL)** *(Optional)* The plane angle between the Y-Z plane and the plane containing both the stylus axis and the Y axis, in degrees of the range [-90,90], a positive tiltX is to the right (default: 0). - :param tilt_y: **(EXPERIMENTAL)** *(Optional)* The plane angle between the X-Z plane and the plane containing both the stylus axis and the X axis, in degrees of the range [-90,90], a positive tiltY is towards the user (default: 0). + :param tilt_x: *(Optional)* The plane angle between the Y-Z plane and the plane containing both the stylus axis and the Y axis, in degrees of the range [-90,90], a positive tiltX is to the right (default: 0). + :param tilt_y: *(Optional)* The plane angle between the X-Z plane and the plane containing both the stylus axis and the X axis, in degrees of the range [-90,90], a positive tiltY is towards the user (default: 0). :param twist: **(EXPERIMENTAL)** *(Optional)* The clockwise rotation of a pen stylus around its own major axis, in degrees in the range [0,359] (default: 0). :param delta_x: *(Optional)* X delta in CSS pixels for mouse wheel event (default: 0). :param delta_y: *(Optional)* Y delta in CSS pixels for mouse wheel event (default: 0). diff --git a/pycdp/cdp/io.py b/pycdp/cdp/io.py index 7a83a13..d2e3f69 100644 --- a/pycdp/cdp/io.py +++ b/pycdp/cdp/io.py @@ -56,7 +56,7 @@ def read( Read a chunk of the stream :param handle: Handle of the stream to read. - :param offset: *(Optional)* Seek to the specified offset before reading (if not specificed, proceed with offset following the last read). Some types of streams may only support sequential reads. + :param offset: *(Optional)* Seek to the specified offset before reading (if not specified, proceed with offset following the last read). Some types of streams may only support sequential reads. :param size: *(Optional)* Maximum number of bytes to read (left upon the agent discretion if not specified). :returns: A tuple with the following items: diff --git a/pycdp/cdp/layer_tree.py b/pycdp/cdp/layer_tree.py index 08d8539..f25ebdc 100644 --- a/pycdp/cdp/layer_tree.py +++ b/pycdp/cdp/layer_tree.py @@ -454,7 +454,7 @@ def from_json(cls, json: T_JSON_DICT) -> LayerPainted: @event_class('LayerTree.layerTreeDidChange') @dataclass class LayerTreeDidChange: - #: Layer tree, absent if not in the comspositing mode. + #: Layer tree, absent if not in the compositing mode. layers: typing.Optional[typing.List[Layer]] @classmethod diff --git a/pycdp/cdp/memory.py b/pycdp/cdp/memory.py index 2336ce1..43d1a0c 100644 --- a/pycdp/cdp/memory.py +++ b/pycdp/cdp/memory.py @@ -116,10 +116,36 @@ def from_json(cls, json: T_JSON_DICT) -> Module: ) -def get_dom_counters() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[int, int, int]]: +@dataclass +class DOMCounter: ''' + DOM object counter data. + ''' + #: Object name. Note: object names should be presumed volatile and clients should not expect + #: the returned names to be consistent across runs. + name: str + + #: Object count. + count: int + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['name'] = self.name + json['count'] = self.count + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> DOMCounter: + return cls( + name=str(json['name']), + count=int(json['count']), + ) +def get_dom_counters() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[int, int, int]]: + ''' + Retruns current DOM object counters. + :returns: A tuple with the following items: 0. **documents** - @@ -137,8 +163,24 @@ def get_dom_counters() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[ ) -def prepare_for_leak_detection() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: +def get_dom_counters_for_leak_detection() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[DOMCounter]]: + ''' + Retruns DOM object counters after preparing renderer for leak detection. + + :returns: DOM object counters. + ''' + cmd_dict: T_JSON_DICT = { + 'method': 'Memory.getDOMCountersForLeakDetection', + } + json = yield cmd_dict + return [DOMCounter.from_json(i) for i in json['counters']] + +def prepare_for_leak_detection() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Prepares for leak detection by terminating workers, stopping spellcheckers, + dropping non-essential internal caches, running garbage collections, etc. + ''' cmd_dict: T_JSON_DICT = { 'method': 'Memory.prepareForLeakDetection', } diff --git a/pycdp/cdp/network.py b/pycdp/cdp/network.py index 33647ab..95fab0f 100644 --- a/pycdp/cdp/network.py +++ b/pycdp/cdp/network.py @@ -68,7 +68,9 @@ def __repr__(self): class RequestId(str): ''' - Unique request identifier. + Unique network request identifier. + Note that this does not identify individual HTTP requests that are part of + a network request. ''' def to_json(self) -> str: return self @@ -305,6 +307,12 @@ class ResourceTiming: #: Finished receiving response headers. receive_headers_end: float + #: Started ServiceWorker static routing source evaluation. + worker_router_evaluation_start: typing.Optional[float] = None + + #: Started cache lookup when the source was evaluated to ``cache``. + worker_cache_lookup_start: typing.Optional[float] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['requestTime'] = self.request_time @@ -326,6 +334,10 @@ def to_json(self) -> T_JSON_DICT: json['pushEnd'] = self.push_end json['receiveHeadersStart'] = self.receive_headers_start json['receiveHeadersEnd'] = self.receive_headers_end + if self.worker_router_evaluation_start is not None: + json['workerRouterEvaluationStart'] = self.worker_router_evaluation_start + if self.worker_cache_lookup_start is not None: + json['workerCacheLookupStart'] = self.worker_cache_lookup_start return json @classmethod @@ -350,6 +362,8 @@ def from_json(cls, json: T_JSON_DICT) -> ResourceTiming: push_end=float(json['pushEnd']), receive_headers_start=float(json['receiveHeadersStart']), receive_headers_end=float(json['receiveHeadersEnd']), + worker_router_evaluation_start=float(json['workerRouterEvaluationStart']) if json.get('workerRouterEvaluationStart', None) is not None else None, + worker_cache_lookup_start=float(json['workerCacheLookupStart']) if json.get('workerCacheLookupStart', None) is not None else None, ) @@ -415,12 +429,13 @@ class Request: url_fragment: typing.Optional[str] = None #: HTTP POST request data. + #: Use postDataEntries instead. post_data: typing.Optional[str] = None #: True when the request has POST data. Note that postData might still be omitted when this flag is true when the data is too long. has_post_data: typing.Optional[bool] = None - #: Request body elements. This will be converted from base64 to binary + #: Request body elements (post data broken into individual entries). post_data_entries: typing.Optional[typing.List[PostDataEntry]] = None #: The mixed content type of the request. @@ -434,7 +449,7 @@ class Request: trust_token_params: typing.Optional[TrustTokenParams] = None #: True if this resource request is considered to be the 'same site' as the - #: request correspondinfg to the main frame. + #: request corresponding to the main frame. is_same_site: typing.Optional[bool] = None def to_json(self) -> T_JSON_DICT: @@ -663,7 +678,10 @@ class BlockedReason(enum.Enum): COOP_SANDBOXED_IFRAME_CANNOT_NAVIGATE_TO_COOP_PAGE = "coop-sandboxed-iframe-cannot-navigate-to-coop-page" CORP_NOT_SAME_ORIGIN = "corp-not-same-origin" CORP_NOT_SAME_ORIGIN_AFTER_DEFAULTED_TO_SAME_ORIGIN_BY_COEP = "corp-not-same-origin-after-defaulted-to-same-origin-by-coep" + CORP_NOT_SAME_ORIGIN_AFTER_DEFAULTED_TO_SAME_ORIGIN_BY_DIP = "corp-not-same-origin-after-defaulted-to-same-origin-by-dip" + CORP_NOT_SAME_ORIGIN_AFTER_DEFAULTED_TO_SAME_ORIGIN_BY_COEP_AND_DIP = "corp-not-same-origin-after-defaulted-to-same-origin-by-coep-and-dip" CORP_NOT_SAME_SITE = "corp-not-same-site" + SRI_MESSAGE_SIGNATURE_MISMATCH = "sri-message-signature-mismatch" def to_json(self) -> str: return self.value @@ -711,6 +729,7 @@ class CorsError(enum.Enum): PREFLIGHT_MISSING_PRIVATE_NETWORK_ACCESS_NAME = "PreflightMissingPrivateNetworkAccessName" PRIVATE_NETWORK_ACCESS_PERMISSION_UNAVAILABLE = "PrivateNetworkAccessPermissionUnavailable" PRIVATE_NETWORK_ACCESS_PERMISSION_DENIED = "PrivateNetworkAccessPermissionDenied" + LOCAL_NETWORK_ACCESS_PERMISSION_DENIED = "LocalNetworkAccessPermissionDenied" def to_json(self) -> str: return self.value @@ -825,6 +844,55 @@ def from_json(cls, json: str) -> AlternateProtocolUsage: return cls(json) +class ServiceWorkerRouterSource(enum.Enum): + ''' + Source of service worker router. + ''' + NETWORK = "network" + CACHE = "cache" + FETCH_EVENT = "fetch-event" + RACE_NETWORK_AND_FETCH_HANDLER = "race-network-and-fetch-handler" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> ServiceWorkerRouterSource: + return cls(json) + + +@dataclass +class ServiceWorkerRouterInfo: + #: ID of the rule matched. If there is a matched rule, this field will + #: be set, otherwiser no value will be set. + rule_id_matched: typing.Optional[int] = None + + #: The router source of the matched rule. If there is a matched rule, this + #: field will be set, otherwise no value will be set. + matched_source_type: typing.Optional[ServiceWorkerRouterSource] = None + + #: The actual router source used. + actual_source_type: typing.Optional[ServiceWorkerRouterSource] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.rule_id_matched is not None: + json['ruleIdMatched'] = self.rule_id_matched + if self.matched_source_type is not None: + json['matchedSourceType'] = self.matched_source_type.to_json() + if self.actual_source_type is not None: + json['actualSourceType'] = self.actual_source_type.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ServiceWorkerRouterInfo: + return cls( + rule_id_matched=int(json['ruleIdMatched']) if json.get('ruleIdMatched', None) is not None else None, + matched_source_type=ServiceWorkerRouterSource.from_json(json['matchedSourceType']) if json.get('matchedSourceType', None) is not None else None, + actual_source_type=ServiceWorkerRouterSource.from_json(json['actualSourceType']) if json.get('actualSourceType', None) is not None else None, + ) + + @dataclass class Response: ''' @@ -845,6 +913,9 @@ class Response: #: Resource mimeType as determined by the browser. mime_type: str + #: Resource charset as determined by the browser (if applicable). + charset: str + #: Specifies whether physical connection was actually reused for this request. connection_reused: bool @@ -881,6 +952,15 @@ class Response: #: Specifies that the request was served from the prefetch cache. from_prefetch_cache: typing.Optional[bool] = None + #: Specifies that the request was served from the prefetch cache. + from_early_hints: typing.Optional[bool] = None + + #: Information about how ServiceWorker Static Router API was used. If this + #: field is set with ``matchedSourceType`` field, a matching rule is found. + #: If this field is set without ``matchedSource``, no matching rule is found. + #: Otherwise, the API is not used. + service_worker_router_info: typing.Optional[ServiceWorkerRouterInfo] = None + #: Timing information for the given request. timing: typing.Optional[ResourceTiming] = None @@ -909,6 +989,7 @@ def to_json(self) -> T_JSON_DICT: json['statusText'] = self.status_text json['headers'] = self.headers.to_json() json['mimeType'] = self.mime_type + json['charset'] = self.charset json['connectionReused'] = self.connection_reused json['connectionId'] = self.connection_id json['encodedDataLength'] = self.encoded_data_length @@ -929,6 +1010,10 @@ def to_json(self) -> T_JSON_DICT: json['fromServiceWorker'] = self.from_service_worker if self.from_prefetch_cache is not None: json['fromPrefetchCache'] = self.from_prefetch_cache + if self.from_early_hints is not None: + json['fromEarlyHints'] = self.from_early_hints + if self.service_worker_router_info is not None: + json['serviceWorkerRouterInfo'] = self.service_worker_router_info.to_json() if self.timing is not None: json['timing'] = self.timing.to_json() if self.service_worker_response_source is not None: @@ -953,6 +1038,7 @@ def from_json(cls, json: T_JSON_DICT) -> Response: status_text=str(json['statusText']), headers=Headers.from_json(json['headers']), mime_type=str(json['mimeType']), + charset=str(json['charset']), connection_reused=bool(json['connectionReused']), connection_id=float(json['connectionId']), encoded_data_length=float(json['encodedDataLength']), @@ -965,6 +1051,8 @@ def from_json(cls, json: T_JSON_DICT) -> Response: from_disk_cache=bool(json['fromDiskCache']) if json.get('fromDiskCache', None) is not None else None, from_service_worker=bool(json['fromServiceWorker']) if json.get('fromServiceWorker', None) is not None else None, from_prefetch_cache=bool(json['fromPrefetchCache']) if json.get('fromPrefetchCache', None) is not None else None, + from_early_hints=bool(json['fromEarlyHints']) if json.get('fromEarlyHints', None) is not None else None, + service_worker_router_info=ServiceWorkerRouterInfo.from_json(json['serviceWorkerRouterInfo']) if json.get('serviceWorkerRouterInfo', None) is not None else None, timing=ResourceTiming.from_json(json['timing']) if json.get('timing', None) is not None else None, service_worker_response_source=ServiceWorkerResponseSource.from_json(json['serviceWorkerResponseSource']) if json.get('serviceWorkerResponseSource', None) is not None else None, response_time=TimeSinceEpoch.from_json(json['responseTime']) if json.get('responseTime', None) is not None else None, @@ -1120,6 +1208,7 @@ class Initiator: type_: str #: Initiator JavaScript stack trace, set for Script only. + #: Requires the Debugger domain to be enabled. stack: typing.Optional[runtime.StackTrace] = None #: Initiator URL, set for Parser type or for Script type (when script is importing module) or for SignedExchange type. @@ -1163,6 +1252,33 @@ def from_json(cls, json: T_JSON_DICT) -> Initiator: ) +@dataclass +class CookiePartitionKey: + ''' + cookiePartitionKey object + The representation of the components of the key that are created by the cookiePartitionKey class contained in net/cookies/cookie_partition_key.h. + ''' + #: The site of the top-level URL the browser was visiting at the start + #: of the request to the endpoint that set the cookie. + top_level_site: str + + #: Indicates if the cookie has any ancestors that are cross-site to the topLevelSite. + has_cross_site_ancestor: bool + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['topLevelSite'] = self.top_level_site + json['hasCrossSiteAncestor'] = self.has_cross_site_ancestor + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CookiePartitionKey: + return cls( + top_level_site=str(json['topLevelSite']), + has_cross_site_ancestor=bool(json['hasCrossSiteAncestor']), + ) + + @dataclass class Cookie: ''' @@ -1212,9 +1328,8 @@ class Cookie: #: Cookie SameSite type. same_site: typing.Optional[CookieSameSite] = None - #: Cookie partition key. The site of the top-level URL the browser was visiting at the start - #: of the request to the endpoint that set the cookie. - partition_key: typing.Optional[str] = None + #: Cookie partition key. + partition_key: typing.Optional[CookiePartitionKey] = None #: True if cookie partition key is opaque. partition_key_opaque: typing.Optional[bool] = None @@ -1238,7 +1353,7 @@ def to_json(self) -> T_JSON_DICT: if self.same_site is not None: json['sameSite'] = self.same_site.to_json() if self.partition_key is not None: - json['partitionKey'] = self.partition_key + json['partitionKey'] = self.partition_key.to_json() if self.partition_key_opaque is not None: json['partitionKeyOpaque'] = self.partition_key_opaque return json @@ -1260,7 +1375,7 @@ def from_json(cls, json: T_JSON_DICT) -> Cookie: source_port=int(json['sourcePort']), expires=float(json['expires']) if json.get('expires', None) is not None else None, same_site=CookieSameSite.from_json(json['sameSite']) if json.get('sameSite', None) is not None else None, - partition_key=str(json['partitionKey']) if json.get('partitionKey', None) is not None else None, + partition_key=CookiePartitionKey.from_json(json['partitionKey']) if json.get('partitionKey', None) is not None else None, partition_key_opaque=bool(json['partitionKeyOpaque']) if json.get('partitionKeyOpaque', None) is not None else None, ) @@ -1275,6 +1390,7 @@ class SetCookieBlockedReason(enum.Enum): SAME_SITE_UNSPECIFIED_TREATED_AS_LAX = "SameSiteUnspecifiedTreatedAsLax" SAME_SITE_NONE_INSECURE = "SameSiteNoneInsecure" USER_PREFERENCES = "UserPreferences" + THIRD_PARTY_PHASEOUT = "ThirdPartyPhaseout" THIRD_PARTY_BLOCKED_IN_FIRST_PARTY_SET = "ThirdPartyBlockedInFirstPartySet" SYNTAX_ERROR = "SyntaxError" SCHEME_NOT_SUPPORTED = "SchemeNotSupported" @@ -1289,6 +1405,7 @@ class SetCookieBlockedReason(enum.Enum): SAME_PARTY_CONFLICTS_WITH_OTHER_ATTRIBUTES = "SamePartyConflictsWithOtherAttributes" NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE = "NameValuePairExceedsMaxSize" DISALLOWED_CHARACTER = "DisallowedCharacter" + NO_COOKIE_CONTENT = "NoCookieContent" def to_json(self) -> str: return self.value @@ -1310,6 +1427,7 @@ class CookieBlockedReason(enum.Enum): SAME_SITE_UNSPECIFIED_TREATED_AS_LAX = "SameSiteUnspecifiedTreatedAsLax" SAME_SITE_NONE_INSECURE = "SameSiteNoneInsecure" USER_PREFERENCES = "UserPreferences" + THIRD_PARTY_PHASEOUT = "ThirdPartyPhaseout" THIRD_PARTY_BLOCKED_IN_FIRST_PARTY_SET = "ThirdPartyBlockedInFirstPartySet" UNKNOWN_ERROR = "UnknownError" SCHEMEFUL_SAME_SITE_STRICT = "SchemefulSameSiteStrict" @@ -1317,6 +1435,8 @@ class CookieBlockedReason(enum.Enum): SCHEMEFUL_SAME_SITE_UNSPECIFIED_TREATED_AS_LAX = "SchemefulSameSiteUnspecifiedTreatedAsLax" SAME_PARTY_FROM_CROSS_PARTY_CONTEXT = "SamePartyFromCrossPartyContext" NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE = "NameValuePairExceedsMaxSize" + PORT_MISMATCH = "PortMismatch" + SCHEME_MISMATCH = "SchemeMismatch" def to_json(self) -> str: return self.value @@ -1326,6 +1446,30 @@ def from_json(cls, json: str) -> CookieBlockedReason: return cls(json) +class CookieExemptionReason(enum.Enum): + ''' + Types of reasons why a cookie should have been blocked by 3PCD but is exempted for the request. + ''' + NONE = "None" + USER_SETTING = "UserSetting" + TPCD_METADATA = "TPCDMetadata" + TPCD_DEPRECATION_TRIAL = "TPCDDeprecationTrial" + TOP_LEVEL_TPCD_DEPRECATION_TRIAL = "TopLevelTPCDDeprecationTrial" + TPCD_HEURISTICS = "TPCDHeuristics" + ENTERPRISE_POLICY = "EnterprisePolicy" + STORAGE_ACCESS = "StorageAccess" + TOP_LEVEL_STORAGE_ACCESS = "TopLevelStorageAccess" + SCHEME = "Scheme" + SAME_SITE_NONE_COOKIES_IN_SANDBOX = "SameSiteNoneCookiesInSandbox" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> CookieExemptionReason: + return cls(json) + + @dataclass class BlockedSetCookieWithReason: ''' @@ -1361,27 +1505,66 @@ def from_json(cls, json: T_JSON_DICT) -> BlockedSetCookieWithReason: @dataclass -class BlockedCookieWithReason: +class ExemptedSetCookieWithReason: ''' - A cookie with was not sent with a request with the corresponding reason. + A cookie should have been blocked by 3PCD but is exempted and stored from a response with the + corresponding reason. A cookie could only have at most one exemption reason. ''' - #: The reason(s) the cookie was blocked. - blocked_reasons: typing.List[CookieBlockedReason] + #: The reason the cookie was exempted. + exemption_reason: CookieExemptionReason + + #: The string representing this individual cookie as it would appear in the header. + cookie_line: str + #: The cookie object representing the cookie. + cookie: Cookie + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['exemptionReason'] = self.exemption_reason.to_json() + json['cookieLine'] = self.cookie_line + json['cookie'] = self.cookie.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ExemptedSetCookieWithReason: + return cls( + exemption_reason=CookieExemptionReason.from_json(json['exemptionReason']), + cookie_line=str(json['cookieLine']), + cookie=Cookie.from_json(json['cookie']), + ) + + +@dataclass +class AssociatedCookie: + ''' + A cookie associated with the request which may or may not be sent with it. + Includes the cookies itself and reasons for blocking or exemption. + ''' #: The cookie object representing the cookie which was not sent. cookie: Cookie + #: The reason(s) the cookie was blocked. If empty means the cookie is included. + blocked_reasons: typing.List[CookieBlockedReason] + + #: The reason the cookie should have been blocked by 3PCD but is exempted. A cookie could + #: only have at most one exemption reason. + exemption_reason: typing.Optional[CookieExemptionReason] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() - json['blockedReasons'] = [i.to_json() for i in self.blocked_reasons] json['cookie'] = self.cookie.to_json() + json['blockedReasons'] = [i.to_json() for i in self.blocked_reasons] + if self.exemption_reason is not None: + json['exemptionReason'] = self.exemption_reason.to_json() return json @classmethod - def from_json(cls, json: T_JSON_DICT) -> BlockedCookieWithReason: + def from_json(cls, json: T_JSON_DICT) -> AssociatedCookie: return cls( - blocked_reasons=[CookieBlockedReason.from_json(i) for i in json['blockedReasons']], cookie=Cookie.from_json(json['cookie']), + blocked_reasons=[CookieBlockedReason.from_json(i) for i in json['blockedReasons']], + exemption_reason=CookieExemptionReason.from_json(json['exemptionReason']) if json.get('exemptionReason', None) is not None else None, ) @@ -1432,10 +1615,8 @@ class CookieParam: #: This is a temporary ability and it will be removed in the future. source_port: typing.Optional[int] = None - #: Cookie partition key. The site of the top-level URL the browser was visiting at the start - #: of the request to the endpoint that set the cookie. - #: If not set, the cookie will be set as not partitioned. - partition_key: typing.Optional[str] = None + #: Cookie partition key. If not set, the cookie will be set as not partitioned. + partition_key: typing.Optional[CookiePartitionKey] = None def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() @@ -1464,7 +1645,7 @@ def to_json(self) -> T_JSON_DICT: if self.source_port is not None: json['sourcePort'] = self.source_port if self.partition_key is not None: - json['partitionKey'] = self.partition_key + json['partitionKey'] = self.partition_key.to_json() return json @classmethod @@ -1483,7 +1664,7 @@ def from_json(cls, json: T_JSON_DICT) -> CookieParam: same_party=bool(json['sameParty']) if json.get('sameParty', None) is not None else None, source_scheme=CookieSourceScheme.from_json(json['sourceScheme']) if json.get('sourceScheme', None) is not None else None, source_port=int(json['sourcePort']) if json.get('sourcePort', None) is not None else None, - partition_key=str(json['partitionKey']) if json.get('partitionKey', None) is not None else None, + partition_key=CookiePartitionKey.from_json(json['partitionKey']) if json.get('partitionKey', None) is not None else None, ) @@ -1779,7 +1960,7 @@ class SignedExchangeInfo: #: Security details for the signed exchange header. security_details: typing.Optional[SecurityDetails] = None - #: Errors occurred while handling the signed exchagne. + #: Errors occurred while handling the signed exchange. errors: typing.Optional[typing.List[SignedExchangeError]] = None def to_json(self) -> T_JSON_DICT: @@ -1820,12 +2001,65 @@ def from_json(cls, json: str) -> ContentEncoding: return cls(json) +class DirectSocketDnsQueryType(enum.Enum): + IPV4 = "ipv4" + IPV6 = "ipv6" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> DirectSocketDnsQueryType: + return cls(json) + + +@dataclass +class DirectTCPSocketOptions: + #: TCP_NODELAY option + no_delay: bool + + #: Expected to be unsigned integer. + keep_alive_delay: typing.Optional[float] = None + + #: Expected to be unsigned integer. + send_buffer_size: typing.Optional[float] = None + + #: Expected to be unsigned integer. + receive_buffer_size: typing.Optional[float] = None + + dns_query_type: typing.Optional[DirectSocketDnsQueryType] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['noDelay'] = self.no_delay + if self.keep_alive_delay is not None: + json['keepAliveDelay'] = self.keep_alive_delay + if self.send_buffer_size is not None: + json['sendBufferSize'] = self.send_buffer_size + if self.receive_buffer_size is not None: + json['receiveBufferSize'] = self.receive_buffer_size + if self.dns_query_type is not None: + json['dnsQueryType'] = self.dns_query_type.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> DirectTCPSocketOptions: + return cls( + no_delay=bool(json['noDelay']), + keep_alive_delay=float(json['keepAliveDelay']) if json.get('keepAliveDelay', None) is not None else None, + send_buffer_size=float(json['sendBufferSize']) if json.get('sendBufferSize', None) is not None else None, + receive_buffer_size=float(json['receiveBufferSize']) if json.get('receiveBufferSize', None) is not None else None, + dns_query_type=DirectSocketDnsQueryType.from_json(json['dnsQueryType']) if json.get('dnsQueryType', None) is not None else None, + ) + + class PrivateNetworkRequestPolicy(enum.Enum): ALLOW = "Allow" BLOCK_FROM_INSECURE_TO_MORE_PRIVATE = "BlockFromInsecureToMorePrivate" WARN_FROM_INSECURE_TO_MORE_PRIVATE = "WarnFromInsecureToMorePrivate" PREFLIGHT_BLOCK = "PreflightBlock" PREFLIGHT_WARN = "PreflightWarn" + PERMISSION_BLOCK = "PermissionBlock" def to_json(self) -> str: return self.value @@ -1899,6 +2133,7 @@ class CrossOriginOpenerPolicyValue(enum.Enum): UNSAFE_NONE = "UnsafeNone" SAME_ORIGIN_PLUS_COEP = "SameOriginPlusCoep" RESTRICT_PROPERTIES_PLUS_COEP = "RestrictPropertiesPlusCoep" + NOOPENER_ALLOW_POPUPS = "NoopenerAllowPopups" def to_json(self) -> str: return self.value @@ -2380,15 +2615,17 @@ def delete_cookies( name: str, url: typing.Optional[str] = None, domain: typing.Optional[str] = None, - path: typing.Optional[str] = None + path: typing.Optional[str] = None, + partition_key: typing.Optional[CookiePartitionKey] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' - Deletes browser cookies with matching name and url or domain/path pair. + Deletes browser cookies with matching name and url or domain/path/partitionKey pair. :param name: Name of the cookies to remove. :param url: *(Optional)* If specified, deletes all the cookies with the given name where domain and path match provided URL. :param domain: *(Optional)* If specified, deletes only cookies with the exact domain. :param path: *(Optional)* If specified, deletes only cookies with the exact path. + :param partition_key: **(EXPERIMENTAL)** *(Optional)* If specified, deletes only cookies with the the given name and partitionKey where all partition key attributes match the cookie partition key attribute. ''' params: T_JSON_DICT = dict() params['name'] = name @@ -2398,6 +2635,8 @@ def delete_cookies( params['domain'] = domain if path is not None: params['path'] = path + if partition_key is not None: + params['partitionKey'] = partition_key.to_json() cmd_dict: T_JSON_DICT = { 'method': 'Network.deleteCookies', 'params': params, @@ -2420,7 +2659,10 @@ def emulate_network_conditions( latency: float, download_throughput: float, upload_throughput: float, - connection_type: typing.Optional[ConnectionType] = None + connection_type: typing.Optional[ConnectionType] = None, + packet_loss: typing.Optional[float] = None, + packet_queue_length: typing.Optional[int] = None, + packet_reordering: typing.Optional[bool] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Activates emulation of network conditions. @@ -2430,6 +2672,9 @@ def emulate_network_conditions( :param download_throughput: Maximal aggregated download throughput (bytes/sec). -1 disables download throttling. :param upload_throughput: Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling. :param connection_type: *(Optional)* Connection type if known. + :param packet_loss: **(EXPERIMENTAL)** *(Optional)* WebRTC packet loss (percent, 0-100). 0 disables packet loss emulation, 100 drops all the packets. + :param packet_queue_length: **(EXPERIMENTAL)** *(Optional)* WebRTC packet queue length (packet). 0 removes any queue length limitations. + :param packet_reordering: **(EXPERIMENTAL)** *(Optional)* WebRTC packetReordering feature. ''' params: T_JSON_DICT = dict() params['offline'] = offline @@ -2438,6 +2683,12 @@ def emulate_network_conditions( params['uploadThroughput'] = upload_throughput if connection_type is not None: params['connectionType'] = connection_type.to_json() + if packet_loss is not None: + params['packetLoss'] = packet_loss + if packet_queue_length is not None: + params['packetQueueLength'] = packet_queue_length + if packet_reordering is not None: + params['packetReordering'] = packet_reordering cmd_dict: T_JSON_DICT = { 'method': 'Network.emulateNetworkConditions', 'params': params, @@ -2704,8 +2955,6 @@ def set_bypass_service_worker( ''' Toggles ignoring of service worker for each request. - **EXPERIMENTAL** - :param bypass: Bypass service worker and load from network. ''' params: T_JSON_DICT = dict() @@ -2748,7 +2997,7 @@ def set_cookie( same_party: typing.Optional[bool] = None, source_scheme: typing.Optional[CookieSourceScheme] = None, source_port: typing.Optional[int] = None, - partition_key: typing.Optional[str] = None + partition_key: typing.Optional[CookiePartitionKey] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,bool]: ''' Sets a cookie with the given cookie data; may overwrite equivalent cookies if they exist. @@ -2766,7 +3015,7 @@ def set_cookie( :param same_party: **(EXPERIMENTAL)** *(Optional)* True if cookie is SameParty. :param source_scheme: **(EXPERIMENTAL)** *(Optional)* Cookie source scheme type. :param source_port: **(EXPERIMENTAL)** *(Optional)* Cookie source port. Valid values are {-1, [1, 65535]}, -1 indicates an unspecified port. An unspecified port value allows protocol clients to emulate legacy cookie scope for the port. This is a temporary ability and it will be removed in the future. - :param partition_key: **(EXPERIMENTAL)** *(Optional)* Cookie partition key. The site of the top-level URL the browser was visiting at the start of the request to the endpoint that set the cookie. If not set, the cookie will be set as not partitioned. + :param partition_key: **(EXPERIMENTAL)** *(Optional)* Cookie partition key. If not set, the cookie will be set as not partitioned. :returns: Always set to true. If an error occurs, the response indicates protocol error. ''' params: T_JSON_DICT = dict() @@ -2795,7 +3044,7 @@ def set_cookie( if source_port is not None: params['sourcePort'] = source_port if partition_key is not None: - params['partitionKey'] = partition_key + params['partitionKey'] = partition_key.to_json() cmd_dict: T_JSON_DICT = { 'method': 'Network.setCookie', 'params': params, @@ -2890,7 +3139,7 @@ def set_user_agent_override( Allows overriding user agent with the given string. :param user_agent: User agent to use. - :param accept_language: *(Optional)* Browser langugage to emulate. + :param accept_language: *(Optional)* Browser language to emulate. :param platform: *(Optional)* The platform navigator.platform should return. :param user_agent_metadata: **(EXPERIMENTAL)** *(Optional)* To be sent in Sec-CH-UA-* headers and returned in navigator.userAgentData ''' @@ -2909,6 +3158,28 @@ def set_user_agent_override( json = yield cmd_dict +def stream_resource_content( + request_id: RequestId + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,str]: + ''' + Enables streaming of the response for the given requestId. + If enabled, the dataReceived event contains the data that was received during streaming. + + **EXPERIMENTAL** + + :param request_id: Identifier of the request to stream. + :returns: Data that has been buffered until streaming is enabled. (Encoded as a base64 string when passed over JSON) + ''' + params: T_JSON_DICT = dict() + params['requestId'] = request_id.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'Network.streamResourceContent', + 'params': params, + } + json = yield cmd_dict + return str(json['bufferedData']) + + def get_security_isolation_status( frame_id: typing.Optional[page.FrameId] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,SecurityIsolationStatus]: @@ -2979,6 +3250,32 @@ def load_network_resource( return LoadNetworkResourcePageResult.from_json(json['resource']) +def set_cookie_controls( + enable_third_party_cookie_restriction: bool, + disable_third_party_cookie_metadata: bool, + disable_third_party_cookie_heuristics: bool + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Sets Controls for third-party cookie access + Page reload is required before the new cookie bahavior will be observed + + **EXPERIMENTAL** + + :param enable_third_party_cookie_restriction: Whether 3pc restriction is enabled. + :param disable_third_party_cookie_metadata: Whether 3pc grace period exception should be enabled; false by default. + :param disable_third_party_cookie_heuristics: Whether 3pc heuristics exceptions should be enabled; false by default. + ''' + params: T_JSON_DICT = dict() + params['enableThirdPartyCookieRestriction'] = enable_third_party_cookie_restriction + params['disableThirdPartyCookieMetadata'] = disable_third_party_cookie_metadata + params['disableThirdPartyCookieHeuristics'] = disable_third_party_cookie_heuristics + cmd_dict: T_JSON_DICT = { + 'method': 'Network.setCookieControls', + 'params': params, + } + json = yield cmd_dict + + @event_class('Network.dataReceived') @dataclass class DataReceived: @@ -2993,6 +3290,8 @@ class DataReceived: data_length: int #: Actual bytes received (might be less than dataLength for compressed encodings). encoded_data_length: int + #: Data that was received. (Encoded as a base64 string when passed over JSON) + data: typing.Optional[str] @classmethod def from_json(cls, json: T_JSON_DICT) -> DataReceived: @@ -3000,7 +3299,8 @@ def from_json(cls, json: T_JSON_DICT) -> DataReceived: request_id=RequestId.from_json(json['requestId']), timestamp=MonotonicTime.from_json(json['timestamp']), data_length=int(json['dataLength']), - encoded_data_length=int(json['encodedDataLength']) + encoded_data_length=int(json['encodedDataLength']), + data=str(json['data']) if json.get('data', None) is not None else None ) @@ -3044,7 +3344,7 @@ class LoadingFailed: timestamp: MonotonicTime #: Resource type. type_: ResourceType - #: User friendly error message. + #: Error message. List of network errors: https://cs.chromium.org/chromium/src/net/base/net_error_list.h error_text: str #: True if loading was canceled. canceled: typing.Optional[bool] @@ -3513,6 +3813,103 @@ def from_json(cls, json: T_JSON_DICT) -> WebTransportClosed: ) +@event_class('Network.directTCPSocketCreated') +@dataclass +class DirectTCPSocketCreated: + ''' + **EXPERIMENTAL** + + Fired upon direct_socket.TCPSocket creation. + ''' + identifier: RequestId + remote_addr: str + #: Unsigned int 16. + remote_port: int + options: DirectTCPSocketOptions + timestamp: MonotonicTime + initiator: typing.Optional[Initiator] + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> DirectTCPSocketCreated: + return cls( + identifier=RequestId.from_json(json['identifier']), + remote_addr=str(json['remoteAddr']), + remote_port=int(json['remotePort']), + options=DirectTCPSocketOptions.from_json(json['options']), + timestamp=MonotonicTime.from_json(json['timestamp']), + initiator=Initiator.from_json(json['initiator']) if json.get('initiator', None) is not None else None + ) + + +@event_class('Network.directTCPSocketOpened') +@dataclass +class DirectTCPSocketOpened: + ''' + **EXPERIMENTAL** + + Fired when direct_socket.TCPSocket connection is opened. + ''' + identifier: RequestId + remote_addr: str + #: Expected to be unsigned integer. + remote_port: int + timestamp: MonotonicTime + local_addr: typing.Optional[str] + #: Expected to be unsigned integer. + local_port: typing.Optional[int] + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> DirectTCPSocketOpened: + return cls( + identifier=RequestId.from_json(json['identifier']), + remote_addr=str(json['remoteAddr']), + remote_port=int(json['remotePort']), + timestamp=MonotonicTime.from_json(json['timestamp']), + local_addr=str(json['localAddr']) if json.get('localAddr', None) is not None else None, + local_port=int(json['localPort']) if json.get('localPort', None) is not None else None + ) + + +@event_class('Network.directTCPSocketAborted') +@dataclass +class DirectTCPSocketAborted: + ''' + **EXPERIMENTAL** + + Fired when direct_socket.TCPSocket is aborted. + ''' + identifier: RequestId + error_message: str + timestamp: MonotonicTime + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> DirectTCPSocketAborted: + return cls( + identifier=RequestId.from_json(json['identifier']), + error_message=str(json['errorMessage']), + timestamp=MonotonicTime.from_json(json['timestamp']) + ) + + +@event_class('Network.directTCPSocketClosed') +@dataclass +class DirectTCPSocketClosed: + ''' + **EXPERIMENTAL** + + Fired when direct_socket.TCPSocket is closed. + ''' + identifier: RequestId + timestamp: MonotonicTime + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> DirectTCPSocketClosed: + return cls( + identifier=RequestId.from_json(json['identifier']), + timestamp=MonotonicTime.from_json(json['timestamp']) + ) + + @event_class('Network.requestWillBeSentExtraInfo') @dataclass class RequestWillBeSentExtraInfo: @@ -3527,8 +3924,8 @@ class RequestWillBeSentExtraInfo: #: Request identifier. Used to match this information to an existing requestWillBeSent event. request_id: RequestId #: A list of cookies potentially associated to the requested URL. This includes both cookies sent with - #: the request and the ones not sent; the latter are distinguished by having blockedReason field set. - associated_cookies: typing.List[BlockedCookieWithReason] + #: the request and the ones not sent; the latter are distinguished by having blockedReasons field set. + associated_cookies: typing.List[AssociatedCookie] #: Raw request headers as they will be sent over the wire. headers: Headers #: Connection timing information for the request. @@ -3542,7 +3939,7 @@ class RequestWillBeSentExtraInfo: def from_json(cls, json: T_JSON_DICT) -> RequestWillBeSentExtraInfo: return cls( request_id=RequestId.from_json(json['requestId']), - associated_cookies=[BlockedCookieWithReason.from_json(i) for i in json['associatedCookies']], + associated_cookies=[AssociatedCookie.from_json(i) for i in json['associatedCookies']], headers=Headers.from_json(json['headers']), connect_timing=ConnectTiming.from_json(json['connectTiming']), client_security_state=ClientSecurityState.from_json(json['clientSecurityState']) if json.get('clientSecurityState', None) is not None else None, @@ -3567,6 +3964,9 @@ class ResponseReceivedExtraInfo: #: are represented by the invalid cookie line string instead of a proper cookie. blocked_cookies: typing.List[BlockedSetCookieWithReason] #: Raw response headers as they were received over the wire. + #: Duplicate headers in the response are represented as a single key with their values + #: concatentated using ``\n`` as the separator. + #: See also ``headersText`` that contains verbatim text for HTTP/1.*. headers: Headers #: The IP address space of the resource. The address space can only be determined once the transport #: established the connection, so we can't send it in ``requestWillBeSentExtraInfo``. @@ -3580,9 +3980,12 @@ class ResponseReceivedExtraInfo: headers_text: typing.Optional[str] #: The cookie partition key that will be used to store partitioned cookies set in this response. #: Only sent when partitioned cookies are enabled. - cookie_partition_key: typing.Optional[str] - #: True if partitioned cookies are enabled, but the partition key is not serializeable to string. + cookie_partition_key: typing.Optional[CookiePartitionKey] + #: True if partitioned cookies are enabled, but the partition key is not serializable to string. cookie_partition_key_opaque: typing.Optional[bool] + #: A list of cookies which should have been blocked by 3PCD but are exempted and stored from + #: the response with the corresponding reason. + exempted_cookies: typing.Optional[typing.List[ExemptedSetCookieWithReason]] @classmethod def from_json(cls, json: T_JSON_DICT) -> ResponseReceivedExtraInfo: @@ -3593,8 +3996,35 @@ def from_json(cls, json: T_JSON_DICT) -> ResponseReceivedExtraInfo: resource_ip_address_space=IPAddressSpace.from_json(json['resourceIPAddressSpace']), status_code=int(json['statusCode']), headers_text=str(json['headersText']) if json.get('headersText', None) is not None else None, - cookie_partition_key=str(json['cookiePartitionKey']) if json.get('cookiePartitionKey', None) is not None else None, - cookie_partition_key_opaque=bool(json['cookiePartitionKeyOpaque']) if json.get('cookiePartitionKeyOpaque', None) is not None else None + cookie_partition_key=CookiePartitionKey.from_json(json['cookiePartitionKey']) if json.get('cookiePartitionKey', None) is not None else None, + cookie_partition_key_opaque=bool(json['cookiePartitionKeyOpaque']) if json.get('cookiePartitionKeyOpaque', None) is not None else None, + exempted_cookies=[ExemptedSetCookieWithReason.from_json(i) for i in json['exemptedCookies']] if json.get('exemptedCookies', None) is not None else None + ) + + +@event_class('Network.responseReceivedEarlyHints') +@dataclass +class ResponseReceivedEarlyHints: + ''' + **EXPERIMENTAL** + + Fired when 103 Early Hints headers is received in addition to the common response. + Not every responseReceived event will have an responseReceivedEarlyHints fired. + Only one responseReceivedEarlyHints may be fired for eached responseReceived event. + ''' + #: Request identifier. Used to match this information to another responseReceived event. + request_id: RequestId + #: Raw response headers as they were received over the wire. + #: Duplicate headers in the response are represented as a single key with their values + #: concatentated using ``\n`` as the separator. + #: See also ``headersText`` that contains verbatim text for HTTP/1.*. + headers: Headers + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ResponseReceivedEarlyHints: + return cls( + request_id=RequestId.from_json(json['requestId']), + headers=Headers.from_json(json['headers']) ) @@ -3635,6 +4065,23 @@ def from_json(cls, json: T_JSON_DICT) -> TrustTokenOperationDone: ) +@event_class('Network.policyUpdated') +@dataclass +class PolicyUpdated: + ''' + **EXPERIMENTAL** + + Fired once security policy has been updated. + ''' + + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> PolicyUpdated: + return cls( + + ) + + @event_class('Network.subresourceWebBundleMetadataReceived') @dataclass class SubresourceWebBundleMetadataReceived: diff --git a/pycdp/cdp/overlay.py b/pycdp/cdp/overlay.py index dad0e6a..11cf041 100644 --- a/pycdp/cdp/overlay.py +++ b/pycdp/cdp/overlay.py @@ -22,7 +22,7 @@ class SourceOrderConfig: ''' Configuration data for drawing the source order of an elements children. ''' - #: the color to outline the givent element in. + #: the color to outline the given element in. parent_outline_color: dom.RGBA #: the color to outline the child elements in. @@ -620,6 +620,36 @@ def from_json(cls, json: T_JSON_DICT) -> HingeConfig: ) +@dataclass +class WindowControlsOverlayConfig: + ''' + Configuration for Window Controls Overlay + ''' + #: Whether the title bar CSS should be shown when emulating the Window Controls Overlay. + show_css: bool + + #: Selected platforms to show the overlay. + selected_platform: str + + #: The theme color defined in app manifest. + theme_color: str + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['showCSS'] = self.show_css + json['selectedPlatform'] = self.selected_platform + json['themeColor'] = self.theme_color + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> WindowControlsOverlayConfig: + return cls( + show_css=bool(json['showCSS']), + selected_platform=str(json['selectedPlatform']), + theme_color=str(json['themeColor']), + ) + + @dataclass class ContainerQueryHighlightConfig: #: A descriptor for the highlight appearance of container query containers. @@ -844,8 +874,8 @@ def highlight_frame( ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Highlights owner element of the frame with given id. - Deprecated: Doesn't work reliablity and cannot be fixed due to process - separatation (the owner node might be in a different process). Determine + Deprecated: Doesn't work reliably and cannot be fixed due to process + separation (the owner node might be in a different process). Determine the owner node in the client and use highlightNode. .. deprecated:: 1.3 @@ -1212,11 +1242,14 @@ def set_show_hit_test_borders( json = yield cmd_dict +@deprecated(version="1.3") def set_show_web_vitals( show: bool ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' - Request that backend shows an overlay with web vital metrics. + Deprecated, no longer has any effect. + + .. deprecated:: 1.3 :param show: ''' @@ -1281,6 +1314,24 @@ def set_show_isolated_elements( json = yield cmd_dict +def set_show_window_controls_overlay( + window_controls_overlay_config: typing.Optional[WindowControlsOverlayConfig] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Show Window Controls Overlay for PWA + + :param window_controls_overlay_config: *(Optional)* Window Controls Overlay data, null means hide Window Controls Overlay + ''' + params: T_JSON_DICT = dict() + if window_controls_overlay_config is not None: + params['windowControlsOverlayConfig'] = window_controls_overlay_config.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'Overlay.setShowWindowControlsOverlay', + 'params': params, + } + json = yield cmd_dict + + @event_class('Overlay.inspectNodeRequested') @dataclass class InspectNodeRequested: diff --git a/pycdp/cdp/page.py b/pycdp/cdp/page.py index 8eacfa7..c7375e3 100644 --- a/pycdp/cdp/page.py +++ b/pycdp/cdp/page.py @@ -165,30 +165,34 @@ def from_json(cls, json: str) -> GatedAPIFeatures: class PermissionsPolicyFeature(enum.Enum): ''' All Permissions Policy features. This enum should match the one defined - in third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5. + in services/network/public/cpp/permissions_policy/permissions_policy_features.json5. ''' ACCELEROMETER = "accelerometer" + ALL_SCREENS_CAPTURE = "all-screens-capture" AMBIENT_LIGHT_SENSOR = "ambient-light-sensor" ATTRIBUTION_REPORTING = "attribution-reporting" AUTOPLAY = "autoplay" BLUETOOTH = "bluetooth" BROWSING_TOPICS = "browsing-topics" CAMERA = "camera" + CAPTURED_SURFACE_CONTROL = "captured-surface-control" CH_DPR = "ch-dpr" CH_DEVICE_MEMORY = "ch-device-memory" CH_DOWNLINK = "ch-downlink" CH_ECT = "ch-ect" CH_PREFERS_COLOR_SCHEME = "ch-prefers-color-scheme" CH_PREFERS_REDUCED_MOTION = "ch-prefers-reduced-motion" + CH_PREFERS_REDUCED_TRANSPARENCY = "ch-prefers-reduced-transparency" CH_RTT = "ch-rtt" CH_SAVE_DATA = "ch-save-data" CH_UA = "ch-ua" CH_UA_ARCH = "ch-ua-arch" CH_UA_BITNESS = "ch-ua-bitness" + CH_UA_HIGH_ENTROPY_VALUES = "ch-ua-high-entropy-values" CH_UA_PLATFORM = "ch-ua-platform" CH_UA_MODEL = "ch-ua-model" CH_UA_MOBILE = "ch-ua-mobile" - CH_UA_FORM_FACTOR = "ch-ua-form-factor" + CH_UA_FORM_FACTORS = "ch-ua-form-factors" CH_UA_FULL_VERSION = "ch-ua-full-version" CH_UA_FULL_VERSION_LIST = "ch-ua-full-version-list" CH_UA_PLATFORM_VERSION = "ch-ua-platform-version" @@ -199,13 +203,19 @@ class PermissionsPolicyFeature(enum.Enum): CLIPBOARD_READ = "clipboard-read" CLIPBOARD_WRITE = "clipboard-write" COMPUTE_PRESSURE = "compute-pressure" + CONTROLLED_FRAME = "controlled-frame" CROSS_ORIGIN_ISOLATED = "cross-origin-isolated" + DEFERRED_FETCH = "deferred-fetch" + DEFERRED_FETCH_MINIMAL = "deferred-fetch-minimal" + DIGITAL_CREDENTIALS_GET = "digital-credentials-get" DIRECT_SOCKETS = "direct-sockets" + DIRECT_SOCKETS_PRIVATE = "direct-sockets-private" DISPLAY_CAPTURE = "display-capture" DOCUMENT_DOMAIN = "document-domain" ENCRYPTED_MEDIA = "encrypted-media" EXECUTION_WHILE_OUT_OF_VIEWPORT = "execution-while-out-of-viewport" EXECUTION_WHILE_NOT_RENDERED = "execution-while-not-rendered" + FENCED_UNPARTITIONED_STORAGE_READ = "fenced-unpartitioned-storage-read" FOCUS_WITHOUT_USER_ACTIVATION = "focus-without-user-activation" FULLSCREEN = "fullscreen" FROBULATE = "frobulate" @@ -220,14 +230,17 @@ class PermissionsPolicyFeature(enum.Enum): KEYBOARD_MAP = "keyboard-map" LOCAL_FONTS = "local-fonts" MAGNETOMETER = "magnetometer" + MEDIA_PLAYBACK_WHILE_NOT_VISIBLE = "media-playback-while-not-visible" MICROPHONE = "microphone" MIDI = "midi" OTP_CREDENTIALS = "otp-credentials" PAYMENT = "payment" PICTURE_IN_PICTURE = "picture-in-picture" + POPINS = "popins" PRIVATE_AGGREGATION = "private-aggregation" PRIVATE_STATE_TOKEN_ISSUANCE = "private-state-token-issuance" PRIVATE_STATE_TOKEN_REDEMPTION = "private-state-token-redemption" + PUBLICKEY_CREDENTIALS_CREATE = "publickey-credentials-create" PUBLICKEY_CREDENTIALS_GET = "publickey-credentials-get" RUN_AD_AUCTION = "run-ad-auction" SCREEN_WAKE_LOCK = "screen-wake-lock" @@ -236,14 +249,18 @@ class PermissionsPolicyFeature(enum.Enum): SHARED_STORAGE = "shared-storage" SHARED_STORAGE_SELECT_URL = "shared-storage-select-url" SMART_CARD = "smart-card" + SPEAKER_SELECTION = "speaker-selection" STORAGE_ACCESS = "storage-access" + SUB_APPS = "sub-apps" SYNC_XHR = "sync-xhr" UNLOAD = "unload" USB = "usb" + USB_UNRESTRICTED = "usb-unrestricted" VERTICAL_SCROLL = "vertical-scroll" + WEB_APP_INSTALLATION = "web-app-installation" + WEB_PRINTING = "web-printing" WEB_SHARE = "web-share" WINDOW_MANAGEMENT = "window-management" - WINDOW_PLACEMENT = "window-placement" XR_SPATIAL_TRACKING = "xr-spatial-tracking" def to_json(self) -> str: @@ -458,6 +475,28 @@ def from_json(cls, json: T_JSON_DICT) -> OriginTrial: ) +@dataclass +class SecurityOriginDetails: + ''' + Additional information about the frame document's security origin. + ''' + #: Indicates whether the frame document's security origin is one + #: of the local hostnames (e.g. "localhost") or IP addresses (IPv4 + #: 127.0.0.0/8 or IPv6 ::1). + is_localhost: bool + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['isLocalhost'] = self.is_localhost + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> SecurityOriginDetails: + return cls( + is_localhost=bool(json['isLocalhost']), + ) + + @dataclass class Frame: ''' @@ -502,6 +541,9 @@ class Frame: #: Frame document's URL fragment including the '#'. url_fragment: typing.Optional[str] = None + #: Additional details about the frame document's security origin. + security_origin_details: typing.Optional[SecurityOriginDetails] = None + #: If the frame failed to load, this contains the URL that could not be loaded. Note that unlike url above, this URL may contain a fragment. unreachable_url: typing.Optional[str] = None @@ -525,6 +567,8 @@ def to_json(self) -> T_JSON_DICT: json['name'] = self.name if self.url_fragment is not None: json['urlFragment'] = self.url_fragment + if self.security_origin_details is not None: + json['securityOriginDetails'] = self.security_origin_details.to_json() if self.unreachable_url is not None: json['unreachableUrl'] = self.unreachable_url if self.ad_frame_status is not None: @@ -546,6 +590,7 @@ def from_json(cls, json: T_JSON_DICT) -> Frame: parent_id=FrameId.from_json(json['parentId']) if json.get('parentId', None) is not None else None, name=str(json['name']) if json.get('name', None) is not None else None, url_fragment=str(json['urlFragment']) if json.get('urlFragment', None) is not None else None, + security_origin_details=SecurityOriginDetails.from_json(json['securityOriginDetails']) if json.get('securityOriginDetails', None) is not None else None, unreachable_url=str(json['unreachableUrl']) if json.get('unreachableUrl', None) is not None else None, ad_frame_status=AdFrameStatus.from_json(json['adFrameStatus']) if json.get('adFrameStatus', None) is not None else None, ) @@ -819,7 +864,7 @@ class AppManifestError: #: Error message. message: str - #: If criticial, this is a non-recoverable parse error. + #: If critical, this is a non-recoverable parse error. critical: int #: Error line. @@ -1107,14 +1152,16 @@ def from_json(cls, json: T_JSON_DICT) -> FontSizes: class ClientNavigationReason(enum.Enum): + ANCHOR_CLICK = "anchorClick" FORM_SUBMISSION_GET = "formSubmissionGet" FORM_SUBMISSION_POST = "formSubmissionPost" HTTP_HEADER_REFRESH = "httpHeaderRefresh" - SCRIPT_INITIATED = "scriptInitiated" + INITIAL_FRAME_NAVIGATION = "initialFrameNavigation" META_TAG_REFRESH = "metaTagRefresh" + OTHER = "other" PAGE_BLOCK_INTERSTITIAL = "pageBlockInterstitial" RELOAD = "reload" - ANCHOR_CLICK = "anchorClick" + SCRIPT_INITIATED = "scriptInitiated" def to_json(self) -> str: return self.value @@ -1233,9 +1280,405 @@ def from_json(cls, json: T_JSON_DICT) -> CompilationCacheParams: ) +@dataclass +class FileFilter: + name: typing.Optional[str] = None + + accepts: typing.Optional[typing.List[str]] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.name is not None: + json['name'] = self.name + if self.accepts is not None: + json['accepts'] = [i for i in self.accepts] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> FileFilter: + return cls( + name=str(json['name']) if json.get('name', None) is not None else None, + accepts=[str(i) for i in json['accepts']] if json.get('accepts', None) is not None else None, + ) + + +@dataclass +class FileHandler: + action: str + + name: str + + #: Won't repeat the enums, using string for easy comparison. Same as the + #: other enums below. + launch_type: str + + icons: typing.Optional[typing.List[ImageResource]] = None + + #: Mimic a map, name is the key, accepts is the value. + accepts: typing.Optional[typing.List[FileFilter]] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['action'] = self.action + json['name'] = self.name + json['launchType'] = self.launch_type + if self.icons is not None: + json['icons'] = [i.to_json() for i in self.icons] + if self.accepts is not None: + json['accepts'] = [i.to_json() for i in self.accepts] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> FileHandler: + return cls( + action=str(json['action']), + name=str(json['name']), + launch_type=str(json['launchType']), + icons=[ImageResource.from_json(i) for i in json['icons']] if json.get('icons', None) is not None else None, + accepts=[FileFilter.from_json(i) for i in json['accepts']] if json.get('accepts', None) is not None else None, + ) + + +@dataclass +class ImageResource: + ''' + The image definition used in both icon and screenshot. + ''' + #: The src field in the definition, but changing to url in favor of + #: consistency. + url: str + + sizes: typing.Optional[str] = None + + type_: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['url'] = self.url + if self.sizes is not None: + json['sizes'] = self.sizes + if self.type_ is not None: + json['type'] = self.type_ + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ImageResource: + return cls( + url=str(json['url']), + sizes=str(json['sizes']) if json.get('sizes', None) is not None else None, + type_=str(json['type']) if json.get('type', None) is not None else None, + ) + + +@dataclass +class LaunchHandler: + client_mode: str + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['clientMode'] = self.client_mode + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> LaunchHandler: + return cls( + client_mode=str(json['clientMode']), + ) + + +@dataclass +class ProtocolHandler: + protocol: str + + url: str + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['protocol'] = self.protocol + json['url'] = self.url + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ProtocolHandler: + return cls( + protocol=str(json['protocol']), + url=str(json['url']), + ) + + +@dataclass +class RelatedApplication: + url: str + + id_: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['url'] = self.url + if self.id_ is not None: + json['id'] = self.id_ + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> RelatedApplication: + return cls( + url=str(json['url']), + id_=str(json['id']) if json.get('id', None) is not None else None, + ) + + +@dataclass +class ScopeExtension: + #: Instead of using tuple, this field always returns the serialized string + #: for easy understanding and comparison. + origin: str + + has_origin_wildcard: bool + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['origin'] = self.origin + json['hasOriginWildcard'] = self.has_origin_wildcard + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ScopeExtension: + return cls( + origin=str(json['origin']), + has_origin_wildcard=bool(json['hasOriginWildcard']), + ) + + +@dataclass +class Screenshot: + image: ImageResource + + form_factor: str + + label: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['image'] = self.image.to_json() + json['formFactor'] = self.form_factor + if self.label is not None: + json['label'] = self.label + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> Screenshot: + return cls( + image=ImageResource.from_json(json['image']), + form_factor=str(json['formFactor']), + label=str(json['label']) if json.get('label', None) is not None else None, + ) + + +@dataclass +class ShareTarget: + action: str + + method: str + + enctype: str + + #: Embed the ShareTargetParams + title: typing.Optional[str] = None + + text: typing.Optional[str] = None + + url: typing.Optional[str] = None + + files: typing.Optional[typing.List[FileFilter]] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['action'] = self.action + json['method'] = self.method + json['enctype'] = self.enctype + if self.title is not None: + json['title'] = self.title + if self.text is not None: + json['text'] = self.text + if self.url is not None: + json['url'] = self.url + if self.files is not None: + json['files'] = [i.to_json() for i in self.files] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> ShareTarget: + return cls( + action=str(json['action']), + method=str(json['method']), + enctype=str(json['enctype']), + title=str(json['title']) if json.get('title', None) is not None else None, + text=str(json['text']) if json.get('text', None) is not None else None, + url=str(json['url']) if json.get('url', None) is not None else None, + files=[FileFilter.from_json(i) for i in json['files']] if json.get('files', None) is not None else None, + ) + + +@dataclass +class Shortcut: + name: str + + url: str + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['name'] = self.name + json['url'] = self.url + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> Shortcut: + return cls( + name=str(json['name']), + url=str(json['url']), + ) + + +@dataclass +class WebAppManifest: + background_color: typing.Optional[str] = None + + #: The extra description provided by the manifest. + description: typing.Optional[str] = None + + dir_: typing.Optional[str] = None + + display: typing.Optional[str] = None + + #: The overrided display mode controlled by the user. + display_overrides: typing.Optional[typing.List[str]] = None + + #: The handlers to open files. + file_handlers: typing.Optional[typing.List[FileHandler]] = None + + icons: typing.Optional[typing.List[ImageResource]] = None + + id_: typing.Optional[str] = None + + lang: typing.Optional[str] = None + + #: TODO(crbug.com/1231886): This field is non-standard and part of a Chrome + #: experiment. See: + #: https://github.com/WICG/web-app-launch/blob/main/launch_handler.md + launch_handler: typing.Optional[LaunchHandler] = None + + name: typing.Optional[str] = None + + orientation: typing.Optional[str] = None + + prefer_related_applications: typing.Optional[bool] = None + + #: The handlers to open protocols. + protocol_handlers: typing.Optional[typing.List[ProtocolHandler]] = None + + related_applications: typing.Optional[typing.List[RelatedApplication]] = None + + scope: typing.Optional[str] = None + + #: Non-standard, see + #: https://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-explainer.md + scope_extensions: typing.Optional[typing.List[ScopeExtension]] = None + + #: The screenshots used by chromium. + screenshots: typing.Optional[typing.List[Screenshot]] = None + + share_target: typing.Optional[ShareTarget] = None + + short_name: typing.Optional[str] = None + + shortcuts: typing.Optional[typing.List[Shortcut]] = None + + start_url: typing.Optional[str] = None + + theme_color: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + if self.background_color is not None: + json['backgroundColor'] = self.background_color + if self.description is not None: + json['description'] = self.description + if self.dir_ is not None: + json['dir'] = self.dir_ + if self.display is not None: + json['display'] = self.display + if self.display_overrides is not None: + json['displayOverrides'] = [i for i in self.display_overrides] + if self.file_handlers is not None: + json['fileHandlers'] = [i.to_json() for i in self.file_handlers] + if self.icons is not None: + json['icons'] = [i.to_json() for i in self.icons] + if self.id_ is not None: + json['id'] = self.id_ + if self.lang is not None: + json['lang'] = self.lang + if self.launch_handler is not None: + json['launchHandler'] = self.launch_handler.to_json() + if self.name is not None: + json['name'] = self.name + if self.orientation is not None: + json['orientation'] = self.orientation + if self.prefer_related_applications is not None: + json['preferRelatedApplications'] = self.prefer_related_applications + if self.protocol_handlers is not None: + json['protocolHandlers'] = [i.to_json() for i in self.protocol_handlers] + if self.related_applications is not None: + json['relatedApplications'] = [i.to_json() for i in self.related_applications] + if self.scope is not None: + json['scope'] = self.scope + if self.scope_extensions is not None: + json['scopeExtensions'] = [i.to_json() for i in self.scope_extensions] + if self.screenshots is not None: + json['screenshots'] = [i.to_json() for i in self.screenshots] + if self.share_target is not None: + json['shareTarget'] = self.share_target.to_json() + if self.short_name is not None: + json['shortName'] = self.short_name + if self.shortcuts is not None: + json['shortcuts'] = [i.to_json() for i in self.shortcuts] + if self.start_url is not None: + json['startUrl'] = self.start_url + if self.theme_color is not None: + json['themeColor'] = self.theme_color + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> WebAppManifest: + return cls( + background_color=str(json['backgroundColor']) if json.get('backgroundColor', None) is not None else None, + description=str(json['description']) if json.get('description', None) is not None else None, + dir_=str(json['dir']) if json.get('dir', None) is not None else None, + display=str(json['display']) if json.get('display', None) is not None else None, + display_overrides=[str(i) for i in json['displayOverrides']] if json.get('displayOverrides', None) is not None else None, + file_handlers=[FileHandler.from_json(i) for i in json['fileHandlers']] if json.get('fileHandlers', None) is not None else None, + icons=[ImageResource.from_json(i) for i in json['icons']] if json.get('icons', None) is not None else None, + id_=str(json['id']) if json.get('id', None) is not None else None, + lang=str(json['lang']) if json.get('lang', None) is not None else None, + launch_handler=LaunchHandler.from_json(json['launchHandler']) if json.get('launchHandler', None) is not None else None, + name=str(json['name']) if json.get('name', None) is not None else None, + orientation=str(json['orientation']) if json.get('orientation', None) is not None else None, + prefer_related_applications=bool(json['preferRelatedApplications']) if json.get('preferRelatedApplications', None) is not None else None, + protocol_handlers=[ProtocolHandler.from_json(i) for i in json['protocolHandlers']] if json.get('protocolHandlers', None) is not None else None, + related_applications=[RelatedApplication.from_json(i) for i in json['relatedApplications']] if json.get('relatedApplications', None) is not None else None, + scope=str(json['scope']) if json.get('scope', None) is not None else None, + scope_extensions=[ScopeExtension.from_json(i) for i in json['scopeExtensions']] if json.get('scopeExtensions', None) is not None else None, + screenshots=[Screenshot.from_json(i) for i in json['screenshots']] if json.get('screenshots', None) is not None else None, + share_target=ShareTarget.from_json(json['shareTarget']) if json.get('shareTarget', None) is not None else None, + short_name=str(json['shortName']) if json.get('shortName', None) is not None else None, + shortcuts=[Shortcut.from_json(i) for i in json['shortcuts']] if json.get('shortcuts', None) is not None else None, + start_url=str(json['startUrl']) if json.get('startUrl', None) is not None else None, + theme_color=str(json['themeColor']) if json.get('themeColor', None) is not None else None, + ) + + class AutoResponseMode(enum.Enum): ''' - Enum of possible auto-reponse for permisison / prompt dialogs. + Enum of possible auto-response for permission / prompt dialogs. ''' NONE = "none" AUTO_ACCEPT = "autoAccept" @@ -1325,6 +1768,12 @@ class BackForwardCacheNotRestoredReason(enum.Enum): COOKIE_DISABLED = "CookieDisabled" HTTP_AUTH_REQUIRED = "HTTPAuthRequired" COOKIE_FLUSHED = "CookieFlushed" + BROADCAST_CHANNEL_ON_MESSAGE = "BroadcastChannelOnMessage" + WEB_VIEW_SETTINGS_CHANGED = "WebViewSettingsChanged" + WEB_VIEW_JAVA_SCRIPT_OBJECT_CHANGED = "WebViewJavaScriptObjectChanged" + WEB_VIEW_MESSAGE_LISTENER_INJECTED = "WebViewMessageListenerInjected" + WEB_VIEW_SAFE_BROWSING_ALLOWLIST_CHANGED = "WebViewSafeBrowsingAllowlistChanged" + WEB_VIEW_DOCUMENT_START_JAVASCRIPT_CHANGED = "WebViewDocumentStartJavascriptChanged" WEB_SOCKET = "WebSocket" WEB_TRANSPORT = "WebTransport" WEB_RTC = "WebRTC" @@ -1334,7 +1783,6 @@ class BackForwardCacheNotRestoredReason(enum.Enum): SUBRESOURCE_HAS_CACHE_CONTROL_NO_CACHE = "SubresourceHasCacheControlNoCache" CONTAINS_PLUGINS = "ContainsPlugins" DOCUMENT_LOADED = "DocumentLoaded" - DEDICATED_WORKER_OR_WORKLET = "DedicatedWorkerOrWorklet" OUTSTANDING_NETWORK_REQUEST_OTHERS = "OutstandingNetworkRequestOthers" REQUESTED_MIDI_PERMISSION = "RequestedMIDIPermission" REQUESTED_AUDIO_CAPTURE_PERMISSION = "RequestedAudioCapturePermission" @@ -1355,7 +1803,6 @@ class BackForwardCacheNotRestoredReason(enum.Enum): PRINTING = "Printing" WEB_DATABASE = "WebDatabase" PICTURE_IN_PICTURE = "PictureInPicture" - PORTAL = "Portal" SPEECH_RECOGNIZER = "SpeechRecognizer" IDLE_MANAGER = "IdleManager" PAYMENT_MANAGER = "PaymentManager" @@ -1372,6 +1819,10 @@ class BackForwardCacheNotRestoredReason(enum.Enum): WEB_RTC_STICKY = "WebRTCSticky" WEB_TRANSPORT_STICKY = "WebTransportSticky" WEB_SOCKET_STICKY = "WebSocketSticky" + SMART_CARD = "SmartCard" + LIVE_MEDIA_STREAM_TRACK = "LiveMediaStreamTrack" + UNLOAD_HANDLER = "UnloadHandler" + PARSER_ABORTED = "ParserAborted" CONTENT_SECURITY_HANDLER = "ContentSecurityHandler" CONTENT_WEB_AUTHENTICATION_API = "ContentWebAuthenticationAPI" CONTENT_FILE_CHOOSER = "ContentFileChooser" @@ -1382,6 +1833,7 @@ class BackForwardCacheNotRestoredReason(enum.Enum): CONTENT_WEB_USB = "ContentWebUSB" CONTENT_MEDIA_SESSION_SERVICE = "ContentMediaSessionService" CONTENT_SCREEN_READER = "ContentScreenReader" + CONTENT_DISCARDED = "ContentDiscarded" EMBEDDER_POPUP_BLOCKER_TAB_HELPER = "EmbedderPopupBlockerTabHelper" EMBEDDER_SAFE_BROWSING_TRIGGERED_POPUP_BLOCKER = "EmbedderSafeBrowsingTriggeredPopupBlocker" EMBEDDER_SAFE_BROWSING_THREAT_DETAILS = "EmbedderSafeBrowsingThreatDetails" @@ -1397,6 +1849,9 @@ class BackForwardCacheNotRestoredReason(enum.Enum): EMBEDDER_EXTENSION_MESSAGING = "EmbedderExtensionMessaging" EMBEDDER_EXTENSION_MESSAGING_FOR_OPEN_PORT = "EmbedderExtensionMessagingForOpenPort" EMBEDDER_EXTENSION_SENT_MESSAGE_TO_CACHED_FRAME = "EmbedderExtensionSentMessageToCachedFrame" + REQUESTED_BY_WEB_VIEW_CLIENT = "RequestedByWebViewClient" + POST_MESSAGE_BY_WEB_VIEW_CLIENT = "PostMessageByWebViewClient" + CACHE_CONTROL_NO_STORE_DEVICE_BOUND_SESSION_TERMINATED = "CacheControlNoStoreDeviceBoundSessionTerminated" def to_json(self) -> str: return self.value @@ -1422,6 +1877,40 @@ def from_json(cls, json: str) -> BackForwardCacheNotRestoredReasonType: return cls(json) +@dataclass +class BackForwardCacheBlockingDetails: + #: Line number in the script (0-based). + line_number: int + + #: Column number in the script (0-based). + column_number: int + + #: Url of the file where blockage happened. Optional because of tests. + url: typing.Optional[str] = None + + #: Function name where blockage happened. Optional because of anonymous functions and tests. + function: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['lineNumber'] = self.line_number + json['columnNumber'] = self.column_number + if self.url is not None: + json['url'] = self.url + if self.function is not None: + json['function'] = self.function + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> BackForwardCacheBlockingDetails: + return cls( + line_number=int(json['lineNumber']), + column_number=int(json['columnNumber']), + url=str(json['url']) if json.get('url', None) is not None else None, + function=str(json['function']) if json.get('function', None) is not None else None, + ) + + @dataclass class BackForwardCacheNotRestoredExplanation: #: Type of the reason @@ -1435,12 +1924,16 @@ class BackForwardCacheNotRestoredExplanation: #: - EmbedderExtensionSentMessageToCachedFrame: the extension ID. context: typing.Optional[str] = None + details: typing.Optional[typing.List[BackForwardCacheBlockingDetails]] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['type'] = self.type_.to_json() json['reason'] = self.reason.to_json() if self.context is not None: json['context'] = self.context + if self.details is not None: + json['details'] = [i.to_json() for i in self.details] return json @classmethod @@ -1449,6 +1942,7 @@ def from_json(cls, json: T_JSON_DICT) -> BackForwardCacheNotRestoredExplanation: type_=BackForwardCacheNotRestoredReasonType.from_json(json['type']), reason=BackForwardCacheNotRestoredReason.from_json(json['reason']), context=str(json['context']) if json.get('context', None) is not None else None, + details=[BackForwardCacheBlockingDetails.from_json(i) for i in json['details']] if json.get('details', None) is not None else None, ) @@ -1712,36 +2206,57 @@ def disable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: json = yield cmd_dict -def enable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: +def enable( + enable_file_chooser_opened_event: typing.Optional[bool] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Enables page domain notifications. + + :param enable_file_chooser_opened_event: **(EXPERIMENTAL)** *(Optional)* If true, the ```Page.fileChooserOpened```` event will be emitted regardless of the state set by ````Page.setInterceptFileChooserDialog``` command (default: false). ''' + params: T_JSON_DICT = dict() + if enable_file_chooser_opened_event is not None: + params['enableFileChooserOpenedEvent'] = enable_file_chooser_opened_event cmd_dict: T_JSON_DICT = { 'method': 'Page.enable', + 'params': params, } json = yield cmd_dict -def get_app_manifest() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[str, typing.List[AppManifestError], typing.Optional[str], typing.Optional[AppManifestParsedProperties]]]: +def get_app_manifest( + manifest_id: typing.Optional[str] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[str, typing.List[AppManifestError], typing.Optional[str], typing.Optional[AppManifestParsedProperties], WebAppManifest]]: ''' + Gets the processed manifest for this current document. + This API always waits for the manifest to be loaded. + If manifestId is provided, and it does not match the manifest of the + current document, this API errors out. + If there is not a loaded page, this API errors out immediately. - + :param manifest_id: *(Optional)* :returns: A tuple with the following items: 0. **url** - Manifest location. 1. **errors** - 2. **data** - *(Optional)* Manifest content. - 3. **parsed** - *(Optional)* Parsed manifest properties + 3. **parsed** - *(Optional)* Parsed manifest properties. Deprecated, use manifest instead. + 4. **manifest** - ''' + params: T_JSON_DICT = dict() + if manifest_id is not None: + params['manifestId'] = manifest_id cmd_dict: T_JSON_DICT = { 'method': 'Page.getAppManifest', + 'params': params, } json = yield cmd_dict return ( str(json['url']), [AppManifestError.from_json(i) for i in json['errors']], str(json['data']) if json.get('data', None) is not None else None, - AppManifestParsedProperties.from_json(json['parsed']) if json.get('parsed', None) is not None else None + AppManifestParsedProperties.from_json(json['parsed']) if json.get('parsed', None) is not None else None, + WebAppManifest.from_json(json['manifest']) ) @@ -1821,26 +2336,6 @@ def get_ad_script_id( return AdScriptId.from_json(json['adScriptId']) if json.get('adScriptId', None) is not None else None -@deprecated(version="1.3") -def get_cookies() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[network.Cookie]]: - ''' - Returns all browser cookies for the page and all of its subframes. Depending - on the backend support, will return detailed cookie information in the - ``cookies`` field. - - .. deprecated:: 1.3 - - **EXPERIMENTAL** - - :returns: Array of cookie objects. - ''' - cmd_dict: T_JSON_DICT = { - 'method': 'Page.getCookies', - } - json = yield cmd_dict - return [network.Cookie.from_json(i) for i in json['cookies']] - - def get_frame_tree() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,FrameTree]: ''' Returns present frame tree structure. @@ -2052,7 +2547,8 @@ def print_to_pdf( footer_template: typing.Optional[str] = None, prefer_css_page_size: typing.Optional[bool] = None, transfer_mode: typing.Optional[str] = None, - generate_tagged_pdf: typing.Optional[bool] = None + generate_tagged_pdf: typing.Optional[bool] = None, + generate_document_outline: typing.Optional[bool] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[str, typing.Optional[io.StreamHandle]]]: ''' Print page as PDF. @@ -2073,6 +2569,7 @@ def print_to_pdf( :param prefer_css_page_size: *(Optional)* Whether or not to prefer page size as defined by css. Defaults to false, in which case the content will be scaled to fit the paper size. :param transfer_mode: **(EXPERIMENTAL)** *(Optional)* return as stream :param generate_tagged_pdf: **(EXPERIMENTAL)** *(Optional)* Whether or not to generate tagged (accessible) PDF. Defaults to embedder choice. + :param generate_document_outline: **(EXPERIMENTAL)** *(Optional)* Whether or not to embed the document outline into the PDF. :returns: A tuple with the following items: 0. **data** - Base64-encoded pdf data. Empty if `` returnAsStream` is specified. (Encoded as a base64 string when passed over JSON) @@ -2111,6 +2608,8 @@ def print_to_pdf( params['transferMode'] = transfer_mode if generate_tagged_pdf is not None: params['generateTaggedPDF'] = generate_tagged_pdf + if generate_document_outline is not None: + params['generateDocumentOutline'] = generate_document_outline cmd_dict: T_JSON_DICT = { 'method': 'Page.printToPDF', 'params': params, @@ -2124,19 +2623,23 @@ def print_to_pdf( def reload( ignore_cache: typing.Optional[bool] = None, - script_to_evaluate_on_load: typing.Optional[str] = None + script_to_evaluate_on_load: typing.Optional[str] = None, + loader_id: typing.Optional[network.LoaderId] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Reloads given page optionally ignoring the cache. :param ignore_cache: *(Optional)* If true, browser cache is ignored (as if the user pressed Shift+refresh). :param script_to_evaluate_on_load: *(Optional)* If set, the script will be injected into all frames of the inspected page after reload. Argument will be ignored if reloading dataURL origin. + :param loader_id: **(EXPERIMENTAL)** *(Optional)* If set, an error will be thrown if the target page's main frame's loader id does not match the provided id. This prevents accidentally reloading an unintended target in case there's a racing navigation. ''' params: T_JSON_DICT = dict() if ignore_cache is not None: params['ignoreCache'] = ignore_cache if script_to_evaluate_on_load is not None: params['scriptToEvaluateOnLoad'] = script_to_evaluate_on_load + if loader_id is not None: + params['loaderId'] = loader_id.to_json() cmd_dict: T_JSON_DICT = { 'method': 'Page.reload', 'params': params, @@ -2262,8 +2765,6 @@ def set_bypass_csp( ''' Enable page Content Security Policy by-passing. - **EXPERIMENTAL** - :param enabled: Whether to bypass page CSP. ''' params: T_JSON_DICT = dict() @@ -2534,8 +3035,6 @@ def set_lifecycle_events_enabled( ''' Controls whether page will emit lifecycle events. - **EXPERIMENTAL** - :param enabled: If true, starts emitting lifecycle events. ''' params: T_JSON_DICT = dict() @@ -2634,8 +3133,6 @@ def crash() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: def close() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Tries to close page, running its beforeunload hooks, if any. - - **EXPERIMENTAL** ''' cmd_dict: T_JSON_DICT = { 'method': 'Page.close', @@ -2681,7 +3178,7 @@ def produce_compilation_cache( ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Requests backend to produce compilation cache for the specified scripts. - ``scripts`` are appeneded to the list of scripts for which the cache + ``scripts`` are appended to the list of scripts for which the cache would be produced. The list may be reset during page navigation. When script with a matching URL is encountered, the cache is optionally produced upon backend discretion, based on internal heuristics. @@ -2818,8 +3315,6 @@ def set_intercept_file_chooser_dialog( When file chooser interception is enabled, native file chooser dialog is not shown. Instead, a protocol event ``Page.fileChooserOpened`` is emitted. - **EXPERIMENTAL** - :param enabled: ''' params: T_JSON_DICT = dict() @@ -2947,6 +3442,25 @@ def from_json(cls, json: T_JSON_DICT) -> FrameDetached: ) +@event_class('Page.frameSubtreeWillBeDetached') +@dataclass +class FrameSubtreeWillBeDetached: + ''' + **EXPERIMENTAL** + + Fired before frame subtree is detached. Emitted before any frame of the + subtree is actually detached. + ''' + #: Id of the frame that is the root of the subtree that will be detached. + frame_id: FrameId + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> FrameSubtreeWillBeDetached: + return cls( + frame_id=FrameId.from_json(json['frameId']) + ) + + @event_class('Page.frameNavigated') @dataclass class FrameNavigated: @@ -3000,6 +3514,41 @@ def from_json(cls, json: T_JSON_DICT) -> FrameResized: ) +@event_class('Page.frameStartedNavigating') +@dataclass +class FrameStartedNavigating: + ''' + **EXPERIMENTAL** + + Fired when a navigation starts. This event is fired for both + renderer-initiated and browser-initiated navigations. For renderer-initiated + navigations, the event is fired after ``frameRequestedNavigation``. + Navigation may still be cancelled after the event is issued. Multiple events + can be fired for a single navigation, for example, when a same-document + navigation becomes a cross-document navigation (such as in the case of a + frameset). + ''' + #: ID of the frame that is being navigated. + frame_id: FrameId + #: The URL the navigation started with. The final URL can be different. + url: str + #: Loader identifier. Even though it is present in case of same-document + #: navigation, the previously committed loaderId would not change unless + #: the navigation changes from a same-document to a cross-document + #: navigation. + loader_id: network.LoaderId + navigation_type: str + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> FrameStartedNavigating: + return cls( + frame_id=FrameId.from_json(json['frameId']), + url=str(json['url']), + loader_id=network.LoaderId.from_json(json['loaderId']), + navigation_type=str(json['navigationType']) + ) + + @event_class('Page.frameRequestedNavigation') @dataclass class FrameRequestedNavigation: @@ -3234,7 +3783,8 @@ def from_json(cls, json: T_JSON_DICT) -> JavascriptDialogOpening: @dataclass class LifecycleEvent: ''' - Fired for top level page lifecycle events such as navigation, load, paint, etc. + Fired for lifecycle events (navigation, load, paint, etc) in the current + target (including local frames). ''' #: Id of the frame. frame_id: FrameId @@ -3264,7 +3814,7 @@ class BackForwardCacheNotUsed: main-frame history navigation where the document changes (non-same-document navigations), when bfcache navigation fails. ''' - #: The loader id for the associated navgation. + #: The loader id for the associated navigation. loader_id: network.LoaderId #: The frame id of the associated frame. frame_id: FrameId @@ -3307,12 +3857,15 @@ class NavigatedWithinDocument: frame_id: FrameId #: Frame's new url. url: str + #: Navigation type + navigation_type: str @classmethod def from_json(cls, json: T_JSON_DICT) -> NavigatedWithinDocument: return cls( frame_id=FrameId.from_json(json['frameId']), - url=str(json['url']) + url=str(json['url']), + navigation_type=str(json['navigationType']) ) diff --git a/pycdp/cdp/performance_timeline.py b/pycdp/cdp/performance_timeline.py index e22e149..dc5087b 100644 --- a/pycdp/cdp/performance_timeline.py +++ b/pycdp/cdp/performance_timeline.py @@ -124,7 +124,7 @@ class TimelineEvent: frame_id: page.FrameId #: The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype - #: This determines which of the optional "details" fiedls is present. + #: This determines which of the optional "details" fields is present. type_: str #: Name may be empty depending on the type. diff --git a/pycdp/cdp/preload.py b/pycdp/cdp/preload.py index cdbf860..a8024e7 100644 --- a/pycdp/cdp/preload.py +++ b/pycdp/cdp/preload.py @@ -193,7 +193,7 @@ class PreloadingAttemptSource: that had a speculation rule that triggered the attempt, and the BackendNodeIds of or elements that triggered the attempt (in the case of attempts triggered by a document rule). It is - possible for mulitple rule sets and links to trigger a single attempt. + possible for multiple rule sets and links to trigger a single attempt. ''' key: PreloadingAttemptKey @@ -217,6 +217,27 @@ def from_json(cls, json: T_JSON_DICT) -> PreloadingAttemptSource: ) +class PreloadPipelineId(str): + ''' + Chrome manages different types of preloads together using a + concept of preloading pipeline. For example, if a site uses a + SpeculationRules for prerender, Chrome first starts a prefetch and + then upgrades it to prerender. + + CDP events for them are emitted separately but they share + ``PreloadPipelineId``. + ''' + def to_json(self) -> str: + return self + + @classmethod + def from_json(cls, json: str) -> PreloadPipelineId: + return cls(json) + + def __repr__(self): + return 'PreloadPipelineId({})'.format(super().__repr__()) + + class PrerenderFinalStatus(enum.Enum): ''' List of FinalStatus reasons for Prerender2. @@ -226,7 +247,6 @@ class PrerenderFinalStatus(enum.Enum): LOW_END_DEVICE = "LowEndDevice" INVALID_SCHEME_REDIRECT = "InvalidSchemeRedirect" INVALID_SCHEME_NAVIGATION = "InvalidSchemeNavigation" - IN_PROGRESS_NAVIGATION = "InProgressNavigation" NAVIGATION_REQUEST_BLOCKED_BY_CSP = "NavigationRequestBlockedByCsp" MAIN_FRAME_NAVIGATION = "MainFrameNavigation" MOJO_BINDER_POLICY = "MojoBinderPolicy" @@ -238,7 +258,6 @@ class PrerenderFinalStatus(enum.Enum): NAVIGATION_BAD_HTTP_STATUS = "NavigationBadHttpStatus" CLIENT_CERT_REQUESTED = "ClientCertRequested" NAVIGATION_REQUEST_NETWORK_ERROR = "NavigationRequestNetworkError" - MAX_NUM_OF_RUNNING_PRERENDERS_EXCEEDED = "MaxNumOfRunningPrerendersExceeded" CANCEL_ALL_HOSTS_FOR_TESTING = "CancelAllHostsForTesting" DID_FAIL_LOAD = "DidFailLoad" STOP = "Stop" @@ -250,9 +269,8 @@ class PrerenderFinalStatus(enum.Enum): MIXED_CONTENT = "MixedContent" TRIGGER_BACKGROUNDED = "TriggerBackgrounded" MEMORY_LIMIT_EXCEEDED = "MemoryLimitExceeded" - FAIL_TO_GET_MEMORY_USAGE = "FailToGetMemoryUsage" DATA_SAVER_ENABLED = "DataSaverEnabled" - HAS_EFFECTIVE_URL = "HasEffectiveUrl" + TRIGGER_URL_HAS_EFFECTIVE_URL = "TriggerUrlHasEffectiveUrl" ACTIVATED_BEFORE_STARTED = "ActivatedBeforeStarted" INACTIVE_PAGE_RESTRICTION = "InactivePageRestriction" START_FAILED = "StartFailed" @@ -281,9 +299,23 @@ class PrerenderFinalStatus(enum.Enum): MEMORY_PRESSURE_ON_TRIGGER = "MemoryPressureOnTrigger" MEMORY_PRESSURE_AFTER_TRIGGERED = "MemoryPressureAfterTriggered" PRERENDERING_DISABLED_BY_DEV_TOOLS = "PrerenderingDisabledByDevTools" - RESOURCE_LOAD_BLOCKED_BY_CLIENT = "ResourceLoadBlockedByClient" SPECULATION_RULE_REMOVED = "SpeculationRuleRemoved" ACTIVATED_WITH_AUXILIARY_BROWSING_CONTEXTS = "ActivatedWithAuxiliaryBrowsingContexts" + MAX_NUM_OF_RUNNING_EAGER_PRERENDERS_EXCEEDED = "MaxNumOfRunningEagerPrerendersExceeded" + MAX_NUM_OF_RUNNING_NON_EAGER_PRERENDERS_EXCEEDED = "MaxNumOfRunningNonEagerPrerendersExceeded" + MAX_NUM_OF_RUNNING_EMBEDDER_PRERENDERS_EXCEEDED = "MaxNumOfRunningEmbedderPrerendersExceeded" + PRERENDERING_URL_HAS_EFFECTIVE_URL = "PrerenderingUrlHasEffectiveUrl" + REDIRECTED_PRERENDERING_URL_HAS_EFFECTIVE_URL = "RedirectedPrerenderingUrlHasEffectiveUrl" + ACTIVATION_URL_HAS_EFFECTIVE_URL = "ActivationUrlHasEffectiveUrl" + JAVA_SCRIPT_INTERFACE_ADDED = "JavaScriptInterfaceAdded" + JAVA_SCRIPT_INTERFACE_REMOVED = "JavaScriptInterfaceRemoved" + ALL_PRERENDERING_CANCELED = "AllPrerenderingCanceled" + WINDOW_CLOSED = "WindowClosed" + SLOW_NETWORK = "SlowNetwork" + OTHER_PRERENDERED_PAGE_ACTIVATED = "OtherPrerenderedPageActivated" + V8_OPTIMIZER_DISABLED = "V8OptimizerDisabled" + PRERENDER_FAILED_DURING_PREFETCH = "PrerenderFailedDuringPrefetch" + BROWSING_DATA_REMOVED = "BrowsingDataRemoved" def to_json(self) -> str: return self.value @@ -324,8 +356,8 @@ class PrefetchStatus(enum.Enum): PREFETCH_FAILED_MIME_NOT_SUPPORTED = "PrefetchFailedMIMENotSupported" PREFETCH_FAILED_NET_ERROR = "PrefetchFailedNetError" PREFETCH_FAILED_NON2_XX = "PrefetchFailedNon2XX" - PREFETCH_FAILED_PER_PAGE_LIMIT_EXCEEDED = "PrefetchFailedPerPageLimitExceeded" - PREFETCH_EVICTED = "PrefetchEvicted" + PREFETCH_EVICTED_AFTER_CANDIDATE_REMOVED = "PrefetchEvictedAfterCandidateRemoved" + PREFETCH_EVICTED_FOR_NEWER_PREFETCH = "PrefetchEvictedForNewerPrefetch" PREFETCH_HELDBACK = "PrefetchHeldback" PREFETCH_INELIGIBLE_RETRY_AFTER = "PrefetchIneligibleRetryAfter" PREFETCH_IS_PRIVACY_DECOY = "PrefetchIsPrivacyDecoy" @@ -339,6 +371,9 @@ class PrefetchStatus(enum.Enum): PREFETCH_NOT_ELIGIBLE_SCHEME_IS_NOT_HTTPS = "PrefetchNotEligibleSchemeIsNotHttps" PREFETCH_NOT_ELIGIBLE_USER_HAS_COOKIES = "PrefetchNotEligibleUserHasCookies" PREFETCH_NOT_ELIGIBLE_USER_HAS_SERVICE_WORKER = "PrefetchNotEligibleUserHasServiceWorker" + PREFETCH_NOT_ELIGIBLE_USER_HAS_SERVICE_WORKER_NO_FETCH_HANDLER = "PrefetchNotEligibleUserHasServiceWorkerNoFetchHandler" + PREFETCH_NOT_ELIGIBLE_REDIRECT_FROM_SERVICE_WORKER = "PrefetchNotEligibleRedirectFromServiceWorker" + PREFETCH_NOT_ELIGIBLE_REDIRECT_TO_SERVICE_WORKER = "PrefetchNotEligibleRedirectToServiceWorker" PREFETCH_NOT_ELIGIBLE_BATTERY_SAVER_ENABLED = "PrefetchNotEligibleBatterySaverEnabled" PREFETCH_NOT_ELIGIBLE_PRELOADING_DISABLED = "PrefetchNotEligiblePreloadingDisabled" PREFETCH_NOT_FINISHED_IN_TIME = "PrefetchNotFinishedInTime" @@ -357,6 +392,35 @@ def from_json(cls, json: str) -> PrefetchStatus: return cls(json) +@dataclass +class PrerenderMismatchedHeaders: + ''' + Information of headers to be displayed when the header mismatch occurred. + ''' + header_name: str + + initial_value: typing.Optional[str] = None + + activation_value: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['headerName'] = self.header_name + if self.initial_value is not None: + json['initialValue'] = self.initial_value + if self.activation_value is not None: + json['activationValue'] = self.activation_value + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> PrerenderMismatchedHeaders: + return cls( + header_name=str(json['headerName']), + initial_value=str(json['initialValue']) if json.get('initialValue', None) is not None else None, + activation_value=str(json['activationValue']) if json.get('activationValue', None) is not None else None, + ) + + def enable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: cmd_dict: T_JSON_DICT = { @@ -400,32 +464,6 @@ def from_json(cls, json: T_JSON_DICT) -> RuleSetRemoved: ) -@event_class('Preload.prerenderAttemptCompleted') -@dataclass -class PrerenderAttemptCompleted: - ''' - Fired when a prerender attempt is completed. - ''' - key: PreloadingAttemptKey - #: The frame id of the frame initiating prerendering. - initiating_frame_id: page.FrameId - prerendering_url: str - final_status: PrerenderFinalStatus - #: This is used to give users more information about the name of the API call - #: that is incompatible with prerender and has caused the cancellation of the attempt - disallowed_api_method: typing.Optional[str] - - @classmethod - def from_json(cls, json: T_JSON_DICT) -> PrerenderAttemptCompleted: - return cls( - key=PreloadingAttemptKey.from_json(json['key']), - initiating_frame_id=page.FrameId.from_json(json['initiatingFrameId']), - prerendering_url=str(json['prerenderingUrl']), - final_status=PrerenderFinalStatus.from_json(json['finalStatus']), - disallowed_api_method=str(json['disallowedApiMethod']) if json.get('disallowedApiMethod', None) is not None else None - ) - - @event_class('Preload.preloadEnabledStateUpdated') @dataclass class PreloadEnabledStateUpdated: @@ -456,6 +494,7 @@ class PrefetchStatusUpdated: Fired when a prefetch attempt is updated. ''' key: PreloadingAttemptKey + pipeline_id: PreloadPipelineId #: The frame id of the frame initiating prefetch. initiating_frame_id: page.FrameId prefetch_url: str @@ -467,6 +506,7 @@ class PrefetchStatusUpdated: def from_json(cls, json: T_JSON_DICT) -> PrefetchStatusUpdated: return cls( key=PreloadingAttemptKey.from_json(json['key']), + pipeline_id=PreloadPipelineId.from_json(json['pipelineId']), initiating_frame_id=page.FrameId.from_json(json['initiatingFrameId']), prefetch_url=str(json['prefetchUrl']), status=PreloadingStatus.from_json(json['status']), @@ -482,19 +522,23 @@ class PrerenderStatusUpdated: Fired when a prerender attempt is updated. ''' key: PreloadingAttemptKey + pipeline_id: PreloadPipelineId status: PreloadingStatus prerender_status: typing.Optional[PrerenderFinalStatus] #: This is used to give users more information about the name of Mojo interface #: that is incompatible with prerender and has caused the cancellation of the attempt. disallowed_mojo_interface: typing.Optional[str] + mismatched_headers: typing.Optional[typing.List[PrerenderMismatchedHeaders]] @classmethod def from_json(cls, json: T_JSON_DICT) -> PrerenderStatusUpdated: return cls( key=PreloadingAttemptKey.from_json(json['key']), + pipeline_id=PreloadPipelineId.from_json(json['pipelineId']), status=PreloadingStatus.from_json(json['status']), prerender_status=PrerenderFinalStatus.from_json(json['prerenderStatus']) if json.get('prerenderStatus', None) is not None else None, - disallowed_mojo_interface=str(json['disallowedMojoInterface']) if json.get('disallowedMojoInterface', None) is not None else None + disallowed_mojo_interface=str(json['disallowedMojoInterface']) if json.get('disallowedMojoInterface', None) is not None else None, + mismatched_headers=[PrerenderMismatchedHeaders.from_json(i) for i in json['mismatchedHeaders']] if json.get('mismatchedHeaders', None) is not None else None ) diff --git a/pycdp/cdp/pwa.py b/pycdp/cdp/pwa.py new file mode 100644 index 0000000..e91a4dc --- /dev/null +++ b/pycdp/cdp/pwa.py @@ -0,0 +1,262 @@ +# DO NOT EDIT THIS FILE! +# +# This file is generated from the CDP specification. If you need to make +# changes, edit the generator and regenerate all of the modules. +# +# CDP domain: PWA (experimental) + +from __future__ import annotations +import enum +import typing +from dataclasses import dataclass +from .util import event_class, T_JSON_DICT + +from . import target + + +@dataclass +class FileHandlerAccept: + ''' + The following types are the replica of + https://crsrc.org/c/chrome/browser/web_applications/proto/web_app_os_integration_state.proto;drc=9910d3be894c8f142c977ba1023f30a656bc13fc;l=67 + ''' + #: New name of the mimetype according to + #: https://www.iana.org/assignments/media-types/media-types.xhtml + media_type: str + + file_extensions: typing.List[str] + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['mediaType'] = self.media_type + json['fileExtensions'] = [i for i in self.file_extensions] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> FileHandlerAccept: + return cls( + media_type=str(json['mediaType']), + file_extensions=[str(i) for i in json['fileExtensions']], + ) + + +@dataclass +class FileHandler: + action: str + + accepts: typing.List[FileHandlerAccept] + + display_name: str + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['action'] = self.action + json['accepts'] = [i.to_json() for i in self.accepts] + json['displayName'] = self.display_name + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> FileHandler: + return cls( + action=str(json['action']), + accepts=[FileHandlerAccept.from_json(i) for i in json['accepts']], + display_name=str(json['displayName']), + ) + + +class DisplayMode(enum.Enum): + ''' + If user prefers opening the app in browser or an app window. + ''' + STANDALONE = "standalone" + BROWSER = "browser" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> DisplayMode: + return cls(json) + + +def get_os_app_state( + manifest_id: str + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[int, typing.List[FileHandler]]]: + ''' + Returns the following OS state for the given manifest id. + + :param manifest_id: The id from the webapp's manifest file, commonly it's the url of the site installing the webapp. See https://web.dev/learn/pwa/web-app-manifest. + :returns: A tuple with the following items: + + 0. **badgeCount** - + 1. **fileHandlers** - + ''' + params: T_JSON_DICT = dict() + params['manifestId'] = manifest_id + cmd_dict: T_JSON_DICT = { + 'method': 'PWA.getOsAppState', + 'params': params, + } + json = yield cmd_dict + return ( + int(json['badgeCount']), + [FileHandler.from_json(i) for i in json['fileHandlers']] + ) + + +def install( + manifest_id: str, + install_url_or_bundle_url: typing.Optional[str] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Installs the given manifest identity, optionally using the given install_url + or IWA bundle location. + + TODO(crbug.com/337872319) Support IWA to meet the following specific + requirement. + IWA-specific install description: If the manifest_id is isolated-app://, + install_url_or_bundle_url is required, and can be either an http(s) URL or + file:// URL pointing to a signed web bundle (.swbn). The .swbn file's + signing key must correspond to manifest_id. If Chrome is not in IWA dev + mode, the installation will fail, regardless of the state of the allowlist. + + :param manifest_id: + :param install_url_or_bundle_url: *(Optional)* The location of the app or bundle overriding the one derived from the manifestId. + ''' + params: T_JSON_DICT = dict() + params['manifestId'] = manifest_id + if install_url_or_bundle_url is not None: + params['installUrlOrBundleUrl'] = install_url_or_bundle_url + cmd_dict: T_JSON_DICT = { + 'method': 'PWA.install', + 'params': params, + } + json = yield cmd_dict + + +def uninstall( + manifest_id: str + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Uninstalls the given manifest_id and closes any opened app windows. + + :param manifest_id: + ''' + params: T_JSON_DICT = dict() + params['manifestId'] = manifest_id + cmd_dict: T_JSON_DICT = { + 'method': 'PWA.uninstall', + 'params': params, + } + json = yield cmd_dict + + +def launch( + manifest_id: str, + url: typing.Optional[str] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,target.TargetID]: + ''' + Launches the installed web app, or an url in the same web app instead of the + default start url if it is provided. Returns a page Target.TargetID which + can be used to attach to via Target.attachToTarget or similar APIs. + + :param manifest_id: + :param url: *(Optional)* + :returns: ID of the tab target created as a result. + ''' + params: T_JSON_DICT = dict() + params['manifestId'] = manifest_id + if url is not None: + params['url'] = url + cmd_dict: T_JSON_DICT = { + 'method': 'PWA.launch', + 'params': params, + } + json = yield cmd_dict + return target.TargetID.from_json(json['targetId']) + + +def launch_files_in_app( + manifest_id: str, + files: typing.List[str] + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[target.TargetID]]: + ''' + Opens one or more local files from an installed web app identified by its + manifestId. The web app needs to have file handlers registered to process + the files. The API returns one or more page Target.TargetIDs which can be + used to attach to via Target.attachToTarget or similar APIs. + If some files in the parameters cannot be handled by the web app, they will + be ignored. If none of the files can be handled, this API returns an error. + If no files are provided as the parameter, this API also returns an error. + + According to the definition of the file handlers in the manifest file, one + Target.TargetID may represent a page handling one or more files. The order + of the returned Target.TargetIDs is not guaranteed. + + TODO(crbug.com/339454034): Check the existences of the input files. + + :param manifest_id: + :param files: + :returns: IDs of the tab targets created as the result. + ''' + params: T_JSON_DICT = dict() + params['manifestId'] = manifest_id + params['files'] = [i for i in files] + cmd_dict: T_JSON_DICT = { + 'method': 'PWA.launchFilesInApp', + 'params': params, + } + json = yield cmd_dict + return [target.TargetID.from_json(i) for i in json['targetIds']] + + +def open_current_page_in_app( + manifest_id: str + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Opens the current page in its web app identified by the manifest id, needs + to be called on a page target. This function returns immediately without + waiting for the app to finish loading. + + :param manifest_id: + ''' + params: T_JSON_DICT = dict() + params['manifestId'] = manifest_id + cmd_dict: T_JSON_DICT = { + 'method': 'PWA.openCurrentPageInApp', + 'params': params, + } + json = yield cmd_dict + + +def change_app_user_settings( + manifest_id: str, + link_capturing: typing.Optional[bool] = None, + display_mode: typing.Optional[DisplayMode] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Changes user settings of the web app identified by its manifestId. If the + app was not installed, this command returns an error. Unset parameters will + be ignored; unrecognized values will cause an error. + + Unlike the ones defined in the manifest files of the web apps, these + settings are provided by the browser and controlled by the users, they + impact the way the browser handling the web apps. + + See the comment of each parameter. + + :param manifest_id: + :param link_capturing: *(Optional)* If user allows the links clicked on by the user in the app's scope, or extended scope if the manifest has scope extensions and the flags ```DesktopPWAsLinkCapturingWithScopeExtensions```` and ````WebAppEnableScopeExtensions``` are enabled. Note, the API does not support resetting the linkCapturing to the initial value, uninstalling and installing the web app again will reset it. TODO(crbug.com/339453269): Setting this value on ChromeOS is not supported yet. + :param display_mode: *(Optional)* + ''' + params: T_JSON_DICT = dict() + params['manifestId'] = manifest_id + if link_capturing is not None: + params['linkCapturing'] = link_capturing + if display_mode is not None: + params['displayMode'] = display_mode.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'PWA.changeAppUserSettings', + 'params': params, + } + json = yield cmd_dict diff --git a/pycdp/cdp/runtime.py b/pycdp/cdp/runtime.py index 6c67e63..f4d8b0c 100644 --- a/pycdp/cdp/runtime.py +++ b/pycdp/cdp/runtime.py @@ -30,8 +30,7 @@ def __repr__(self): @dataclass class SerializationOptions: ''' - Represents options for serialization. Overrides ``generatePreview``, ``returnByValue`` and - ``generateWebDriverValue``. + Represents options for serialization. Overrides ``generatePreview`` and ``returnByValue``. ''' serialization: str @@ -155,9 +154,6 @@ class RemoteObject: #: String representation of the object. description: typing.Optional[str] = None - #: Deprecated. Use ``deepSerializedValue`` instead. WebDriver BiDi representation of the value. - web_driver_value: typing.Optional[DeepSerializedValue] = None - #: Deep serialized value. deep_serialized_value: typing.Optional[DeepSerializedValue] = None @@ -182,8 +178,6 @@ def to_json(self) -> T_JSON_DICT: json['unserializableValue'] = self.unserializable_value.to_json() if self.description is not None: json['description'] = self.description - if self.web_driver_value is not None: - json['webDriverValue'] = self.web_driver_value.to_json() if self.deep_serialized_value is not None: json['deepSerializedValue'] = self.deep_serialized_value.to_json() if self.object_id is not None: @@ -203,7 +197,6 @@ def from_json(cls, json: T_JSON_DICT) -> RemoteObject: value=json['value'] if json.get('value', None) is not None else None, unserializable_value=UnserializableValue.from_json(json['unserializableValue']) if json.get('unserializableValue', None) is not None else None, description=str(json['description']) if json.get('description', None) is not None else None, - web_driver_value=DeepSerializedValue.from_json(json['webDriverValue']) if json.get('webDriverValue', None) is not None else None, deep_serialized_value=DeepSerializedValue.from_json(json['deepSerializedValue']) if json.get('deepSerializedValue', None) is not None else None, object_id=RemoteObjectId.from_json(json['objectId']) if json.get('objectId', None) is not None else None, preview=ObjectPreview.from_json(json['preview']) if json.get('preview', None) is not None else None, @@ -852,7 +845,6 @@ def call_function_on( object_group: typing.Optional[str] = None, throw_on_side_effect: typing.Optional[bool] = None, unique_context_id: typing.Optional[str] = None, - generate_web_driver_value: typing.Optional[bool] = None, serialization_options: typing.Optional[SerializationOptions] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[RemoteObject, typing.Optional[ExceptionDetails]]]: ''' @@ -871,8 +863,7 @@ def call_function_on( :param object_group: *(Optional)* Symbolic group name that can be used to release multiple objects. If objectGroup is not specified and objectId is, objectGroup will be inherited from object. :param throw_on_side_effect: **(EXPERIMENTAL)** *(Optional)* Whether to throw an exception if side effect cannot be ruled out during evaluation. :param unique_context_id: **(EXPERIMENTAL)** *(Optional)* An alternative way to specify the execution context to call function on. Compared to contextId that may be reused across processes, this is guaranteed to be system-unique, so it can be used to prevent accidental function call in context different than intended (e.g. as a result of navigation across process boundaries). This is mutually exclusive with ````executionContextId````. - :param generate_web_driver_value: **(DEPRECATED)** *(Optional)* Deprecated. Use ````serializationOptions: {serialization:"deep"}```` instead. Whether the result should contain ````webDriverValue````, serialized according to https://w3c.github.io/webdriver-bidi. This is mutually exclusive with ````returnByValue````, but resulting ````objectId```` is still provided. - :param serialization_options: **(EXPERIMENTAL)** *(Optional)* Specifies the result serialization. If provided, overrides ````generatePreview````, ````returnByValue```` and ````generateWebDriverValue```. + :param serialization_options: **(EXPERIMENTAL)** *(Optional)* Specifies the result serialization. If provided, overrides ````generatePreview```` and ````returnByValue```. :returns: A tuple with the following items: 0. **result** - Call result. @@ -902,8 +893,6 @@ def call_function_on( params['throwOnSideEffect'] = throw_on_side_effect if unique_context_id is not None: params['uniqueContextId'] = unique_context_id - if generate_web_driver_value is not None: - params['generateWebDriverValue'] = generate_web_driver_value if serialization_options is not None: params['serializationOptions'] = serialization_options.to_json() cmd_dict: T_JSON_DICT = { @@ -1000,7 +989,6 @@ def evaluate( repl_mode: typing.Optional[bool] = None, allow_unsafe_eval_blocked_by_csp: typing.Optional[bool] = None, unique_context_id: typing.Optional[str] = None, - generate_web_driver_value: typing.Optional[bool] = None, serialization_options: typing.Optional[SerializationOptions] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[RemoteObject, typing.Optional[ExceptionDetails]]]: ''' @@ -1021,8 +1009,7 @@ def evaluate( :param repl_mode: **(EXPERIMENTAL)** *(Optional)* Setting this flag to true enables ````let```` re-declaration and top-level ````await````. Note that ````let```` variables can only be re-declared if they originate from ````replMode```` themselves. :param allow_unsafe_eval_blocked_by_csp: **(EXPERIMENTAL)** *(Optional)* The Content Security Policy (CSP) for the target might block 'unsafe-eval' which includes eval(), Function(), setTimeout() and setInterval() when called with non-callable arguments. This flag bypasses CSP for this evaluation and allows unsafe-eval. Defaults to true. :param unique_context_id: **(EXPERIMENTAL)** *(Optional)* An alternative way to specify the execution context to evaluate in. Compared to contextId that may be reused across processes, this is guaranteed to be system-unique, so it can be used to prevent accidental evaluation of the expression in context different than intended (e.g. as a result of navigation across process boundaries). This is mutually exclusive with ````contextId````. - :param generate_web_driver_value: **(DEPRECATED)** *(Optional)* Deprecated. Use ````serializationOptions: {serialization:"deep"}```` instead. Whether the result should contain ````webDriverValue````, serialized according to https://w3c.github.io/webdriver-bidi. This is mutually exclusive with ````returnByValue````, but resulting ````objectId```` is still provided. - :param serialization_options: **(EXPERIMENTAL)** *(Optional)* Specifies the result serialization. If provided, overrides ````generatePreview````, ````returnByValue```` and ````generateWebDriverValue```. + :param serialization_options: **(EXPERIMENTAL)** *(Optional)* Specifies the result serialization. If provided, overrides ````generatePreview```` and ````returnByValue```. :returns: A tuple with the following items: 0. **result** - Evaluation result. @@ -1058,8 +1045,6 @@ def evaluate( params['allowUnsafeEvalBlockedByCSP'] = allow_unsafe_eval_blocked_by_csp if unique_context_id is not None: params['uniqueContextId'] = unique_context_id - if generate_web_driver_value is not None: - params['generateWebDriverValue'] = generate_web_driver_value if serialization_options is not None: params['serializationOptions'] = serialization_options.to_json() cmd_dict: T_JSON_DICT = { @@ -1088,7 +1073,7 @@ def get_isolate_id() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,str]: return str(json['id']) -def get_heap_usage() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[float, float]]: +def get_heap_usage() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[float, float, float, float]]: ''' Returns the JavaScript heap usage. It is the total usage of the corresponding isolate not scoped to a particular Runtime. @@ -1097,8 +1082,10 @@ def get_heap_usage() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[fl :returns: A tuple with the following items: - 0. **usedSize** - Used heap size in bytes. - 1. **totalSize** - Allocated heap size in bytes. + 0. **usedSize** - Used JavaScript heap size in bytes. + 1. **totalSize** - Allocated JavaScript heap size in bytes. + 2. **embedderHeapUsedSize** - Used size in bytes in the embedder's garbage-collected heap. + 3. **backingStorageSize** - Size in bytes of backing storage for array buffers and external strings. ''' cmd_dict: T_JSON_DICT = { 'method': 'Runtime.getHeapUsage', @@ -1106,7 +1093,9 @@ def get_heap_usage() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[fl json = yield cmd_dict return ( float(json['usedSize']), - float(json['totalSize']) + float(json['totalSize']), + float(json['embedderHeapUsedSize']), + float(json['backingStorageSize']) ) @@ -1375,11 +1364,9 @@ def add_binding( in case of any other input, function throws an exception. Each binding function call produces Runtime.bindingCalled notification. - **EXPERIMENTAL** - :param name: - :param execution_context_id: **(DEPRECATED)** *(Optional)* If specified, the binding would only be exposed to the specified execution context. If omitted and ```executionContextName```` is not set, the binding is exposed to all execution contexts of the target. This parameter is mutually exclusive with ````executionContextName````. Deprecated in favor of ````executionContextName```` due to an unclear use case and bugs in implementation (crbug.com/1169639). ````executionContextId```` will be removed in the future. - :param execution_context_name: **(EXPERIMENTAL)** *(Optional)* If specified, the binding is exposed to the executionContext with matching name, even for contexts created after the binding is added. See also ````ExecutionContext.name```` and ````worldName```` parameter to ````Page.addScriptToEvaluateOnNewDocument````. This parameter is mutually exclusive with ````executionContextId```. + :param execution_context_id: **(DEPRECATED)** **(EXPERIMENTAL)** *(Optional)* If specified, the binding would only be exposed to the specified execution context. If omitted and ```executionContextName```` is not set, the binding is exposed to all execution contexts of the target. This parameter is mutually exclusive with ````executionContextName````. Deprecated in favor of ````executionContextName```` due to an unclear use case and bugs in implementation (crbug.com/1169639). ````executionContextId```` will be removed in the future. + :param execution_context_name: *(Optional)* If specified, the binding is exposed to the executionContext with matching name, even for contexts created after the binding is added. See also ````ExecutionContext.name```` and ````worldName```` parameter to ````Page.addScriptToEvaluateOnNewDocument````. This parameter is mutually exclusive with ````executionContextId```. ''' params: T_JSON_DICT = dict() params['name'] = name @@ -1401,8 +1388,6 @@ def remove_binding( This method does not remove binding function from global object but unsubscribes current runtime agent from Runtime.bindingCalled notifications. - **EXPERIMENTAL** - :param name: ''' params: T_JSON_DICT = dict() diff --git a/pycdp/cdp/security.py b/pycdp/cdp/security.py index 93313fb..81c6bdd 100644 --- a/pycdp/cdp/security.py +++ b/pycdp/cdp/security.py @@ -95,7 +95,7 @@ class CertificateSecurityState: #: Certificate valid to (expiration) date valid_to: network.TimeSinceEpoch - #: True if the certificate uses a weak signature aglorithm. + #: True if the certificate uses a weak signature algorithm. certificate_has_weak_signature: bool #: True if the certificate has a SHA1 signature in the chain. @@ -389,8 +389,6 @@ def set_ignore_certificate_errors( ''' Enable/disable whether all certificate errors should be ignored. - **EXPERIMENTAL** - :param ignore: If true, all certificate errors will be ignored. ''' params: T_JSON_DICT = dict() diff --git a/pycdp/cdp/service_worker.py b/pycdp/cdp/service_worker.py index a303e9f..8df9318 100644 --- a/pycdp/cdp/service_worker.py +++ b/pycdp/cdp/service_worker.py @@ -109,6 +109,8 @@ class ServiceWorkerVersion: target_id: typing.Optional[target.TargetID] = None + router_rules: typing.Optional[str] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['versionId'] = self.version_id @@ -124,6 +126,8 @@ def to_json(self) -> T_JSON_DICT: json['controlledClients'] = [i.to_json() for i in self.controlled_clients] if self.target_id is not None: json['targetId'] = self.target_id.to_json() + if self.router_rules is not None: + json['routerRules'] = self.router_rules return json @classmethod @@ -138,6 +142,7 @@ def from_json(cls, json: T_JSON_DICT) -> ServiceWorkerVersion: script_response_time=float(json['scriptResponseTime']) if json.get('scriptResponseTime', None) is not None else None, controlled_clients=[target.TargetID.from_json(i) for i in json['controlledClients']] if json.get('controlledClients', None) is not None else None, target_id=target.TargetID.from_json(json['targetId']) if json.get('targetId', None) is not None else None, + router_rules=str(json['routerRules']) if json.get('routerRules', None) is not None else None, ) diff --git a/pycdp/cdp/storage.py b/pycdp/cdp/storage.py index 517fd7b..87c889a 100644 --- a/pycdp/cdp/storage.py +++ b/pycdp/cdp/storage.py @@ -32,7 +32,6 @@ class StorageType(enum.Enum): ''' Enum of possible storage types. ''' - APPCACHE = "appcache" COOKIES = "cookies" FILE_SYSTEMS = "file_systems" INDEXEDDB = "indexeddb" @@ -104,6 +103,21 @@ def from_json(cls, json: T_JSON_DICT) -> TrustTokens: ) +class InterestGroupAuctionId(str): + ''' + Protected audience interest group auction identifier. + ''' + def to_json(self) -> str: + return self + + @classmethod + def from_json(cls, json: str) -> InterestGroupAuctionId: + return cls(json) + + def __repr__(self): + return 'InterestGroupAuctionId({})'.format(super().__repr__()) + + class InterestGroupAccessType(enum.Enum): ''' Enum of interest group access types. @@ -114,6 +128,11 @@ class InterestGroupAccessType(enum.Enum): LOADED = "loaded" BID = "bid" WIN = "win" + ADDITIONAL_BID = "additionalBid" + ADDITIONAL_BID_WIN = "additionalBidWin" + TOP_LEVEL_BID = "topLevelBid" + TOP_LEVEL_ADDITIONAL_BID = "topLevelAdditionalBid" + CLEAR = "clear" def to_json(self) -> str: return self.value @@ -123,96 +142,37 @@ def from_json(cls, json: str) -> InterestGroupAccessType: return cls(json) -@dataclass -class InterestGroupAd: +class InterestGroupAuctionEventType(enum.Enum): ''' - Ad advertising element inside an interest group. + Enum of auction events. ''' - render_url: str - - metadata: typing.Optional[str] = None + STARTED = "started" + CONFIG_RESOLVED = "configResolved" - def to_json(self) -> T_JSON_DICT: - json: T_JSON_DICT = dict() - json['renderUrl'] = self.render_url - if self.metadata is not None: - json['metadata'] = self.metadata - return json + def to_json(self) -> str: + return self.value @classmethod - def from_json(cls, json: T_JSON_DICT) -> InterestGroupAd: - return cls( - render_url=str(json['renderUrl']), - metadata=str(json['metadata']) if json.get('metadata', None) is not None else None, - ) + def from_json(cls, json: str) -> InterestGroupAuctionEventType: + return cls(json) -@dataclass -class InterestGroupDetails: +class InterestGroupAuctionFetchType(enum.Enum): ''' - The full details of an interest group. + Enum of network fetches auctions can do. ''' - owner_origin: str - - name: str + BIDDER_JS = "bidderJs" + BIDDER_WASM = "bidderWasm" + SELLER_JS = "sellerJs" + BIDDER_TRUSTED_SIGNALS = "bidderTrustedSignals" + SELLER_TRUSTED_SIGNALS = "sellerTrustedSignals" - expiration_time: network.TimeSinceEpoch - - joining_origin: str - - trusted_bidding_signals_keys: typing.List[str] - - ads: typing.List[InterestGroupAd] - - ad_components: typing.List[InterestGroupAd] - - bidding_url: typing.Optional[str] = None - - bidding_wasm_helper_url: typing.Optional[str] = None - - update_url: typing.Optional[str] = None - - trusted_bidding_signals_url: typing.Optional[str] = None - - user_bidding_signals: typing.Optional[str] = None - - def to_json(self) -> T_JSON_DICT: - json: T_JSON_DICT = dict() - json['ownerOrigin'] = self.owner_origin - json['name'] = self.name - json['expirationTime'] = self.expiration_time.to_json() - json['joiningOrigin'] = self.joining_origin - json['trustedBiddingSignalsKeys'] = [i for i in self.trusted_bidding_signals_keys] - json['ads'] = [i.to_json() for i in self.ads] - json['adComponents'] = [i.to_json() for i in self.ad_components] - if self.bidding_url is not None: - json['biddingUrl'] = self.bidding_url - if self.bidding_wasm_helper_url is not None: - json['biddingWasmHelperUrl'] = self.bidding_wasm_helper_url - if self.update_url is not None: - json['updateUrl'] = self.update_url - if self.trusted_bidding_signals_url is not None: - json['trustedBiddingSignalsUrl'] = self.trusted_bidding_signals_url - if self.user_bidding_signals is not None: - json['userBiddingSignals'] = self.user_bidding_signals - return json + def to_json(self) -> str: + return self.value @classmethod - def from_json(cls, json: T_JSON_DICT) -> InterestGroupDetails: - return cls( - owner_origin=str(json['ownerOrigin']), - name=str(json['name']), - expiration_time=network.TimeSinceEpoch.from_json(json['expirationTime']), - joining_origin=str(json['joiningOrigin']), - trusted_bidding_signals_keys=[str(i) for i in json['trustedBiddingSignalsKeys']], - ads=[InterestGroupAd.from_json(i) for i in json['ads']], - ad_components=[InterestGroupAd.from_json(i) for i in json['adComponents']], - bidding_url=str(json['biddingUrl']) if json.get('biddingUrl', None) is not None else None, - bidding_wasm_helper_url=str(json['biddingWasmHelperUrl']) if json.get('biddingWasmHelperUrl', None) is not None else None, - update_url=str(json['updateUrl']) if json.get('updateUrl', None) is not None else None, - trusted_bidding_signals_url=str(json['trustedBiddingSignalsUrl']) if json.get('trustedBiddingSignalsUrl', None) is not None else None, - user_bidding_signals=str(json['userBiddingSignals']) if json.get('userBiddingSignals', None) is not None else None, - ) + def from_json(cls, json: str) -> InterestGroupAuctionFetchType: + return cls(json) class SharedStorageAccessType(enum.Enum): @@ -226,6 +186,7 @@ class SharedStorageAccessType(enum.Enum): DOCUMENT_APPEND = "documentAppend" DOCUMENT_DELETE = "documentDelete" DOCUMENT_CLEAR = "documentClear" + DOCUMENT_GET = "documentGet" WORKLET_SET = "workletSet" WORKLET_APPEND = "workletAppend" WORKLET_DELETE = "workletDelete" @@ -235,6 +196,10 @@ class SharedStorageAccessType(enum.Enum): WORKLET_ENTRIES = "workletEntries" WORKLET_LENGTH = "workletLength" WORKLET_REMAINING_BUDGET = "workletRemainingBudget" + HEADER_SET = "headerSet" + HEADER_APPEND = "headerAppend" + HEADER_DELETE = "headerDelete" + HEADER_CLEAR = "headerClear" def to_json(self) -> str: return self.value @@ -272,17 +237,25 @@ class SharedStorageMetadata: ''' Details for an origin's shared storage. ''' + #: Time when the origin's shared storage was last created. creation_time: network.TimeSinceEpoch + #: Number of key-value pairs stored in origin's shared storage. length: int + #: Current amount of bits of entropy remaining in the navigation budget. remaining_budget: float + #: Total number of bytes stored as key-value pairs in origin's shared + #: storage. + bytes_used: int + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['creationTime'] = self.creation_time.to_json() json['length'] = self.length json['remainingBudget'] = self.remaining_budget + json['bytesUsed'] = self.bytes_used return json @classmethod @@ -291,6 +264,7 @@ def from_json(cls, json: T_JSON_DICT) -> SharedStorageMetadata: creation_time=network.TimeSinceEpoch.from_json(json['creationTime']), length=int(json['length']), remaining_budget=float(json['remainingBudget']), + bytes_used=int(json['bytesUsed']), ) @@ -372,20 +346,26 @@ class SharedStorageAccessParams: #: SharedStorageAccessType.documentDelete, #: SharedStorageAccessType.workletSet, #: SharedStorageAccessType.workletAppend, - #: SharedStorageAccessType.workletDelete, and - #: SharedStorageAccessType.workletGet. + #: SharedStorageAccessType.workletDelete, + #: SharedStorageAccessType.workletGet, + #: SharedStorageAccessType.headerSet, + #: SharedStorageAccessType.headerAppend, and + #: SharedStorageAccessType.headerDelete. key: typing.Optional[str] = None #: Value for a specific entry in an origin's shared storage. #: Present only for SharedStorageAccessType.documentSet, #: SharedStorageAccessType.documentAppend, - #: SharedStorageAccessType.workletSet, and - #: SharedStorageAccessType.workletAppend. + #: SharedStorageAccessType.workletSet, + #: SharedStorageAccessType.workletAppend, + #: SharedStorageAccessType.headerSet, and + #: SharedStorageAccessType.headerAppend. value: typing.Optional[str] = None #: Whether or not to set an entry for a key if that key is already present. - #: Present only for SharedStorageAccessType.documentSet and - #: SharedStorageAccessType.workletSet. + #: Present only for SharedStorageAccessType.documentSet, + #: SharedStorageAccessType.workletSet, and + #: SharedStorageAccessType.headerSet. ignore_if_present: typing.Optional[bool] = None def to_json(self) -> T_JSON_DICT: @@ -558,6 +538,48 @@ def from_json(cls, json: T_JSON_DICT) -> AttributionReportingFilterDataEntry: ) +@dataclass +class AttributionReportingFilterConfig: + filter_values: typing.List[AttributionReportingFilterDataEntry] + + #: duration in seconds + lookback_window: typing.Optional[int] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['filterValues'] = [i.to_json() for i in self.filter_values] + if self.lookback_window is not None: + json['lookbackWindow'] = self.lookback_window + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingFilterConfig: + return cls( + filter_values=[AttributionReportingFilterDataEntry.from_json(i) for i in json['filterValues']], + lookback_window=int(json['lookbackWindow']) if json.get('lookbackWindow', None) is not None else None, + ) + + +@dataclass +class AttributionReportingFilterPair: + filters: typing.List[AttributionReportingFilterConfig] + + not_filters: typing.List[AttributionReportingFilterConfig] + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['filters'] = [i.to_json() for i in self.filters] + json['notFilters'] = [i.to_json() for i in self.not_filters] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingFilterPair: + return cls( + filters=[AttributionReportingFilterConfig.from_json(i) for i in json['filters']], + not_filters=[AttributionReportingFilterConfig.from_json(i) for i in json['notFilters']], + ) + + @dataclass class AttributionReportingAggregationKeysEntry: key: str @@ -578,10 +600,158 @@ def from_json(cls, json: T_JSON_DICT) -> AttributionReportingAggregationKeysEntr ) +@dataclass +class AttributionReportingEventReportWindows: + #: duration in seconds + start: int + + #: duration in seconds + ends: typing.List[int] + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['start'] = self.start + json['ends'] = [i for i in self.ends] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingEventReportWindows: + return cls( + start=int(json['start']), + ends=[int(i) for i in json['ends']], + ) + + +@dataclass +class AttributionReportingTriggerSpec: + #: number instead of integer because not all uint32 can be represented by + #: int + trigger_data: typing.List[float] + + event_report_windows: AttributionReportingEventReportWindows + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['triggerData'] = [i for i in self.trigger_data] + json['eventReportWindows'] = self.event_report_windows.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingTriggerSpec: + return cls( + trigger_data=[float(i) for i in json['triggerData']], + event_report_windows=AttributionReportingEventReportWindows.from_json(json['eventReportWindows']), + ) + + +class AttributionReportingTriggerDataMatching(enum.Enum): + EXACT = "exact" + MODULUS = "modulus" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> AttributionReportingTriggerDataMatching: + return cls(json) + + +@dataclass +class AttributionReportingAggregatableDebugReportingData: + key_piece: UnsignedInt128AsBase16 + + #: number instead of integer because not all uint32 can be represented by + #: int + value: float + + types: typing.List[str] + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['keyPiece'] = self.key_piece.to_json() + json['value'] = self.value + json['types'] = [i for i in self.types] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingAggregatableDebugReportingData: + return cls( + key_piece=UnsignedInt128AsBase16.from_json(json['keyPiece']), + value=float(json['value']), + types=[str(i) for i in json['types']], + ) + + +@dataclass +class AttributionReportingAggregatableDebugReportingConfig: + key_piece: UnsignedInt128AsBase16 + + debug_data: typing.List[AttributionReportingAggregatableDebugReportingData] + + #: number instead of integer because not all uint32 can be represented by + #: int, only present for source registrations + budget: typing.Optional[float] = None + + aggregation_coordinator_origin: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['keyPiece'] = self.key_piece.to_json() + json['debugData'] = [i.to_json() for i in self.debug_data] + if self.budget is not None: + json['budget'] = self.budget + if self.aggregation_coordinator_origin is not None: + json['aggregationCoordinatorOrigin'] = self.aggregation_coordinator_origin + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingAggregatableDebugReportingConfig: + return cls( + key_piece=UnsignedInt128AsBase16.from_json(json['keyPiece']), + debug_data=[AttributionReportingAggregatableDebugReportingData.from_json(i) for i in json['debugData']], + budget=float(json['budget']) if json.get('budget', None) is not None else None, + aggregation_coordinator_origin=str(json['aggregationCoordinatorOrigin']) if json.get('aggregationCoordinatorOrigin', None) is not None else None, + ) + + +@dataclass +class AttributionScopesData: + values: typing.List[str] + + #: number instead of integer because not all uint32 can be represented by + #: int + limit: float + + max_event_states: float + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['values'] = [i for i in self.values] + json['limit'] = self.limit + json['maxEventStates'] = self.max_event_states + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionScopesData: + return cls( + values=[str(i) for i in json['values']], + limit=float(json['limit']), + max_event_states=float(json['maxEventStates']), + ) + + @dataclass class AttributionReportingSourceRegistration: time: network.TimeSinceEpoch + #: duration in seconds + expiry: int + + trigger_specs: typing.List[AttributionReportingTriggerSpec] + + #: duration in seconds + aggregatable_report_window: int + type_: AttributionReportingSourceType source_origin: str @@ -598,20 +768,24 @@ class AttributionReportingSourceRegistration: aggregation_keys: typing.List[AttributionReportingAggregationKeysEntry] - #: duration in seconds - expiry: typing.Optional[int] = None + trigger_data_matching: AttributionReportingTriggerDataMatching - #: duration in seconds - event_report_window: typing.Optional[int] = None + destination_limit_priority: SignedInt64AsBase10 - #: duration in seconds - aggregatable_report_window: typing.Optional[int] = None + aggregatable_debug_reporting_config: AttributionReportingAggregatableDebugReportingConfig + + max_event_level_reports: int debug_key: typing.Optional[UnsignedInt64AsBase10] = None + scopes_data: typing.Optional[AttributionScopesData] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['time'] = self.time.to_json() + json['expiry'] = self.expiry + json['triggerSpecs'] = [i.to_json() for i in self.trigger_specs] + json['aggregatableReportWindow'] = self.aggregatable_report_window json['type'] = self.type_.to_json() json['sourceOrigin'] = self.source_origin json['reportingOrigin'] = self.reporting_origin @@ -620,20 +794,23 @@ def to_json(self) -> T_JSON_DICT: json['priority'] = self.priority.to_json() json['filterData'] = [i.to_json() for i in self.filter_data] json['aggregationKeys'] = [i.to_json() for i in self.aggregation_keys] - if self.expiry is not None: - json['expiry'] = self.expiry - if self.event_report_window is not None: - json['eventReportWindow'] = self.event_report_window - if self.aggregatable_report_window is not None: - json['aggregatableReportWindow'] = self.aggregatable_report_window + json['triggerDataMatching'] = self.trigger_data_matching.to_json() + json['destinationLimitPriority'] = self.destination_limit_priority.to_json() + json['aggregatableDebugReportingConfig'] = self.aggregatable_debug_reporting_config.to_json() + json['maxEventLevelReports'] = self.max_event_level_reports if self.debug_key is not None: json['debugKey'] = self.debug_key.to_json() + if self.scopes_data is not None: + json['scopesData'] = self.scopes_data.to_json() return json @classmethod def from_json(cls, json: T_JSON_DICT) -> AttributionReportingSourceRegistration: return cls( time=network.TimeSinceEpoch.from_json(json['time']), + expiry=int(json['expiry']), + trigger_specs=[AttributionReportingTriggerSpec.from_json(i) for i in json['triggerSpecs']], + aggregatable_report_window=int(json['aggregatableReportWindow']), type_=AttributionReportingSourceType.from_json(json['type']), source_origin=str(json['sourceOrigin']), reporting_origin=str(json['reportingOrigin']), @@ -642,10 +819,12 @@ def from_json(cls, json: T_JSON_DICT) -> AttributionReportingSourceRegistration: priority=SignedInt64AsBase10.from_json(json['priority']), filter_data=[AttributionReportingFilterDataEntry.from_json(i) for i in json['filterData']], aggregation_keys=[AttributionReportingAggregationKeysEntry.from_json(i) for i in json['aggregationKeys']], - expiry=int(json['expiry']) if json.get('expiry', None) is not None else None, - event_report_window=int(json['eventReportWindow']) if json.get('eventReportWindow', None) is not None else None, - aggregatable_report_window=int(json['aggregatableReportWindow']) if json.get('aggregatableReportWindow', None) is not None else None, + trigger_data_matching=AttributionReportingTriggerDataMatching.from_json(json['triggerDataMatching']), + destination_limit_priority=SignedInt64AsBase10.from_json(json['destinationLimitPriority']), + aggregatable_debug_reporting_config=AttributionReportingAggregatableDebugReportingConfig.from_json(json['aggregatableDebugReportingConfig']), + max_event_level_reports=int(json['maxEventLevelReports']), debug_key=UnsignedInt64AsBase10.from_json(json['debugKey']) if json.get('debugKey', None) is not None else None, + scopes_data=AttributionScopesData.from_json(json['scopesData']) if json.get('scopesData', None) is not None else None, ) @@ -662,6 +841,10 @@ class AttributionReportingSourceRegistrationResult(enum.Enum): DESTINATION_BOTH_LIMITS_REACHED = "destinationBothLimitsReached" REPORTING_ORIGINS_PER_SITE_LIMIT_REACHED = "reportingOriginsPerSiteLimitReached" EXCEEDS_MAX_CHANNEL_CAPACITY = "exceedsMaxChannelCapacity" + EXCEEDS_MAX_SCOPES_CHANNEL_CAPACITY = "exceedsMaxScopesChannelCapacity" + EXCEEDS_MAX_TRIGGER_STATE_CARDINALITY = "exceedsMaxTriggerStateCardinality" + EXCEEDS_MAX_EVENT_STATES_LIMIT = "exceedsMaxEventStatesLimit" + DESTINATION_PER_DAY_REPORTING_LIMIT_REACHED = "destinationPerDayReportingLimitReached" def to_json(self) -> str: return self.value @@ -671,6 +854,289 @@ def from_json(cls, json: str) -> AttributionReportingSourceRegistrationResult: return cls(json) +class AttributionReportingSourceRegistrationTimeConfig(enum.Enum): + INCLUDE = "include" + EXCLUDE = "exclude" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> AttributionReportingSourceRegistrationTimeConfig: + return cls(json) + + +@dataclass +class AttributionReportingAggregatableValueDictEntry: + key: str + + #: number instead of integer because not all uint32 can be represented by + #: int + value: float + + filtering_id: UnsignedInt64AsBase10 + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['key'] = self.key + json['value'] = self.value + json['filteringId'] = self.filtering_id.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingAggregatableValueDictEntry: + return cls( + key=str(json['key']), + value=float(json['value']), + filtering_id=UnsignedInt64AsBase10.from_json(json['filteringId']), + ) + + +@dataclass +class AttributionReportingAggregatableValueEntry: + values: typing.List[AttributionReportingAggregatableValueDictEntry] + + filters: AttributionReportingFilterPair + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['values'] = [i.to_json() for i in self.values] + json['filters'] = self.filters.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingAggregatableValueEntry: + return cls( + values=[AttributionReportingAggregatableValueDictEntry.from_json(i) for i in json['values']], + filters=AttributionReportingFilterPair.from_json(json['filters']), + ) + + +@dataclass +class AttributionReportingEventTriggerData: + data: UnsignedInt64AsBase10 + + priority: SignedInt64AsBase10 + + filters: AttributionReportingFilterPair + + dedup_key: typing.Optional[UnsignedInt64AsBase10] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['data'] = self.data.to_json() + json['priority'] = self.priority.to_json() + json['filters'] = self.filters.to_json() + if self.dedup_key is not None: + json['dedupKey'] = self.dedup_key.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingEventTriggerData: + return cls( + data=UnsignedInt64AsBase10.from_json(json['data']), + priority=SignedInt64AsBase10.from_json(json['priority']), + filters=AttributionReportingFilterPair.from_json(json['filters']), + dedup_key=UnsignedInt64AsBase10.from_json(json['dedupKey']) if json.get('dedupKey', None) is not None else None, + ) + + +@dataclass +class AttributionReportingAggregatableTriggerData: + key_piece: UnsignedInt128AsBase16 + + source_keys: typing.List[str] + + filters: AttributionReportingFilterPair + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['keyPiece'] = self.key_piece.to_json() + json['sourceKeys'] = [i for i in self.source_keys] + json['filters'] = self.filters.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingAggregatableTriggerData: + return cls( + key_piece=UnsignedInt128AsBase16.from_json(json['keyPiece']), + source_keys=[str(i) for i in json['sourceKeys']], + filters=AttributionReportingFilterPair.from_json(json['filters']), + ) + + +@dataclass +class AttributionReportingAggregatableDedupKey: + filters: AttributionReportingFilterPair + + dedup_key: typing.Optional[UnsignedInt64AsBase10] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['filters'] = self.filters.to_json() + if self.dedup_key is not None: + json['dedupKey'] = self.dedup_key.to_json() + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingAggregatableDedupKey: + return cls( + filters=AttributionReportingFilterPair.from_json(json['filters']), + dedup_key=UnsignedInt64AsBase10.from_json(json['dedupKey']) if json.get('dedupKey', None) is not None else None, + ) + + +@dataclass +class AttributionReportingTriggerRegistration: + filters: AttributionReportingFilterPair + + aggregatable_dedup_keys: typing.List[AttributionReportingAggregatableDedupKey] + + event_trigger_data: typing.List[AttributionReportingEventTriggerData] + + aggregatable_trigger_data: typing.List[AttributionReportingAggregatableTriggerData] + + aggregatable_values: typing.List[AttributionReportingAggregatableValueEntry] + + aggregatable_filtering_id_max_bytes: int + + debug_reporting: bool + + source_registration_time_config: AttributionReportingSourceRegistrationTimeConfig + + aggregatable_debug_reporting_config: AttributionReportingAggregatableDebugReportingConfig + + scopes: typing.List[str] + + debug_key: typing.Optional[UnsignedInt64AsBase10] = None + + aggregation_coordinator_origin: typing.Optional[str] = None + + trigger_context_id: typing.Optional[str] = None + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['filters'] = self.filters.to_json() + json['aggregatableDedupKeys'] = [i.to_json() for i in self.aggregatable_dedup_keys] + json['eventTriggerData'] = [i.to_json() for i in self.event_trigger_data] + json['aggregatableTriggerData'] = [i.to_json() for i in self.aggregatable_trigger_data] + json['aggregatableValues'] = [i.to_json() for i in self.aggregatable_values] + json['aggregatableFilteringIdMaxBytes'] = self.aggregatable_filtering_id_max_bytes + json['debugReporting'] = self.debug_reporting + json['sourceRegistrationTimeConfig'] = self.source_registration_time_config.to_json() + json['aggregatableDebugReportingConfig'] = self.aggregatable_debug_reporting_config.to_json() + json['scopes'] = [i for i in self.scopes] + if self.debug_key is not None: + json['debugKey'] = self.debug_key.to_json() + if self.aggregation_coordinator_origin is not None: + json['aggregationCoordinatorOrigin'] = self.aggregation_coordinator_origin + if self.trigger_context_id is not None: + json['triggerContextId'] = self.trigger_context_id + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingTriggerRegistration: + return cls( + filters=AttributionReportingFilterPair.from_json(json['filters']), + aggregatable_dedup_keys=[AttributionReportingAggregatableDedupKey.from_json(i) for i in json['aggregatableDedupKeys']], + event_trigger_data=[AttributionReportingEventTriggerData.from_json(i) for i in json['eventTriggerData']], + aggregatable_trigger_data=[AttributionReportingAggregatableTriggerData.from_json(i) for i in json['aggregatableTriggerData']], + aggregatable_values=[AttributionReportingAggregatableValueEntry.from_json(i) for i in json['aggregatableValues']], + aggregatable_filtering_id_max_bytes=int(json['aggregatableFilteringIdMaxBytes']), + debug_reporting=bool(json['debugReporting']), + source_registration_time_config=AttributionReportingSourceRegistrationTimeConfig.from_json(json['sourceRegistrationTimeConfig']), + aggregatable_debug_reporting_config=AttributionReportingAggregatableDebugReportingConfig.from_json(json['aggregatableDebugReportingConfig']), + scopes=[str(i) for i in json['scopes']], + debug_key=UnsignedInt64AsBase10.from_json(json['debugKey']) if json.get('debugKey', None) is not None else None, + aggregation_coordinator_origin=str(json['aggregationCoordinatorOrigin']) if json.get('aggregationCoordinatorOrigin', None) is not None else None, + trigger_context_id=str(json['triggerContextId']) if json.get('triggerContextId', None) is not None else None, + ) + + +class AttributionReportingEventLevelResult(enum.Enum): + SUCCESS = "success" + SUCCESS_DROPPED_LOWER_PRIORITY = "successDroppedLowerPriority" + INTERNAL_ERROR = "internalError" + NO_CAPACITY_FOR_ATTRIBUTION_DESTINATION = "noCapacityForAttributionDestination" + NO_MATCHING_SOURCES = "noMatchingSources" + DEDUPLICATED = "deduplicated" + EXCESSIVE_ATTRIBUTIONS = "excessiveAttributions" + PRIORITY_TOO_LOW = "priorityTooLow" + NEVER_ATTRIBUTED_SOURCE = "neverAttributedSource" + EXCESSIVE_REPORTING_ORIGINS = "excessiveReportingOrigins" + NO_MATCHING_SOURCE_FILTER_DATA = "noMatchingSourceFilterData" + PROHIBITED_BY_BROWSER_POLICY = "prohibitedByBrowserPolicy" + NO_MATCHING_CONFIGURATIONS = "noMatchingConfigurations" + EXCESSIVE_REPORTS = "excessiveReports" + FALSELY_ATTRIBUTED_SOURCE = "falselyAttributedSource" + REPORT_WINDOW_PASSED = "reportWindowPassed" + NOT_REGISTERED = "notRegistered" + REPORT_WINDOW_NOT_STARTED = "reportWindowNotStarted" + NO_MATCHING_TRIGGER_DATA = "noMatchingTriggerData" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> AttributionReportingEventLevelResult: + return cls(json) + + +class AttributionReportingAggregatableResult(enum.Enum): + SUCCESS = "success" + INTERNAL_ERROR = "internalError" + NO_CAPACITY_FOR_ATTRIBUTION_DESTINATION = "noCapacityForAttributionDestination" + NO_MATCHING_SOURCES = "noMatchingSources" + EXCESSIVE_ATTRIBUTIONS = "excessiveAttributions" + EXCESSIVE_REPORTING_ORIGINS = "excessiveReportingOrigins" + NO_HISTOGRAMS = "noHistograms" + INSUFFICIENT_BUDGET = "insufficientBudget" + INSUFFICIENT_NAMED_BUDGET = "insufficientNamedBudget" + NO_MATCHING_SOURCE_FILTER_DATA = "noMatchingSourceFilterData" + NOT_REGISTERED = "notRegistered" + PROHIBITED_BY_BROWSER_POLICY = "prohibitedByBrowserPolicy" + DEDUPLICATED = "deduplicated" + REPORT_WINDOW_PASSED = "reportWindowPassed" + EXCESSIVE_REPORTS = "excessiveReports" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> AttributionReportingAggregatableResult: + return cls(json) + + +@dataclass +class RelatedWebsiteSet: + ''' + A single Related Website Set object. + ''' + #: The primary site of this set, along with the ccTLDs if there is any. + primary_sites: typing.List[str] + + #: The associated sites of this set, along with the ccTLDs if there is any. + associated_sites: typing.List[str] + + #: The service sites of this set, along with the ccTLDs if there is any. + service_sites: typing.List[str] + + def to_json(self) -> T_JSON_DICT: + json: T_JSON_DICT = dict() + json['primarySites'] = [i for i in self.primary_sites] + json['associatedSites'] = [i for i in self.associated_sites] + json['serviceSites'] = [i for i in self.service_sites] + return json + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> RelatedWebsiteSet: + return cls( + primary_sites=[str(i) for i in json['primarySites']], + associated_sites=[str(i) for i in json['associatedSites']], + service_sites=[str(i) for i in json['serviceSites']], + ) + + def get_storage_key_for_frame( frame_id: page.FrameId ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,SerializedStorageKey]: @@ -1018,7 +1484,7 @@ def clear_trust_tokens( def get_interest_group_details( owner_origin: str, name: str - ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,InterestGroupDetails]: + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,dict]: ''' Gets details for a named interest group. @@ -1026,7 +1492,7 @@ def get_interest_group_details( :param owner_origin: :param name: - :returns: + :returns: This largely corresponds to: https://wicg.github.io/turtledove/#dictdef-generatebidinterestgroup but has absolute expirationTime instead of relative lifetimeMs and also adds joiningOrigin. ''' params: T_JSON_DICT = dict() params['ownerOrigin'] = owner_origin @@ -1036,7 +1502,7 @@ def get_interest_group_details( 'params': params, } json = yield cmd_dict - return InterestGroupDetails.from_json(json['details']) + return dict(json['details']) def set_interest_group_tracking( @@ -1058,6 +1524,26 @@ def set_interest_group_tracking( json = yield cmd_dict +def set_interest_group_auction_tracking( + enable: bool + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Enables/Disables issuing of interestGroupAuctionEventOccurred and + interestGroupAuctionNetworkRequestCreated. + + **EXPERIMENTAL** + + :param enable: + ''' + params: T_JSON_DICT = dict() + params['enable'] = enable + cmd_dict: T_JSON_DICT = { + 'method': 'Storage.setInterestGroupAuctionTracking', + 'params': params, + } + json = yield cmd_dict + + def get_shared_storage_metadata( owner_origin: str ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,SharedStorageMetadata]: @@ -1302,6 +1788,64 @@ def set_attribution_reporting_tracking( json = yield cmd_dict +def send_pending_attribution_reports() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,int]: + ''' + Sends all pending Attribution Reports immediately, regardless of their + scheduled report time. + + **EXPERIMENTAL** + + :returns: The number of reports that were sent. + ''' + cmd_dict: T_JSON_DICT = { + 'method': 'Storage.sendPendingAttributionReports', + } + json = yield cmd_dict + return int(json['numSent']) + + +def get_related_website_sets() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[RelatedWebsiteSet]]: + ''' + Returns the effective Related Website Sets in use by this profile for the browser + session. The effective Related Website Sets will not change during a browser session. + + **EXPERIMENTAL** + + :returns: + ''' + cmd_dict: T_JSON_DICT = { + 'method': 'Storage.getRelatedWebsiteSets', + } + json = yield cmd_dict + return [RelatedWebsiteSet.from_json(i) for i in json['sets']] + + +def get_affected_urls_for_third_party_cookie_metadata( + first_party_url: str, + third_party_urls: typing.List[str] + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[str]]: + ''' + Returns the list of URLs from a page and its embedded resources that match + existing grace period URL pattern rules. + https://developers.google.com/privacy-sandbox/cookies/temporary-exceptions/grace-period + + **EXPERIMENTAL** + + :param first_party_url: The URL of the page currently being visited. + :param third_party_urls: The list of embedded resource URLs from the page. + :returns: Array of matching URLs. If there is a primary pattern match for the first- party URL, only the first-party URL is returned in the array. + ''' + params: T_JSON_DICT = dict() + params['firstPartyUrl'] = first_party_url + params['thirdPartyUrls'] = [i for i in third_party_urls] + cmd_dict: T_JSON_DICT = { + 'method': 'Storage.getAffectedUrlsForThirdPartyCookieMetadata', + 'params': params, + } + json = yield cmd_dict + return [str(i) for i in json['matchedUrls']] + + @event_class('Storage.cacheStorageContentUpdated') @dataclass class CacheStorageContentUpdated: @@ -1403,12 +1947,21 @@ def from_json(cls, json: T_JSON_DICT) -> IndexedDBListUpdated: @dataclass class InterestGroupAccessed: ''' - One of the interest groups was accessed by the associated page. + One of the interest groups was accessed. Note that these events are global + to all targets sharing an interest group store. ''' access_time: network.TimeSinceEpoch type_: InterestGroupAccessType owner_origin: str name: str + #: For topLevelBid/topLevelAdditionalBid, and when appropriate, + #: win and additionalBidWin + component_seller_origin: typing.Optional[str] + #: For bid or somethingBid event, if done locally and not on a server. + bid: typing.Optional[float] + bid_currency: typing.Optional[str] + #: For non-global events --- links to interestGroupAuctionEvent + unique_auction_id: typing.Optional[InterestGroupAuctionId] @classmethod def from_json(cls, json: T_JSON_DICT) -> InterestGroupAccessed: @@ -1416,7 +1969,62 @@ def from_json(cls, json: T_JSON_DICT) -> InterestGroupAccessed: access_time=network.TimeSinceEpoch.from_json(json['accessTime']), type_=InterestGroupAccessType.from_json(json['type']), owner_origin=str(json['ownerOrigin']), - name=str(json['name']) + name=str(json['name']), + component_seller_origin=str(json['componentSellerOrigin']) if json.get('componentSellerOrigin', None) is not None else None, + bid=float(json['bid']) if json.get('bid', None) is not None else None, + bid_currency=str(json['bidCurrency']) if json.get('bidCurrency', None) is not None else None, + unique_auction_id=InterestGroupAuctionId.from_json(json['uniqueAuctionId']) if json.get('uniqueAuctionId', None) is not None else None + ) + + +@event_class('Storage.interestGroupAuctionEventOccurred') +@dataclass +class InterestGroupAuctionEventOccurred: + ''' + An auction involving interest groups is taking place. These events are + target-specific. + ''' + event_time: network.TimeSinceEpoch + type_: InterestGroupAuctionEventType + unique_auction_id: InterestGroupAuctionId + #: Set for child auctions. + parent_auction_id: typing.Optional[InterestGroupAuctionId] + #: Set for started and configResolved + auction_config: typing.Optional[dict] + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> InterestGroupAuctionEventOccurred: + return cls( + event_time=network.TimeSinceEpoch.from_json(json['eventTime']), + type_=InterestGroupAuctionEventType.from_json(json['type']), + unique_auction_id=InterestGroupAuctionId.from_json(json['uniqueAuctionId']), + parent_auction_id=InterestGroupAuctionId.from_json(json['parentAuctionId']) if json.get('parentAuctionId', None) is not None else None, + auction_config=dict(json['auctionConfig']) if json.get('auctionConfig', None) is not None else None + ) + + +@event_class('Storage.interestGroupAuctionNetworkRequestCreated') +@dataclass +class InterestGroupAuctionNetworkRequestCreated: + ''' + Specifies which auctions a particular network fetch may be related to, and + in what role. Note that it is not ordered with respect to + Network.requestWillBeSent (but will happen before loadingFinished + loadingFailed). + ''' + type_: InterestGroupAuctionFetchType + request_id: network.RequestId + #: This is the set of the auctions using the worklet that issued this + #: request. In the case of trusted signals, it's possible that only some of + #: them actually care about the keys being queried. + auctions: typing.List[InterestGroupAuctionId] + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> InterestGroupAuctionNetworkRequestCreated: + return cls( + type_=InterestGroupAuctionFetchType.from_json(json['type']), + request_id=network.RequestId.from_json(json['requestId']), + auctions=[InterestGroupAuctionId.from_json(i) for i in json['auctions']] ) @@ -1435,7 +2043,7 @@ class SharedStorageAccessed: main_frame_id: page.FrameId #: Serialized origin for the context that invoked the Shared Storage API. owner_origin: str - #: The sub-parameters warapped by ``params`` are all optional and their + #: The sub-parameters wrapped by ``params`` are all optional and their #: presence/absence depends on ``type``. params: SharedStorageAccessParams @@ -1480,8 +2088,7 @@ class AttributionReportingSourceRegistered: ''' **EXPERIMENTAL** - TODO(crbug.com/1458532): Add other Attribution Reporting events, e.g. - trigger registration. + ''' registration: AttributionReportingSourceRegistration result: AttributionReportingSourceRegistrationResult @@ -1492,3 +2099,24 @@ def from_json(cls, json: T_JSON_DICT) -> AttributionReportingSourceRegistered: registration=AttributionReportingSourceRegistration.from_json(json['registration']), result=AttributionReportingSourceRegistrationResult.from_json(json['result']) ) + + +@event_class('Storage.attributionReportingTriggerRegistered') +@dataclass +class AttributionReportingTriggerRegistered: + ''' + **EXPERIMENTAL** + + + ''' + registration: AttributionReportingTriggerRegistration + event_level: AttributionReportingEventLevelResult + aggregatable: AttributionReportingAggregatableResult + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> AttributionReportingTriggerRegistered: + return cls( + registration=AttributionReportingTriggerRegistration.from_json(json['registration']), + event_level=AttributionReportingEventLevelResult.from_json(json['eventLevel']), + aggregatable=AttributionReportingAggregatableResult.from_json(json['aggregatable']) + ) diff --git a/pycdp/cdp/target.py b/pycdp/cdp/target.py index 13bb14c..e0deed0 100644 --- a/pycdp/cdp/target.py +++ b/pycdp/cdp/target.py @@ -47,6 +47,7 @@ def __repr__(self): class TargetInfo: target_id: TargetID + #: List of types: https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_agent_host_impl.cc?ss=chromium&q=f:devtools%20-f:out%20%22::kTypeTab%5B%5D%22 type_: str title: str @@ -68,7 +69,7 @@ class TargetInfo: browser_context_id: typing.Optional[browser.BrowserContextID] = None #: Provides additional details for specific target types. For example, for - #: the type of "page", this may be set to "portal" or "prerender". + #: the type of "page", this may be set to "prerender". subtype: typing.Optional[str] = None def to_json(self) -> T_JSON_DICT: @@ -110,7 +111,7 @@ class FilterEntry: ''' A filter used by target query/discovery/auto-attach operations. ''' - #: If set, causes exclusion of mathcing targets from the list. + #: If set, causes exclusion of matching targets from the list. exclude: typing.Optional[bool] = None #: If not present, matches any type. @@ -172,6 +173,23 @@ def from_json(cls, json: T_JSON_DICT) -> RemoteLocation: ) +class WindowState(enum.Enum): + ''' + The state of the target window. + ''' + NORMAL = "normal" + MINIMIZED = "minimized" + MAXIMIZED = "maximized" + FULLSCREEN = "fullscreen" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> WindowState: + return cls(json) + + def activate_target( target_id: TargetID ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: @@ -248,7 +266,8 @@ def close_target( def expose_dev_tools_protocol( target_id: TargetID, - binding_name: typing.Optional[str] = None + binding_name: typing.Optional[str] = None, + inherit_permissions: typing.Optional[bool] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: ''' Inject object to the target's main frame that provides a communication @@ -256,7 +275,7 @@ def expose_dev_tools_protocol( Injected object will be available as ``window[bindingName]``. - The object has the follwing API: + The object has the following API: - ``binding.send(json)`` - a method to send messages over the remote debugging protocol - ``binding.onmessage = json => handleMessage(json)`` - a callback that will be called for the protocol notifications and command responses. @@ -264,11 +283,14 @@ def expose_dev_tools_protocol( :param target_id: :param binding_name: *(Optional)* Binding name, 'cdp' if not specified. + :param inherit_permissions: *(Optional)* If true, inherits the current root session's permissions (default: false). ''' params: T_JSON_DICT = dict() params['targetId'] = target_id.to_json() if binding_name is not None: params['bindingName'] = binding_name + if inherit_permissions is not None: + params['inheritPermissions'] = inherit_permissions cmd_dict: T_JSON_DICT = { 'method': 'Target.exposeDevToolsProtocol', 'params': params, @@ -286,12 +308,10 @@ def create_browser_context( Creates a new empty BrowserContext. Similar to an incognito profile but you can have more than one. - **EXPERIMENTAL** - - :param dispose_on_detach: *(Optional)* If specified, disposes this context when debugging session disconnects. - :param proxy_server: *(Optional)* Proxy server, similar to the one passed to --proxy-server - :param proxy_bypass_list: *(Optional)* Proxy bypass list, similar to the one passed to --proxy-bypass-list - :param origins_with_universal_network_access: *(Optional)* An optional list of origins to grant unlimited cross-origin access to. Parts of the URL other than those constituting origin are ignored. + :param dispose_on_detach: **(EXPERIMENTAL)** *(Optional)* If specified, disposes this context when debugging session disconnects. + :param proxy_server: **(EXPERIMENTAL)** *(Optional)* Proxy server, similar to the one passed to --proxy-server + :param proxy_bypass_list: **(EXPERIMENTAL)** *(Optional)* Proxy bypass list, similar to the one passed to --proxy-bypass-list + :param origins_with_universal_network_access: **(EXPERIMENTAL)** *(Optional)* An optional list of origins to grant unlimited cross-origin access to. Parts of the URL other than those constituting origin are ignored. :returns: The id of the context created. ''' params: T_JSON_DICT = dict() @@ -315,8 +335,6 @@ def get_browser_contexts() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Li ''' Returns all browser contexts created with ``Target.createBrowserContext`` method. - **EXPERIMENTAL** - :returns: An array of browser context ids. ''' cmd_dict: T_JSON_DICT = { @@ -328,8 +346,11 @@ def get_browser_contexts() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Li def create_target( url: str, + left: typing.Optional[int] = None, + top: typing.Optional[int] = None, width: typing.Optional[int] = None, height: typing.Optional[int] = None, + window_state: typing.Optional[WindowState] = None, browser_context_id: typing.Optional[browser.BrowserContextID] = None, enable_begin_frame_control: typing.Optional[bool] = None, new_window: typing.Optional[bool] = None, @@ -340,21 +361,30 @@ def create_target( Creates a new page. :param url: The initial URL the page will be navigated to. An empty string indicates about:blank. - :param width: *(Optional)* Frame width in DIP (headless chrome only). - :param height: *(Optional)* Frame height in DIP (headless chrome only). + :param left: **(EXPERIMENTAL)** *(Optional)* Frame left origin in DIP (requires newWindow to be true or headless shell). + :param top: **(EXPERIMENTAL)** *(Optional)* Frame top origin in DIP (requires newWindow to be true or headless shell). + :param width: *(Optional)* Frame width in DIP (requires newWindow to be true or headless shell). + :param height: *(Optional)* Frame height in DIP (requires newWindow to be true or headless shell). + :param window_state: *(Optional)* Frame window state (requires newWindow to be true or headless shell). Default is normal. :param browser_context_id: **(EXPERIMENTAL)** *(Optional)* The browser context to create the page in. - :param enable_begin_frame_control: **(EXPERIMENTAL)** *(Optional)* Whether BeginFrames for this target will be controlled via DevTools (headless chrome only, not supported on MacOS yet, false by default). - :param new_window: *(Optional)* Whether to create a new Window or Tab (chrome-only, false by default). - :param background: *(Optional)* Whether to create the target in background or foreground (chrome-only, false by default). + :param enable_begin_frame_control: **(EXPERIMENTAL)** *(Optional)* Whether BeginFrames for this target will be controlled via DevTools (headless shell only, not supported on MacOS yet, false by default). + :param new_window: *(Optional)* Whether to create a new Window or Tab (false by default, not supported by headless shell). + :param background: *(Optional)* Whether to create the target in background or foreground (false by default, not supported by headless shell). :param for_tab: **(EXPERIMENTAL)** *(Optional)* Whether to create the target of type "tab". :returns: The id of the page opened. ''' params: T_JSON_DICT = dict() params['url'] = url + if left is not None: + params['left'] = left + if top is not None: + params['top'] = top if width is not None: params['width'] = width if height is not None: params['height'] = height + if window_state is not None: + params['windowState'] = window_state.to_json() if browser_context_id is not None: params['browserContextId'] = browser_context_id.to_json() if enable_begin_frame_control is not None: @@ -402,8 +432,6 @@ def dispose_browser_context( Deletes a BrowserContext. All the belonging pages will be closed without calling their beforeunload hooks. - **EXPERIMENTAL** - :param browser_context_id: ''' params: T_JSON_DICT = dict() @@ -500,11 +528,9 @@ def set_auto_attach( This also clears all targets added by ``autoAttachRelated`` from the list of targets to watch for creation of related targets. - **EXPERIMENTAL** - :param auto_attach: Whether to auto-attach to related targets. :param wait_for_debugger_on_start: Whether to pause new targets when attaching to them. Use ```Runtime.runIfWaitingForDebugger``` to run paused targets. - :param flatten: *(Optional)* Enables "flat" access to the session via specifying sessionId attribute in the commands. We plan to make this the default, deprecate non-flattened mode, and eventually retire it. See crbug.com/991325. + :param flatten: **(EXPERIMENTAL)** *(Optional)* Enables "flat" access to the session via specifying sessionId attribute in the commands. We plan to make this the default, deprecate non-flattened mode, and eventually retire it. See crbug.com/991325. :param filter_: **(EXPERIMENTAL)** *(Optional)* Only targets matching filter will be attached. ''' params: T_JSON_DICT = dict() diff --git a/pycdp/cdp/tracing.py b/pycdp/cdp/tracing.py index d69a605..35d5ec5 100644 --- a/pycdp/cdp/tracing.py +++ b/pycdp/cdp/tracing.py @@ -3,7 +3,7 @@ # This file is generated from the CDP specification. If you need to make # changes, edit the generator and regenerate all of the modules. # -# CDP domain: Tracing (experimental) +# CDP domain: Tracing from __future__ import annotations import enum @@ -179,6 +179,8 @@ def get_categories() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[str ''' Gets supported tracing categories. + **EXPERIMENTAL** + :returns: A list of supported tracing categories. ''' cmd_dict: T_JSON_DICT = { @@ -194,6 +196,8 @@ def record_clock_sync_marker( ''' Record a clock sync marker in the trace. + **EXPERIMENTAL** + :param sync_id: The ID of this clock sync marker ''' params: T_JSON_DICT = dict() @@ -212,6 +216,8 @@ def request_memory_dump( ''' Request a global memory dump. + **EXPERIMENTAL** + :param deterministic: *(Optional)* Enables more deterministic results by forcing garbage collection :param level_of_detail: *(Optional)* Specifies level of details in memory dump. Defaults to "detailed". :returns: A tuple with the following items: @@ -249,15 +255,15 @@ def start( ''' Start trace events collection. - :param categories: **(DEPRECATED)** *(Optional)* Category/tag filter - :param options: **(DEPRECATED)** *(Optional)* Tracing options - :param buffer_usage_reporting_interval: *(Optional)* If set, the agent will issue bufferUsage events at this interval, specified in milliseconds + :param categories: **(DEPRECATED)** **(EXPERIMENTAL)** *(Optional)* Category/tag filter + :param options: **(DEPRECATED)** **(EXPERIMENTAL)** *(Optional)* Tracing options + :param buffer_usage_reporting_interval: **(EXPERIMENTAL)** *(Optional)* If set, the agent will issue bufferUsage events at this interval, specified in milliseconds :param transfer_mode: *(Optional)* Whether to report trace events as series of dataCollected events or to save trace to a stream (defaults to ```ReportEvents````). :param stream_format: *(Optional)* Trace data format to use. This only applies when using ````ReturnAsStream```` transfer mode (defaults to ````json````). - :param stream_compression: *(Optional)* Compression format to use. This only applies when using ````ReturnAsStream```` transfer mode (defaults to ````none````) + :param stream_compression: **(EXPERIMENTAL)** *(Optional)* Compression format to use. This only applies when using ````ReturnAsStream```` transfer mode (defaults to ````none````) :param trace_config: *(Optional)* - :param perfetto_config: *(Optional)* Base64-encoded serialized perfetto.protos.TraceConfig protobuf message When specified, the parameters ````categories````, ````options````, ````traceConfig```` are ignored. (Encoded as a base64 string when passed over JSON) - :param tracing_backend: *(Optional)* Backend type (defaults to ````auto```) + :param perfetto_config: **(EXPERIMENTAL)** *(Optional)* Base64-encoded serialized perfetto.protos.TraceConfig protobuf message When specified, the parameters ````categories````, ````options````, ````traceConfig```` are ignored. (Encoded as a base64 string when passed over JSON) + :param tracing_backend: **(EXPERIMENTAL)** *(Optional)* Backend type (defaults to ````auto```) ''' params: T_JSON_DICT = dict() if categories is not None: @@ -288,6 +294,11 @@ def start( @event_class('Tracing.bufferUsage') @dataclass class BufferUsage: + ''' + **EXPERIMENTAL** + + + ''' #: A number in range [0..1] that indicates the used size of event buffer as a fraction of its #: total size. percent_full: typing.Optional[float] @@ -310,6 +321,8 @@ def from_json(cls, json: T_JSON_DICT) -> BufferUsage: @dataclass class DataCollected: ''' + **EXPERIMENTAL** + Contains a bucket of collected trace events. When tracing is stopped collected events will be sent as a sequence of dataCollected events followed by tracingComplete event. ''' diff --git a/pycdp/cdp/util.py b/pycdp/cdp/util.py index 82c9de3..1af0255 100644 --- a/pycdp/cdp/util.py +++ b/pycdp/cdp/util.py @@ -5,6 +5,49 @@ _event_parsers = dict() +class UnknownObject: + def __init__(self, elements: dict): + self._elements = elements + + def __getattr__(self, name): + # some names are appended a `_` so they don't collide with the python namespace + # example: id_ and type_ + name = name.removesuffix('_') + + if name not in self._elements: + raise AttributeError + + return self._elements[name] + + @classmethod + def from_json(cls, json: T_JSON_DICT): + if isinstance(json, dict): + value = {key: cls.from_json(val) for key, val in json.items()} + obj = cls(value) + elif isinstance(json, list): + obj = [cls.from_json(val) for val in json] + else: + obj = json + + return obj + + +class UnknownEvent(UnknownObject): + def __init__(self, name, elements): + super().__init__(elements) + self.name = name + + @classmethod + def from_json(cls, json: T_JSON_DICT): + name = json['method'] + obj = UnknownObject.from_json(json['params']) + + if isinstance(obj, UnknownObject): + return cls(name, obj._elements) + + return obj + + def event_class(method): ''' A decorator that registers a class as an event class. ''' def decorate(cls): @@ -15,4 +58,7 @@ def decorate(cls): def parse_json_event(json: T_JSON_DICT) -> typing.Any: ''' Parse a JSON dictionary into a CDP event. ''' + if json['method'] not in _event_parsers: + return UnknownEvent.from_json(json) + return _event_parsers[json['method']].from_json(json['params']) diff --git a/pycdp/cdp/web_audio.py b/pycdp/cdp/web_audio.py index 011f52c..c2489d3 100644 --- a/pycdp/cdp/web_audio.py +++ b/pycdp/cdp/web_audio.py @@ -49,6 +49,7 @@ class ContextState(enum.Enum): SUSPENDED = "suspended" RUNNING = "running" CLOSED = "closed" + INTERRUPTED = "interrupted" def to_json(self) -> str: return self.value diff --git a/pycdp/cdp/web_authn.py b/pycdp/cdp/web_authn.py index 2e2f5a1..ec501b9 100644 --- a/pycdp/cdp/web_authn.py +++ b/pycdp/cdp/web_authn.py @@ -106,6 +106,16 @@ class VirtualAuthenticatorOptions: #: Defaults to false. is_user_verified: typing.Optional[bool] = None + #: Credentials created by this authenticator will have the backup + #: eligibility (BE) flag set to this value. Defaults to false. + #: https://w3c.github.io/webauthn/#sctn-credential-backup + default_backup_eligibility: typing.Optional[bool] = None + + #: Credentials created by this authenticator will have the backup state + #: (BS) flag set to this value. Defaults to false. + #: https://w3c.github.io/webauthn/#sctn-credential-backup + default_backup_state: typing.Optional[bool] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['protocol'] = self.protocol.to_json() @@ -128,6 +138,10 @@ def to_json(self) -> T_JSON_DICT: json['automaticPresenceSimulation'] = self.automatic_presence_simulation if self.is_user_verified is not None: json['isUserVerified'] = self.is_user_verified + if self.default_backup_eligibility is not None: + json['defaultBackupEligibility'] = self.default_backup_eligibility + if self.default_backup_state is not None: + json['defaultBackupState'] = self.default_backup_state return json @classmethod @@ -144,6 +158,8 @@ def from_json(cls, json: T_JSON_DICT) -> VirtualAuthenticatorOptions: has_prf=bool(json['hasPrf']) if json.get('hasPrf', None) is not None else None, automatic_presence_simulation=bool(json['automaticPresenceSimulation']) if json.get('automaticPresenceSimulation', None) is not None else None, is_user_verified=bool(json['isUserVerified']) if json.get('isUserVerified', None) is not None else None, + default_backup_eligibility=bool(json['defaultBackupEligibility']) if json.get('defaultBackupEligibility', None) is not None else None, + default_backup_state=bool(json['defaultBackupState']) if json.get('defaultBackupState', None) is not None else None, ) @@ -173,6 +189,25 @@ class Credential: #: See https://w3c.github.io/webauthn/#sctn-large-blob-extension (Encoded as a base64 string when passed over JSON) large_blob: typing.Optional[str] = None + #: Assertions returned by this credential will have the backup eligibility + #: (BE) flag set to this value. Defaults to the authenticator's + #: defaultBackupEligibility value. + backup_eligibility: typing.Optional[bool] = None + + #: Assertions returned by this credential will have the backup state (BS) + #: flag set to this value. Defaults to the authenticator's + #: defaultBackupState value. + backup_state: typing.Optional[bool] = None + + #: The credential's user.name property. Equivalent to empty if not set. + #: https://w3c.github.io/webauthn/#dom-publickeycredentialentity-name + user_name: typing.Optional[str] = None + + #: The credential's user.displayName property. Equivalent to empty if + #: not set. + #: https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-displayname + user_display_name: typing.Optional[str] = None + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['credentialId'] = self.credential_id @@ -185,6 +220,14 @@ def to_json(self) -> T_JSON_DICT: json['userHandle'] = self.user_handle if self.large_blob is not None: json['largeBlob'] = self.large_blob + if self.backup_eligibility is not None: + json['backupEligibility'] = self.backup_eligibility + if self.backup_state is not None: + json['backupState'] = self.backup_state + if self.user_name is not None: + json['userName'] = self.user_name + if self.user_display_name is not None: + json['userDisplayName'] = self.user_display_name return json @classmethod @@ -197,6 +240,10 @@ def from_json(cls, json: T_JSON_DICT) -> Credential: rp_id=str(json['rpId']) if json.get('rpId', None) is not None else None, user_handle=str(json['userHandle']) if json.get('userHandle', None) is not None else None, large_blob=str(json['largeBlob']) if json.get('largeBlob', None) is not None else None, + backup_eligibility=bool(json['backupEligibility']) if json.get('backupEligibility', None) is not None else None, + backup_state=bool(json['backupState']) if json.get('backupState', None) is not None else None, + user_name=str(json['userName']) if json.get('userName', None) is not None else None, + user_display_name=str(json['userDisplayName']) if json.get('userDisplayName', None) is not None else None, ) @@ -435,6 +482,35 @@ def set_automatic_presence_simulation( json = yield cmd_dict +def set_credential_properties( + authenticator_id: AuthenticatorId, + credential_id: str, + backup_eligibility: typing.Optional[bool] = None, + backup_state: typing.Optional[bool] = None + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Allows setting credential properties. + https://w3c.github.io/webauthn/#sctn-automation-set-credential-properties + + :param authenticator_id: + :param credential_id: + :param backup_eligibility: *(Optional)* + :param backup_state: *(Optional)* + ''' + params: T_JSON_DICT = dict() + params['authenticatorId'] = authenticator_id.to_json() + params['credentialId'] = credential_id + if backup_eligibility is not None: + params['backupEligibility'] = backup_eligibility + if backup_state is not None: + params['backupState'] = backup_state + cmd_dict: T_JSON_DICT = { + 'method': 'WebAuthn.setCredentialProperties', + 'params': params, + } + json = yield cmd_dict + + @event_class('WebAuthn.credentialAdded') @dataclass class CredentialAdded: @@ -452,6 +528,42 @@ def from_json(cls, json: T_JSON_DICT) -> CredentialAdded: ) +@event_class('WebAuthn.credentialDeleted') +@dataclass +class CredentialDeleted: + ''' + Triggered when a credential is deleted, e.g. through + PublicKeyCredential.signalUnknownCredential(). + ''' + authenticator_id: AuthenticatorId + credential_id: str + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CredentialDeleted: + return cls( + authenticator_id=AuthenticatorId.from_json(json['authenticatorId']), + credential_id=str(json['credentialId']) + ) + + +@event_class('WebAuthn.credentialUpdated') +@dataclass +class CredentialUpdated: + ''' + Triggered when a credential is updated, e.g. through + PublicKeyCredential.signalCurrentUserDetails(). + ''' + authenticator_id: AuthenticatorId + credential: Credential + + @classmethod + def from_json(cls, json: T_JSON_DICT) -> CredentialUpdated: + return cls( + authenticator_id=AuthenticatorId.from_json(json['authenticatorId']), + credential=Credential.from_json(json['credential']) + ) + + @event_class('WebAuthn.credentialAsserted') @dataclass class CredentialAsserted: diff --git a/pycdp/gen/browser_protocol.json b/pycdp/gen/browser_protocol.json index 35ee320..e16ad85 100644 --- a/pycdp/gen/browser_protocol.json +++ b/pycdp/gen/browser_protocol.json @@ -210,6 +210,7 @@ "description": "Values of AXProperty name:\n- from 'busy' to 'roledescription': states which apply to every AX node\n- from 'live' to 'root': attributes which apply to nodes in live regions\n- from 'autocomplete' to 'valuetext': attributes which apply to widgets\n- from 'checked' to 'selected': states which apply to widgets\n- from 'activedescendant' to 'owns' - relationships between elements other than parent/child/sibling.", "type": "string", "enum": [ + "actions", "busy", "disabled", "editable", @@ -248,7 +249,8 @@ "errormessage", "flowto", "labelledby", - "owns" + "owns", + "url" ] }, { @@ -407,7 +409,7 @@ }, { "name": "frameId", - "description": "The frame for whose document the AX tree should be retrieved.\nIf omited, the root frame is used.", + "description": "The frame for whose document the AX tree should be retrieved.\nIf omitted, the root frame is used.", "optional": true, "$ref": "Page.FrameId" } @@ -503,7 +505,7 @@ }, { "name": "queryAXTree", - "description": "Query a DOM node's accessibility subtree for accessible name and role.\nThis command computes the name and role for all nodes in the subtree, including those that are\nignored for accessibility, and returns those that mactch the specified name and role. If no DOM\nnode is specified, or the DOM node does not exist, the command returns an error. If neither\n`accessibleName` or `role` is specified, it returns all the accessibility nodes in the subtree.", + "description": "Query a DOM node's accessibility subtree for accessible name and role.\nThis command computes the name and role for all nodes in the subtree, including those that are\nignored for accessibility, and returns those that match the specified name and role. If no DOM\nnode is specified, or the DOM node does not exist, the command returns an error. If neither\n`accessibleName` or `role` is specified, it returns all the accessibility nodes in the subtree.", "experimental": true, "parameters": [ { @@ -619,7 +621,7 @@ }, { "name": "startTime", - "description": "`Animation`'s start time.", + "description": "`Animation`'s start time.\nMilliseconds for time based animations and\npercentage [0 - 100] for scroll driven animations\n(i.e. when viewOrScrollTimeline exists).", "type": "number" }, { @@ -648,6 +650,48 @@ "description": "A unique ID for `Animation` representing the sources that triggered this CSS\nanimation/transition.", "optional": true, "type": "string" + }, + { + "name": "viewOrScrollTimeline", + "description": "View or scroll timeline", + "optional": true, + "$ref": "ViewOrScrollTimeline" + } + ] + }, + { + "id": "ViewOrScrollTimeline", + "description": "Timeline instance", + "type": "object", + "properties": [ + { + "name": "sourceNodeId", + "description": "Scroll container node", + "optional": true, + "$ref": "DOM.BackendNodeId" + }, + { + "name": "startOffset", + "description": "Represents the starting scroll position of the timeline\nas a length offset in pixels from scroll origin.", + "optional": true, + "type": "number" + }, + { + "name": "endOffset", + "description": "Represents the ending scroll position of the timeline\nas a length offset in pixels from scroll origin.", + "optional": true, + "type": "number" + }, + { + "name": "subjectNodeId", + "description": "The element whose principal box's visibility in the\nscrollport defined the progress of the timeline.\nDoes not exist for animations with ScrollTimeline", + "optional": true, + "$ref": "DOM.BackendNodeId" + }, + { + "name": "axis", + "description": "Orientation of the scroll", + "$ref": "DOM.ScrollOrientation" } ] }, @@ -678,7 +722,7 @@ }, { "name": "duration", - "description": "`AnimationEffect`'s iteration duration.", + "description": "`AnimationEffect`'s iteration duration.\nMilliseconds for time based animations and\npercentage [0 - 100] for scroll driven animations\n(i.e. when viewOrScrollTimeline exists).", "type": "number" }, { @@ -923,6 +967,17 @@ "$ref": "Animation" } ] + }, + { + "name": "animationUpdated", + "description": "Event for animation that has been updated.", + "parameters": [ + { + "name": "animation", + "description": "Animation that was updated.", + "$ref": "Animation" + } + ] } ] }, @@ -962,11 +1017,11 @@ { "name": "requestId", "description": "The unique request id.", + "optional": true, "$ref": "Network.RequestId" }, { "name": "url", - "optional": true, "type": "string" } ] @@ -993,7 +1048,10 @@ "ExcludeInvalidSameParty", "ExcludeSamePartyCrossPartyContext", "ExcludeDomainNonASCII", - "ExcludeThirdPartyCookieBlockedInFirstPartySet" + "ExcludeThirdPartyCookieBlockedInFirstPartySet", + "ExcludeThirdPartyPhaseout", + "ExcludePortMismatch", + "ExcludeSchemeMismatch" ] }, { @@ -1010,7 +1068,10 @@ "WarnSameSiteLaxCrossDowngradeLax", "WarnAttributeValueExceedsMaxSize", "WarnDomainNonASCII", - "WarnThirdPartyPhaseout" + "WarnThirdPartyPhaseout", + "WarnCrossSiteRedirectDowngradeChangesInclusion", + "WarnDeprecationTrialMetadata", + "WarnThirdPartyCookieHeuristic" ] }, { @@ -1021,6 +1082,33 @@ "ReadCookie" ] }, + { + "id": "InsightType", + "description": "Represents the category of insight that a cookie issue falls under.", + "type": "string", + "enum": [ + "GitHubResource", + "GracePeriod", + "Heuristics" + ] + }, + { + "id": "CookieIssueInsight", + "description": "Information about the suggested solution to a cookie issue.", + "type": "object", + "properties": [ + { + "name": "type", + "$ref": "InsightType" + }, + { + "name": "tableEntryUrl", + "description": "Link to table entry in third-party cookie migration readiness list.", + "optional": true, + "type": "string" + } + ] + }, { "id": "CookieIssueDetails", "description": "This information is currently necessary, as the front-end has a difficult\ntime finding a specific cookie. With this, we can convey specific error\ninformation without the cookie.", @@ -1070,6 +1158,12 @@ "name": "request", "optional": true, "$ref": "AffectedRequest" + }, + { + "name": "insight", + "description": "The recommended solution to the issue.", + "optional": true, + "$ref": "CookieIssueInsight" } ] }, @@ -1098,6 +1192,7 @@ "Frame", "Image", "Import", + "JSON", "Manifest", "Ping", "PluginData", @@ -1107,6 +1202,7 @@ "Script", "ServiceWorker", "SharedWorker", + "SpeculationRules", "Stylesheet", "Track", "Video", @@ -1163,7 +1259,10 @@ "CoopSandboxedIFrameCannotNavigateToCoopPage", "CorpNotSameOrigin", "CorpNotSameOriginAfterDefaultedToSameOriginByCoep", - "CorpNotSameSite" + "CorpNotSameOriginAfterDefaultedToSameOriginByDip", + "CorpNotSameOriginAfterDefaultedToSameOriginByCoepAndDip", + "CorpNotSameSite", + "SRIMessageSignatureMismatch" ] }, { @@ -1236,6 +1335,7 @@ "kInlineViolation", "kEvalViolation", "kURLViolation", + "kSRIViolation", "kTrustedTypesSinkViolation", "kTrustedTypesPolicyViolation", "kWasmEvalViolation" @@ -1422,7 +1522,68 @@ "InvalidRegisterOsTriggerHeader", "WebAndOsHeaders", "NoWebOrOsSupport", - "NavigationRegistrationWithoutTransientUserActivation" + "NavigationRegistrationWithoutTransientUserActivation", + "InvalidInfoHeader", + "NoRegisterSourceHeader", + "NoRegisterTriggerHeader", + "NoRegisterOsSourceHeader", + "NoRegisterOsTriggerHeader", + "NavigationRegistrationUniqueScopeAlreadySet" + ] + }, + { + "id": "SharedDictionaryError", + "type": "string", + "enum": [ + "UseErrorCrossOriginNoCorsRequest", + "UseErrorDictionaryLoadFailure", + "UseErrorMatchingDictionaryNotUsed", + "UseErrorUnexpectedContentDictionaryHeader", + "WriteErrorCossOriginNoCorsRequest", + "WriteErrorDisallowedBySettings", + "WriteErrorExpiredResponse", + "WriteErrorFeatureDisabled", + "WriteErrorInsufficientResources", + "WriteErrorInvalidMatchField", + "WriteErrorInvalidStructuredHeader", + "WriteErrorNavigationRequest", + "WriteErrorNoMatchField", + "WriteErrorNonListMatchDestField", + "WriteErrorNonSecureContext", + "WriteErrorNonStringIdField", + "WriteErrorNonStringInMatchDestList", + "WriteErrorNonStringMatchField", + "WriteErrorNonTokenTypeField", + "WriteErrorRequestAborted", + "WriteErrorShuttingDown", + "WriteErrorTooLongIdField", + "WriteErrorUnsupportedType" + ] + }, + { + "id": "SRIMessageSignatureError", + "type": "string", + "enum": [ + "MissingSignatureHeader", + "MissingSignatureInputHeader", + "InvalidSignatureHeader", + "InvalidSignatureInputHeader", + "SignatureHeaderValueIsNotByteSequence", + "SignatureHeaderValueIsParameterized", + "SignatureHeaderValueIsIncorrectLength", + "SignatureInputHeaderMissingLabel", + "SignatureInputHeaderValueNotInnerList", + "SignatureInputHeaderValueMissingComponents", + "SignatureInputHeaderInvalidComponentType", + "SignatureInputHeaderInvalidComponentName", + "SignatureInputHeaderInvalidHeaderComponentParameter", + "SignatureInputHeaderInvalidDerivedComponentParameter", + "SignatureInputHeaderKeyIdLength", + "SignatureInputHeaderInvalidParameter", + "SignatureInputHeaderMissingRequiredParameters", + "ValidationFailedSignatureExpired", + "ValidationFailedInvalidLength", + "ValidationFailedSignatureMismatch" ] }, { @@ -1495,11 +1656,38 @@ } ] }, + { + "id": "SharedDictionaryIssueDetails", + "type": "object", + "properties": [ + { + "name": "sharedDictionaryError", + "$ref": "SharedDictionaryError" + }, + { + "name": "request", + "$ref": "AffectedRequest" + } + ] + }, + { + "id": "SRIMessageSignatureIssueDetails", + "type": "object", + "properties": [ + { + "name": "error", + "$ref": "SRIMessageSignatureError" + }, + { + "name": "request", + "$ref": "AffectedRequest" + } + ] + }, { "id": "GenericIssueErrorType", "type": "string", "enum": [ - "CrossOriginPortalPostMessageError", "FormLabelForNameError", "FormDuplicateIdForInputError", "FormInputWithNoLabelError", @@ -1580,6 +1768,32 @@ } ] }, + { + "id": "CookieDeprecationMetadataIssueDetails", + "description": "This issue warns about third-party sites that are accessing cookies on the\ncurrent page, and have been permitted due to having a global metadata grant.\nNote that in this context 'site' means eTLD+1. For example, if the URL\n`https://example.test:80/web_page` was accessing cookies, the site reported\nwould be `example.test`.", + "type": "object", + "properties": [ + { + "name": "allowedSites", + "type": "array", + "items": { + "type": "string" + } + }, + { + "name": "optOutPercentage", + "type": "number" + }, + { + "name": "isOptOutTopLevel", + "type": "boolean" + }, + { + "name": "operation", + "$ref": "CookieOperation" + } + ] + }, { "id": "ClientHintIssueReason", "type": "string", @@ -1620,7 +1834,9 @@ "ClientMetadataNoResponse", "ClientMetadataInvalidResponse", "ClientMetadataInvalidContentType", + "IdpNotPotentiallyTrustworthy", "DisabledInSettings", + "DisabledInFlags", "ErrorFetchingSignin", "InvalidSigninResponse", "AccountsHttpNotFound", @@ -1631,13 +1847,23 @@ "IdTokenHttpNotFound", "IdTokenNoResponse", "IdTokenInvalidResponse", + "IdTokenIdpErrorResponse", + "IdTokenCrossSiteIdpErrorResponse", "IdTokenInvalidRequest", "IdTokenInvalidContentType", "ErrorIdToken", "Canceled", "RpPageNotVisible", "SilentMediationFailure", - "ThirdPartyCookiesBlocked" + "ThirdPartyCookiesBlocked", + "NotSignedInWithIdp", + "MissingTransientUserActivation", + "ReplacedByActiveMode", + "InvalidFieldsSpecified", + "RelyingPartyOriginIsOpaque", + "TypeNotMatching", + "UiDismissedNoEmbargo", + "CorsError" ] }, { @@ -1702,6 +1928,60 @@ } ] }, + { + "id": "PartitioningBlobURLInfo", + "type": "string", + "enum": [ + "BlockedCrossPartitionFetching", + "EnforceNoopenerForNavigation" + ] + }, + { + "id": "PartitioningBlobURLIssueDetails", + "type": "object", + "properties": [ + { + "name": "url", + "description": "The BlobURL that failed to load.", + "type": "string" + }, + { + "name": "partitioningBlobURLInfo", + "description": "Additional information about the Partitioning Blob URL issue.", + "$ref": "PartitioningBlobURLInfo" + } + ] + }, + { + "id": "SelectElementAccessibilityIssueReason", + "type": "string", + "enum": [ + "DisallowedSelectChild", + "DisallowedOptGroupChild", + "NonPhrasingContentOptionChild", + "InteractiveContentOptionChild", + "InteractiveContentLegendChild" + ] + }, + { + "id": "SelectElementAccessibilityIssueDetails", + "description": "This issue warns about errors in the select element content model.", + "type": "object", + "properties": [ + { + "name": "nodeId", + "$ref": "DOM.BackendNodeId" + }, + { + "name": "selectElementAccessibilityIssueReason", + "$ref": "SelectElementAccessibilityIssueReason" + }, + { + "name": "hasDisallowedAttributes", + "type": "boolean" + } + ] + }, { "id": "StyleSheetLoadingIssueReason", "type": "string", @@ -1733,6 +2013,39 @@ } ] }, + { + "id": "PropertyRuleIssueReason", + "type": "string", + "enum": [ + "InvalidSyntax", + "InvalidInitialValue", + "InvalidInherits", + "InvalidName" + ] + }, + { + "id": "PropertyRuleIssueDetails", + "description": "This issue warns about errors in property rules that lead to property\nregistrations being ignored.", + "type": "object", + "properties": [ + { + "name": "sourceCodeLocation", + "description": "Source code position of the property rule.", + "$ref": "SourceCodeLocation" + }, + { + "name": "propertyRuleIssueReason", + "description": "Reason why the property rule was discarded.", + "$ref": "PropertyRuleIssueReason" + }, + { + "name": "propertyValue", + "description": "The value of the property rule property that failed to parse", + "optional": true, + "type": "string" + } + ] + }, { "id": "InspectorIssueCode", "description": "A unique identifier for the type of issue. Each type may use one of the\noptional fields in InspectorIssueDetails to convey more specific\ninformation about the kind of issue.", @@ -1748,14 +2061,20 @@ "CorsIssue", "AttributionReportingIssue", "QuirksModeIssue", + "PartitioningBlobURLIssue", "NavigatorUserAgentIssue", "GenericIssue", "DeprecationIssue", "ClientHintIssue", "FederatedAuthRequestIssue", "BounceTrackingIssue", + "CookieDeprecationMetadataIssue", "StylesheetLoadingIssue", - "FederatedAuthUserInfoRequestIssue" + "FederatedAuthUserInfoRequestIssue", + "PropertyRuleIssue", + "SharedDictionaryIssue", + "SelectElementAccessibilityIssue", + "SRIMessageSignatureIssue" ] }, { @@ -1813,6 +2132,11 @@ "optional": true, "$ref": "QuirksModeIssueDetails" }, + { + "name": "partitioningBlobURLIssueDetails", + "optional": true, + "$ref": "PartitioningBlobURLIssueDetails" + }, { "name": "navigatorUserAgentIssueDetails", "deprecated": true, @@ -1844,15 +2168,40 @@ "optional": true, "$ref": "BounceTrackingIssueDetails" }, + { + "name": "cookieDeprecationMetadataIssueDetails", + "optional": true, + "$ref": "CookieDeprecationMetadataIssueDetails" + }, { "name": "stylesheetLoadingIssueDetails", "optional": true, "$ref": "StylesheetLoadingIssueDetails" }, + { + "name": "propertyRuleIssueDetails", + "optional": true, + "$ref": "PropertyRuleIssueDetails" + }, { "name": "federatedAuthUserInfoRequestIssueDetails", "optional": true, "$ref": "FederatedAuthUserInfoRequestIssueDetails" + }, + { + "name": "sharedDictionaryIssueDetails", + "optional": true, + "$ref": "SharedDictionaryIssueDetails" + }, + { + "name": "selectElementAccessibilityIssueDetails", + "optional": true, + "$ref": "SelectElementAccessibilityIssueDetails" + }, + { + "name": "sriMessageSignatureIssueDetails", + "optional": true, + "$ref": "SRIMessageSignatureIssueDetails" } ] }, @@ -1982,70 +2331,316 @@ ] }, { - "domain": "Autofill", - "description": "Defines commands and events for Autofill.", + "domain": "Extensions", + "description": "Defines commands and events for browser extensions.", "experimental": true, "types": [ { - "id": "CreditCard", - "type": "object", - "properties": [ + "id": "StorageArea", + "description": "Storage areas.", + "type": "string", + "enum": [ + "session", + "local", + "sync", + "managed" + ] + } + ], + "commands": [ + { + "name": "loadUnpacked", + "description": "Installs an unpacked extension from the filesystem similar to\n--load-extension CLI flags. Returns extension ID once the extension\nhas been installed. Available if the client is connected using the\n--remote-debugging-pipe flag and the --enable-unsafe-extension-debugging\nflag is set.", + "parameters": [ { - "name": "number", - "description": "16-digit credit card number.", + "name": "path", + "description": "Absolute file path.", "type": "string" - }, + } + ], + "returns": [ { - "name": "name", - "description": "Name of the credit card owner.", + "name": "id", + "description": "Extension id.", "type": "string" - }, + } + ] + }, + { + "name": "uninstall", + "description": "Uninstalls an unpacked extension (others not supported) from the profile.\nAvailable if the client is connected using the --remote-debugging-pipe flag\nand the --enable-unsafe-extension-debugging.", + "parameters": [ { - "name": "expiryMonth", - "description": "2-digit expiry month.", + "name": "id", + "description": "Extension id.", "type": "string" - }, + } + ] + }, + { + "name": "getStorageItems", + "description": "Gets data from extension storage in the given `storageArea`. If `keys` is\nspecified, these are used to filter the result.", + "parameters": [ { - "name": "expiryYear", - "description": "4-digit expiry year.", + "name": "id", + "description": "ID of extension.", "type": "string" }, { - "name": "cvc", - "description": "3-digit card verification code.", - "type": "string" + "name": "storageArea", + "description": "StorageArea to retrieve data from.", + "$ref": "StorageArea" + }, + { + "name": "keys", + "description": "Keys to retrieve.", + "optional": true, + "type": "array", + "items": { + "type": "string" + } + } + ], + "returns": [ + { + "name": "data", + "type": "object" } ] }, { - "id": "AddressField", - "type": "object", - "properties": [ + "name": "removeStorageItems", + "description": "Removes `keys` from extension storage in the given `storageArea`.", + "parameters": [ { - "name": "name", - "description": "address field name, for example GIVEN_NAME.", + "name": "id", + "description": "ID of extension.", "type": "string" }, { - "name": "value", - "description": "address field name, for example Jon Doe.", - "type": "string" + "name": "storageArea", + "description": "StorageArea to remove data from.", + "$ref": "StorageArea" + }, + { + "name": "keys", + "description": "Keys to remove.", + "type": "array", + "items": { + "type": "string" + } } ] }, { - "id": "Address", - "type": "object", + "name": "clearStorageItems", + "description": "Clears extension storage in the given `storageArea`.", + "parameters": [ + { + "name": "id", + "description": "ID of extension.", + "type": "string" + }, + { + "name": "storageArea", + "description": "StorageArea to remove data from.", + "$ref": "StorageArea" + } + ] + }, + { + "name": "setStorageItems", + "description": "Sets `values` in extension storage in the given `storageArea`. The provided `values`\nwill be merged with existing values in the storage area.", + "parameters": [ + { + "name": "id", + "description": "ID of extension.", + "type": "string" + }, + { + "name": "storageArea", + "description": "StorageArea to set data in.", + "$ref": "StorageArea" + }, + { + "name": "values", + "description": "Values to set.", + "type": "object" + } + ] + } + ] + }, + { + "domain": "Autofill", + "description": "Defines commands and events for Autofill.", + "experimental": true, + "types": [ + { + "id": "CreditCard", + "type": "object", + "properties": [ + { + "name": "number", + "description": "16-digit credit card number.", + "type": "string" + }, + { + "name": "name", + "description": "Name of the credit card owner.", + "type": "string" + }, + { + "name": "expiryMonth", + "description": "2-digit expiry month.", + "type": "string" + }, + { + "name": "expiryYear", + "description": "4-digit expiry year.", + "type": "string" + }, + { + "name": "cvc", + "description": "3-digit card verification code.", + "type": "string" + } + ] + }, + { + "id": "AddressField", + "type": "object", + "properties": [ + { + "name": "name", + "description": "address field name, for example GIVEN_NAME.", + "type": "string" + }, + { + "name": "value", + "description": "address field value, for example Jon Doe.", + "type": "string" + } + ] + }, + { + "id": "AddressFields", + "description": "A list of address fields.", + "type": "object", + "properties": [ + { + "name": "fields", + "type": "array", + "items": { + "$ref": "AddressField" + } + } + ] + }, + { + "id": "Address", + "type": "object", "properties": [ { "name": "fields", - "description": "fields and values defining a test address.", + "description": "fields and values defining an address.", "type": "array", "items": { "$ref": "AddressField" } } ] + }, + { + "id": "AddressUI", + "description": "Defines how an address can be displayed like in chrome://settings/addresses.\nAddress UI is a two dimensional array, each inner array is an \"address information line\", and when rendered in a UI surface should be displayed as such.\nThe following address UI for instance:\n[[{name: \"GIVE_NAME\", value: \"Jon\"}, {name: \"FAMILY_NAME\", value: \"Doe\"}], [{name: \"CITY\", value: \"Munich\"}, {name: \"ZIP\", value: \"81456\"}]]\nshould allow the receiver to render:\nJon Doe\nMunich 81456", + "type": "object", + "properties": [ + { + "name": "addressFields", + "description": "A two dimension array containing the representation of values from an address profile.", + "type": "array", + "items": { + "$ref": "AddressFields" + } + } + ] + }, + { + "id": "FillingStrategy", + "description": "Specified whether a filled field was done so by using the html autocomplete attribute or autofill heuristics.", + "type": "string", + "enum": [ + "autocompleteAttribute", + "autofillInferred" + ] + }, + { + "id": "FilledField", + "type": "object", + "properties": [ + { + "name": "htmlType", + "description": "The type of the field, e.g text, password etc.", + "type": "string" + }, + { + "name": "id", + "description": "the html id", + "type": "string" + }, + { + "name": "name", + "description": "the html name", + "type": "string" + }, + { + "name": "value", + "description": "the field value", + "type": "string" + }, + { + "name": "autofillType", + "description": "The actual field type, e.g FAMILY_NAME", + "type": "string" + }, + { + "name": "fillingStrategy", + "description": "The filling strategy", + "$ref": "FillingStrategy" + }, + { + "name": "frameId", + "description": "The frame the field belongs to", + "$ref": "Page.FrameId" + }, + { + "name": "fieldId", + "description": "The form field's DOM node", + "$ref": "DOM.BackendNodeId" + } + ] + } + ], + "events": [ + { + "name": "addressFormFilled", + "description": "Emitted when an address form is filled.", + "parameters": [ + { + "name": "filledFields", + "description": "Information about the fields that were filled", + "type": "array", + "items": { + "$ref": "FilledField" + } + }, + { + "name": "addressUi", + "description": "An UI representation of the address used to fill the form.\nConsists of a 2D array where each child represents an address/profile line.", + "$ref": "AddressUI" + } + ] } ], "commands": [ @@ -2083,6 +2678,14 @@ } } ] + }, + { + "name": "disable", + "description": "Disables autofill domain notifications." + }, + { + "name": "enable", + "description": "Enables autofill domain notifications." } ] }, @@ -2311,17 +2914,21 @@ "experimental": true, "type": "string", "enum": [ - "accessibilityEvents", + "ar", "audioCapture", - "backgroundSync", + "automaticFullscreen", "backgroundFetch", + "backgroundSync", + "cameraPanTiltZoom", + "capturedSurfaceControl", "clipboardReadWrite", "clipboardSanitizedWrite", "displayCapture", "durableStorage", - "flash", "geolocation", + "handTracking", "idleDetection", + "keyboardLock", "localFonts", "midi", "midiSysex", @@ -2329,14 +2936,19 @@ "notifications", "paymentHandler", "periodicBackgroundSync", + "pointerLock", "protectedMediaIdentifier", "sensors", + "smartCard", + "speakerSelection", "storageAccess", "topLevelStorageAccess", "videoCapture", - "videoCapturePanTiltZoom", + "vr", "wakeLockScreen", "wakeLockSystem", + "webAppInstallation", + "webPrinting", "windowManagement" ] }, @@ -2352,7 +2964,7 @@ }, { "id": "PermissionDescriptor", - "description": "Definition of PermissionDescriptor defined in the Permissions API:\nhttps://w3c.github.io/permissions/#dictdef-permissiondescriptor.", + "description": "Definition of PermissionDescriptor defined in the Permissions API:\nhttps://w3c.github.io/permissions/#dom-permissiondescriptor.", "experimental": true, "type": "object", "properties": [ @@ -2379,6 +2991,12 @@ "optional": true, "type": "boolean" }, + { + "name": "allowWithoutGesture", + "description": "For \"fullscreen\" permission, must specify allowWithoutGesture:true.", + "optional": true, + "type": "boolean" + }, { "name": "panTiltZoom", "description": "For \"camera\" permission, may specify panTiltZoom.", @@ -2511,7 +3129,6 @@ { "name": "resetPermissions", "description": "Reset all permission management for all origins.", - "experimental": true, "parameters": [ { "name": "browserContextId", @@ -2528,7 +3145,7 @@ "parameters": [ { "name": "behavior", - "description": "Whether to allow all or deny all download requests, or use default Chrome behavior if\navailable (otherwise deny). |allowAndName| allows download and names files according to\ntheir dowmload guids.", + "description": "Whether to allow all or deny all download requests, or use default Chrome behavior if\navailable (otherwise deny). |allowAndName| allows download and names files according to\ntheir download guids.", "type": "string", "enum": [ "deny", @@ -2902,6 +3519,24 @@ } ] }, + { + "id": "CSSAnimationStyle", + "description": "CSS style coming from animations with the name of the animation.", + "type": "object", + "properties": [ + { + "name": "name", + "description": "The name of the animation.", + "optional": true, + "type": "string" + }, + { + "name": "style", + "description": "The style coming from the animation.", + "$ref": "CSSStyle" + } + ] + }, { "id": "InheritedStyleEntry", "description": "Inherited CSS rule collection from ancestor node.", @@ -2923,6 +3558,28 @@ } ] }, + { + "id": "InheritedAnimatedStyleEntry", + "description": "Inherited CSS style collection for animated styles from ancestor node.", + "type": "object", + "properties": [ + { + "name": "animationStyles", + "description": "Styles coming from the animations of the ancestor, if any, in the style inheritance chain.", + "optional": true, + "type": "array", + "items": { + "$ref": "CSSAnimationStyle" + } + }, + { + "name": "transitionsStyle", + "description": "The style coming from the transitions of the ancestor, if any, in the style inheritance chain.", + "optional": true, + "$ref": "CSSStyle" + } + ] + }, { "id": "InheritedPseudoElementMatches", "description": "Inherited pseudo element matches from pseudos of an ancestor node.", @@ -3043,7 +3700,7 @@ }, { "name": "sourceURL", - "description": "Stylesheet resource URL. Empty if this is a constructed stylesheet created using\nnew CSSStyleSheet() (but non-empty if this is a constructed sylesheet imported\nas a CSS module script).", + "description": "Stylesheet resource URL. Empty if this is a constructed stylesheet created using\nnew CSSStyleSheet() (but non-empty if this is a constructed stylesheet imported\nas a CSS module script).", "type": "string" }, { @@ -3222,6 +3879,16 @@ "items": { "$ref": "CSSRuleType" } + }, + { + "name": "startingStyles", + "description": "@starting-style CSS at-rule array.\nThe array enumerates @starting-style at-rules starting with the innermost one, going outwards.", + "experimental": true, + "optional": true, + "type": "array", + "items": { + "$ref": "CSSStartingStyle" + } } ] }, @@ -3236,7 +3903,8 @@ "ContainerRule", "LayerRule", "ScopeRule", - "StyleRule" + "StyleRule", + "StartingStyleRule" ] }, { @@ -3579,6 +4247,12 @@ "description": "Optional logical axes queried for the container.", "optional": true, "$ref": "DOM.LogicalAxes" + }, + { + "name": "queriesScrollState", + "description": "true if the query contains scroll-state() queries.", + "optional": true, + "type": "boolean" } ] }, @@ -3662,6 +4336,26 @@ } ] }, + { + "id": "CSSStartingStyle", + "description": "CSS Starting Style at-rule descriptor.", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "range", + "description": "The associated rule header range in the enclosing stylesheet (if\navailable).", + "optional": true, + "$ref": "SourceRange" + }, + { + "name": "styleSheetId", + "description": "Identifier of the stylesheet containing this object (if exists).", + "optional": true, + "$ref": "StyleSheetId" + } + ] + }, { "id": "CSSLayerData", "description": "CSS Layer data.", @@ -3699,6 +4393,11 @@ "description": "Font's family name reported by platform.", "type": "string" }, + { + "name": "postScriptName", + "description": "Font's PostScript name reported by platform.", + "type": "string" + }, { "name": "isCustomFont", "description": "Indicates if the font was downloaded or resolved locally.", @@ -3828,21 +4527,34 @@ ] }, { - "id": "CSSPositionFallbackRule", - "description": "CSS position-fallback rule representation.", + "id": "CSSPositionTryRule", + "description": "CSS @position-try rule representation.", "type": "object", "properties": [ { "name": "name", + "description": "The prelude dashed-ident name", "$ref": "Value" }, { - "name": "tryRules", - "description": "List of keyframes.", - "type": "array", - "items": { - "$ref": "CSSTryRule" - } + "name": "styleSheetId", + "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified\nstylesheet rules) this rule came from.", + "optional": true, + "$ref": "StyleSheetId" + }, + { + "name": "origin", + "description": "Parent stylesheet's origin.", + "$ref": "StyleSheetOrigin" + }, + { + "name": "style", + "description": "Associated style declaration.", + "$ref": "CSSStyle" + }, + { + "name": "active", + "type": "boolean" } ] }, @@ -3867,15 +4579,208 @@ ] }, { - "id": "CSSKeyframeRule", - "description": "CSS keyframe rule representation.", + "id": "CSSPropertyRegistration", + "description": "Representation of a custom property registration through CSS.registerProperty", "type": "object", "properties": [ { - "name": "styleSheetId", - "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified\nstylesheet rules) this rule came from.", - "optional": true, - "$ref": "StyleSheetId" + "name": "propertyName", + "type": "string" + }, + { + "name": "initialValue", + "optional": true, + "$ref": "Value" + }, + { + "name": "inherits", + "type": "boolean" + }, + { + "name": "syntax", + "type": "string" + } + ] + }, + { + "id": "CSSFontPaletteValuesRule", + "description": "CSS font-palette-values rule representation.", + "type": "object", + "properties": [ + { + "name": "styleSheetId", + "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified\nstylesheet rules) this rule came from.", + "optional": true, + "$ref": "StyleSheetId" + }, + { + "name": "origin", + "description": "Parent stylesheet's origin.", + "$ref": "StyleSheetOrigin" + }, + { + "name": "fontPaletteName", + "description": "Associated font palette name.", + "$ref": "Value" + }, + { + "name": "style", + "description": "Associated style declaration.", + "$ref": "CSSStyle" + } + ] + }, + { + "id": "CSSPropertyRule", + "description": "CSS property at-rule representation.", + "type": "object", + "properties": [ + { + "name": "styleSheetId", + "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified\nstylesheet rules) this rule came from.", + "optional": true, + "$ref": "StyleSheetId" + }, + { + "name": "origin", + "description": "Parent stylesheet's origin.", + "$ref": "StyleSheetOrigin" + }, + { + "name": "propertyName", + "description": "Associated property name.", + "$ref": "Value" + }, + { + "name": "style", + "description": "Associated style declaration.", + "$ref": "CSSStyle" + } + ] + }, + { + "id": "CSSFunctionParameter", + "description": "CSS function argument representation.", + "type": "object", + "properties": [ + { + "name": "name", + "description": "The parameter name.", + "type": "string" + }, + { + "name": "type", + "description": "The parameter type.", + "type": "string" + } + ] + }, + { + "id": "CSSFunctionConditionNode", + "description": "CSS function conditional block representation.", + "type": "object", + "properties": [ + { + "name": "media", + "description": "Media query for this conditional block. Only one type of condition should be set.", + "optional": true, + "$ref": "CSSMedia" + }, + { + "name": "containerQueries", + "description": "Container query for this conditional block. Only one type of condition should be set.", + "optional": true, + "$ref": "CSSContainerQuery" + }, + { + "name": "supports", + "description": "@supports CSS at-rule condition. Only one type of condition should be set.", + "optional": true, + "$ref": "CSSSupports" + }, + { + "name": "children", + "description": "Block body.", + "type": "array", + "items": { + "$ref": "CSSFunctionNode" + } + }, + { + "name": "conditionText", + "description": "The condition text.", + "type": "string" + } + ] + }, + { + "id": "CSSFunctionNode", + "description": "Section of the body of a CSS function rule.", + "type": "object", + "properties": [ + { + "name": "condition", + "description": "A conditional block. If set, style should not be set.", + "optional": true, + "$ref": "CSSFunctionConditionNode" + }, + { + "name": "style", + "description": "Values set by this node. If set, condition should not be set.", + "optional": true, + "$ref": "CSSStyle" + } + ] + }, + { + "id": "CSSFunctionRule", + "description": "CSS function at-rule representation.", + "type": "object", + "properties": [ + { + "name": "name", + "description": "Name of the function.", + "$ref": "Value" + }, + { + "name": "styleSheetId", + "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified\nstylesheet rules) this rule came from.", + "optional": true, + "$ref": "StyleSheetId" + }, + { + "name": "origin", + "description": "Parent stylesheet's origin.", + "$ref": "StyleSheetOrigin" + }, + { + "name": "parameters", + "description": "List of parameters.", + "type": "array", + "items": { + "$ref": "CSSFunctionParameter" + } + }, + { + "name": "children", + "description": "Function body.", + "type": "array", + "items": { + "$ref": "CSSFunctionNode" + } + } + ] + }, + { + "id": "CSSKeyframeRule", + "description": "CSS keyframe rule representation.", + "type": "object", + "properties": [ + { + "name": "styleSheetId", + "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified\nstylesheet rules) this rule came from.", + "optional": true, + "$ref": "StyleSheetId" }, { "name": "origin", @@ -3936,6 +4841,13 @@ "name": "location", "description": "Text position of a new rule in the target style sheet.", "$ref": "SourceRange" + }, + { + "name": "nodeForPropertySyntaxValidation", + "description": "NodeId for the DOM node in whose context custom property declarations for registered properties should be\nvalidated. If omitted, declarations in the new rule text can only be validated statically, which may produce\nincorrect results if the declaration contains a var() for example.", + "experimental": true, + "optional": true, + "$ref": "DOM.NodeId" } ], "returns": [ @@ -3974,6 +4886,12 @@ "name": "frameId", "description": "Identifier of the frame where \"via-inspector\" stylesheet should be created.", "$ref": "Page.FrameId" + }, + { + "name": "force", + "description": "If true, creates a new stylesheet for every call. If false,\nreturns a stylesheet previously created by a call with force=false\nfor the frame's document if it exists or creates a new stylesheet\n(default: false).", + "optional": true, + "type": "boolean" } ], "returns": [ @@ -4011,6 +4929,22 @@ } ] }, + { + "name": "forceStartingStyle", + "description": "Ensures that the given node is in its starting-style state.", + "parameters": [ + { + "name": "nodeId", + "description": "The element id for which to force the starting-style state.", + "$ref": "DOM.NodeId" + }, + { + "name": "forced", + "description": "Boolean indicating if this is on or off.", + "type": "boolean" + } + ] + }, { "name": "getBackgroundColors", "parameters": [ @@ -4064,6 +4998,77 @@ } ] }, + { + "name": "resolveValues", + "description": "Resolve the specified values in the context of the provided element.\nFor example, a value of '1em' is evaluated according to the computed\n'font-size' of the element and a value 'calc(1px + 2px)' will be\nresolved to '3px'.", + "parameters": [ + { + "name": "values", + "description": "Substitution functions (var()/env()/attr()) and cascade-dependent\nkeywords (revert/revert-layer) do not work.", + "type": "array", + "items": { + "type": "string" + } + }, + { + "name": "nodeId", + "description": "Id of the node in whose context the expression is evaluated", + "$ref": "DOM.NodeId" + }, + { + "name": "propertyName", + "description": "Only longhands and custom property names are accepted.", + "optional": true, + "type": "string" + }, + { + "name": "pseudoType", + "description": "Pseudo element type, only works for pseudo elements that generate\nelements in the tree, such as ::before and ::after.", + "experimental": true, + "optional": true, + "$ref": "DOM.PseudoType" + }, + { + "name": "pseudoIdentifier", + "description": "Pseudo element custom ident.", + "experimental": true, + "optional": true, + "type": "string" + } + ], + "returns": [ + { + "name": "results", + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + { + "name": "getLonghandProperties", + "experimental": true, + "parameters": [ + { + "name": "shorthandName", + "type": "string" + }, + { + "name": "value", + "type": "string" + } + ], + "returns": [ + { + "name": "longhandProperties", + "type": "array", + "items": { + "$ref": "CSSProperty" + } + } + ] + }, { "name": "getInlineStylesForNode", "description": "Returns the styles defined inline (explicitly in the \"style\" attribute and implicitly, using DOM\nattributes) for a DOM node identified by `nodeId`.", @@ -4089,8 +5094,9 @@ ] }, { - "name": "getMatchedStylesForNode", - "description": "Returns requested styles for a DOM node identified by `nodeId`.", + "name": "getAnimatedStylesForNode", + "description": "Returns the styles coming from animations & transitions\nincluding the animation & transition styles coming from inheritance chain.", + "experimental": true, "parameters": [ { "name": "nodeId", @@ -4099,24 +5105,60 @@ ], "returns": [ { - "name": "inlineStyle", - "description": "Inline style for the specified DOM node.", + "name": "animationStyles", + "description": "Styles coming from animations.", "optional": true, - "$ref": "CSSStyle" + "type": "array", + "items": { + "$ref": "CSSAnimationStyle" + } }, { - "name": "attributesStyle", - "description": "Attribute-defined element style (e.g. resulting from \"width=20 height=100%\").", + "name": "transitionsStyle", + "description": "Style coming from transitions.", "optional": true, "$ref": "CSSStyle" }, { - "name": "matchedCSSRules", - "description": "CSS rules matching this node, from all applicable stylesheets.", + "name": "inherited", + "description": "Inherited style entries for animationsStyle and transitionsStyle from\nthe inheritance chain of the element.", "optional": true, "type": "array", "items": { - "$ref": "RuleMatch" + "$ref": "InheritedAnimatedStyleEntry" + } + } + ] + }, + { + "name": "getMatchedStylesForNode", + "description": "Returns requested styles for a DOM node identified by `nodeId`.", + "parameters": [ + { + "name": "nodeId", + "$ref": "DOM.NodeId" + } + ], + "returns": [ + { + "name": "inlineStyle", + "description": "Inline style for the specified DOM node.", + "optional": true, + "$ref": "CSSStyle" + }, + { + "name": "attributesStyle", + "description": "Attribute-defined element style (e.g. resulting from \"width=20 height=100%\").", + "optional": true, + "$ref": "CSSStyle" + }, + { + "name": "matchedCSSRules", + "description": "CSS rules matching this node, from all applicable stylesheets.", + "optional": true, + "type": "array", + "items": { + "$ref": "RuleMatch" } }, { @@ -4156,20 +5198,60 @@ } }, { - "name": "cssPositionFallbackRules", - "description": "A list of CSS position fallbacks matching this node.", + "name": "cssPositionTryRules", + "description": "A list of CSS @position-try rules matching this node, based on the position-try-fallbacks property.", + "optional": true, + "type": "array", + "items": { + "$ref": "CSSPositionTryRule" + } + }, + { + "name": "activePositionFallbackIndex", + "description": "Index of the active fallback in the applied position-try-fallback property,\nwill not be set if there is no active position-try fallback.", + "optional": true, + "type": "integer" + }, + { + "name": "cssPropertyRules", + "description": "A list of CSS at-property rules matching this node.", + "optional": true, + "type": "array", + "items": { + "$ref": "CSSPropertyRule" + } + }, + { + "name": "cssPropertyRegistrations", + "description": "A list of CSS property registrations matching this node.", "optional": true, "type": "array", "items": { - "$ref": "CSSPositionFallbackRule" + "$ref": "CSSPropertyRegistration" } }, + { + "name": "cssFontPaletteValuesRule", + "description": "A font-palette-values rule matching this node.", + "optional": true, + "$ref": "CSSFontPaletteValuesRule" + }, { "name": "parentLayoutNodeId", "description": "Id of the first parent element that does not have display: contents.", "experimental": true, "optional": true, "$ref": "DOM.NodeId" + }, + { + "name": "cssFunctionRules", + "description": "A list of CSS at-function rules referenced by styles of this node.", + "experimental": true, + "optional": true, + "type": "array", + "items": { + "$ref": "CSSFunctionRule" + } } ] }, @@ -4240,6 +5322,42 @@ } ] }, + { + "name": "getLocationForSelector", + "description": "Given a CSS selector text and a style sheet ID, getLocationForSelector\nreturns an array of locations of the CSS selector in the style sheet.", + "experimental": true, + "parameters": [ + { + "name": "styleSheetId", + "$ref": "StyleSheetId" + }, + { + "name": "selectorText", + "type": "string" + } + ], + "returns": [ + { + "name": "ranges", + "type": "array", + "items": { + "$ref": "SourceRange" + } + } + ] + }, + { + "name": "trackComputedStyleUpdatesForNode", + "description": "Starts tracking the given node for the computed style updates\nand whenever the computed style is updated for node, it queues\na `computedStyleUpdated` event with throttling.\nThere can only be 1 node tracked for computed style updates\nso passing a new node id removes tracking from the previous node.\nPass `undefined` to disable tracking.", + "experimental": true, + "parameters": [ + { + "name": "nodeId", + "optional": true, + "$ref": "DOM.NodeId" + } + ] + }, { "name": "trackComputedStyleUpdates", "description": "Starts tracking the given computed styles for updates. The specified array of properties\nreplaces the one previously specified. Pass empty array to disable tracking.\nUse takeComputedStyleUpdates to retrieve the list of nodes that had properties modified.\nThe changes to computed style properties are only tracked for nodes pushed to the front-end\nby the DOM agent. If no changes to the tracked properties occur after the node has been pushed\nto the front-end, no updates will be issued for the node.", @@ -4288,6 +5406,31 @@ } ] }, + { + "name": "setPropertyRulePropertyName", + "description": "Modifies the property rule property name.", + "parameters": [ + { + "name": "styleSheetId", + "$ref": "StyleSheetId" + }, + { + "name": "range", + "$ref": "SourceRange" + }, + { + "name": "propertyName", + "type": "string" + } + ], + "returns": [ + { + "name": "propertyName", + "description": "The resulting key text after modification.", + "$ref": "Value" + } + ] + }, { "name": "setKeyframeKey", "description": "Modifies the keyframe rule key text.", @@ -4473,6 +5616,13 @@ "items": { "$ref": "StyleDeclarationEdit" } + }, + { + "name": "nodeForPropertySyntaxValidation", + "description": "NodeId for the DOM node in whose context custom property declarations for registered properties should be\nvalidated. If omitted, declarations in the new rule text can only be validated statically, which may produce\nincorrect results if the declaration contains a var() for example.", + "experimental": true, + "optional": true, + "$ref": "DOM.NodeId" } ], "returns": [ @@ -4582,6 +5732,17 @@ "$ref": "StyleSheetId" } ] + }, + { + "name": "computedStyleUpdated", + "experimental": true, + "parameters": [ + { + "name": "nodeId", + "description": "The node id that has updated computed styles.", + "$ref": "DOM.NodeId" + } + ] } ] }, @@ -5016,16 +6177,23 @@ "enum": [ "first-line", "first-letter", + "checkmark", "before", "after", + "picker-icon", "marker", "backdrop", + "column", "selection", + "search-text", "target-text", "spelling-error", "grammar-error", "highlight", "first-line-inherited", + "scroll-marker", + "scroll-marker-group", + "scroll-button", "scrollbar", "scrollbar-thumb", "scrollbar-button", @@ -5038,7 +6206,11 @@ "view-transition-group", "view-transition-image-pair", "view-transition-old", - "view-transition-new" + "view-transition-new", + "placeholder", + "file-selector-button", + "details-content", + "picker" ] }, { @@ -5081,6 +6253,15 @@ "Both" ] }, + { + "id": "ScrollOrientation", + "description": "Physical scroll orientation", + "type": "string", + "enum": [ + "horizontal", + "vertical" + ] + }, { "id": "Node", "description": "DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes.\nDOMNode is a base node mirror type.", @@ -5279,6 +6460,30 @@ "name": "assignedSlot", "optional": true, "$ref": "BackendNode" + }, + { + "name": "isScrollable", + "experimental": true, + "optional": true, + "type": "boolean" + } + ] + }, + { + "id": "DetachedElementInfo", + "description": "A structure to hold the top-level node of a detached tree and an array of its retained descendants.", + "type": "object", + "properties": [ + { + "name": "treeNode", + "$ref": "Node" + }, + { + "name": "retainedNodeIds", + "type": "array", + "items": { + "$ref": "NodeId" + } } ] }, @@ -5532,7 +6737,6 @@ { "name": "scrollIntoViewIfNeeded", "description": "Scrolls the specified rect of the given node into view if not already visible.\nNote: exactly one between nodeId, backendNodeId and objectId should be passed\nto identify the node.", - "experimental": true, "parameters": [ { "name": "nodeId", @@ -5623,7 +6827,7 @@ "parameters": [ { "name": "nodeId", - "description": "Id of the node to retrieve attibutes for.", + "description": "Id of the node to retrieve attributes for.", "$ref": "NodeId" } ], @@ -6109,6 +7313,34 @@ } ] }, + { + "name": "getElementByRelation", + "description": "Returns the NodeId of the matched element according to certain relations.", + "experimental": true, + "parameters": [ + { + "name": "nodeId", + "description": "Id of the node from which to query the relation.", + "$ref": "NodeId" + }, + { + "name": "relation", + "description": "Type of relation to get.", + "type": "string", + "enum": [ + "PopoverTarget", + "InterestTarget" + ] + } + ], + "returns": [ + { + "name": "nodeId", + "description": "NodeId of the element matching the queried relation.", + "$ref": "NodeId" + } + ] + }, { "name": "redo", "description": "Re-does the last undone action.", @@ -6344,6 +7576,21 @@ } ] }, + { + "name": "getDetachedDomNodes", + "description": "Returns list of detached nodes", + "experimental": true, + "returns": [ + { + "name": "detachedNodes", + "description": "The list of detached nodes", + "type": "array", + "items": { + "$ref": "DetachedElementInfo" + } + } + ] + }, { "name": "setInspectedNode", "description": "Enables console to refer to the node with given id via $x (see Command Line API for more details\n$x functions).", @@ -6442,7 +7689,7 @@ }, { "name": "getContainerForNode", - "description": "Returns the query container of the given node based on container query\nconditions: containerName, physical, and logical axes. If no axes are\nprovided, the style container is returned, which is the direct parent or the\nclosest element with a matching container-name.", + "description": "Returns the query container of the given node based on container query\nconditions: containerName, physical and logical axes, and whether it queries\nscroll-state. If no axes are provided and queriesScrollState is false, the\nstyle container is returned, which is the direct parent or the closest\nelement with a matching container-name.", "experimental": true, "parameters": [ { @@ -6463,6 +7710,11 @@ "name": "logicalAxes", "optional": true, "$ref": "LogicalAxes" + }, + { + "name": "queriesScrollState", + "optional": true, + "type": "boolean" } ], "returns": [ @@ -6495,6 +7747,31 @@ } } ] + }, + { + "name": "getAnchorElement", + "description": "Returns the target anchor element of the given anchor query according to\nhttps://www.w3.org/TR/css-anchor-position-1/#target.", + "experimental": true, + "parameters": [ + { + "name": "nodeId", + "description": "Id of the positioned element from which to find the anchor.", + "$ref": "NodeId" + }, + { + "name": "anchorSpecifier", + "description": "An optional anchor specifier, as defined in\nhttps://www.w3.org/TR/css-anchor-position-1/#anchor-specifier.\nIf not provided, it will return the implicit anchor element for\nthe given positioned element.", + "optional": true, + "type": "string" + } + ], + "returns": [ + { + "name": "nodeId", + "description": "The anchor element of the given anchor query.", + "$ref": "NodeId" + } + ] } ], "events": [ @@ -6665,6 +7942,23 @@ "description": "Called when top layer elements are changed.", "experimental": true }, + { + "name": "scrollableFlagUpdated", + "description": "Fired when a node's scrollability state changes.", + "experimental": true, + "parameters": [ + { + "name": "nodeId", + "description": "The id of the node.", + "$ref": "DOM.NodeId" + }, + { + "name": "isScrollable", + "description": "If the node is scrollable.", + "type": "boolean" + } + ] + }, { "name": "pseudoElementRemoved", "description": "Called when a pseudo element is removed from an element.", @@ -6742,7 +8036,6 @@ "description": "DOM debugging allows setting breakpoints on particular DOM operations and events. JavaScript\nexecution will stop on these operations as if there was a regular breakpoint set.", "dependencies": [ "DOM", - "Debugger", "Runtime" ], "types": [ @@ -6899,6 +8192,8 @@ "name": "removeInstrumentationBreakpoint", "description": "Removes breakpoint on particular native event.", "experimental": true, + "deprecated": true, + "redirect": "EventBreakpoints", "parameters": [ { "name": "eventName", @@ -6971,6 +8266,8 @@ "name": "setInstrumentationBreakpoint", "description": "Sets breakpoint on particular native event.", "experimental": true, + "deprecated": true, + "redirect": "EventBreakpoints", "parameters": [ { "name": "eventName", @@ -6994,7 +8291,7 @@ }, { "domain": "EventBreakpoints", - "description": "EventBreakpoints permits setting breakpoints on particular operations and\nevents in targets that run JavaScript but do not have a DOM.\nJavaScript execution will stop on these operations as if there was a regular\nbreakpoint set.", + "description": "EventBreakpoints permits setting JavaScript breakpoints on operations and events\noccurring in native code invoked from JavaScript. Once breakpoint is hit, it is\nreported through Debugger domain, similarly to regular breakpoints being hit.", "experimental": true, "commands": [ { @@ -7018,6 +8315,10 @@ "type": "string" } ] + }, + { + "name": "disable", + "description": "Removes all breakpoints" } ] }, @@ -8046,175 +9347,100 @@ ] }, { - "domain": "Database", + "domain": "DeviceOrientation", "experimental": true, - "types": [ + "commands": [ { - "id": "DatabaseId", - "description": "Unique identifier of Database object.", - "type": "string" + "name": "clearDeviceOrientationOverride", + "description": "Clears the overridden Device Orientation." }, { - "id": "Database", - "description": "Database object.", - "type": "object", - "properties": [ - { - "name": "id", - "description": "Database ID.", - "$ref": "DatabaseId" - }, + "name": "setDeviceOrientationOverride", + "description": "Overrides the Device Orientation.", + "parameters": [ { - "name": "domain", - "description": "Database domain.", - "type": "string" + "name": "alpha", + "description": "Mock alpha", + "type": "number" }, { - "name": "name", - "description": "Database name.", - "type": "string" + "name": "beta", + "description": "Mock beta", + "type": "number" }, { - "name": "version", - "description": "Database version.", - "type": "string" - } - ] - }, - { - "id": "Error", - "description": "Database error.", - "type": "object", - "properties": [ - { - "name": "message", - "description": "Error message.", - "type": "string" - }, - { - "name": "code", - "description": "Error code.", - "type": "integer" + "name": "gamma", + "description": "Mock gamma", + "type": "number" } ] } + ] + }, + { + "domain": "Emulation", + "description": "This domain emulates different environments for the page.", + "dependencies": [ + "DOM", + "Page", + "Runtime" ], - "commands": [ - { - "name": "disable", - "description": "Disables database tracking, prevents database events from being sent to the client." - }, - { - "name": "enable", - "description": "Enables database tracking, database events will now be delivered to the client." - }, + "types": [ { - "name": "executeSQL", - "parameters": [ + "id": "SafeAreaInsets", + "experimental": true, + "type": "object", + "properties": [ { - "name": "databaseId", - "$ref": "DatabaseId" + "name": "top", + "description": "Overrides safe-area-inset-top.", + "optional": true, + "type": "integer" }, { - "name": "query", - "type": "string" - } - ], - "returns": [ - { - "name": "columnNames", + "name": "topMax", + "description": "Overrides safe-area-max-inset-top.", "optional": true, - "type": "array", - "items": { - "type": "string" - } + "type": "integer" }, { - "name": "values", + "name": "left", + "description": "Overrides safe-area-inset-left.", "optional": true, - "type": "array", - "items": { - "type": "any" - } + "type": "integer" }, { - "name": "sqlError", + "name": "leftMax", + "description": "Overrides safe-area-max-inset-left.", "optional": true, - "$ref": "Error" - } - ] - }, - { - "name": "getDatabaseTableNames", - "parameters": [ - { - "name": "databaseId", - "$ref": "DatabaseId" - } - ], - "returns": [ - { - "name": "tableNames", - "type": "array", - "items": { - "type": "string" - } - } - ] - } - ], - "events": [ - { - "name": "addDatabase", - "parameters": [ + "type": "integer" + }, { - "name": "database", - "$ref": "Database" - } - ] - } - ] - }, - { - "domain": "DeviceOrientation", - "experimental": true, - "commands": [ - { - "name": "clearDeviceOrientationOverride", - "description": "Clears the overridden Device Orientation." - }, - { - "name": "setDeviceOrientationOverride", - "description": "Overrides the Device Orientation.", - "parameters": [ + "name": "bottom", + "description": "Overrides safe-area-inset-bottom.", + "optional": true, + "type": "integer" + }, { - "name": "alpha", - "description": "Mock alpha", - "type": "number" + "name": "bottomMax", + "description": "Overrides safe-area-max-inset-bottom.", + "optional": true, + "type": "integer" }, { - "name": "beta", - "description": "Mock beta", - "type": "number" + "name": "right", + "description": "Overrides safe-area-inset-right.", + "optional": true, + "type": "integer" }, { - "name": "gamma", - "description": "Mock gamma", - "type": "number" + "name": "rightMax", + "description": "Overrides safe-area-max-inset-right.", + "optional": true, + "type": "integer" } ] - } - ] - }, - { - "domain": "Emulation", - "description": "This domain emulates different environments for the page.", - "dependencies": [ - "DOM", - "Page", - "Runtime" - ], - "types": [ + }, { "id": "ScreenOrientation", "description": "Screen orientation.", @@ -8263,6 +9489,21 @@ } ] }, + { + "id": "DevicePosture", + "type": "object", + "properties": [ + { + "name": "type", + "description": "Current posture of the device", + "type": "string", + "enum": [ + "continuous", + "folded" + ] + } + ] + }, { "id": "MediaFeature", "type": "object", @@ -8290,7 +9531,7 @@ }, { "id": "UserAgentBrandVersion", - "description": "Used to specify User Agent Cient Hints to emulate. See https://wicg.github.io/ua-client-hints", + "description": "Used to specify User Agent Client Hints to emulate. See https://wicg.github.io/ua-client-hints", "experimental": true, "type": "object", "properties": [ @@ -8306,7 +9547,7 @@ }, { "id": "UserAgentMetadata", - "description": "Used to specify User Agent Cient Hints to emulate. See https://wicg.github.io/ua-client-hints\nMissing optional values will be filled in by the target with what it would normally use.", + "description": "Used to specify User Agent Client Hints to emulate. See https://wicg.github.io/ua-client-hints\nMissing optional values will be filled in by the target with what it would normally use.", "experimental": true, "type": "object", "properties": [ @@ -8366,6 +9607,150 @@ } ] }, + { + "id": "SensorType", + "description": "Used to specify sensor types to emulate.\nSee https://w3c.github.io/sensors/#automation for more information.", + "experimental": true, + "type": "string", + "enum": [ + "absolute-orientation", + "accelerometer", + "ambient-light", + "gravity", + "gyroscope", + "linear-acceleration", + "magnetometer", + "relative-orientation" + ] + }, + { + "id": "SensorMetadata", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "available", + "optional": true, + "type": "boolean" + }, + { + "name": "minimumFrequency", + "optional": true, + "type": "number" + }, + { + "name": "maximumFrequency", + "optional": true, + "type": "number" + } + ] + }, + { + "id": "SensorReadingSingle", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "value", + "type": "number" + } + ] + }, + { + "id": "SensorReadingXYZ", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "x", + "type": "number" + }, + { + "name": "y", + "type": "number" + }, + { + "name": "z", + "type": "number" + } + ] + }, + { + "id": "SensorReadingQuaternion", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "x", + "type": "number" + }, + { + "name": "y", + "type": "number" + }, + { + "name": "z", + "type": "number" + }, + { + "name": "w", + "type": "number" + } + ] + }, + { + "id": "SensorReading", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "single", + "optional": true, + "$ref": "SensorReadingSingle" + }, + { + "name": "xyz", + "optional": true, + "$ref": "SensorReadingXYZ" + }, + { + "name": "quaternion", + "optional": true, + "$ref": "SensorReadingQuaternion" + } + ] + }, + { + "id": "PressureSource", + "experimental": true, + "type": "string", + "enum": [ + "cpu" + ] + }, + { + "id": "PressureState", + "experimental": true, + "type": "string", + "enum": [ + "nominal", + "fair", + "serious", + "critical" + ] + }, + { + "id": "PressureMetadata", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "available", + "optional": true, + "type": "boolean" + } + ] + }, { "id": "DisabledImageType", "description": "Enum of image types that can be disabled.", @@ -8381,6 +9766,7 @@ { "name": "canEmulate", "description": "Tells whether emulation is supported.", + "deprecated": true, "returns": [ { "name": "result", @@ -8430,7 +9816,6 @@ { "name": "setCPUThrottlingRate", "description": "Enables CPU throttling to emulate slow CPUs.", - "experimental": true, "parameters": [ { "name": "rate", @@ -8451,6 +9836,17 @@ } ] }, + { + "name": "setSafeAreaInsetsOverride", + "description": "Overrides the values for env(safe-area-inset-*) and env(safe-area-max-inset-*). Unset values will cause the\nrespective variables to be undefined, even if previously overridden.", + "experimental": true, + "parameters": [ + { + "name": "insets", + "$ref": "SafeAreaInsets" + } + ] + }, { "name": "setDeviceMetricsOverride", "description": "Overrides the values of device screen dimensions (window.screen.width, window.screen.height,\nwindow.innerWidth, window.innerHeight, and \"device-width\"/\"device-height\"-related CSS media\nquery results).", @@ -8536,9 +9932,33 @@ "experimental": true, "optional": true, "$ref": "DisplayFeature" + }, + { + "name": "devicePosture", + "description": "If set, the posture of a foldable device. If not set the posture is set\nto continuous.\nDeprecated, use Emulation.setDevicePostureOverride.", + "experimental": true, + "deprecated": true, + "optional": true, + "$ref": "DevicePosture" + } + ] + }, + { + "name": "setDevicePostureOverride", + "description": "Start reporting the given posture value to the Device Posture API.\nThis override can also be set in setDeviceMetricsOverride().", + "experimental": true, + "parameters": [ + { + "name": "posture", + "$ref": "DevicePosture" } ] }, + { + "name": "clearDevicePostureOverride", + "description": "Clears a device posture override set with either setDeviceMetricsOverride()\nor setDevicePostureOverride() and starts using posture information from the\nplatform again.\nDoes nothing if no override is set.", + "experimental": true + }, { "name": "setScrollbarsHidden", "experimental": true, @@ -8606,7 +10026,6 @@ { "name": "setEmulatedVisionDeficiency", "description": "Emulates the given vision deficiency.", - "experimental": true, "parameters": [ { "name": "type", @@ -8648,10 +10067,95 @@ } ] }, + { + "name": "getOverriddenSensorInformation", + "experimental": true, + "parameters": [ + { + "name": "type", + "$ref": "SensorType" + } + ], + "returns": [ + { + "name": "requestedSamplingFrequency", + "type": "number" + } + ] + }, + { + "name": "setSensorOverrideEnabled", + "description": "Overrides a platform sensor of a given type. If |enabled| is true, calls to\nSensor.start() will use a virtual sensor as backend rather than fetching\ndata from a real hardware sensor. Otherwise, existing virtual\nsensor-backend Sensor objects will fire an error event and new calls to\nSensor.start() will attempt to use a real sensor instead.", + "experimental": true, + "parameters": [ + { + "name": "enabled", + "type": "boolean" + }, + { + "name": "type", + "$ref": "SensorType" + }, + { + "name": "metadata", + "optional": true, + "$ref": "SensorMetadata" + } + ] + }, + { + "name": "setSensorOverrideReadings", + "description": "Updates the sensor readings reported by a sensor type previously overridden\nby setSensorOverrideEnabled.", + "experimental": true, + "parameters": [ + { + "name": "type", + "$ref": "SensorType" + }, + { + "name": "reading", + "$ref": "SensorReading" + } + ] + }, + { + "name": "setPressureSourceOverrideEnabled", + "description": "Overrides a pressure source of a given type, as used by the Compute\nPressure API, so that updates to PressureObserver.observe() are provided\nvia setPressureStateOverride instead of being retrieved from\nplatform-provided telemetry data.", + "experimental": true, + "parameters": [ + { + "name": "enabled", + "type": "boolean" + }, + { + "name": "source", + "$ref": "PressureSource" + }, + { + "name": "metadata", + "optional": true, + "$ref": "PressureMetadata" + } + ] + }, + { + "name": "setPressureStateOverride", + "description": "Provides a given pressure state that will be processed and eventually be\ndelivered to PressureObserver users. |source| must have been previously\noverridden by setPressureSourceOverrideEnabled.", + "experimental": true, + "parameters": [ + { + "name": "source", + "$ref": "PressureSource" + }, + { + "name": "state", + "$ref": "PressureState" + } + ] + }, { "name": "setIdleOverride", "description": "Overrides the Idle state.", - "experimental": true, "parameters": [ { "name": "isUserActive", @@ -8667,8 +10171,7 @@ }, { "name": "clearIdleOverride", - "description": "Clears Idle state overrides.", - "experimental": true + "description": "Clears Idle state overrides." }, { "name": "setNavigatorOverrides", @@ -8775,11 +10278,10 @@ { "name": "setTimezoneOverride", "description": "Overrides default host system timezone with the specified one.", - "experimental": true, "parameters": [ { "name": "timezoneId", - "description": "The timezone identifier. If empty, disables the override and\nrestores default host system timezone.", + "description": "The timezone identifier. List of supported timezones:\nhttps://source.chromium.org/chromium/chromium/deps/icu.git/+/faee8bc70570192d82d2978a71e2a615788597d1:source/data/misc/metaZones.txt\nIf empty, disables the override and restores default host system timezone.", "type": "string" } ] @@ -8829,7 +10331,7 @@ }, { "name": "setUserAgentOverride", - "description": "Allows overriding user agent with the given string.", + "description": "Allows overriding user agent with the given string.\n`userAgentMetadata` must be set for Client Hint headers to be sent.", "parameters": [ { "name": "userAgent", @@ -8838,7 +10340,7 @@ }, { "name": "acceptLanguage", - "description": "Browser langugage to emulate.", + "description": "Browser language to emulate.", "optional": true, "type": "string" }, @@ -9007,7 +10509,7 @@ }, { "name": "offset", - "description": "Seek to the specified offset before reading (if not specificed, proceed with offset\nfollowing the last read). Some types of streams may only support sequential reads.", + "description": "Seek to the specified offset before reading (if not specified, proceed with offset\nfollowing the last read). Some types of streams may only support sequential reads.", "optional": true, "type": "integer" }, @@ -9057,6 +10559,108 @@ } ] }, + { + "domain": "FileSystem", + "experimental": true, + "dependencies": [ + "Network", + "Storage" + ], + "types": [ + { + "id": "File", + "type": "object", + "properties": [ + { + "name": "name", + "type": "string" + }, + { + "name": "lastModified", + "description": "Timestamp", + "$ref": "Network.TimeSinceEpoch" + }, + { + "name": "size", + "description": "Size in bytes", + "type": "number" + }, + { + "name": "type", + "type": "string" + } + ] + }, + { + "id": "Directory", + "type": "object", + "properties": [ + { + "name": "name", + "type": "string" + }, + { + "name": "nestedDirectories", + "type": "array", + "items": { + "type": "string" + } + }, + { + "name": "nestedFiles", + "description": "Files that are directly nested under this directory.", + "type": "array", + "items": { + "$ref": "File" + } + } + ] + }, + { + "id": "BucketFileSystemLocator", + "type": "object", + "properties": [ + { + "name": "storageKey", + "description": "Storage key", + "$ref": "Storage.SerializedStorageKey" + }, + { + "name": "bucketName", + "description": "Bucket name. Not passing a `bucketName` will retrieve the default Bucket. (https://developer.mozilla.org/en-US/docs/Web/API/Storage_API#storage_buckets)", + "optional": true, + "type": "string" + }, + { + "name": "pathComponents", + "description": "Path to the directory using each path component as an array item.", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "commands": [ + { + "name": "getDirectory", + "parameters": [ + { + "name": "bucketFileSystemLocator", + "$ref": "BucketFileSystemLocator" + } + ], + "returns": [ + { + "name": "directory", + "description": "Returns the directory object at the path.", + "$ref": "Directory" + } + ] + } + ] + }, { "domain": "IndexedDB", "experimental": true, @@ -9624,16 +11228,14 @@ { "name": "tiltX", "description": "The plane angle between the Y-Z plane and the plane containing both the stylus axis and the Y axis, in degrees of the range [-90,90], a positive tiltX is to the right (default: 0)", - "experimental": true, "optional": true, - "type": "integer" + "type": "number" }, { "name": "tiltY", "description": "The plane angle between the X-Z plane and the plane containing both the stylus axis and the X axis, in degrees of the range [-90,90], a positive tiltY is towards the user (default: 0).", - "experimental": true, "optional": true, - "type": "integer" + "type": "number" }, { "name": "twist", @@ -9893,7 +11495,7 @@ }, { "name": "imeSetComposition", - "description": "This method sets the current candidate text for ime.\nUse imeCommitComposition to commit the final text.\nUse imeSetComposition with empty string as text to cancel composition.", + "description": "This method sets the current candidate text for IME.\nUse imeCommitComposition to commit the final text.\nUse imeSetComposition with empty string as text to cancel composition.", "experimental": true, "parameters": [ { @@ -9997,16 +11599,14 @@ { "name": "tiltX", "description": "The plane angle between the Y-Z plane and the plane containing both the stylus axis and the Y axis, in degrees of the range [-90,90], a positive tiltX is to the right (default: 0).", - "experimental": true, "optional": true, - "type": "integer" + "type": "number" }, { "name": "tiltY", "description": "The plane angle between the X-Z plane and the plane containing both the stylus axis and the X axis, in degrees of the range [-90,90], a positive tiltY is towards the user (default: 0).", - "experimental": true, "optional": true, - "type": "integer" + "type": "number" }, { "name": "twist", @@ -10767,7 +12367,7 @@ "parameters": [ { "name": "layers", - "description": "Layer tree, absent if not in the comspositing mode.", + "description": "Layer tree, absent if not in the compositing mode.", "optional": true, "type": "array", "items": { @@ -11039,11 +12639,29 @@ "type": "number" } ] + }, + { + "id": "DOMCounter", + "description": "DOM object counter data.", + "type": "object", + "properties": [ + { + "name": "name", + "description": "Object name. Note: object names should be presumed volatile and clients should not expect\nthe returned names to be consistent across runs.", + "type": "string" + }, + { + "name": "count", + "description": "Object count.", + "type": "integer" + } + ] } ], "commands": [ { "name": "getDOMCounters", + "description": "Retruns current DOM object counters.", "returns": [ { "name": "documents", @@ -11060,7 +12678,22 @@ ] }, { - "name": "prepareForLeakDetection" + "name": "getDOMCountersForLeakDetection", + "description": "Retruns DOM object counters after preparing renderer for leak detection.", + "returns": [ + { + "name": "counters", + "description": "DOM object counters.", + "type": "array", + "items": { + "$ref": "DOMCounter" + } + } + ] + }, + { + "name": "prepareForLeakDetection", + "description": "Prepares for leak detection by terminating workers, stopping spellcheckers,\ndropping non-essential internal caches, running garbage collections, etc." }, { "name": "forciblyPurgeJavaScriptMemory", @@ -11183,7 +12816,7 @@ }, { "id": "RequestId", - "description": "Unique request identifier.", + "description": "Unique network request identifier.\nNote that this does not identify individual HTTP requests that are part of\na network request.", "type": "string" }, { @@ -11349,6 +12982,20 @@ "experimental": true, "type": "number" }, + { + "name": "workerRouterEvaluationStart", + "description": "Started ServiceWorker static routing source evaluation.", + "experimental": true, + "optional": true, + "type": "number" + }, + { + "name": "workerCacheLookupStart", + "description": "Started cache lookup when the source was evaluated to `cache`.", + "experimental": true, + "optional": true, + "type": "number" + }, { "name": "sendStart", "description": "Started sending request.", @@ -11436,7 +13083,8 @@ }, { "name": "postData", - "description": "HTTP POST request data.", + "description": "HTTP POST request data.\nUse postDataEntries instead.", + "deprecated": true, "optional": true, "type": "string" }, @@ -11448,7 +13096,7 @@ }, { "name": "postDataEntries", - "description": "Request body elements. This will be converted from base64 to binary", + "description": "Request body elements (post data broken into individual entries).", "experimental": true, "optional": true, "type": "array", @@ -11497,7 +13145,7 @@ }, { "name": "isSameSite", - "description": "True if this resource request is considered to be the 'same site' as the\nrequest correspondinfg to the main frame.", + "description": "True if this resource request is considered to be the 'same site' as the\nrequest corresponding to the main frame.", "experimental": true, "optional": true, "type": "boolean" @@ -11668,7 +13316,10 @@ "coop-sandboxed-iframe-cannot-navigate-to-coop-page", "corp-not-same-origin", "corp-not-same-origin-after-defaulted-to-same-origin-by-coep", - "corp-not-same-site" + "corp-not-same-origin-after-defaulted-to-same-origin-by-dip", + "corp-not-same-origin-after-defaulted-to-same-origin-by-coep-and-dip", + "corp-not-same-site", + "sri-message-signature-mismatch" ] }, { @@ -11709,7 +13360,8 @@ "PreflightMissingPrivateNetworkAccessId", "PreflightMissingPrivateNetworkAccessName", "PrivateNetworkAccessPermissionUnavailable", - "PrivateNetworkAccessPermissionDenied" + "PrivateNetworkAccessPermissionDenied", + "LocalNetworkAccessPermissionDenied" ] }, { @@ -11793,6 +13445,42 @@ "unspecifiedReason" ] }, + { + "id": "ServiceWorkerRouterSource", + "description": "Source of service worker router.", + "type": "string", + "enum": [ + "network", + "cache", + "fetch-event", + "race-network-and-fetch-handler" + ] + }, + { + "id": "ServiceWorkerRouterInfo", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "ruleIdMatched", + "description": "ID of the rule matched. If there is a matched rule, this field will\nbe set, otherwiser no value will be set.", + "optional": true, + "type": "integer" + }, + { + "name": "matchedSourceType", + "description": "The router source of the matched rule. If there is a matched rule, this\nfield will be set, otherwise no value will be set.", + "optional": true, + "$ref": "ServiceWorkerRouterSource" + }, + { + "name": "actualSourceType", + "description": "The actual router source used.", + "optional": true, + "$ref": "ServiceWorkerRouterSource" + } + ] + }, { "id": "Response", "description": "HTTP response data.", @@ -11830,6 +13518,11 @@ "description": "Resource mimeType as determined by the browser.", "type": "string" }, + { + "name": "charset", + "description": "Resource charset as determined by the browser (if applicable).", + "type": "string" + }, { "name": "requestHeaders", "description": "Refined HTTP request headers that were actually transmitted over the network.", @@ -11883,6 +13576,19 @@ "optional": true, "type": "boolean" }, + { + "name": "fromEarlyHints", + "description": "Specifies that the request was served from the prefetch cache.", + "optional": true, + "type": "boolean" + }, + { + "name": "serviceWorkerRouterInfo", + "description": "Information about how ServiceWorker Static Router API was used. If this\nfield is set with `matchedSourceType` field, a matching rule is found.\nIf this field is set without `matchedSource`, no matching rule is found.\nOtherwise, the API is not used.", + "experimental": true, + "optional": true, + "$ref": "ServiceWorkerRouterInfo" + }, { "name": "encodedDataLength", "description": "Total number of bytes received for this request so far.", @@ -12060,7 +13766,7 @@ }, { "name": "stack", - "description": "Initiator JavaScript stack trace, set for Script only.", + "description": "Initiator JavaScript stack trace, set for Script only.\nRequires the Debugger domain to be enabled.", "optional": true, "$ref": "Runtime.StackTrace" }, @@ -12090,6 +13796,24 @@ } ] }, + { + "id": "CookiePartitionKey", + "description": "cookiePartitionKey object\nThe representation of the components of the key that are created by the cookiePartitionKey class contained in net/cookies/cookie_partition_key.h.", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "topLevelSite", + "description": "The site of the top-level URL the browser was visiting at the start\nof the request to the endpoint that set the cookie.", + "type": "string" + }, + { + "name": "hasCrossSiteAncestor", + "description": "Indicates if the cookie has any ancestors that are cross-site to the topLevelSite.", + "type": "boolean" + } + ] + }, { "id": "Cookie", "description": "Cookie object", @@ -12156,6 +13880,7 @@ "name": "sameParty", "description": "True if cookie is SameParty.", "experimental": true, + "deprecated": true, "type": "boolean" }, { @@ -12172,10 +13897,10 @@ }, { "name": "partitionKey", - "description": "Cookie partition key. The site of the top-level URL the browser was visiting at the start\nof the request to the endpoint that set the cookie.", + "description": "Cookie partition key.", "experimental": true, "optional": true, - "type": "string" + "$ref": "CookiePartitionKey" }, { "name": "partitionKeyOpaque", @@ -12198,6 +13923,7 @@ "SameSiteUnspecifiedTreatedAsLax", "SameSiteNoneInsecure", "UserPreferences", + "ThirdPartyPhaseout", "ThirdPartyBlockedInFirstPartySet", "SyntaxError", "SchemeNotSupported", @@ -12211,7 +13937,8 @@ "SamePartyFromCrossPartyContext", "SamePartyConflictsWithOtherAttributes", "NameValuePairExceedsMaxSize", - "DisallowedCharacter" + "DisallowedCharacter", + "NoCookieContent" ] }, { @@ -12228,13 +13955,35 @@ "SameSiteUnspecifiedTreatedAsLax", "SameSiteNoneInsecure", "UserPreferences", + "ThirdPartyPhaseout", "ThirdPartyBlockedInFirstPartySet", "UnknownError", "SchemefulSameSiteStrict", "SchemefulSameSiteLax", "SchemefulSameSiteUnspecifiedTreatedAsLax", "SamePartyFromCrossPartyContext", - "NameValuePairExceedsMaxSize" + "NameValuePairExceedsMaxSize", + "PortMismatch", + "SchemeMismatch" + ] + }, + { + "id": "CookieExemptionReason", + "description": "Types of reasons why a cookie should have been blocked by 3PCD but is exempted for the request.", + "experimental": true, + "type": "string", + "enum": [ + "None", + "UserSetting", + "TPCDMetadata", + "TPCDDeprecationTrial", + "TopLevelTPCDDeprecationTrial", + "TPCDHeuristics", + "EnterprisePolicy", + "StorageAccess", + "TopLevelStorageAccess", + "Scheme", + "SameSiteNoneCookiesInSandbox" ] }, { @@ -12265,23 +14014,52 @@ ] }, { - "id": "BlockedCookieWithReason", - "description": "A cookie with was not sent with a request with the corresponding reason.", + "id": "ExemptedSetCookieWithReason", + "description": "A cookie should have been blocked by 3PCD but is exempted and stored from a response with the\ncorresponding reason. A cookie could only have at most one exemption reason.", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "exemptionReason", + "description": "The reason the cookie was exempted.", + "$ref": "CookieExemptionReason" + }, + { + "name": "cookieLine", + "description": "The string representing this individual cookie as it would appear in the header.", + "type": "string" + }, + { + "name": "cookie", + "description": "The cookie object representing the cookie.", + "$ref": "Cookie" + } + ] + }, + { + "id": "AssociatedCookie", + "description": "A cookie associated with the request which may or may not be sent with it.\nIncludes the cookies itself and reasons for blocking or exemption.", "experimental": true, "type": "object", "properties": [ + { + "name": "cookie", + "description": "The cookie object representing the cookie which was not sent.", + "$ref": "Cookie" + }, { "name": "blockedReasons", - "description": "The reason(s) the cookie was blocked.", + "description": "The reason(s) the cookie was blocked. If empty means the cookie is included.", "type": "array", "items": { "$ref": "CookieBlockedReason" } }, { - "name": "cookie", - "description": "The cookie object representing the cookie which was not sent.", - "$ref": "Cookie" + "name": "exemptionReason", + "description": "The reason the cookie should have been blocked by 3PCD but is exempted. A cookie could\nonly have at most one exemption reason.", + "optional": true, + "$ref": "CookieExemptionReason" } ] }, @@ -12372,10 +14150,10 @@ }, { "name": "partitionKey", - "description": "Cookie partition key. The site of the top-level URL the browser was visiting at the start\nof the request to the endpoint that set the cookie.\nIf not set, the cookie will be set as not partitioned.", + "description": "Cookie partition key. If not set, the cookie will be set as not partitioned.", "experimental": true, "optional": true, - "type": "string" + "$ref": "CookiePartitionKey" } ] }, @@ -12637,7 +14415,7 @@ }, { "name": "errors", - "description": "Errors occurred while handling the signed exchagne.", + "description": "Errors occurred while handling the signed exchange.", "optional": true, "type": "array", "items": { @@ -12658,6 +14436,50 @@ "zstd" ] }, + { + "id": "DirectSocketDnsQueryType", + "experimental": true, + "type": "string", + "enum": [ + "ipv4", + "ipv6" + ] + }, + { + "id": "DirectTCPSocketOptions", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "noDelay", + "description": "TCP_NODELAY option", + "type": "boolean" + }, + { + "name": "keepAliveDelay", + "description": "Expected to be unsigned integer.", + "optional": true, + "type": "number" + }, + { + "name": "sendBufferSize", + "description": "Expected to be unsigned integer.", + "optional": true, + "type": "number" + }, + { + "name": "receiveBufferSize", + "description": "Expected to be unsigned integer.", + "optional": true, + "type": "number" + }, + { + "name": "dnsQueryType", + "optional": true, + "$ref": "DirectSocketDnsQueryType" + } + ] + }, { "id": "PrivateNetworkRequestPolicy", "experimental": true, @@ -12667,7 +14489,8 @@ "BlockFromInsecureToMorePrivate", "WarnFromInsecureToMorePrivate", "PreflightBlock", - "PreflightWarn" + "PreflightWarn", + "PermissionBlock" ] }, { @@ -12722,7 +14545,8 @@ "RestrictProperties", "UnsafeNone", "SameOriginPlusCoep", - "RestrictPropertiesPlusCoep" + "RestrictPropertiesPlusCoep", + "NoopenerAllowPopups" ] }, { @@ -13100,7 +14924,7 @@ }, { "name": "deleteCookies", - "description": "Deletes browser cookies with matching name and url or domain/path pair.", + "description": "Deletes browser cookies with matching name and url or domain/path/partitionKey pair.", "parameters": [ { "name": "name", @@ -13124,6 +14948,13 @@ "description": "If specified, deletes only cookies with the exact path.", "optional": true, "type": "string" + }, + { + "name": "partitionKey", + "description": "If specified, deletes only cookies with the the given name and partitionKey where\nall partition key attributes match the cookie partition key attribute.", + "experimental": true, + "optional": true, + "$ref": "CookiePartitionKey" } ] }, @@ -13160,6 +14991,27 @@ "description": "Connection type if known.", "optional": true, "$ref": "ConnectionType" + }, + { + "name": "packetLoss", + "description": "WebRTC packet loss (percent, 0-100). 0 disables packet loss emulation, 100 drops all the packets.", + "experimental": true, + "optional": true, + "type": "number" + }, + { + "name": "packetQueueLength", + "description": "WebRTC packet queue length (packet). 0 removes any queue length limitations.", + "experimental": true, + "optional": true, + "type": "integer" + }, + { + "name": "packetReordering", + "description": "WebRTC packetReordering feature.", + "experimental": true, + "optional": true, + "type": "boolean" } ] }, @@ -13401,7 +15253,6 @@ { "name": "setBypassServiceWorker", "description": "Toggles ignoring of service worker for each request.", - "experimental": true, "parameters": [ { "name": "bypass", @@ -13507,10 +15358,10 @@ }, { "name": "partitionKey", - "description": "Cookie partition key. The site of the top-level URL the browser was visiting at the start\nof the request to the endpoint that set the cookie.\nIf not set, the cookie will be set as not partitioned.", + "description": "Cookie partition key. If not set, the cookie will be set as not partitioned.", "experimental": true, "optional": true, - "type": "string" + "$ref": "CookiePartitionKey" } ], "returns": [ @@ -13587,7 +15438,7 @@ }, { "name": "acceptLanguage", - "description": "Browser langugage to emulate.", + "description": "Browser language to emulate.", "optional": true, "type": "string" }, @@ -13606,6 +15457,25 @@ } ] }, + { + "name": "streamResourceContent", + "description": "Enables streaming of the response for the given requestId.\nIf enabled, the dataReceived event contains the data that was received during streaming.", + "experimental": true, + "parameters": [ + { + "name": "requestId", + "description": "Identifier of the request to stream.", + "$ref": "RequestId" + } + ], + "returns": [ + { + "name": "bufferedData", + "description": "Data that has been buffered until streaming is enabled. (Encoded as a base64 string when passed over JSON)", + "type": "string" + } + ] + }, { "name": "getSecurityIsolationStatus", "description": "Returns information about the COEP/COOP isolation status.", @@ -13665,6 +15535,28 @@ "$ref": "LoadNetworkResourcePageResult" } ] + }, + { + "name": "setCookieControls", + "description": "Sets Controls for third-party cookie access\nPage reload is required before the new cookie bahavior will be observed", + "experimental": true, + "parameters": [ + { + "name": "enableThirdPartyCookieRestriction", + "description": "Whether 3pc restriction is enabled.", + "type": "boolean" + }, + { + "name": "disableThirdPartyCookieMetadata", + "description": "Whether 3pc grace period exception should be enabled; false by default.", + "type": "boolean" + }, + { + "name": "disableThirdPartyCookieHeuristics", + "description": "Whether 3pc heuristics exceptions should be enabled; false by default.", + "type": "boolean" + } + ] } ], "events": [ @@ -13691,6 +15583,13 @@ "name": "encodedDataLength", "description": "Actual bytes received (might be less than dataLength for compressed encodings).", "type": "integer" + }, + { + "name": "data", + "description": "Data that was received. (Encoded as a base64 string when passed over JSON)", + "experimental": true, + "optional": true, + "type": "string" } ] }, @@ -13746,7 +15645,7 @@ }, { "name": "errorText", - "description": "User friendly error message.", + "description": "Error message. List of network errors: https://cs.chromium.org/chromium/src/net/base/net_error_list.h", "type": "string" }, { @@ -14235,6 +16134,108 @@ } ] }, + { + "name": "directTCPSocketCreated", + "description": "Fired upon direct_socket.TCPSocket creation.", + "experimental": true, + "parameters": [ + { + "name": "identifier", + "$ref": "RequestId" + }, + { + "name": "remoteAddr", + "type": "string" + }, + { + "name": "remotePort", + "description": "Unsigned int 16.", + "type": "integer" + }, + { + "name": "options", + "$ref": "DirectTCPSocketOptions" + }, + { + "name": "timestamp", + "$ref": "MonotonicTime" + }, + { + "name": "initiator", + "optional": true, + "$ref": "Initiator" + } + ] + }, + { + "name": "directTCPSocketOpened", + "description": "Fired when direct_socket.TCPSocket connection is opened.", + "experimental": true, + "parameters": [ + { + "name": "identifier", + "$ref": "RequestId" + }, + { + "name": "remoteAddr", + "type": "string" + }, + { + "name": "remotePort", + "description": "Expected to be unsigned integer.", + "type": "integer" + }, + { + "name": "timestamp", + "$ref": "MonotonicTime" + }, + { + "name": "localAddr", + "optional": true, + "type": "string" + }, + { + "name": "localPort", + "description": "Expected to be unsigned integer.", + "optional": true, + "type": "integer" + } + ] + }, + { + "name": "directTCPSocketAborted", + "description": "Fired when direct_socket.TCPSocket is aborted.", + "experimental": true, + "parameters": [ + { + "name": "identifier", + "$ref": "RequestId" + }, + { + "name": "errorMessage", + "type": "string" + }, + { + "name": "timestamp", + "$ref": "MonotonicTime" + } + ] + }, + { + "name": "directTCPSocketClosed", + "description": "Fired when direct_socket.TCPSocket is closed.", + "experimental": true, + "parameters": [ + { + "name": "identifier", + "$ref": "RequestId" + }, + { + "name": "timestamp", + "$ref": "MonotonicTime" + } + ] + }, { "name": "requestWillBeSentExtraInfo", "description": "Fired when additional information about a requestWillBeSent event is available from the\nnetwork stack. Not every requestWillBeSent event will have an additional\nrequestWillBeSentExtraInfo fired for it, and there is no guarantee whether requestWillBeSent\nor requestWillBeSentExtraInfo will be fired first for the same request.", @@ -14247,10 +16248,10 @@ }, { "name": "associatedCookies", - "description": "A list of cookies potentially associated to the requested URL. This includes both cookies sent with\nthe request and the ones not sent; the latter are distinguished by having blockedReason field set.", + "description": "A list of cookies potentially associated to the requested URL. This includes both cookies sent with\nthe request and the ones not sent; the latter are distinguished by having blockedReasons field set.", "type": "array", "items": { - "$ref": "BlockedCookieWithReason" + "$ref": "AssociatedCookie" } }, { @@ -14298,7 +16299,7 @@ }, { "name": "headers", - "description": "Raw response headers as they were received over the wire.", + "description": "Raw response headers as they were received over the wire.\nDuplicate headers in the response are represented as a single key with their values\nconcatentated using `\\n` as the separator.\nSee also `headersText` that contains verbatim text for HTTP/1.*.", "$ref": "Headers" }, { @@ -14320,14 +16321,41 @@ { "name": "cookiePartitionKey", "description": "The cookie partition key that will be used to store partitioned cookies set in this response.\nOnly sent when partitioned cookies are enabled.", + "experimental": true, "optional": true, - "type": "string" + "$ref": "CookiePartitionKey" }, { "name": "cookiePartitionKeyOpaque", - "description": "True if partitioned cookies are enabled, but the partition key is not serializeable to string.", + "description": "True if partitioned cookies are enabled, but the partition key is not serializable to string.", "optional": true, "type": "boolean" + }, + { + "name": "exemptedCookies", + "description": "A list of cookies which should have been blocked by 3PCD but are exempted and stored from\nthe response with the corresponding reason.", + "optional": true, + "type": "array", + "items": { + "$ref": "ExemptedSetCookieWithReason" + } + } + ] + }, + { + "name": "responseReceivedEarlyHints", + "description": "Fired when 103 Early Hints headers is received in addition to the common response.\nNot every responseReceived event will have an responseReceivedEarlyHints fired.\nOnly one responseReceivedEarlyHints may be fired for eached responseReceived event.", + "experimental": true, + "parameters": [ + { + "name": "requestId", + "description": "Request identifier. Used to match this information to another responseReceived event.", + "$ref": "RequestId" + }, + { + "name": "headers", + "description": "Raw response headers as they were received over the wire.\nDuplicate headers in the response are represented as a single key with their values\nconcatentated using `\\n` as the separator.\nSee also `headersText` that contains verbatim text for HTTP/1.*.", + "$ref": "Headers" } ] }, @@ -14347,12 +16375,13 @@ "FailedPrecondition", "ResourceExhausted", "AlreadyExists", - "Unavailable", + "ResourceLimited", "Unauthorized", "BadResponse", "InternalError", "UnknownError", - "FulfilledLocally" + "FulfilledLocally", + "SiteIssuerLimit" ] }, { @@ -14383,6 +16412,11 @@ } ] }, + { + "name": "policyUpdated", + "description": "Fired once security policy has been updated.", + "experimental": true + }, { "name": "subresourceWebBundleMetadataReceived", "description": "Fired once when parsing the .wbn file has succeeded.\nThe event contains the information about the web bundle contents.", @@ -14529,7 +16563,7 @@ "properties": [ { "name": "parentOutlineColor", - "description": "the color to outline the givent element in.", + "description": "the color to outline the given element in.", "$ref": "DOM.RGBA" }, { @@ -15033,6 +17067,28 @@ } ] }, + { + "id": "WindowControlsOverlayConfig", + "description": "Configuration for Window Controls Overlay", + "type": "object", + "properties": [ + { + "name": "showCSS", + "description": "Whether the title bar CSS should be shown when emulating the Window Controls Overlay.", + "type": "boolean" + }, + { + "name": "selectedPlatform", + "description": "Selected platforms to show the overlay.", + "type": "string" + }, + { + "name": "themeColor", + "description": "The theme color defined in app manifest.", + "type": "string" + } + ] + }, { "id": "ContainerQueryHighlightConfig", "type": "object", @@ -15215,7 +17271,7 @@ }, { "name": "highlightFrame", - "description": "Highlights owner element of the frame with given id.\nDeprecated: Doesn't work reliablity and cannot be fixed due to process\nseparatation (the owner node might be in a different process). Determine\nthe owner node in the client and use highlightNode.", + "description": "Highlights owner element of the frame with given id.\nDeprecated: Doesn't work reliably and cannot be fixed due to process\nseparation (the owner node might be in a different process). Determine\nthe owner node in the client and use highlightNode.", "deprecated": true, "parameters": [ { @@ -15523,7 +17579,8 @@ }, { "name": "setShowWebVitals", - "description": "Request that backend shows an overlay with web vital metrics.", + "description": "Deprecated, no longer has any effect.", + "deprecated": true, "parameters": [ { "name": "show", @@ -15567,6 +17624,18 @@ } } ] + }, + { + "name": "setShowWindowControlsOverlay", + "description": "Show Window Controls Overlay for PWA", + "parameters": [ + { + "name": "windowControlsOverlayConfig", + "description": "Window Controls Overlay data, null means hide Window Controls Overlay", + "optional": true, + "$ref": "WindowControlsOverlayConfig" + } + ] } ], "events": [ @@ -15719,32 +17788,36 @@ }, { "id": "PermissionsPolicyFeature", - "description": "All Permissions Policy features. This enum should match the one defined\nin third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5.", + "description": "All Permissions Policy features. This enum should match the one defined\nin services/network/public/cpp/permissions_policy/permissions_policy_features.json5.", "experimental": true, "type": "string", "enum": [ "accelerometer", + "all-screens-capture", "ambient-light-sensor", "attribution-reporting", "autoplay", "bluetooth", "browsing-topics", "camera", + "captured-surface-control", "ch-dpr", "ch-device-memory", "ch-downlink", "ch-ect", "ch-prefers-color-scheme", "ch-prefers-reduced-motion", + "ch-prefers-reduced-transparency", "ch-rtt", "ch-save-data", "ch-ua", "ch-ua-arch", "ch-ua-bitness", + "ch-ua-high-entropy-values", "ch-ua-platform", "ch-ua-model", "ch-ua-mobile", - "ch-ua-form-factor", + "ch-ua-form-factors", "ch-ua-full-version", "ch-ua-full-version-list", "ch-ua-platform-version", @@ -15755,13 +17828,19 @@ "clipboard-read", "clipboard-write", "compute-pressure", + "controlled-frame", "cross-origin-isolated", + "deferred-fetch", + "deferred-fetch-minimal", + "digital-credentials-get", "direct-sockets", + "direct-sockets-private", "display-capture", "document-domain", "encrypted-media", "execution-while-out-of-viewport", "execution-while-not-rendered", + "fenced-unpartitioned-storage-read", "focus-without-user-activation", "fullscreen", "frobulate", @@ -15776,14 +17855,17 @@ "keyboard-map", "local-fonts", "magnetometer", + "media-playback-while-not-visible", "microphone", "midi", "otp-credentials", "payment", "picture-in-picture", + "popins", "private-aggregation", "private-state-token-issuance", "private-state-token-redemption", + "publickey-credentials-create", "publickey-credentials-get", "run-ad-auction", "screen-wake-lock", @@ -15792,14 +17874,18 @@ "shared-storage", "shared-storage-select-url", "smart-card", + "speaker-selection", "storage-access", + "sub-apps", "sync-xhr", "unload", "usb", + "usb-unrestricted", "vertical-scroll", + "web-app-installation", + "web-printing", "web-share", "window-management", - "window-placement", "xr-spatial-tracking" ] }, @@ -15965,6 +18051,19 @@ } ] }, + { + "id": "SecurityOriginDetails", + "description": "Additional information about the frame document's security origin.", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "isLocalhost", + "description": "Indicates whether the frame document's security origin is one\nof the local hostnames (e.g. \"localhost\") or IP addresses (IPv4\n127.0.0.0/8 or IPv6 ::1).", + "type": "boolean" + } + ] + }, { "id": "Frame", "description": "Information about the Frame on the page.", @@ -16015,6 +18114,13 @@ "description": "Frame document's security origin.", "type": "string" }, + { + "name": "securityOriginDetails", + "description": "Additional details about the frame document's security origin.", + "experimental": true, + "optional": true, + "$ref": "SecurityOriginDetails" + }, { "name": "mimeType", "description": "Frame document's mimeType as determined by the browser.", @@ -16279,7 +18385,7 @@ }, { "name": "critical", - "description": "If criticial, this is a non-recoverable parse error.", + "description": "If critical, this is a non-recoverable parse error.", "type": "integer" }, { @@ -16507,14 +18613,16 @@ "experimental": true, "type": "string", "enum": [ + "anchorClick", "formSubmissionGet", "formSubmissionPost", "httpHeaderRefresh", - "scriptInitiated", + "initialFrameNavigation", "metaTagRefresh", + "other", "pageBlockInterstitial", "reload", - "anchorClick" + "scriptInitiated" ] }, { @@ -16602,841 +18710,1265 @@ ] }, { - "id": "AutoResponseMode", - "description": "Enum of possible auto-reponse for permisison / prompt dialogs.", - "experimental": true, - "type": "string", - "enum": [ - "none", - "autoAccept", - "autoReject", - "autoOptOut" - ] - }, - { - "id": "NavigationType", - "description": "The type of a frameNavigated event.", - "experimental": true, - "type": "string", - "enum": [ - "Navigation", - "BackForwardCacheRestore" - ] - }, - { - "id": "BackForwardCacheNotRestoredReason", - "description": "List of not restored reasons for back-forward cache.", - "experimental": true, - "type": "string", - "enum": [ - "NotPrimaryMainFrame", - "BackForwardCacheDisabled", - "RelatedActiveContentsExist", - "HTTPStatusNotOK", - "SchemeNotHTTPOrHTTPS", - "Loading", - "WasGrantedMediaAccess", - "DisableForRenderFrameHostCalled", - "DomainNotAllowed", - "HTTPMethodNotGET", - "SubframeIsNavigating", - "Timeout", - "CacheLimit", - "JavaScriptExecution", - "RendererProcessKilled", - "RendererProcessCrashed", - "SchedulerTrackedFeatureUsed", - "ConflictingBrowsingInstance", - "CacheFlushed", - "ServiceWorkerVersionActivation", - "SessionRestored", - "ServiceWorkerPostMessage", - "EnteredBackForwardCacheBeforeServiceWorkerHostAdded", - "RenderFrameHostReused_SameSite", - "RenderFrameHostReused_CrossSite", - "ServiceWorkerClaim", - "IgnoreEventAndEvict", - "HaveInnerContents", - "TimeoutPuttingInCache", - "BackForwardCacheDisabledByLowMemory", - "BackForwardCacheDisabledByCommandLine", - "NetworkRequestDatapipeDrainedAsBytesConsumer", - "NetworkRequestRedirected", - "NetworkRequestTimeout", - "NetworkExceedsBufferLimit", - "NavigationCancelledWhileRestoring", - "NotMostRecentNavigationEntry", - "BackForwardCacheDisabledForPrerender", - "UserAgentOverrideDiffers", - "ForegroundCacheLimit", - "BrowsingInstanceNotSwapped", - "BackForwardCacheDisabledForDelegate", - "UnloadHandlerExistsInMainFrame", - "UnloadHandlerExistsInSubFrame", - "ServiceWorkerUnregistration", - "CacheControlNoStore", - "CacheControlNoStoreCookieModified", - "CacheControlNoStoreHTTPOnlyCookieModified", - "NoResponseHead", - "Unknown", - "ActivationNavigationsDisallowedForBug1234857", - "ErrorDocument", - "FencedFramesEmbedder", - "CookieDisabled", - "HTTPAuthRequired", - "CookieFlushed", - "WebSocket", - "WebTransport", - "WebRTC", - "MainResourceHasCacheControlNoStore", - "MainResourceHasCacheControlNoCache", - "SubresourceHasCacheControlNoStore", - "SubresourceHasCacheControlNoCache", - "ContainsPlugins", - "DocumentLoaded", - "DedicatedWorkerOrWorklet", - "OutstandingNetworkRequestOthers", - "RequestedMIDIPermission", - "RequestedAudioCapturePermission", - "RequestedVideoCapturePermission", - "RequestedBackForwardCacheBlockedSensors", - "RequestedBackgroundWorkPermission", - "BroadcastChannel", - "WebXR", - "SharedWorker", - "WebLocks", - "WebHID", - "WebShare", - "RequestedStorageAccessGrant", - "WebNfc", - "OutstandingNetworkRequestFetch", - "OutstandingNetworkRequestXHR", - "AppBanner", - "Printing", - "WebDatabase", - "PictureInPicture", - "Portal", - "SpeechRecognizer", - "IdleManager", - "PaymentManager", - "SpeechSynthesis", - "KeyboardLock", - "WebOTPService", - "OutstandingNetworkRequestDirectSocket", - "InjectedJavascript", - "InjectedStyleSheet", - "KeepaliveRequest", - "IndexedDBEvent", - "Dummy", - "JsNetworkRequestReceivedCacheControlNoStoreResource", - "WebRTCSticky", - "WebTransportSticky", - "WebSocketSticky", - "ContentSecurityHandler", - "ContentWebAuthenticationAPI", - "ContentFileChooser", - "ContentSerial", - "ContentFileSystemAccess", - "ContentMediaDevicesDispatcherHost", - "ContentWebBluetooth", - "ContentWebUSB", - "ContentMediaSessionService", - "ContentScreenReader", - "EmbedderPopupBlockerTabHelper", - "EmbedderSafeBrowsingTriggeredPopupBlocker", - "EmbedderSafeBrowsingThreatDetails", - "EmbedderAppBannerManager", - "EmbedderDomDistillerViewerSource", - "EmbedderDomDistillerSelfDeletingRequestDelegate", - "EmbedderOomInterventionTabHelper", - "EmbedderOfflinePage", - "EmbedderChromePasswordManagerClientBindCredentialManager", - "EmbedderPermissionRequestManager", - "EmbedderModalDialog", - "EmbedderExtensions", - "EmbedderExtensionMessaging", - "EmbedderExtensionMessagingForOpenPort", - "EmbedderExtensionSentMessageToCachedFrame" - ] - }, - { - "id": "BackForwardCacheNotRestoredReasonType", - "description": "Types of not restored reasons for back-forward cache.", - "experimental": true, - "type": "string", - "enum": [ - "SupportPending", - "PageSupportNeeded", - "Circumstantial" - ] - }, - { - "id": "BackForwardCacheNotRestoredExplanation", + "id": "FileFilter", "experimental": true, "type": "object", "properties": [ { - "name": "type", - "description": "Type of the reason", - "$ref": "BackForwardCacheNotRestoredReasonType" - }, - { - "name": "reason", - "description": "Not restored reason", - "$ref": "BackForwardCacheNotRestoredReason" + "name": "name", + "optional": true, + "type": "string" }, { - "name": "context", - "description": "Context associated with the reason. The meaning of this context is\ndependent on the reason:\n- EmbedderExtensionSentMessageToCachedFrame: the extension ID.", + "name": "accepts", "optional": true, - "type": "string" + "type": "array", + "items": { + "type": "string" + } } ] }, { - "id": "BackForwardCacheNotRestoredExplanationTree", + "id": "FileHandler", "experimental": true, "type": "object", "properties": [ { - "name": "url", - "description": "URL of each frame", + "name": "action", "type": "string" }, { - "name": "explanations", - "description": "Not restored reasons of each frame", + "name": "name", + "type": "string" + }, + { + "name": "icons", + "optional": true, "type": "array", "items": { - "$ref": "BackForwardCacheNotRestoredExplanation" + "$ref": "ImageResource" } }, { - "name": "children", - "description": "Array of children frame", + "name": "accepts", + "description": "Mimic a map, name is the key, accepts is the value.", + "optional": true, "type": "array", "items": { - "$ref": "BackForwardCacheNotRestoredExplanationTree" + "$ref": "FileFilter" } - } - ] - } - ], - "commands": [ - { - "name": "addScriptToEvaluateOnLoad", - "description": "Deprecated, please use addScriptToEvaluateOnNewDocument instead.", - "experimental": true, - "deprecated": true, - "parameters": [ + }, { - "name": "scriptSource", + "name": "launchType", + "description": "Won't repeat the enums, using string for easy comparison. Same as the\nother enums below.", "type": "string" } - ], - "returns": [ - { - "name": "identifier", - "description": "Identifier of the added script.", - "$ref": "ScriptIdentifier" - } ] }, { - "name": "addScriptToEvaluateOnNewDocument", - "description": "Evaluates given script in every frame upon creation (before loading frame's scripts).", - "parameters": [ + "id": "ImageResource", + "description": "The image definition used in both icon and screenshot.", + "experimental": true, + "type": "object", + "properties": [ { - "name": "source", + "name": "url", + "description": "The src field in the definition, but changing to url in favor of\nconsistency.", "type": "string" }, { - "name": "worldName", - "description": "If specified, creates an isolated world with the given name and evaluates given script in it.\nThis world name will be used as the ExecutionContextDescription::name when the corresponding\nevent is emitted.", - "experimental": true, + "name": "sizes", "optional": true, "type": "string" }, { - "name": "includeCommandLineAPI", - "description": "Specifies whether command line API should be available to the script, defaults\nto false.", - "experimental": true, - "optional": true, - "type": "boolean" - }, - { - "name": "runImmediately", - "description": "If true, runs the script immediately on existing execution contexts or worlds.\nDefault: false.", - "experimental": true, + "name": "type", "optional": true, - "type": "boolean" - } - ], - "returns": [ - { - "name": "identifier", - "description": "Identifier of the added script.", - "$ref": "ScriptIdentifier" + "type": "string" } ] }, { - "name": "bringToFront", - "description": "Brings page to front (activates tab)." + "id": "LaunchHandler", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "clientMode", + "type": "string" + } + ] }, { - "name": "captureScreenshot", - "description": "Capture page screenshot.", - "parameters": [ - { - "name": "format", - "description": "Image compression format (defaults to png).", - "optional": true, - "type": "string", - "enum": [ - "jpeg", - "png", - "webp" - ] - }, - { - "name": "quality", - "description": "Compression quality from range [0..100] (jpeg only).", - "optional": true, - "type": "integer" - }, - { - "name": "clip", - "description": "Capture the screenshot of a given region only.", - "optional": true, - "$ref": "Viewport" - }, - { - "name": "fromSurface", - "description": "Capture the screenshot from the surface, rather than the view. Defaults to true.", - "experimental": true, - "optional": true, - "type": "boolean" - }, + "id": "ProtocolHandler", + "experimental": true, + "type": "object", + "properties": [ { - "name": "captureBeyondViewport", - "description": "Capture the screenshot beyond the viewport. Defaults to false.", - "experimental": true, - "optional": true, - "type": "boolean" + "name": "protocol", + "type": "string" }, { - "name": "optimizeForSpeed", - "description": "Optimize image encoding for speed, not for resulting size (defaults to false)", - "experimental": true, - "optional": true, - "type": "boolean" - } - ], - "returns": [ - { - "name": "data", - "description": "Base64-encoded image data. (Encoded as a base64 string when passed over JSON)", + "name": "url", "type": "string" } ] }, { - "name": "captureSnapshot", - "description": "Returns a snapshot of the page as a string. For MHTML format, the serialization includes\niframes, shadow DOM, external resources, and element-inline styles.", + "id": "RelatedApplication", "experimental": true, - "parameters": [ + "type": "object", + "properties": [ { - "name": "format", - "description": "Format (defaults to mhtml).", + "name": "id", "optional": true, - "type": "string", - "enum": [ - "mhtml" - ] - } - ], - "returns": [ + "type": "string" + }, { - "name": "data", - "description": "Serialized page data.", + "name": "url", "type": "string" } ] }, { - "name": "clearDeviceMetricsOverride", - "description": "Clears the overridden device metrics.", + "id": "ScopeExtension", "experimental": true, - "deprecated": true, - "redirect": "Emulation" + "type": "object", + "properties": [ + { + "name": "origin", + "description": "Instead of using tuple, this field always returns the serialized string\nfor easy understanding and comparison.", + "type": "string" + }, + { + "name": "hasOriginWildcard", + "type": "boolean" + } + ] }, { - "name": "clearDeviceOrientationOverride", - "description": "Clears the overridden Device Orientation.", + "id": "Screenshot", "experimental": true, - "deprecated": true, - "redirect": "DeviceOrientation" - }, - { - "name": "clearGeolocationOverride", - "description": "Clears the overridden Geolocation Position and Error.", - "deprecated": true, - "redirect": "Emulation" - }, - { - "name": "createIsolatedWorld", - "description": "Creates an isolated world for the given frame.", - "parameters": [ + "type": "object", + "properties": [ { - "name": "frameId", - "description": "Id of the frame in which the isolated world should be created.", - "$ref": "FrameId" + "name": "image", + "$ref": "ImageResource" }, { - "name": "worldName", - "description": "An optional name which is reported in the Execution Context.", - "optional": true, + "name": "formFactor", "type": "string" }, { - "name": "grantUniveralAccess", - "description": "Whether or not universal access should be granted to the isolated world. This is a powerful\noption, use with caution.", + "name": "label", "optional": true, - "type": "boolean" - } - ], - "returns": [ - { - "name": "executionContextId", - "description": "Execution context of the isolated world.", - "$ref": "Runtime.ExecutionContextId" + "type": "string" } ] }, { - "name": "deleteCookie", - "description": "Deletes browser cookie with given name, domain and path.", + "id": "ShareTarget", "experimental": true, - "deprecated": true, - "redirect": "Network", - "parameters": [ + "type": "object", + "properties": [ { - "name": "cookieName", - "description": "Name of the cookie to remove.", + "name": "action", "type": "string" }, { - "name": "url", - "description": "URL to match cooke domain and path.", + "name": "method", "type": "string" - } - ] - }, - { - "name": "disable", - "description": "Disables page domain notifications." - }, - { - "name": "enable", - "description": "Enables page domain notifications." - }, - { - "name": "getAppManifest", - "returns": [ + }, { - "name": "url", - "description": "Manifest location.", + "name": "enctype", "type": "string" }, { - "name": "errors", - "type": "array", - "items": { - "$ref": "AppManifestError" - } + "name": "title", + "description": "Embed the ShareTargetParams", + "optional": true, + "type": "string" }, { - "name": "data", - "description": "Manifest content.", + "name": "text", "optional": true, "type": "string" }, { - "name": "parsed", - "description": "Parsed manifest properties", - "experimental": true, + "name": "url", "optional": true, - "$ref": "AppManifestParsedProperties" - } - ] - }, - { - "name": "getInstallabilityErrors", - "experimental": true, - "returns": [ + "type": "string" + }, { - "name": "installabilityErrors", + "name": "files", + "optional": true, "type": "array", "items": { - "$ref": "InstallabilityError" + "$ref": "FileFilter" } } ] }, { - "name": "getManifestIcons", - "description": "Deprecated because it's not guaranteed that the returned icon is in fact the one used for PWA installation.", + "id": "Shortcut", "experimental": true, - "deprecated": true, - "returns": [ + "type": "object", + "properties": [ { - "name": "primaryIcon", - "optional": true, + "name": "name", + "type": "string" + }, + { + "name": "url", "type": "string" } ] }, { - "name": "getAppId", - "description": "Returns the unique (PWA) app id.\nOnly returns values if the feature flag 'WebAppEnableManifestId' is enabled", + "id": "WebAppManifest", "experimental": true, - "returns": [ + "type": "object", + "properties": [ { - "name": "appId", - "description": "App id, either from manifest's id attribute or computed from start_url", + "name": "backgroundColor", "optional": true, "type": "string" }, { - "name": "recommendedId", - "description": "Recommendation for manifest's id attribute to match current id computed from start_url", + "name": "description", + "description": "The extra description provided by the manifest.", "optional": true, "type": "string" - } - ] - }, - { - "name": "getAdScriptId", - "experimental": true, - "parameters": [ + }, { - "name": "frameId", - "$ref": "FrameId" - } - ], - "returns": [ + "name": "dir", + "optional": true, + "type": "string" + }, { - "name": "adScriptId", - "description": "Identifies the bottom-most script which caused the frame to be labelled\nas an ad. Only sent if frame is labelled as an ad and id is available.", + "name": "display", "optional": true, - "$ref": "AdScriptId" - } - ] - }, - { - "name": "getCookies", - "description": "Returns all browser cookies for the page and all of its subframes. Depending\non the backend support, will return detailed cookie information in the\n`cookies` field.", - "experimental": true, - "deprecated": true, - "redirect": "Network", - "returns": [ + "type": "string" + }, { - "name": "cookies", - "description": "Array of cookie objects.", + "name": "displayOverrides", + "description": "The overrided display mode controlled by the user.", + "optional": true, "type": "array", "items": { - "$ref": "Network.Cookie" + "type": "string" } - } - ] - }, - { - "name": "getFrameTree", - "description": "Returns present frame tree structure.", - "returns": [ - { - "name": "frameTree", - "description": "Present frame tree structure.", - "$ref": "FrameTree" - } - ] - }, - { - "name": "getLayoutMetrics", - "description": "Returns metrics relating to the layouting of the page, such as viewport bounds/scale.", - "returns": [ - { - "name": "layoutViewport", - "description": "Deprecated metrics relating to the layout viewport. Is in device pixels. Use `cssLayoutViewport` instead.", - "deprecated": true, - "$ref": "LayoutViewport" - }, - { - "name": "visualViewport", - "description": "Deprecated metrics relating to the visual viewport. Is in device pixels. Use `cssVisualViewport` instead.", - "deprecated": true, - "$ref": "VisualViewport" - }, - { - "name": "contentSize", - "description": "Deprecated size of scrollable area. Is in DP. Use `cssContentSize` instead.", - "deprecated": true, - "$ref": "DOM.Rect" - }, - { - "name": "cssLayoutViewport", - "description": "Metrics relating to the layout viewport in CSS pixels.", - "$ref": "LayoutViewport" - }, - { - "name": "cssVisualViewport", - "description": "Metrics relating to the visual viewport in CSS pixels.", - "$ref": "VisualViewport" - }, - { - "name": "cssContentSize", - "description": "Size of scrollable area in CSS pixels.", - "$ref": "DOM.Rect" - } - ] - }, - { - "name": "getNavigationHistory", - "description": "Returns navigation history for the current page.", - "returns": [ - { - "name": "currentIndex", - "description": "Index of the current navigation history entry.", - "type": "integer" }, { - "name": "entries", - "description": "Array of navigation history entries.", + "name": "fileHandlers", + "description": "The handlers to open files.", + "optional": true, "type": "array", "items": { - "$ref": "NavigationEntry" + "$ref": "FileHandler" } - } - ] - }, - { - "name": "resetNavigationHistory", - "description": "Resets navigation history for the current page." - }, - { - "name": "getResourceContent", - "description": "Returns content of the given resource.", - "experimental": true, - "parameters": [ - { - "name": "frameId", - "description": "Frame id to get resource for.", - "$ref": "FrameId" - }, - { - "name": "url", - "description": "URL of the resource to get content for.", - "type": "string" - } - ], - "returns": [ - { - "name": "content", - "description": "Resource content.", - "type": "string" - }, - { - "name": "base64Encoded", - "description": "True, if content was served as base64.", - "type": "boolean" - } - ] - }, - { - "name": "getResourceTree", - "description": "Returns present frame / resource tree structure.", - "experimental": true, - "returns": [ - { - "name": "frameTree", - "description": "Present frame / resource tree structure.", - "$ref": "FrameResourceTree" - } - ] - }, - { - "name": "handleJavaScriptDialog", - "description": "Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).", - "parameters": [ - { - "name": "accept", - "description": "Whether to accept or dismiss the dialog.", - "type": "boolean" }, { - "name": "promptText", - "description": "The text to enter into the dialog prompt before accepting. Used only if this is a prompt\ndialog.", + "name": "icons", "optional": true, - "type": "string" - } - ] - }, - { - "name": "navigate", - "description": "Navigates current page to the given URL.", - "parameters": [ - { - "name": "url", - "description": "URL to navigate the page to.", - "type": "string" + "type": "array", + "items": { + "$ref": "ImageResource" + } }, { - "name": "referrer", - "description": "Referrer URL.", + "name": "id", "optional": true, "type": "string" }, { - "name": "transitionType", - "description": "Intended transition type.", - "optional": true, - "$ref": "TransitionType" - }, - { - "name": "frameId", - "description": "Frame id to navigate, if not specified navigates the top frame.", - "optional": true, - "$ref": "FrameId" - }, - { - "name": "referrerPolicy", - "description": "Referrer-policy used for the navigation.", - "experimental": true, + "name": "lang", "optional": true, - "$ref": "ReferrerPolicy" - } - ], - "returns": [ - { - "name": "frameId", - "description": "Frame id that has navigated (or failed to navigate)", - "$ref": "FrameId" + "type": "string" }, { - "name": "loaderId", - "description": "Loader identifier. This is omitted in case of same-document navigation,\nas the previously committed loaderId would not change.", + "name": "launchHandler", + "description": "TODO(crbug.com/1231886): This field is non-standard and part of a Chrome\nexperiment. See:\nhttps://github.com/WICG/web-app-launch/blob/main/launch_handler.md", "optional": true, - "$ref": "Network.LoaderId" + "$ref": "LaunchHandler" }, { - "name": "errorText", - "description": "User friendly error message, present if and only if navigation has failed.", + "name": "name", "optional": true, "type": "string" - } - ] - }, - { - "name": "navigateToHistoryEntry", - "description": "Navigates current page to the given history entry.", - "parameters": [ - { - "name": "entryId", - "description": "Unique id of the entry to navigate to.", - "type": "integer" - } - ] - }, - { - "name": "printToPDF", - "description": "Print page as PDF.", - "parameters": [ - { - "name": "landscape", - "description": "Paper orientation. Defaults to false.", - "optional": true, - "type": "boolean" }, { - "name": "displayHeaderFooter", - "description": "Display header and footer. Defaults to false.", + "name": "orientation", "optional": true, - "type": "boolean" + "type": "string" }, { - "name": "printBackground", - "description": "Print background graphics. Defaults to false.", + "name": "preferRelatedApplications", "optional": true, "type": "boolean" }, { - "name": "scale", - "description": "Scale of the webpage rendering. Defaults to 1.", - "optional": true, - "type": "number" - }, - { - "name": "paperWidth", - "description": "Paper width in inches. Defaults to 8.5 inches.", + "name": "protocolHandlers", + "description": "The handlers to open protocols.", "optional": true, - "type": "number" + "type": "array", + "items": { + "$ref": "ProtocolHandler" + } }, { - "name": "paperHeight", - "description": "Paper height in inches. Defaults to 11 inches.", + "name": "relatedApplications", "optional": true, - "type": "number" + "type": "array", + "items": { + "$ref": "RelatedApplication" + } }, { - "name": "marginTop", - "description": "Top margin in inches. Defaults to 1cm (~0.4 inches).", + "name": "scope", "optional": true, - "type": "number" + "type": "string" }, { - "name": "marginBottom", - "description": "Bottom margin in inches. Defaults to 1cm (~0.4 inches).", + "name": "scopeExtensions", + "description": "Non-standard, see\nhttps://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-explainer.md", "optional": true, - "type": "number" + "type": "array", + "items": { + "$ref": "ScopeExtension" + } }, { - "name": "marginLeft", - "description": "Left margin in inches. Defaults to 1cm (~0.4 inches).", + "name": "screenshots", + "description": "The screenshots used by chromium.", "optional": true, - "type": "number" + "type": "array", + "items": { + "$ref": "Screenshot" + } }, { - "name": "marginRight", - "description": "Right margin in inches. Defaults to 1cm (~0.4 inches).", + "name": "shareTarget", "optional": true, - "type": "number" + "$ref": "ShareTarget" }, { - "name": "pageRanges", - "description": "Paper ranges to print, one based, e.g., '1-5, 8, 11-13'. Pages are\nprinted in the document order, not in the order specified, and no\nmore than once.\nDefaults to empty string, which implies the entire document is printed.\nThe page numbers are quietly capped to actual page count of the\ndocument, and ranges beyond the end of the document are ignored.\nIf this results in no pages to print, an error is reported.\nIt is an error to specify a range with start greater than end.", + "name": "shortName", "optional": true, "type": "string" }, { - "name": "headerTemplate", - "description": "HTML template for the print header. Should be valid HTML markup with following\nclasses used to inject printing values into them:\n- `date`: formatted print date\n- `title`: document title\n- `url`: document location\n- `pageNumber`: current page number\n- `totalPages`: total pages in the document\n\nFor example, `` would generate span containing the title.", + "name": "shortcuts", "optional": true, - "type": "string" + "type": "array", + "items": { + "$ref": "Shortcut" + } }, { - "name": "footerTemplate", - "description": "HTML template for the print footer. Should use the same format as the `headerTemplate`.", + "name": "startUrl", "optional": true, "type": "string" }, { - "name": "preferCSSPageSize", - "description": "Whether or not to prefer page size as defined by css. Defaults to false,\nin which case the content will be scaled to fit the paper size.", + "name": "themeColor", "optional": true, - "type": "boolean" - }, - { + "type": "string" + } + ] + }, + { + "id": "AutoResponseMode", + "description": "Enum of possible auto-response for permission / prompt dialogs.", + "experimental": true, + "type": "string", + "enum": [ + "none", + "autoAccept", + "autoReject", + "autoOptOut" + ] + }, + { + "id": "NavigationType", + "description": "The type of a frameNavigated event.", + "experimental": true, + "type": "string", + "enum": [ + "Navigation", + "BackForwardCacheRestore" + ] + }, + { + "id": "BackForwardCacheNotRestoredReason", + "description": "List of not restored reasons for back-forward cache.", + "experimental": true, + "type": "string", + "enum": [ + "NotPrimaryMainFrame", + "BackForwardCacheDisabled", + "RelatedActiveContentsExist", + "HTTPStatusNotOK", + "SchemeNotHTTPOrHTTPS", + "Loading", + "WasGrantedMediaAccess", + "DisableForRenderFrameHostCalled", + "DomainNotAllowed", + "HTTPMethodNotGET", + "SubframeIsNavigating", + "Timeout", + "CacheLimit", + "JavaScriptExecution", + "RendererProcessKilled", + "RendererProcessCrashed", + "SchedulerTrackedFeatureUsed", + "ConflictingBrowsingInstance", + "CacheFlushed", + "ServiceWorkerVersionActivation", + "SessionRestored", + "ServiceWorkerPostMessage", + "EnteredBackForwardCacheBeforeServiceWorkerHostAdded", + "RenderFrameHostReused_SameSite", + "RenderFrameHostReused_CrossSite", + "ServiceWorkerClaim", + "IgnoreEventAndEvict", + "HaveInnerContents", + "TimeoutPuttingInCache", + "BackForwardCacheDisabledByLowMemory", + "BackForwardCacheDisabledByCommandLine", + "NetworkRequestDatapipeDrainedAsBytesConsumer", + "NetworkRequestRedirected", + "NetworkRequestTimeout", + "NetworkExceedsBufferLimit", + "NavigationCancelledWhileRestoring", + "NotMostRecentNavigationEntry", + "BackForwardCacheDisabledForPrerender", + "UserAgentOverrideDiffers", + "ForegroundCacheLimit", + "BrowsingInstanceNotSwapped", + "BackForwardCacheDisabledForDelegate", + "UnloadHandlerExistsInMainFrame", + "UnloadHandlerExistsInSubFrame", + "ServiceWorkerUnregistration", + "CacheControlNoStore", + "CacheControlNoStoreCookieModified", + "CacheControlNoStoreHTTPOnlyCookieModified", + "NoResponseHead", + "Unknown", + "ActivationNavigationsDisallowedForBug1234857", + "ErrorDocument", + "FencedFramesEmbedder", + "CookieDisabled", + "HTTPAuthRequired", + "CookieFlushed", + "BroadcastChannelOnMessage", + "WebViewSettingsChanged", + "WebViewJavaScriptObjectChanged", + "WebViewMessageListenerInjected", + "WebViewSafeBrowsingAllowlistChanged", + "WebViewDocumentStartJavascriptChanged", + "WebSocket", + "WebTransport", + "WebRTC", + "MainResourceHasCacheControlNoStore", + "MainResourceHasCacheControlNoCache", + "SubresourceHasCacheControlNoStore", + "SubresourceHasCacheControlNoCache", + "ContainsPlugins", + "DocumentLoaded", + "OutstandingNetworkRequestOthers", + "RequestedMIDIPermission", + "RequestedAudioCapturePermission", + "RequestedVideoCapturePermission", + "RequestedBackForwardCacheBlockedSensors", + "RequestedBackgroundWorkPermission", + "BroadcastChannel", + "WebXR", + "SharedWorker", + "WebLocks", + "WebHID", + "WebShare", + "RequestedStorageAccessGrant", + "WebNfc", + "OutstandingNetworkRequestFetch", + "OutstandingNetworkRequestXHR", + "AppBanner", + "Printing", + "WebDatabase", + "PictureInPicture", + "SpeechRecognizer", + "IdleManager", + "PaymentManager", + "SpeechSynthesis", + "KeyboardLock", + "WebOTPService", + "OutstandingNetworkRequestDirectSocket", + "InjectedJavascript", + "InjectedStyleSheet", + "KeepaliveRequest", + "IndexedDBEvent", + "Dummy", + "JsNetworkRequestReceivedCacheControlNoStoreResource", + "WebRTCSticky", + "WebTransportSticky", + "WebSocketSticky", + "SmartCard", + "LiveMediaStreamTrack", + "UnloadHandler", + "ParserAborted", + "ContentSecurityHandler", + "ContentWebAuthenticationAPI", + "ContentFileChooser", + "ContentSerial", + "ContentFileSystemAccess", + "ContentMediaDevicesDispatcherHost", + "ContentWebBluetooth", + "ContentWebUSB", + "ContentMediaSessionService", + "ContentScreenReader", + "ContentDiscarded", + "EmbedderPopupBlockerTabHelper", + "EmbedderSafeBrowsingTriggeredPopupBlocker", + "EmbedderSafeBrowsingThreatDetails", + "EmbedderAppBannerManager", + "EmbedderDomDistillerViewerSource", + "EmbedderDomDistillerSelfDeletingRequestDelegate", + "EmbedderOomInterventionTabHelper", + "EmbedderOfflinePage", + "EmbedderChromePasswordManagerClientBindCredentialManager", + "EmbedderPermissionRequestManager", + "EmbedderModalDialog", + "EmbedderExtensions", + "EmbedderExtensionMessaging", + "EmbedderExtensionMessagingForOpenPort", + "EmbedderExtensionSentMessageToCachedFrame", + "RequestedByWebViewClient", + "PostMessageByWebViewClient", + "CacheControlNoStoreDeviceBoundSessionTerminated" + ] + }, + { + "id": "BackForwardCacheNotRestoredReasonType", + "description": "Types of not restored reasons for back-forward cache.", + "experimental": true, + "type": "string", + "enum": [ + "SupportPending", + "PageSupportNeeded", + "Circumstantial" + ] + }, + { + "id": "BackForwardCacheBlockingDetails", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "url", + "description": "Url of the file where blockage happened. Optional because of tests.", + "optional": true, + "type": "string" + }, + { + "name": "function", + "description": "Function name where blockage happened. Optional because of anonymous functions and tests.", + "optional": true, + "type": "string" + }, + { + "name": "lineNumber", + "description": "Line number in the script (0-based).", + "type": "integer" + }, + { + "name": "columnNumber", + "description": "Column number in the script (0-based).", + "type": "integer" + } + ] + }, + { + "id": "BackForwardCacheNotRestoredExplanation", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "type", + "description": "Type of the reason", + "$ref": "BackForwardCacheNotRestoredReasonType" + }, + { + "name": "reason", + "description": "Not restored reason", + "$ref": "BackForwardCacheNotRestoredReason" + }, + { + "name": "context", + "description": "Context associated with the reason. The meaning of this context is\ndependent on the reason:\n- EmbedderExtensionSentMessageToCachedFrame: the extension ID.", + "optional": true, + "type": "string" + }, + { + "name": "details", + "optional": true, + "type": "array", + "items": { + "$ref": "BackForwardCacheBlockingDetails" + } + } + ] + }, + { + "id": "BackForwardCacheNotRestoredExplanationTree", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "url", + "description": "URL of each frame", + "type": "string" + }, + { + "name": "explanations", + "description": "Not restored reasons of each frame", + "type": "array", + "items": { + "$ref": "BackForwardCacheNotRestoredExplanation" + } + }, + { + "name": "children", + "description": "Array of children frame", + "type": "array", + "items": { + "$ref": "BackForwardCacheNotRestoredExplanationTree" + } + } + ] + } + ], + "commands": [ + { + "name": "addScriptToEvaluateOnLoad", + "description": "Deprecated, please use addScriptToEvaluateOnNewDocument instead.", + "experimental": true, + "deprecated": true, + "parameters": [ + { + "name": "scriptSource", + "type": "string" + } + ], + "returns": [ + { + "name": "identifier", + "description": "Identifier of the added script.", + "$ref": "ScriptIdentifier" + } + ] + }, + { + "name": "addScriptToEvaluateOnNewDocument", + "description": "Evaluates given script in every frame upon creation (before loading frame's scripts).", + "parameters": [ + { + "name": "source", + "type": "string" + }, + { + "name": "worldName", + "description": "If specified, creates an isolated world with the given name and evaluates given script in it.\nThis world name will be used as the ExecutionContextDescription::name when the corresponding\nevent is emitted.", + "experimental": true, + "optional": true, + "type": "string" + }, + { + "name": "includeCommandLineAPI", + "description": "Specifies whether command line API should be available to the script, defaults\nto false.", + "experimental": true, + "optional": true, + "type": "boolean" + }, + { + "name": "runImmediately", + "description": "If true, runs the script immediately on existing execution contexts or worlds.\nDefault: false.", + "experimental": true, + "optional": true, + "type": "boolean" + } + ], + "returns": [ + { + "name": "identifier", + "description": "Identifier of the added script.", + "$ref": "ScriptIdentifier" + } + ] + }, + { + "name": "bringToFront", + "description": "Brings page to front (activates tab)." + }, + { + "name": "captureScreenshot", + "description": "Capture page screenshot.", + "parameters": [ + { + "name": "format", + "description": "Image compression format (defaults to png).", + "optional": true, + "type": "string", + "enum": [ + "jpeg", + "png", + "webp" + ] + }, + { + "name": "quality", + "description": "Compression quality from range [0..100] (jpeg only).", + "optional": true, + "type": "integer" + }, + { + "name": "clip", + "description": "Capture the screenshot of a given region only.", + "optional": true, + "$ref": "Viewport" + }, + { + "name": "fromSurface", + "description": "Capture the screenshot from the surface, rather than the view. Defaults to true.", + "experimental": true, + "optional": true, + "type": "boolean" + }, + { + "name": "captureBeyondViewport", + "description": "Capture the screenshot beyond the viewport. Defaults to false.", + "experimental": true, + "optional": true, + "type": "boolean" + }, + { + "name": "optimizeForSpeed", + "description": "Optimize image encoding for speed, not for resulting size (defaults to false)", + "experimental": true, + "optional": true, + "type": "boolean" + } + ], + "returns": [ + { + "name": "data", + "description": "Base64-encoded image data. (Encoded as a base64 string when passed over JSON)", + "type": "string" + } + ] + }, + { + "name": "captureSnapshot", + "description": "Returns a snapshot of the page as a string. For MHTML format, the serialization includes\niframes, shadow DOM, external resources, and element-inline styles.", + "experimental": true, + "parameters": [ + { + "name": "format", + "description": "Format (defaults to mhtml).", + "optional": true, + "type": "string", + "enum": [ + "mhtml" + ] + } + ], + "returns": [ + { + "name": "data", + "description": "Serialized page data.", + "type": "string" + } + ] + }, + { + "name": "clearDeviceMetricsOverride", + "description": "Clears the overridden device metrics.", + "experimental": true, + "deprecated": true, + "redirect": "Emulation" + }, + { + "name": "clearDeviceOrientationOverride", + "description": "Clears the overridden Device Orientation.", + "experimental": true, + "deprecated": true, + "redirect": "DeviceOrientation" + }, + { + "name": "clearGeolocationOverride", + "description": "Clears the overridden Geolocation Position and Error.", + "deprecated": true, + "redirect": "Emulation" + }, + { + "name": "createIsolatedWorld", + "description": "Creates an isolated world for the given frame.", + "parameters": [ + { + "name": "frameId", + "description": "Id of the frame in which the isolated world should be created.", + "$ref": "FrameId" + }, + { + "name": "worldName", + "description": "An optional name which is reported in the Execution Context.", + "optional": true, + "type": "string" + }, + { + "name": "grantUniveralAccess", + "description": "Whether or not universal access should be granted to the isolated world. This is a powerful\noption, use with caution.", + "optional": true, + "type": "boolean" + } + ], + "returns": [ + { + "name": "executionContextId", + "description": "Execution context of the isolated world.", + "$ref": "Runtime.ExecutionContextId" + } + ] + }, + { + "name": "deleteCookie", + "description": "Deletes browser cookie with given name, domain and path.", + "experimental": true, + "deprecated": true, + "redirect": "Network", + "parameters": [ + { + "name": "cookieName", + "description": "Name of the cookie to remove.", + "type": "string" + }, + { + "name": "url", + "description": "URL to match cooke domain and path.", + "type": "string" + } + ] + }, + { + "name": "disable", + "description": "Disables page domain notifications." + }, + { + "name": "enable", + "description": "Enables page domain notifications.", + "parameters": [ + { + "name": "enableFileChooserOpenedEvent", + "description": "If true, the `Page.fileChooserOpened` event will be emitted regardless of the state set by\n`Page.setInterceptFileChooserDialog` command (default: false).", + "experimental": true, + "optional": true, + "type": "boolean" + } + ] + }, + { + "name": "getAppManifest", + "description": "Gets the processed manifest for this current document.\n This API always waits for the manifest to be loaded.\n If manifestId is provided, and it does not match the manifest of the\n current document, this API errors out.\n If there is not a loaded page, this API errors out immediately.", + "parameters": [ + { + "name": "manifestId", + "optional": true, + "type": "string" + } + ], + "returns": [ + { + "name": "url", + "description": "Manifest location.", + "type": "string" + }, + { + "name": "errors", + "type": "array", + "items": { + "$ref": "AppManifestError" + } + }, + { + "name": "data", + "description": "Manifest content.", + "optional": true, + "type": "string" + }, + { + "name": "parsed", + "description": "Parsed manifest properties. Deprecated, use manifest instead.", + "experimental": true, + "deprecated": true, + "optional": true, + "$ref": "AppManifestParsedProperties" + }, + { + "name": "manifest", + "experimental": true, + "$ref": "WebAppManifest" + } + ] + }, + { + "name": "getInstallabilityErrors", + "experimental": true, + "returns": [ + { + "name": "installabilityErrors", + "type": "array", + "items": { + "$ref": "InstallabilityError" + } + } + ] + }, + { + "name": "getManifestIcons", + "description": "Deprecated because it's not guaranteed that the returned icon is in fact the one used for PWA installation.", + "experimental": true, + "deprecated": true, + "returns": [ + { + "name": "primaryIcon", + "optional": true, + "type": "string" + } + ] + }, + { + "name": "getAppId", + "description": "Returns the unique (PWA) app id.\nOnly returns values if the feature flag 'WebAppEnableManifestId' is enabled", + "experimental": true, + "returns": [ + { + "name": "appId", + "description": "App id, either from manifest's id attribute or computed from start_url", + "optional": true, + "type": "string" + }, + { + "name": "recommendedId", + "description": "Recommendation for manifest's id attribute to match current id computed from start_url", + "optional": true, + "type": "string" + } + ] + }, + { + "name": "getAdScriptId", + "experimental": true, + "parameters": [ + { + "name": "frameId", + "$ref": "FrameId" + } + ], + "returns": [ + { + "name": "adScriptId", + "description": "Identifies the bottom-most script which caused the frame to be labelled\nas an ad. Only sent if frame is labelled as an ad and id is available.", + "optional": true, + "$ref": "AdScriptId" + } + ] + }, + { + "name": "getFrameTree", + "description": "Returns present frame tree structure.", + "returns": [ + { + "name": "frameTree", + "description": "Present frame tree structure.", + "$ref": "FrameTree" + } + ] + }, + { + "name": "getLayoutMetrics", + "description": "Returns metrics relating to the layouting of the page, such as viewport bounds/scale.", + "returns": [ + { + "name": "layoutViewport", + "description": "Deprecated metrics relating to the layout viewport. Is in device pixels. Use `cssLayoutViewport` instead.", + "deprecated": true, + "$ref": "LayoutViewport" + }, + { + "name": "visualViewport", + "description": "Deprecated metrics relating to the visual viewport. Is in device pixels. Use `cssVisualViewport` instead.", + "deprecated": true, + "$ref": "VisualViewport" + }, + { + "name": "contentSize", + "description": "Deprecated size of scrollable area. Is in DP. Use `cssContentSize` instead.", + "deprecated": true, + "$ref": "DOM.Rect" + }, + { + "name": "cssLayoutViewport", + "description": "Metrics relating to the layout viewport in CSS pixels.", + "$ref": "LayoutViewport" + }, + { + "name": "cssVisualViewport", + "description": "Metrics relating to the visual viewport in CSS pixels.", + "$ref": "VisualViewport" + }, + { + "name": "cssContentSize", + "description": "Size of scrollable area in CSS pixels.", + "$ref": "DOM.Rect" + } + ] + }, + { + "name": "getNavigationHistory", + "description": "Returns navigation history for the current page.", + "returns": [ + { + "name": "currentIndex", + "description": "Index of the current navigation history entry.", + "type": "integer" + }, + { + "name": "entries", + "description": "Array of navigation history entries.", + "type": "array", + "items": { + "$ref": "NavigationEntry" + } + } + ] + }, + { + "name": "resetNavigationHistory", + "description": "Resets navigation history for the current page." + }, + { + "name": "getResourceContent", + "description": "Returns content of the given resource.", + "experimental": true, + "parameters": [ + { + "name": "frameId", + "description": "Frame id to get resource for.", + "$ref": "FrameId" + }, + { + "name": "url", + "description": "URL of the resource to get content for.", + "type": "string" + } + ], + "returns": [ + { + "name": "content", + "description": "Resource content.", + "type": "string" + }, + { + "name": "base64Encoded", + "description": "True, if content was served as base64.", + "type": "boolean" + } + ] + }, + { + "name": "getResourceTree", + "description": "Returns present frame / resource tree structure.", + "experimental": true, + "returns": [ + { + "name": "frameTree", + "description": "Present frame / resource tree structure.", + "$ref": "FrameResourceTree" + } + ] + }, + { + "name": "handleJavaScriptDialog", + "description": "Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).", + "parameters": [ + { + "name": "accept", + "description": "Whether to accept or dismiss the dialog.", + "type": "boolean" + }, + { + "name": "promptText", + "description": "The text to enter into the dialog prompt before accepting. Used only if this is a prompt\ndialog.", + "optional": true, + "type": "string" + } + ] + }, + { + "name": "navigate", + "description": "Navigates current page to the given URL.", + "parameters": [ + { + "name": "url", + "description": "URL to navigate the page to.", + "type": "string" + }, + { + "name": "referrer", + "description": "Referrer URL.", + "optional": true, + "type": "string" + }, + { + "name": "transitionType", + "description": "Intended transition type.", + "optional": true, + "$ref": "TransitionType" + }, + { + "name": "frameId", + "description": "Frame id to navigate, if not specified navigates the top frame.", + "optional": true, + "$ref": "FrameId" + }, + { + "name": "referrerPolicy", + "description": "Referrer-policy used for the navigation.", + "experimental": true, + "optional": true, + "$ref": "ReferrerPolicy" + } + ], + "returns": [ + { + "name": "frameId", + "description": "Frame id that has navigated (or failed to navigate)", + "$ref": "FrameId" + }, + { + "name": "loaderId", + "description": "Loader identifier. This is omitted in case of same-document navigation,\nas the previously committed loaderId would not change.", + "optional": true, + "$ref": "Network.LoaderId" + }, + { + "name": "errorText", + "description": "User friendly error message, present if and only if navigation has failed.", + "optional": true, + "type": "string" + } + ] + }, + { + "name": "navigateToHistoryEntry", + "description": "Navigates current page to the given history entry.", + "parameters": [ + { + "name": "entryId", + "description": "Unique id of the entry to navigate to.", + "type": "integer" + } + ] + }, + { + "name": "printToPDF", + "description": "Print page as PDF.", + "parameters": [ + { + "name": "landscape", + "description": "Paper orientation. Defaults to false.", + "optional": true, + "type": "boolean" + }, + { + "name": "displayHeaderFooter", + "description": "Display header and footer. Defaults to false.", + "optional": true, + "type": "boolean" + }, + { + "name": "printBackground", + "description": "Print background graphics. Defaults to false.", + "optional": true, + "type": "boolean" + }, + { + "name": "scale", + "description": "Scale of the webpage rendering. Defaults to 1.", + "optional": true, + "type": "number" + }, + { + "name": "paperWidth", + "description": "Paper width in inches. Defaults to 8.5 inches.", + "optional": true, + "type": "number" + }, + { + "name": "paperHeight", + "description": "Paper height in inches. Defaults to 11 inches.", + "optional": true, + "type": "number" + }, + { + "name": "marginTop", + "description": "Top margin in inches. Defaults to 1cm (~0.4 inches).", + "optional": true, + "type": "number" + }, + { + "name": "marginBottom", + "description": "Bottom margin in inches. Defaults to 1cm (~0.4 inches).", + "optional": true, + "type": "number" + }, + { + "name": "marginLeft", + "description": "Left margin in inches. Defaults to 1cm (~0.4 inches).", + "optional": true, + "type": "number" + }, + { + "name": "marginRight", + "description": "Right margin in inches. Defaults to 1cm (~0.4 inches).", + "optional": true, + "type": "number" + }, + { + "name": "pageRanges", + "description": "Paper ranges to print, one based, e.g., '1-5, 8, 11-13'. Pages are\nprinted in the document order, not in the order specified, and no\nmore than once.\nDefaults to empty string, which implies the entire document is printed.\nThe page numbers are quietly capped to actual page count of the\ndocument, and ranges beyond the end of the document are ignored.\nIf this results in no pages to print, an error is reported.\nIt is an error to specify a range with start greater than end.", + "optional": true, + "type": "string" + }, + { + "name": "headerTemplate", + "description": "HTML template for the print header. Should be valid HTML markup with following\nclasses used to inject printing values into them:\n- `date`: formatted print date\n- `title`: document title\n- `url`: document location\n- `pageNumber`: current page number\n- `totalPages`: total pages in the document\n\nFor example, `` would generate span containing the title.", + "optional": true, + "type": "string" + }, + { + "name": "footerTemplate", + "description": "HTML template for the print footer. Should use the same format as the `headerTemplate`.", + "optional": true, + "type": "string" + }, + { + "name": "preferCSSPageSize", + "description": "Whether or not to prefer page size as defined by css. Defaults to false,\nin which case the content will be scaled to fit the paper size.", + "optional": true, + "type": "boolean" + }, + { "name": "transferMode", "description": "return as stream", "experimental": true, @@ -17453,6 +19985,13 @@ "experimental": true, "optional": true, "type": "boolean" + }, + { + "name": "generateDocumentOutline", + "description": "Whether or not to embed the document outline into the PDF.", + "experimental": true, + "optional": true, + "type": "boolean" } ], "returns": [ @@ -17485,6 +20024,13 @@ "description": "If set, the script will be injected into all frames of the inspected page after reload.\nArgument will be ignored if reloading dataURL origin.", "optional": true, "type": "string" + }, + { + "name": "loaderId", + "description": "If set, an error will be thrown if the target page's main frame's\nloader id does not match the provided id. This prevents accidentally\nreloading an unintended target in case there's a racing navigation.", + "experimental": true, + "optional": true, + "$ref": "Network.LoaderId" } ] }, @@ -17581,7 +20127,6 @@ { "name": "setBypassCSP", "description": "Enable page Content Security Policy by-passing.", - "experimental": true, "parameters": [ { "name": "enabled", @@ -17833,7 +20378,6 @@ { "name": "setLifecycleEventsEnabled", "description": "Controls whether page will emit lifecycle events.", - "experimental": true, "parameters": [ { "name": "enabled", @@ -17918,8 +20462,7 @@ }, { "name": "close", - "description": "Tries to close page, running its beforeunload hooks, if any.", - "experimental": true + "description": "Tries to close page, running its beforeunload hooks, if any." }, { "name": "setWebLifecycleState", @@ -17944,7 +20487,7 @@ }, { "name": "produceCompilationCache", - "description": "Requests backend to produce compilation cache for the specified scripts.\n`scripts` are appeneded to the list of scripts for which the cache\nwould be produced. The list may be reset during page navigation.\nWhen script with a matching URL is encountered, the cache is optionally\nproduced upon backend discretion, based on internal heuristics.\nSee also: `Page.compilationCacheProduced`.", + "description": "Requests backend to produce compilation cache for the specified scripts.\n`scripts` are appended to the list of scripts for which the cache\nwould be produced. The list may be reset during page navigation.\nWhen script with a matching URL is encountered, the cache is optionally\nproduced upon backend discretion, based on internal heuristics.\nSee also: `Page.compilationCacheProduced`.", "experimental": true, "parameters": [ { @@ -18025,7 +20568,6 @@ { "name": "setInterceptFileChooserDialog", "description": "Intercept file chooser requests and transfer control to protocol clients.\nWhen file chooser interception is enabled, native file chooser dialog is not shown.\nInstead, a protocol event `Page.fileChooserOpened` is emitted.", - "experimental": true, "parameters": [ { "name": "enabled", @@ -18137,6 +20679,18 @@ } ] }, + { + "name": "frameSubtreeWillBeDetached", + "description": "Fired before frame subtree is detached. Emitted before any frame of the\nsubtree is actually detached.", + "experimental": true, + "parameters": [ + { + "name": "frameId", + "description": "Id of the frame that is the root of the subtree that will be detached.", + "$ref": "FrameId" + } + ] + }, { "name": "frameNavigated", "description": "Fired once navigation of the frame has completed. Frame is now associated with the new loader.", @@ -18169,6 +20723,42 @@ "name": "frameResized", "experimental": true }, + { + "name": "frameStartedNavigating", + "description": "Fired when a navigation starts. This event is fired for both\nrenderer-initiated and browser-initiated navigations. For renderer-initiated\nnavigations, the event is fired after `frameRequestedNavigation`.\nNavigation may still be cancelled after the event is issued. Multiple events\ncan be fired for a single navigation, for example, when a same-document\nnavigation becomes a cross-document navigation (such as in the case of a\nframeset).", + "experimental": true, + "parameters": [ + { + "name": "frameId", + "description": "ID of the frame that is being navigated.", + "$ref": "FrameId" + }, + { + "name": "url", + "description": "The URL the navigation started with. The final URL can be different.", + "type": "string" + }, + { + "name": "loaderId", + "description": "Loader identifier. Even though it is present in case of same-document\nnavigation, the previously committed loaderId would not change unless\nthe navigation changes from a same-document to a cross-document\nnavigation.", + "$ref": "Network.LoaderId" + }, + { + "name": "navigationType", + "type": "string", + "enum": [ + "reload", + "reloadBypassingCache", + "restore", + "restoreWithPost", + "historySameDocument", + "historyDifferentDocument", + "sameDocument", + "differentDocument" + ] + } + ] + }, { "name": "frameRequestedNavigation", "description": "Fired when a renderer-initiated navigation is requested.\nNavigation may still be cancelled after the event is issued.", @@ -18366,7 +20956,7 @@ }, { "name": "lifecycleEvent", - "description": "Fired for top level page lifecycle events such as navigation, load, paint, etc.", + "description": "Fired for lifecycle events (navigation, load, paint, etc) in the current\ntarget (including local frames).", "parameters": [ { "name": "frameId", @@ -18395,7 +20985,7 @@ "parameters": [ { "name": "loaderId", - "description": "The loader id for the associated navgation.", + "description": "The loader id for the associated navigation.", "$ref": "Network.LoaderId" }, { @@ -18442,6 +21032,16 @@ "name": "url", "description": "Frame's new url.", "type": "string" + }, + { + "name": "navigationType", + "description": "Navigation type", + "type": "string", + "enum": [ + "fragment", + "historyApi", + "other" + ] } ] }, @@ -18725,7 +21325,7 @@ }, { "name": "type", - "description": "The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype\nThis determines which of the optional \"details\" fiedls is present.", + "description": "The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype\nThis determines which of the optional \"details\" fields is present.", "type": "string" }, { @@ -18887,7 +21487,7 @@ }, { "name": "certificateHasWeakSignature", - "description": "True if the certificate uses a weak signature aglorithm.", + "description": "True if the certificate uses a weak signature algorithm.", "type": "boolean" }, { @@ -19096,7 +21696,6 @@ { "name": "setIgnoreCertificateErrors", "description": "Enable/disable whether all certificate errors should be ignored.", - "experimental": true, "parameters": [ { "name": "ignore", @@ -19313,6 +21912,11 @@ "name": "targetId", "optional": true, "$ref": "Target.TargetID" + }, + { + "name": "routerRules", + "optional": true, + "type": "string" } ] }, @@ -19482,549 +22086,961 @@ "name": "workerErrorReported", "parameters": [ { - "name": "errorMessage", - "$ref": "ServiceWorkerErrorMessage" + "name": "errorMessage", + "$ref": "ServiceWorkerErrorMessage" + } + ] + }, + { + "name": "workerRegistrationUpdated", + "parameters": [ + { + "name": "registrations", + "type": "array", + "items": { + "$ref": "ServiceWorkerRegistration" + } + } + ] + }, + { + "name": "workerVersionUpdated", + "parameters": [ + { + "name": "versions", + "type": "array", + "items": { + "$ref": "ServiceWorkerVersion" + } + } + ] + } + ] + }, + { + "domain": "Storage", + "experimental": true, + "dependencies": [ + "Browser", + "Network" + ], + "types": [ + { + "id": "SerializedStorageKey", + "type": "string" + }, + { + "id": "StorageType", + "description": "Enum of possible storage types.", + "type": "string", + "enum": [ + "cookies", + "file_systems", + "indexeddb", + "local_storage", + "shader_cache", + "websql", + "service_workers", + "cache_storage", + "interest_groups", + "shared_storage", + "storage_buckets", + "all", + "other" + ] + }, + { + "id": "UsageForType", + "description": "Usage for a storage type.", + "type": "object", + "properties": [ + { + "name": "storageType", + "description": "Name of storage type.", + "$ref": "StorageType" + }, + { + "name": "usage", + "description": "Storage usage (bytes).", + "type": "number" + } + ] + }, + { + "id": "TrustTokens", + "description": "Pair of issuer origin and number of available (signed, but not used) Trust\nTokens from that issuer.", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "issuerOrigin", + "type": "string" + }, + { + "name": "count", + "type": "number" + } + ] + }, + { + "id": "InterestGroupAuctionId", + "description": "Protected audience interest group auction identifier.", + "type": "string" + }, + { + "id": "InterestGroupAccessType", + "description": "Enum of interest group access types.", + "type": "string", + "enum": [ + "join", + "leave", + "update", + "loaded", + "bid", + "win", + "additionalBid", + "additionalBidWin", + "topLevelBid", + "topLevelAdditionalBid", + "clear" + ] + }, + { + "id": "InterestGroupAuctionEventType", + "description": "Enum of auction events.", + "type": "string", + "enum": [ + "started", + "configResolved" + ] + }, + { + "id": "InterestGroupAuctionFetchType", + "description": "Enum of network fetches auctions can do.", + "type": "string", + "enum": [ + "bidderJs", + "bidderWasm", + "sellerJs", + "bidderTrustedSignals", + "sellerTrustedSignals" + ] + }, + { + "id": "SharedStorageAccessType", + "description": "Enum of shared storage access types.", + "type": "string", + "enum": [ + "documentAddModule", + "documentSelectURL", + "documentRun", + "documentSet", + "documentAppend", + "documentDelete", + "documentClear", + "documentGet", + "workletSet", + "workletAppend", + "workletDelete", + "workletClear", + "workletGet", + "workletKeys", + "workletEntries", + "workletLength", + "workletRemainingBudget", + "headerSet", + "headerAppend", + "headerDelete", + "headerClear" + ] + }, + { + "id": "SharedStorageEntry", + "description": "Struct for a single key-value pair in an origin's shared storage.", + "type": "object", + "properties": [ + { + "name": "key", + "type": "string" + }, + { + "name": "value", + "type": "string" + } + ] + }, + { + "id": "SharedStorageMetadata", + "description": "Details for an origin's shared storage.", + "type": "object", + "properties": [ + { + "name": "creationTime", + "description": "Time when the origin's shared storage was last created.", + "$ref": "Network.TimeSinceEpoch" + }, + { + "name": "length", + "description": "Number of key-value pairs stored in origin's shared storage.", + "type": "integer" + }, + { + "name": "remainingBudget", + "description": "Current amount of bits of entropy remaining in the navigation budget.", + "type": "number" + }, + { + "name": "bytesUsed", + "description": "Total number of bytes stored as key-value pairs in origin's shared\nstorage.", + "type": "integer" + } + ] + }, + { + "id": "SharedStorageReportingMetadata", + "description": "Pair of reporting metadata details for a candidate URL for `selectURL()`.", + "type": "object", + "properties": [ + { + "name": "eventType", + "type": "string" + }, + { + "name": "reportingUrl", + "type": "string" } ] }, { - "name": "workerRegistrationUpdated", - "parameters": [ + "id": "SharedStorageUrlWithMetadata", + "description": "Bundles a candidate URL with its reporting metadata.", + "type": "object", + "properties": [ { - "name": "registrations", + "name": "url", + "description": "Spec of candidate URL.", + "type": "string" + }, + { + "name": "reportingMetadata", + "description": "Any associated reporting metadata.", "type": "array", "items": { - "$ref": "ServiceWorkerRegistration" + "$ref": "SharedStorageReportingMetadata" } } ] }, { - "name": "workerVersionUpdated", - "parameters": [ + "id": "SharedStorageAccessParams", + "description": "Bundles the parameters for shared storage access events whose\npresence/absence can vary according to SharedStorageAccessType.", + "type": "object", + "properties": [ { - "name": "versions", + "name": "scriptSourceUrl", + "description": "Spec of the module script URL.\nPresent only for SharedStorageAccessType.documentAddModule.", + "optional": true, + "type": "string" + }, + { + "name": "operationName", + "description": "Name of the registered operation to be run.\nPresent only for SharedStorageAccessType.documentRun and\nSharedStorageAccessType.documentSelectURL.", + "optional": true, + "type": "string" + }, + { + "name": "serializedData", + "description": "The operation's serialized data in bytes (converted to a string).\nPresent only for SharedStorageAccessType.documentRun and\nSharedStorageAccessType.documentSelectURL.", + "optional": true, + "type": "string" + }, + { + "name": "urlsWithMetadata", + "description": "Array of candidate URLs' specs, along with any associated metadata.\nPresent only for SharedStorageAccessType.documentSelectURL.", + "optional": true, "type": "array", "items": { - "$ref": "ServiceWorkerVersion" + "$ref": "SharedStorageUrlWithMetadata" } + }, + { + "name": "key", + "description": "Key for a specific entry in an origin's shared storage.\nPresent only for SharedStorageAccessType.documentSet,\nSharedStorageAccessType.documentAppend,\nSharedStorageAccessType.documentDelete,\nSharedStorageAccessType.workletSet,\nSharedStorageAccessType.workletAppend,\nSharedStorageAccessType.workletDelete,\nSharedStorageAccessType.workletGet,\nSharedStorageAccessType.headerSet,\nSharedStorageAccessType.headerAppend, and\nSharedStorageAccessType.headerDelete.", + "optional": true, + "type": "string" + }, + { + "name": "value", + "description": "Value for a specific entry in an origin's shared storage.\nPresent only for SharedStorageAccessType.documentSet,\nSharedStorageAccessType.documentAppend,\nSharedStorageAccessType.workletSet,\nSharedStorageAccessType.workletAppend,\nSharedStorageAccessType.headerSet, and\nSharedStorageAccessType.headerAppend.", + "optional": true, + "type": "string" + }, + { + "name": "ignoreIfPresent", + "description": "Whether or not to set an entry for a key if that key is already present.\nPresent only for SharedStorageAccessType.documentSet,\nSharedStorageAccessType.workletSet, and\nSharedStorageAccessType.headerSet.", + "optional": true, + "type": "boolean" } ] - } - ] - }, - { - "domain": "Storage", - "experimental": true, - "dependencies": [ - "Browser", - "Network" - ], - "types": [ - { - "id": "SerializedStorageKey", - "type": "string" }, { - "id": "StorageType", - "description": "Enum of possible storage types.", + "id": "StorageBucketsDurability", "type": "string", "enum": [ - "appcache", - "cookies", - "file_systems", - "indexeddb", - "local_storage", - "shader_cache", - "websql", - "service_workers", - "cache_storage", - "interest_groups", - "shared_storage", - "storage_buckets", - "all", - "other" + "relaxed", + "strict" ] }, { - "id": "UsageForType", - "description": "Usage for a storage type.", + "id": "StorageBucket", "type": "object", "properties": [ { - "name": "storageType", - "description": "Name of storage type.", - "$ref": "StorageType" + "name": "storageKey", + "$ref": "SerializedStorageKey" }, { - "name": "usage", - "description": "Storage usage (bytes).", - "type": "number" + "name": "name", + "description": "If not specified, it is the default bucket of the storageKey.", + "optional": true, + "type": "string" } ] }, { - "id": "TrustTokens", - "description": "Pair of issuer origin and number of available (signed, but not used) Trust\nTokens from that issuer.", - "experimental": true, + "id": "StorageBucketInfo", "type": "object", "properties": [ { - "name": "issuerOrigin", + "name": "bucket", + "$ref": "StorageBucket" + }, + { + "name": "id", "type": "string" }, { - "name": "count", + "name": "expiration", + "$ref": "Network.TimeSinceEpoch" + }, + { + "name": "quota", + "description": "Storage quota (bytes).", "type": "number" + }, + { + "name": "persistent", + "type": "boolean" + }, + { + "name": "durability", + "$ref": "StorageBucketsDurability" } ] }, { - "id": "InterestGroupAccessType", - "description": "Enum of interest group access types.", + "id": "AttributionReportingSourceType", + "experimental": true, "type": "string", "enum": [ - "join", - "leave", - "update", - "loaded", - "bid", - "win" + "navigation", + "event" ] }, { - "id": "InterestGroupAd", - "description": "Ad advertising element inside an interest group.", + "id": "UnsignedInt64AsBase10", + "experimental": true, + "type": "string" + }, + { + "id": "UnsignedInt128AsBase16", + "experimental": true, + "type": "string" + }, + { + "id": "SignedInt64AsBase10", + "experimental": true, + "type": "string" + }, + { + "id": "AttributionReportingFilterDataEntry", + "experimental": true, "type": "object", "properties": [ { - "name": "renderUrl", + "name": "key", "type": "string" }, { - "name": "metadata", - "optional": true, - "type": "string" + "name": "values", + "type": "array", + "items": { + "type": "string" + } } ] }, { - "id": "InterestGroupDetails", - "description": "The full details of an interest group.", + "id": "AttributionReportingFilterConfig", + "experimental": true, "type": "object", "properties": [ { - "name": "ownerOrigin", - "type": "string" - }, - { - "name": "name", - "type": "string" - }, - { - "name": "expirationTime", - "$ref": "Network.TimeSinceEpoch" - }, - { - "name": "joiningOrigin", - "type": "string" - }, - { - "name": "biddingUrl", - "optional": true, - "type": "string" - }, - { - "name": "biddingWasmHelperUrl", - "optional": true, - "type": "string" + "name": "filterValues", + "type": "array", + "items": { + "$ref": "AttributionReportingFilterDataEntry" + } }, { - "name": "updateUrl", + "name": "lookbackWindow", + "description": "duration in seconds", "optional": true, - "type": "string" - }, + "type": "integer" + } + ] + }, + { + "id": "AttributionReportingFilterPair", + "experimental": true, + "type": "object", + "properties": [ { - "name": "trustedBiddingSignalsUrl", - "optional": true, - "type": "string" + "name": "filters", + "type": "array", + "items": { + "$ref": "AttributionReportingFilterConfig" + } }, { - "name": "trustedBiddingSignalsKeys", + "name": "notFilters", "type": "array", "items": { - "type": "string" + "$ref": "AttributionReportingFilterConfig" } - }, + } + ] + }, + { + "id": "AttributionReportingAggregationKeysEntry", + "experimental": true, + "type": "object", + "properties": [ { - "name": "userBiddingSignals", - "optional": true, + "name": "key", "type": "string" }, { - "name": "ads", + "name": "value", + "$ref": "UnsignedInt128AsBase16" + } + ] + }, + { + "id": "AttributionReportingEventReportWindows", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "start", + "description": "duration in seconds", + "type": "integer" + }, + { + "name": "ends", + "description": "duration in seconds", "type": "array", "items": { - "$ref": "InterestGroupAd" + "type": "integer" } - }, + } + ] + }, + { + "id": "AttributionReportingTriggerSpec", + "experimental": true, + "type": "object", + "properties": [ { - "name": "adComponents", + "name": "triggerData", + "description": "number instead of integer because not all uint32 can be represented by\nint", "type": "array", "items": { - "$ref": "InterestGroupAd" + "type": "number" } + }, + { + "name": "eventReportWindows", + "$ref": "AttributionReportingEventReportWindows" } ] }, { - "id": "SharedStorageAccessType", - "description": "Enum of shared storage access types.", + "id": "AttributionReportingTriggerDataMatching", + "experimental": true, "type": "string", "enum": [ - "documentAddModule", - "documentSelectURL", - "documentRun", - "documentSet", - "documentAppend", - "documentDelete", - "documentClear", - "workletSet", - "workletAppend", - "workletDelete", - "workletClear", - "workletGet", - "workletKeys", - "workletEntries", - "workletLength", - "workletRemainingBudget" + "exact", + "modulus" ] }, { - "id": "SharedStorageEntry", - "description": "Struct for a single key-value pair in an origin's shared storage.", + "id": "AttributionReportingAggregatableDebugReportingData", + "experimental": true, "type": "object", "properties": [ { - "name": "key", - "type": "string" + "name": "keyPiece", + "$ref": "UnsignedInt128AsBase16" }, { "name": "value", - "type": "string" + "description": "number instead of integer because not all uint32 can be represented by\nint", + "type": "number" + }, + { + "name": "types", + "type": "array", + "items": { + "type": "string" + } } ] }, { - "id": "SharedStorageMetadata", - "description": "Details for an origin's shared storage.", + "id": "AttributionReportingAggregatableDebugReportingConfig", + "experimental": true, "type": "object", "properties": [ { - "name": "creationTime", - "$ref": "Network.TimeSinceEpoch" + "name": "budget", + "description": "number instead of integer because not all uint32 can be represented by\nint, only present for source registrations", + "optional": true, + "type": "number" }, { - "name": "length", - "type": "integer" + "name": "keyPiece", + "$ref": "UnsignedInt128AsBase16" }, { - "name": "remainingBudget", - "type": "number" + "name": "debugData", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregatableDebugReportingData" + } + }, + { + "name": "aggregationCoordinatorOrigin", + "optional": true, + "type": "string" } ] }, { - "id": "SharedStorageReportingMetadata", - "description": "Pair of reporting metadata details for a candidate URL for `selectURL()`.", + "id": "AttributionScopesData", + "experimental": true, "type": "object", "properties": [ { - "name": "eventType", - "type": "string" + "name": "values", + "type": "array", + "items": { + "type": "string" + } }, { - "name": "reportingUrl", - "type": "string" + "name": "limit", + "description": "number instead of integer because not all uint32 can be represented by\nint", + "type": "number" + }, + { + "name": "maxEventStates", + "type": "number" } ] }, { - "id": "SharedStorageUrlWithMetadata", - "description": "Bundles a candidate URL with its reporting metadata.", + "id": "AttributionReportingSourceRegistration", + "experimental": true, "type": "object", "properties": [ { - "name": "url", - "description": "Spec of candidate URL.", - "type": "string" + "name": "time", + "$ref": "Network.TimeSinceEpoch" }, { - "name": "reportingMetadata", - "description": "Any associated reporting metadata.", + "name": "expiry", + "description": "duration in seconds", + "type": "integer" + }, + { + "name": "triggerSpecs", "type": "array", "items": { - "$ref": "SharedStorageReportingMetadata" + "$ref": "AttributionReportingTriggerSpec" } - } - ] - }, - { - "id": "SharedStorageAccessParams", - "description": "Bundles the parameters for shared storage access events whose\npresence/absence can vary according to SharedStorageAccessType.", - "type": "object", - "properties": [ + }, { - "name": "scriptSourceUrl", - "description": "Spec of the module script URL.\nPresent only for SharedStorageAccessType.documentAddModule.", - "optional": true, - "type": "string" + "name": "aggregatableReportWindow", + "description": "duration in seconds", + "type": "integer" }, { - "name": "operationName", - "description": "Name of the registered operation to be run.\nPresent only for SharedStorageAccessType.documentRun and\nSharedStorageAccessType.documentSelectURL.", - "optional": true, + "name": "type", + "$ref": "AttributionReportingSourceType" + }, + { + "name": "sourceOrigin", "type": "string" }, { - "name": "serializedData", - "description": "The operation's serialized data in bytes (converted to a string).\nPresent only for SharedStorageAccessType.documentRun and\nSharedStorageAccessType.documentSelectURL.", - "optional": true, + "name": "reportingOrigin", "type": "string" }, { - "name": "urlsWithMetadata", - "description": "Array of candidate URLs' specs, along with any associated metadata.\nPresent only for SharedStorageAccessType.documentSelectURL.", - "optional": true, + "name": "destinationSites", "type": "array", "items": { - "$ref": "SharedStorageUrlWithMetadata" + "type": "string" } }, { - "name": "key", - "description": "Key for a specific entry in an origin's shared storage.\nPresent only for SharedStorageAccessType.documentSet,\nSharedStorageAccessType.documentAppend,\nSharedStorageAccessType.documentDelete,\nSharedStorageAccessType.workletSet,\nSharedStorageAccessType.workletAppend,\nSharedStorageAccessType.workletDelete, and\nSharedStorageAccessType.workletGet.", - "optional": true, - "type": "string" + "name": "eventId", + "$ref": "UnsignedInt64AsBase10" }, { - "name": "value", - "description": "Value for a specific entry in an origin's shared storage.\nPresent only for SharedStorageAccessType.documentSet,\nSharedStorageAccessType.documentAppend,\nSharedStorageAccessType.workletSet, and\nSharedStorageAccessType.workletAppend.", + "name": "priority", + "$ref": "SignedInt64AsBase10" + }, + { + "name": "filterData", + "type": "array", + "items": { + "$ref": "AttributionReportingFilterDataEntry" + } + }, + { + "name": "aggregationKeys", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregationKeysEntry" + } + }, + { + "name": "debugKey", "optional": true, - "type": "string" + "$ref": "UnsignedInt64AsBase10" }, { - "name": "ignoreIfPresent", - "description": "Whether or not to set an entry for a key if that key is already present.\nPresent only for SharedStorageAccessType.documentSet and\nSharedStorageAccessType.workletSet.", + "name": "triggerDataMatching", + "$ref": "AttributionReportingTriggerDataMatching" + }, + { + "name": "destinationLimitPriority", + "$ref": "SignedInt64AsBase10" + }, + { + "name": "aggregatableDebugReportingConfig", + "$ref": "AttributionReportingAggregatableDebugReportingConfig" + }, + { + "name": "scopesData", "optional": true, - "type": "boolean" + "$ref": "AttributionScopesData" + }, + { + "name": "maxEventLevelReports", + "type": "integer" } ] }, { - "id": "StorageBucketsDurability", + "id": "AttributionReportingSourceRegistrationResult", + "experimental": true, "type": "string", "enum": [ - "relaxed", - "strict" + "success", + "internalError", + "insufficientSourceCapacity", + "insufficientUniqueDestinationCapacity", + "excessiveReportingOrigins", + "prohibitedByBrowserPolicy", + "successNoised", + "destinationReportingLimitReached", + "destinationGlobalLimitReached", + "destinationBothLimitsReached", + "reportingOriginsPerSiteLimitReached", + "exceedsMaxChannelCapacity", + "exceedsMaxScopesChannelCapacity", + "exceedsMaxTriggerStateCardinality", + "exceedsMaxEventStatesLimit", + "destinationPerDayReportingLimitReached" ] }, { - "id": "StorageBucket", + "id": "AttributionReportingSourceRegistrationTimeConfig", + "experimental": true, + "type": "string", + "enum": [ + "include", + "exclude" + ] + }, + { + "id": "AttributionReportingAggregatableValueDictEntry", + "experimental": true, "type": "object", "properties": [ { - "name": "storageKey", - "$ref": "SerializedStorageKey" + "name": "key", + "type": "string" }, { - "name": "name", - "description": "If not specified, it is the default bucket of the storageKey.", - "optional": true, - "type": "string" + "name": "value", + "description": "number instead of integer because not all uint32 can be represented by\nint", + "type": "number" + }, + { + "name": "filteringId", + "$ref": "UnsignedInt64AsBase10" } ] }, { - "id": "StorageBucketInfo", + "id": "AttributionReportingAggregatableValueEntry", + "experimental": true, "type": "object", "properties": [ { - "name": "bucket", - "$ref": "StorageBucket" + "name": "values", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregatableValueDictEntry" + } }, { - "name": "id", - "type": "string" - }, + "name": "filters", + "$ref": "AttributionReportingFilterPair" + } + ] + }, + { + "id": "AttributionReportingEventTriggerData", + "experimental": true, + "type": "object", + "properties": [ { - "name": "expiration", - "$ref": "Network.TimeSinceEpoch" + "name": "data", + "$ref": "UnsignedInt64AsBase10" }, { - "name": "quota", - "description": "Storage quota (bytes).", - "type": "number" + "name": "priority", + "$ref": "SignedInt64AsBase10" }, { - "name": "persistent", - "type": "boolean" + "name": "dedupKey", + "optional": true, + "$ref": "UnsignedInt64AsBase10" }, { - "name": "durability", - "$ref": "StorageBucketsDurability" + "name": "filters", + "$ref": "AttributionReportingFilterPair" } ] }, { - "id": "AttributionReportingSourceType", - "experimental": true, - "type": "string", - "enum": [ - "navigation", - "event" - ] - }, - { - "id": "UnsignedInt64AsBase10", - "experimental": true, - "type": "string" - }, - { - "id": "UnsignedInt128AsBase16", - "experimental": true, - "type": "string" - }, - { - "id": "SignedInt64AsBase10", - "experimental": true, - "type": "string" - }, - { - "id": "AttributionReportingFilterDataEntry", + "id": "AttributionReportingAggregatableTriggerData", "experimental": true, "type": "object", "properties": [ { - "name": "key", - "type": "string" + "name": "keyPiece", + "$ref": "UnsignedInt128AsBase16" }, { - "name": "values", + "name": "sourceKeys", "type": "array", "items": { "type": "string" } + }, + { + "name": "filters", + "$ref": "AttributionReportingFilterPair" } ] }, { - "id": "AttributionReportingAggregationKeysEntry", + "id": "AttributionReportingAggregatableDedupKey", "experimental": true, "type": "object", "properties": [ { - "name": "key", - "type": "string" + "name": "dedupKey", + "optional": true, + "$ref": "UnsignedInt64AsBase10" }, { - "name": "value", - "$ref": "UnsignedInt128AsBase16" + "name": "filters", + "$ref": "AttributionReportingFilterPair" } ] }, { - "id": "AttributionReportingSourceRegistration", + "id": "AttributionReportingTriggerRegistration", "experimental": true, "type": "object", "properties": [ { - "name": "time", - "$ref": "Network.TimeSinceEpoch" + "name": "filters", + "$ref": "AttributionReportingFilterPair" }, { - "name": "expiry", - "description": "duration in seconds", + "name": "debugKey", "optional": true, - "type": "integer" + "$ref": "UnsignedInt64AsBase10" }, { - "name": "eventReportWindow", - "description": "duration in seconds", - "optional": true, - "type": "integer" + "name": "aggregatableDedupKeys", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregatableDedupKey" + } }, { - "name": "aggregatableReportWindow", - "description": "duration in seconds", - "optional": true, - "type": "integer" + "name": "eventTriggerData", + "type": "array", + "items": { + "$ref": "AttributionReportingEventTriggerData" + } }, { - "name": "type", - "$ref": "AttributionReportingSourceType" + "name": "aggregatableTriggerData", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregatableTriggerData" + } }, { - "name": "sourceOrigin", - "type": "string" + "name": "aggregatableValues", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregatableValueEntry" + } }, { - "name": "reportingOrigin", - "type": "string" + "name": "aggregatableFilteringIdMaxBytes", + "type": "integer" }, { - "name": "destinationSites", - "type": "array", - "items": { - "type": "string" - } + "name": "debugReporting", + "type": "boolean" }, { - "name": "eventId", - "$ref": "UnsignedInt64AsBase10" + "name": "aggregationCoordinatorOrigin", + "optional": true, + "type": "string" }, { - "name": "priority", - "$ref": "SignedInt64AsBase10" + "name": "sourceRegistrationTimeConfig", + "$ref": "AttributionReportingSourceRegistrationTimeConfig" }, { - "name": "filterData", - "type": "array", - "items": { - "$ref": "AttributionReportingFilterDataEntry" - } + "name": "triggerContextId", + "optional": true, + "type": "string" }, { - "name": "aggregationKeys", + "name": "aggregatableDebugReportingConfig", + "$ref": "AttributionReportingAggregatableDebugReportingConfig" + }, + { + "name": "scopes", "type": "array", "items": { - "$ref": "AttributionReportingAggregationKeysEntry" + "type": "string" } - }, - { - "name": "debugKey", - "optional": true, - "$ref": "UnsignedInt64AsBase10" } ] }, { - "id": "AttributionReportingSourceRegistrationResult", + "id": "AttributionReportingEventLevelResult", "experimental": true, "type": "string", "enum": [ "success", + "successDroppedLowerPriority", "internalError", - "insufficientSourceCapacity", - "insufficientUniqueDestinationCapacity", + "noCapacityForAttributionDestination", + "noMatchingSources", + "deduplicated", + "excessiveAttributions", + "priorityTooLow", + "neverAttributedSource", "excessiveReportingOrigins", + "noMatchingSourceFilterData", "prohibitedByBrowserPolicy", - "successNoised", - "destinationReportingLimitReached", - "destinationGlobalLimitReached", - "destinationBothLimitsReached", - "reportingOriginsPerSiteLimitReached", - "exceedsMaxChannelCapacity" + "noMatchingConfigurations", + "excessiveReports", + "falselyAttributedSource", + "reportWindowPassed", + "notRegistered", + "reportWindowNotStarted", + "noMatchingTriggerData" + ] + }, + { + "id": "AttributionReportingAggregatableResult", + "experimental": true, + "type": "string", + "enum": [ + "success", + "internalError", + "noCapacityForAttributionDestination", + "noMatchingSources", + "excessiveAttributions", + "excessiveReportingOrigins", + "noHistograms", + "insufficientBudget", + "insufficientNamedBudget", + "noMatchingSourceFilterData", + "notRegistered", + "prohibitedByBrowserPolicy", + "deduplicated", + "reportWindowPassed", + "excessiveReports" + ] + }, + { + "id": "RelatedWebsiteSet", + "description": "A single Related Website Set object.", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "primarySites", + "description": "The primary site of this set, along with the ccTLDs if there is any.", + "type": "array", + "items": { + "type": "string" + } + }, + { + "name": "associatedSites", + "description": "The associated sites of this set, along with the ccTLDs if there is any.", + "type": "array", + "items": { + "type": "string" + } + }, + { + "name": "serviceSites", + "description": "The service sites of this set, along with the ccTLDs if there is any.", + "type": "array", + "items": { + "type": "string" + } + } ] } ], @@ -20322,7 +23338,8 @@ "returns": [ { "name": "details", - "$ref": "InterestGroupDetails" + "description": "This largely corresponds to:\nhttps://wicg.github.io/turtledove/#dictdef-generatebidinterestgroup\nbut has absolute expirationTime instead of relative lifetimeMs and\nalso adds joiningOrigin.", + "type": "object" } ] }, @@ -20337,6 +23354,17 @@ } ] }, + { + "name": "setInterestGroupAuctionTracking", + "description": "Enables/Disables issuing of interestGroupAuctionEventOccurred and\ninterestGroupAuctionNetworkRequestCreated.", + "experimental": true, + "parameters": [ + { + "name": "enable", + "type": "boolean" + } + ] + }, { "name": "getSharedStorageMetadata", "description": "Gets metadata for an origin's shared storage.", @@ -20509,6 +23537,62 @@ "type": "boolean" } ] + }, + { + "name": "sendPendingAttributionReports", + "description": "Sends all pending Attribution Reports immediately, regardless of their\nscheduled report time.", + "experimental": true, + "returns": [ + { + "name": "numSent", + "description": "The number of reports that were sent.", + "type": "integer" + } + ] + }, + { + "name": "getRelatedWebsiteSets", + "description": "Returns the effective Related Website Sets in use by this profile for the browser\nsession. The effective Related Website Sets will not change during a browser session.", + "experimental": true, + "returns": [ + { + "name": "sets", + "type": "array", + "items": { + "$ref": "RelatedWebsiteSet" + } + } + ] + }, + { + "name": "getAffectedUrlsForThirdPartyCookieMetadata", + "description": "Returns the list of URLs from a page and its embedded resources that match\nexisting grace period URL pattern rules.\nhttps://developers.google.com/privacy-sandbox/cookies/temporary-exceptions/grace-period", + "experimental": true, + "parameters": [ + { + "name": "firstPartyUrl", + "description": "The URL of the page currently being visited.", + "type": "string" + }, + { + "name": "thirdPartyUrls", + "description": "The list of embedded resource URLs from the page.", + "type": "array", + "items": { + "type": "string" + } + } + ], + "returns": [ + { + "name": "matchedUrls", + "description": "Array of matching URLs. If there is a primary pattern match for the first-\nparty URL, only the first-party URL is returned in the array.", + "type": "array", + "items": { + "type": "string" + } + } + ] } ], "events": [ @@ -20613,7 +23697,7 @@ }, { "name": "interestGroupAccessed", - "description": "One of the interest groups was accessed by the associated page.", + "description": "One of the interest groups was accessed. Note that these events are global\nto all targets sharing an interest group store.", "parameters": [ { "name": "accessTime", @@ -20630,6 +23714,81 @@ { "name": "name", "type": "string" + }, + { + "name": "componentSellerOrigin", + "description": "For topLevelBid/topLevelAdditionalBid, and when appropriate,\nwin and additionalBidWin", + "optional": true, + "type": "string" + }, + { + "name": "bid", + "description": "For bid or somethingBid event, if done locally and not on a server.", + "optional": true, + "type": "number" + }, + { + "name": "bidCurrency", + "optional": true, + "type": "string" + }, + { + "name": "uniqueAuctionId", + "description": "For non-global events --- links to interestGroupAuctionEvent", + "optional": true, + "$ref": "InterestGroupAuctionId" + } + ] + }, + { + "name": "interestGroupAuctionEventOccurred", + "description": "An auction involving interest groups is taking place. These events are\ntarget-specific.", + "parameters": [ + { + "name": "eventTime", + "$ref": "Network.TimeSinceEpoch" + }, + { + "name": "type", + "$ref": "InterestGroupAuctionEventType" + }, + { + "name": "uniqueAuctionId", + "$ref": "InterestGroupAuctionId" + }, + { + "name": "parentAuctionId", + "description": "Set for child auctions.", + "optional": true, + "$ref": "InterestGroupAuctionId" + }, + { + "name": "auctionConfig", + "description": "Set for started and configResolved", + "optional": true, + "type": "object" + } + ] + }, + { + "name": "interestGroupAuctionNetworkRequestCreated", + "description": "Specifies which auctions a particular network fetch may be related to, and\nin what role. Note that it is not ordered with respect to\nNetwork.requestWillBeSent (but will happen before loadingFinished\nloadingFailed).", + "parameters": [ + { + "name": "type", + "$ref": "InterestGroupAuctionFetchType" + }, + { + "name": "requestId", + "$ref": "Network.RequestId" + }, + { + "name": "auctions", + "description": "This is the set of the auctions using the worklet that issued this\nrequest. In the case of trusted signals, it's possible that only some of\nthem actually care about the keys being queried.", + "type": "array", + "items": { + "$ref": "InterestGroupAuctionId" + } } ] }, @@ -20659,7 +23818,7 @@ }, { "name": "params", - "description": "The sub-parameters warapped by `params` are all optional and their\npresence/absence depends on `type`.", + "description": "The sub-parameters wrapped by `params` are all optional and their\npresence/absence depends on `type`.", "$ref": "SharedStorageAccessParams" } ] @@ -20684,7 +23843,6 @@ }, { "name": "attributionReportingSourceRegistered", - "description": "TODO(crbug.com/1458532): Add other Attribution Reporting events, e.g.\ntrigger registration.", "experimental": true, "parameters": [ { @@ -20696,6 +23854,24 @@ "$ref": "AttributionReportingSourceRegistrationResult" } ] + }, + { + "name": "attributionReportingTriggerRegistered", + "experimental": true, + "parameters": [ + { + "name": "registration", + "$ref": "AttributionReportingTriggerRegistration" + }, + { + "name": "eventLevel", + "$ref": "AttributionReportingEventLevelResult" + }, + { + "name": "aggregatable", + "$ref": "AttributionReportingAggregatableResult" + } + ] } ] }, @@ -21032,6 +24208,7 @@ }, { "name": "type", + "description": "List of types: https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_agent_host_impl.cc?ss=chromium&q=f:devtools%20-f:out%20%22::kTypeTab%5B%5D%22", "type": "string" }, { @@ -21074,7 +24251,7 @@ }, { "name": "subtype", - "description": "Provides additional details for specific target types. For example, for\nthe type of \"page\", this may be set to \"portal\" or \"prerender\".", + "description": "Provides additional details for specific target types. For example, for\nthe type of \"page\", this may be set to \"prerender\".", "experimental": true, "optional": true, "type": "string" @@ -21089,7 +24266,7 @@ "properties": [ { "name": "exclude", - "description": "If set, causes exclusion of mathcing targets from the list.", + "description": "If set, causes exclusion of matching targets from the list.", "optional": true, "type": "boolean" }, @@ -21124,6 +24301,18 @@ "type": "integer" } ] + }, + { + "id": "WindowState", + "description": "The state of the target window.", + "experimental": true, + "type": "string", + "enum": [ + "normal", + "minimized", + "maximized", + "fullscreen" + ] } ], "commands": [ @@ -21192,7 +24381,7 @@ }, { "name": "exposeDevToolsProtocol", - "description": "Inject object to the target's main frame that provides a communication\nchannel with browser target.\n\nInjected object will be available as `window[bindingName]`.\n\nThe object has the follwing API:\n- `binding.send(json)` - a method to send messages over the remote debugging protocol\n- `binding.onmessage = json => handleMessage(json)` - a callback that will be called for the protocol notifications and command responses.", + "description": "Inject object to the target's main frame that provides a communication\nchannel with browser target.\n\nInjected object will be available as `window[bindingName]`.\n\nThe object has the following API:\n- `binding.send(json)` - a method to send messages over the remote debugging protocol\n- `binding.onmessage = json => handleMessage(json)` - a callback that will be called for the protocol notifications and command responses.", "experimental": true, "parameters": [ { @@ -21204,35 +24393,44 @@ "description": "Binding name, 'cdp' if not specified.", "optional": true, "type": "string" + }, + { + "name": "inheritPermissions", + "description": "If true, inherits the current root session's permissions (default: false).", + "optional": true, + "type": "boolean" } ] }, { "name": "createBrowserContext", "description": "Creates a new empty BrowserContext. Similar to an incognito profile but you can have more than\none.", - "experimental": true, "parameters": [ { "name": "disposeOnDetach", "description": "If specified, disposes this context when debugging session disconnects.", + "experimental": true, "optional": true, "type": "boolean" }, { "name": "proxyServer", "description": "Proxy server, similar to the one passed to --proxy-server", + "experimental": true, "optional": true, "type": "string" }, { "name": "proxyBypassList", "description": "Proxy bypass list, similar to the one passed to --proxy-bypass-list", + "experimental": true, "optional": true, "type": "string" }, { "name": "originsWithUniversalNetworkAccess", "description": "An optional list of origins to grant unlimited cross-origin access to.\nParts of the URL other than those constituting origin are ignored.", + "experimental": true, "optional": true, "type": "array", "items": { @@ -21251,7 +24449,6 @@ { "name": "getBrowserContexts", "description": "Returns all browser contexts created with `Target.createBrowserContext` method.", - "experimental": true, "returns": [ { "name": "browserContextIds", @@ -21272,18 +24469,38 @@ "description": "The initial URL the page will be navigated to. An empty string indicates about:blank.", "type": "string" }, + { + "name": "left", + "description": "Frame left origin in DIP (requires newWindow to be true or headless shell).", + "experimental": true, + "optional": true, + "type": "integer" + }, + { + "name": "top", + "description": "Frame top origin in DIP (requires newWindow to be true or headless shell).", + "experimental": true, + "optional": true, + "type": "integer" + }, { "name": "width", - "description": "Frame width in DIP (headless chrome only).", + "description": "Frame width in DIP (requires newWindow to be true or headless shell).", "optional": true, "type": "integer" }, { "name": "height", - "description": "Frame height in DIP (headless chrome only).", + "description": "Frame height in DIP (requires newWindow to be true or headless shell).", "optional": true, "type": "integer" }, + { + "name": "windowState", + "description": "Frame window state (requires newWindow to be true or headless shell).\nDefault is normal.", + "optional": true, + "$ref": "WindowState" + }, { "name": "browserContextId", "description": "The browser context to create the page in.", @@ -21293,20 +24510,20 @@ }, { "name": "enableBeginFrameControl", - "description": "Whether BeginFrames for this target will be controlled via DevTools (headless chrome only,\nnot supported on MacOS yet, false by default).", + "description": "Whether BeginFrames for this target will be controlled via DevTools (headless shell only,\nnot supported on MacOS yet, false by default).", "experimental": true, "optional": true, "type": "boolean" }, { "name": "newWindow", - "description": "Whether to create a new Window or Tab (chrome-only, false by default).", + "description": "Whether to create a new Window or Tab (false by default, not supported by headless shell).", "optional": true, "type": "boolean" }, { "name": "background", - "description": "Whether to create the target in background or foreground (chrome-only,\nfalse by default).", + "description": "Whether to create the target in background or foreground (false by default, not supported\nby headless shell).", "optional": true, "type": "boolean" }, @@ -21348,7 +24565,6 @@ { "name": "disposeBrowserContext", "description": "Deletes a BrowserContext. All the belonging pages will be closed without calling their\nbeforeunload hooks.", - "experimental": true, "parameters": [ { "name": "browserContextId", @@ -21424,7 +24640,6 @@ { "name": "setAutoAttach", "description": "Controls whether to automatically attach to new targets which are considered to be related to\nthis one. When turned on, attaches to all existing related targets as well. When turned off,\nautomatically detaches from all currently attached targets.\nThis also clears all targets added by `autoAttachRelated` from the list of targets to watch\nfor creation of related targets.", - "experimental": true, "parameters": [ { "name": "autoAttach", @@ -21439,6 +24654,7 @@ { "name": "flatten", "description": "Enables \"flat\" access to the session via specifying sessionId attribute in the commands.\nWe plan to make this the default, deprecate non-flattened mode,\nand eventually retire it. See crbug.com/991325.", + "experimental": true, "optional": true, "type": "boolean" }, @@ -21671,7 +24887,6 @@ }, { "domain": "Tracing", - "experimental": true, "dependencies": [ "IO" ], @@ -21679,6 +24894,7 @@ { "id": "MemoryDumpConfig", "description": "Configuration for memory dump. Used only when \"memory-infra\" category is enabled.", + "experimental": true, "type": "object" }, { @@ -21688,6 +24904,7 @@ { "name": "recordMode", "description": "Controls how the trace buffer stores data.", + "experimental": true, "optional": true, "type": "string", "enum": [ @@ -21700,24 +24917,28 @@ { "name": "traceBufferSizeInKb", "description": "Size of the trace buffer in kilobytes. If not specified or zero is passed, a default value\nof 200 MB would be used.", + "experimental": true, "optional": true, "type": "number" }, { "name": "enableSampling", "description": "Turns on JavaScript stack sampling.", + "experimental": true, "optional": true, "type": "boolean" }, { "name": "enableSystrace", "description": "Turns on system tracing.", + "experimental": true, "optional": true, "type": "boolean" }, { "name": "enableArgumentFilter", "description": "Turns on argument filter.", + "experimental": true, "optional": true, "type": "boolean" }, @@ -21742,6 +24963,7 @@ { "name": "syntheticDelays", "description": "Configuration to synthesize the delays in tracing.", + "experimental": true, "optional": true, "type": "array", "items": { @@ -21751,6 +24973,7 @@ { "name": "memoryDumpConfig", "description": "Configuration for memory dump triggers. Used only when \"memory-infra\" category is enabled.", + "experimental": true, "optional": true, "$ref": "MemoryDumpConfig" } @@ -21759,6 +24982,7 @@ { "id": "StreamFormat", "description": "Data format of a trace. Can be either the legacy JSON format or the\nprotocol buffer format. Note that the JSON format will be deprecated soon.", + "experimental": true, "type": "string", "enum": [ "json", @@ -21768,6 +24992,7 @@ { "id": "StreamCompression", "description": "Compression type to use for traces returned via streams.", + "experimental": true, "type": "string", "enum": [ "none", @@ -21777,6 +25002,7 @@ { "id": "MemoryDumpLevelOfDetail", "description": "Details exposed when memory request explicitly declared.\nKeep consistent with memory_dump_request_args.h and\nmemory_instrumentation.mojom", + "experimental": true, "type": "string", "enum": [ "background", @@ -21787,6 +25013,7 @@ { "id": "TracingBackend", "description": "Backend type to use for tracing. `chrome` uses the Chrome-integrated\ntracing service and is supported on all platforms. `system` is only\nsupported on Chrome OS and uses the Perfetto system tracing service.\n`auto` chooses `system` when the perfettoConfig provided to Tracing.start\nspecifies at least one non-Chrome data source; otherwise uses `chrome`.", + "experimental": true, "type": "string", "enum": [ "auto", @@ -21803,6 +25030,7 @@ { "name": "getCategories", "description": "Gets supported tracing categories.", + "experimental": true, "returns": [ { "name": "categories", @@ -21817,6 +25045,7 @@ { "name": "recordClockSyncMarker", "description": "Record a clock sync marker in the trace.", + "experimental": true, "parameters": [ { "name": "syncId", @@ -21828,6 +25057,7 @@ { "name": "requestMemoryDump", "description": "Request a global memory dump.", + "experimental": true, "parameters": [ { "name": "deterministic", @@ -21862,6 +25092,7 @@ { "name": "categories", "description": "Category/tag filter", + "experimental": true, "deprecated": true, "optional": true, "type": "string" @@ -21869,6 +25100,7 @@ { "name": "options", "description": "Tracing options", + "experimental": true, "deprecated": true, "optional": true, "type": "string" @@ -21876,6 +25108,7 @@ { "name": "bufferUsageReportingInterval", "description": "If set, the agent will issue bufferUsage events at this interval, specified in milliseconds", + "experimental": true, "optional": true, "type": "number" }, @@ -21898,6 +25131,7 @@ { "name": "streamCompression", "description": "Compression format to use. This only applies when using `ReturnAsStream`\ntransfer mode (defaults to `none`)", + "experimental": true, "optional": true, "$ref": "StreamCompression" }, @@ -21909,12 +25143,14 @@ { "name": "perfettoConfig", "description": "Base64-encoded serialized perfetto.protos.TraceConfig protobuf message\nWhen specified, the parameters `categories`, `options`, `traceConfig`\nare ignored. (Encoded as a base64 string when passed over JSON)", + "experimental": true, "optional": true, "type": "string" }, { "name": "tracingBackend", "description": "Backend type (defaults to `auto`)", + "experimental": true, "optional": true, "$ref": "TracingBackend" } @@ -21924,6 +25160,7 @@ "events": [ { "name": "bufferUsage", + "experimental": true, "parameters": [ { "name": "percentFull", @@ -21948,6 +25185,7 @@ { "name": "dataCollected", "description": "Contains a bucket of collected trace events. When tracing is stopped collected events will be\nsent as a sequence of dataCollected events followed by tracingComplete event.", + "experimental": true, "parameters": [ { "name": "value", @@ -22000,7 +25238,7 @@ "types": [ { "id": "RequestId", - "description": "Unique request identifier.", + "description": "Unique request identifier.\nNote that this does not identify individual HTTP requests that are part of\na network request.", "type": "string" }, { @@ -22464,7 +25702,8 @@ "enum": [ "suspended", "running", - "closed" + "closed", + "interrupted" ] }, { @@ -23003,6 +26242,18 @@ "description": "Sets whether User Verification succeeds or fails for an authenticator.\nDefaults to false.", "optional": true, "type": "boolean" + }, + { + "name": "defaultBackupEligibility", + "description": "Credentials created by this authenticator will have the backup\neligibility (BE) flag set to this value. Defaults to false.\nhttps://w3c.github.io/webauthn/#sctn-credential-backup", + "optional": true, + "type": "boolean" + }, + { + "name": "defaultBackupState", + "description": "Credentials created by this authenticator will have the backup state\n(BS) flag set to this value. Defaults to false.\nhttps://w3c.github.io/webauthn/#sctn-credential-backup", + "optional": true, + "type": "boolean" } ] }, @@ -23045,6 +26296,30 @@ "description": "The large blob associated with the credential.\nSee https://w3c.github.io/webauthn/#sctn-large-blob-extension (Encoded as a base64 string when passed over JSON)", "optional": true, "type": "string" + }, + { + "name": "backupEligibility", + "description": "Assertions returned by this credential will have the backup eligibility\n(BE) flag set to this value. Defaults to the authenticator's\ndefaultBackupEligibility value.", + "optional": true, + "type": "boolean" + }, + { + "name": "backupState", + "description": "Assertions returned by this credential will have the backup state (BS)\nflag set to this value. Defaults to the authenticator's\ndefaultBackupState value.", + "optional": true, + "type": "boolean" + }, + { + "name": "userName", + "description": "The credential's user.name property. Equivalent to empty if not set.\nhttps://w3c.github.io/webauthn/#dom-publickeycredentialentity-name", + "optional": true, + "type": "string" + }, + { + "name": "userDisplayName", + "description": "The credential's user.displayName property. Equivalent to empty if\nnot set.\nhttps://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-displayname", + "optional": true, + "type": "string" } ] } @@ -23224,6 +26499,30 @@ "type": "boolean" } ] + }, + { + "name": "setCredentialProperties", + "description": "Allows setting credential properties.\nhttps://w3c.github.io/webauthn/#sctn-automation-set-credential-properties", + "parameters": [ + { + "name": "authenticatorId", + "$ref": "AuthenticatorId" + }, + { + "name": "credentialId", + "type": "string" + }, + { + "name": "backupEligibility", + "optional": true, + "type": "boolean" + }, + { + "name": "backupState", + "optional": true, + "type": "boolean" + } + ] } ], "events": [ @@ -23241,6 +26540,34 @@ } ] }, + { + "name": "credentialDeleted", + "description": "Triggered when a credential is deleted, e.g. through\nPublicKeyCredential.signalUnknownCredential().", + "parameters": [ + { + "name": "authenticatorId", + "$ref": "AuthenticatorId" + }, + { + "name": "credentialId", + "type": "string" + } + ] + }, + { + "name": "credentialUpdated", + "description": "Triggered when a credential is updated, e.g. through\nPublicKeyCredential.signalCurrentUserDetails().", + "parameters": [ + { + "name": "authenticatorId", + "$ref": "AuthenticatorId" + }, + { + "name": "credential", + "$ref": "Credential" + } + ] + }, { "name": "credentialAsserted", "description": "Triggered when a credential is used in a webauthn assertion.", @@ -23369,133 +26696,482 @@ } }, { - "name": "data", - "description": "Extra data attached to an error, such as an HRESULT, Video Codec, etc.", - "type": "object" + "name": "data", + "description": "Extra data attached to an error, such as an HRESULT, Video Codec, etc.", + "type": "object" + } + ] + } + ], + "events": [ + { + "name": "playerPropertiesChanged", + "description": "This can be called multiple times, and can be used to set / override /\nremove player properties. A null propValue indicates removal.", + "parameters": [ + { + "name": "playerId", + "$ref": "PlayerId" + }, + { + "name": "properties", + "type": "array", + "items": { + "$ref": "PlayerProperty" + } + } + ] + }, + { + "name": "playerEventsAdded", + "description": "Send events as a list, allowing them to be batched on the browser for less\ncongestion. If batched, events must ALWAYS be in chronological order.", + "parameters": [ + { + "name": "playerId", + "$ref": "PlayerId" + }, + { + "name": "events", + "type": "array", + "items": { + "$ref": "PlayerEvent" + } + } + ] + }, + { + "name": "playerMessagesLogged", + "description": "Send a list of any messages that need to be delivered.", + "parameters": [ + { + "name": "playerId", + "$ref": "PlayerId" + }, + { + "name": "messages", + "type": "array", + "items": { + "$ref": "PlayerMessage" + } + } + ] + }, + { + "name": "playerErrorsRaised", + "description": "Send a list of any errors that need to be delivered.", + "parameters": [ + { + "name": "playerId", + "$ref": "PlayerId" + }, + { + "name": "errors", + "type": "array", + "items": { + "$ref": "PlayerError" + } + } + ] + }, + { + "name": "playersCreated", + "description": "Called whenever a player is created, or when a new agent joins and receives\na list of active players. If an agent is restored, it will receive the full\nlist of player ids and all events again.", + "parameters": [ + { + "name": "players", + "type": "array", + "items": { + "$ref": "PlayerId" + } + } + ] + } + ], + "commands": [ + { + "name": "enable", + "description": "Enables the Media domain" + }, + { + "name": "disable", + "description": "Disables the Media domain." + } + ] + }, + { + "domain": "DeviceAccess", + "experimental": true, + "types": [ + { + "id": "RequestId", + "description": "Device request id.", + "type": "string" + }, + { + "id": "DeviceId", + "description": "A device id.", + "type": "string" + }, + { + "id": "PromptDevice", + "description": "Device information displayed in a user prompt to select a device.", + "type": "object", + "properties": [ + { + "name": "id", + "$ref": "DeviceId" + }, + { + "name": "name", + "description": "Display name as it appears in a device request user prompt.", + "type": "string" + } + ] + } + ], + "commands": [ + { + "name": "enable", + "description": "Enable events in this domain." + }, + { + "name": "disable", + "description": "Disable events in this domain." + }, + { + "name": "selectPrompt", + "description": "Select a device in response to a DeviceAccess.deviceRequestPrompted event.", + "parameters": [ + { + "name": "id", + "$ref": "RequestId" + }, + { + "name": "deviceId", + "$ref": "DeviceId" + } + ] + }, + { + "name": "cancelPrompt", + "description": "Cancel a prompt in response to a DeviceAccess.deviceRequestPrompted event.", + "parameters": [ + { + "name": "id", + "$ref": "RequestId" } ] } ], "events": [ { - "name": "playerPropertiesChanged", - "description": "This can be called multiple times, and can be used to set / override /\nremove player properties. A null propValue indicates removal.", + "name": "deviceRequestPrompted", + "description": "A device request opened a user prompt to select a device. Respond with the\nselectPrompt or cancelPrompt command.", "parameters": [ { - "name": "playerId", - "$ref": "PlayerId" + "name": "id", + "$ref": "RequestId" }, { - "name": "properties", + "name": "devices", "type": "array", "items": { - "$ref": "PlayerProperty" + "$ref": "PromptDevice" } } ] + } + ] + }, + { + "domain": "Preload", + "experimental": true, + "types": [ + { + "id": "RuleSetId", + "description": "Unique id", + "type": "string" }, { - "name": "playerEventsAdded", - "description": "Send events as a list, allowing them to be batched on the browser for less\ncongestion. If batched, events must ALWAYS be in chronological order.", - "parameters": [ + "id": "RuleSet", + "description": "Corresponds to SpeculationRuleSet", + "type": "object", + "properties": [ { - "name": "playerId", - "$ref": "PlayerId" + "name": "id", + "$ref": "RuleSetId" }, { - "name": "events", - "type": "array", - "items": { - "$ref": "PlayerEvent" - } + "name": "loaderId", + "description": "Identifies a document which the rule set is associated with.", + "$ref": "Network.LoaderId" + }, + { + "name": "sourceText", + "description": "Source text of JSON representing the rule set. If it comes from\n`