From 178d2ea6dcca1cbdbe1eb54f9ae9140d0d18eaa1 Mon Sep 17 00:00:00 2001 From: Razvan Pricop <22615594+RazorBest@users.noreply.github.com> Date: Wed, 28 Aug 2024 12:48:23 +0300 Subject: [PATCH 1/5] update CDP wrappers to r1336433 --- docs/api/animation.rst | 10 + docs/api/audits.rst | 25 + docs/api/autofill.rst | 33 +- docs/api/css.rst | 21 +- docs/api/dom.rst | 9 + docs/api/emulation.rst | 64 + docs/api/event_breakpoints.rst | 9 +- docs/api/extensions.rst | 46 + docs/api/fed_cm.rst | 19 + docs/api/file_system.rst | 52 + docs/api/network.rst | 39 +- docs/api/overlay.rst | 7 + docs/api/page.rst | 62 +- docs/api/preload.rst | 10 +- docs/api/pwa.rst | 66 + docs/api/storage.rst | 115 +- docs/api/tracing.rst | 2 - docs/api/web_authn.rst | 2 + pycdp/cdp/__init__.py | 2 +- pycdp/cdp/accessibility.py | 5 +- pycdp/cdp/animation.py | 76 + pycdp/cdp/audits.py | 174 +- pycdp/cdp/autofill.py | 156 +- pycdp/cdp/browser.py | 14 +- pycdp/cdp/css.py | 222 +- pycdp/cdp/dom.py | 72 +- pycdp/cdp/dom_debugger.py | 7 + pycdp/cdp/emulation.py | 394 ++- pycdp/cdp/event_breakpoints.py | 10 + pycdp/cdp/extensions.py | 79 + pycdp/cdp/fed_cm.py | 96 +- pycdp/cdp/file_system.py | 115 + pycdp/cdp/input_.py | 18 +- pycdp/cdp/io.py | 2 +- pycdp/cdp/layer_tree.py | 2 +- pycdp/cdp/network.py | 335 ++- pycdp/cdp/overlay.py | 54 +- pycdp/cdp/page.py | 531 +++- pycdp/cdp/performance_timeline.py | 2 +- pycdp/cdp/preload.py | 82 +- pycdp/cdp/pwa.py | 262 ++ pycdp/cdp/runtime.py | 29 +- pycdp/cdp/security.py | 4 +- pycdp/cdp/service_worker.py | 5 + pycdp/cdp/storage.py | 775 ++++- pycdp/cdp/target.py | 25 +- pycdp/cdp/tracing.py | 27 +- pycdp/cdp/web_authn.py | 61 + pycdp/gen/browser_protocol.json | 4419 +++++++++++++++++++++++------ pycdp/gen/js_protocol.json | 34 +- 50 files changed, 7359 insertions(+), 1321 deletions(-) create mode 100644 docs/api/extensions.rst create mode 100644 docs/api/file_system.rst create mode 100644 docs/api/pwa.rst create mode 100644 pycdp/cdp/extensions.py create mode 100644 pycdp/cdp/file_system.py create mode 100644 pycdp/cdp/pwa.py 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..01cb2f9 100644 --- a/docs/api/audits.rst +++ b/docs/api/audits.rst @@ -134,6 +134,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: SharedDictionaryError + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: AttributionReportingIssueDetails :members: :undoc-members: @@ -149,6 +154,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: SharedDictionaryIssueDetails + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: GenericIssueErrorType :members: :undoc-members: @@ -169,6 +179,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: @@ -214,6 +229,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/css.rst b/docs/api/css.rst index 85ca375..8fabbf1 100644 --- a/docs/api/css.rst +++ b/docs/api/css.rst @@ -174,7 +174,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 +184,21 @@ 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:: CSSKeyframeRule :members: :undoc-members: @@ -226,6 +241,8 @@ to. For more information, see .. autofunction:: get_layers_for_node +.. autofunction:: get_location_for_selector + .. autofunction:: get_matched_styles_for_node .. autofunction:: get_media_queries @@ -244,6 +261,8 @@ to. For more information, see .. autofunction:: set_media_text +.. autofunction:: set_property_rule_property_name + .. autofunction:: set_rule_selector .. autofunction:: set_scope_text diff --git a/docs/api/dom.rst b/docs/api/dom.rst index 748e90e..2b3d468 100644 --- a/docs/api/dom.rst +++ b/docs/api/dom.rst @@ -63,6 +63,11 @@ 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: @@ -124,6 +129,8 @@ to. For more information, see .. autofunction:: focus +.. autofunction:: get_anchor_element + .. autofunction:: get_attributes .. autofunction:: get_box_model @@ -134,6 +141,8 @@ to. For more information, see .. autofunction:: get_document +.. autofunction:: get_element_by_relation + .. autofunction:: get_file_info .. autofunction:: get_flattened_document diff --git a/docs/api/emulation.rst b/docs/api/emulation.rst index 019e50d..aa7809e 100644 --- a/docs/api/emulation.rst +++ b/docs/api/emulation.rst @@ -27,6 +27,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 +52,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 +118,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 +138,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 +164,18 @@ to. For more information, see .. autofunction:: set_page_scale_factor +.. autofunction:: set_pressure_source_override_enabled + +.. autofunction:: set_pressure_state_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..e0943bf --- /dev/null +++ b/docs/api/extensions.rst @@ -0,0 +1,46 @@ +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:: get_storage_items + +.. autofunction:: load_unpacked + +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/network.rst b/docs/api/network.rst index 23fa448..a96943a 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 @@ -419,6 +444,8 @@ to. For more information, see .. autofunction:: set_user_agent_override +.. autofunction:: stream_resource_content + .. autofunction:: take_response_body_for_interception_as_stream Events @@ -538,11 +565,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..c50d044 100644 --- a/docs/api/page.rst +++ b/docs/api/page.rst @@ -222,6 +222,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 +297,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 +364,6 @@ to. For more information, see .. autofunction:: get_app_manifest -.. autofunction:: get_cookies - .. autofunction:: get_frame_tree .. autofunction:: get_installability_errors diff --git a/docs/api/preload.rst b/docs/api/preload.rst index bec744a..efe5d67 100644 --- a/docs/api/preload.rst +++ b/docs/api/preload.rst @@ -67,6 +67,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 +105,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..822cc06 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,46 @@ 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:: AttributionReportingSourceRegistration :members: :undoc-members: @@ -137,6 +177,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 -------- @@ -167,6 +257,8 @@ to. For more information, see .. autofunction:: get_interest_group_details +.. autofunction:: get_related_website_sets + .. autofunction:: get_shared_storage_entries .. autofunction:: get_shared_storage_metadata @@ -183,12 +275,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 +341,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 +370,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/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..3d7dd8c 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 diff --git a/pycdp/cdp/__init__.py b/pycdp/cdp/__init__.py index 4a47920..d0cc11a 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, browser, css, cache_storage, cast, console, dom, dom_debugger, dom_snapshot, dom_storage, database, 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..267bb50 100644 --- a/pycdp/cdp/accessibility.py +++ b/pycdp/cdp/accessibility.py @@ -308,6 +308,7 @@ class AXPropertyName(enum.Enum): FLOWTO = "flowto" LABELLEDBY = "labelledby" OWNS = "owns" + URL = "url" def to_json(self) -> str: return self.value @@ -473,7 +474,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 +580,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..83e81bd 100644 --- a/pycdp/cdp/audits.py +++ b/pycdp/cdp/audits.py @@ -98,6 +98,7 @@ 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" def to_json(self) -> str: return self.value @@ -119,6 +120,7 @@ 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" def to_json(self) -> str: return self.value @@ -226,6 +228,7 @@ class MixedContentResourceType(enum.Enum): FRAME = "Frame" IMAGE = "Image" IMPORT = "Import" + JSON = "JSON" MANIFEST = "Manifest" PING = "Ping" PLUGIN_DATA = "PluginData" @@ -235,6 +238,7 @@ class MixedContentResourceType(enum.Enum): SCRIPT = "Script" SERVICE_WORKER = "ServiceWorker" SHARED_WORKER = "SharedWorker" + SPECULATION_RULES = "SpeculationRules" STYLESHEET = "Stylesheet" TRACK = "Track" VIDEO = "Video" @@ -308,6 +312,8 @@ 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" def to_json(self) -> str: @@ -640,6 +646,11 @@ 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" def to_json(self) -> str: return self.value @@ -649,6 +660,39 @@ 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) + + @dataclass class AttributionReportingIssueDetails: ''' @@ -743,8 +787,27 @@ 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']), + ) + + 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 +921,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 +1008,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 +1021,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 +1030,12 @@ 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_BUTTON_MODE = "ReplacedByButtonMode" + INVALID_FIELDS_SPECIFIED = "InvalidFieldsSpecified" + RELYING_PARTY_ORIGIN_IS_OPAQUE = "RelyingPartyOriginIsOpaque" + TYPE_NOT_MATCHING = "TypeNotMatching" def to_json(self) -> str: return self.value @@ -1071,6 +1179,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 @@ -1093,8 +1247,11 @@ class InspectorIssueCode(enum.Enum): 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" def to_json(self) -> str: return self.value @@ -1143,10 +1300,16 @@ 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 + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() if self.cookie_issue_details is not None: @@ -1181,10 +1344,16 @@ 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() return json @classmethod @@ -1206,8 +1375,11 @@ def from_json(cls, json: T_JSON_DICT) -> InspectorIssueDetails: 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, ) 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/browser.py b/pycdp/cdp/browser.py index 28bc1fb..696d33c 100644 --- a/pycdp/cdp/browser.py +++ b/pycdp/cdp/browser.py @@ -106,6 +106,7 @@ class PermissionType(enum.Enum): AUDIO_CAPTURE = "audioCapture" BACKGROUND_SYNC = "backgroundSync" BACKGROUND_FETCH = "backgroundFetch" + CAPTURED_SURFACE_CONTROL = "capturedSurfaceControl" CLIPBOARD_READ_WRITE = "clipboardReadWrite" CLIPBOARD_SANITIZED_WRITE = "clipboardSanitizedWrite" DISPLAY_CAPTURE = "displayCapture" @@ -123,6 +124,7 @@ class PermissionType(enum.Enum): PROTECTED_MEDIA_IDENTIFIER = "protectedMediaIdentifier" SENSORS = "sensors" STORAGE_ACCESS = "storageAccess" + SPEAKER_SELECTION = "speakerSelection" TOP_LEVEL_STORAGE_ACCESS = "topLevelStorageAccess" VIDEO_CAPTURE = "videoCapture" VIDEO_CAPTURE_PAN_TILT_ZOOM = "videoCapturePanTiltZoom" @@ -155,7 +157,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 +173,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 +188,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 +201,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 +349,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 +372,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..4e6aa14 100644 --- a/pycdp/cdp/css.py +++ b/pycdp/cdp/css.py @@ -249,7 +249,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 @@ -1005,6 +1005,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 +1017,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 +1026,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 +1172,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 +1237,112 @@ 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 CSSKeyframeRule: ''' @@ -1285,7 +1413,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 +1423,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, @@ -1460,7 +1592,7 @@ def get_inline_styles_for_node( 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]]]: ''' Returns requested styles for a DOM node identified by ``nodeId``. @@ -1474,8 +1606,12 @@ 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. ''' params: T_JSON_DICT = dict() params['nodeId'] = node_id.to_json() @@ -1492,7 +1628,11 @@ 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, + [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 ) @@ -1573,6 +1713,31 @@ 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( properties_to_track: typing.List[CSSComputedStyleProperty] ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: @@ -1636,6 +1801,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 +2005,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, diff --git a/pycdp/cdp/dom.py b/pycdp/cdp/dom.py index e8ebf69..7a75d93 100644 --- a/pycdp/cdp/dom.py +++ b/pycdp/cdp/dom.py @@ -87,11 +87,14 @@ class PseudoType(enum.Enum): MARKER = "marker" BACKDROP = "backdrop" 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" SCROLLBAR = "scrollbar" SCROLLBAR_THUMB = "scrollbar-thumb" SCROLLBAR_BUTTON = "scrollbar-button" @@ -178,6 +181,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: ''' @@ -664,8 +682,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 +783,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 +1256,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. @@ -1687,6 +1727,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: 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..07f9e8d 100644 --- a/pycdp/cdp/emulation.py +++ b/pycdp/cdp/emulation.py @@ -72,6 +72,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 +131,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 +154,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 +214,193 @@ 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" + PROXIMITY = "proximity" + 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 +416,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 +509,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() @@ -347,7 +552,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 +573,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 +598,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 +607,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 +731,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 +769,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 +903,6 @@ def set_idle_override( ''' Overrides the Idle state. - **EXPERIMENTAL** - :param is_user_active: Mock isUserActive :param is_screen_unlocked: Mock isScreenUnlocked ''' @@ -552,8 +919,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 +1065,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 +1149,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..757c2fd --- /dev/null +++ b/pycdp/cdp/extensions.py @@ -0,0 +1,79 @@ +# 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 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 ``area``. 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']) 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/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/network.py b/pycdp/cdp/network.py index 33647ab..d25e359 100644 --- a/pycdp/cdp/network.py +++ b/pycdp/cdp/network.py @@ -305,6 +305,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 +332,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 +360,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 +427,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 +447,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,6 +676,8 @@ 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" def to_json(self) -> str: @@ -825,6 +840,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 +909,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 +948,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 +985,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 +1006,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 +1034,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 +1047,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, @@ -1163,6 +1247,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 +1323,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 +1348,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 +1370,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 +1385,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 +1400,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 +1422,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" @@ -1326,6 +1439,29 @@ 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" + TPCD_HEURISTICS = "TPCDHeuristics" + ENTERPRISE_POLICY = "EnterprisePolicy" + STORAGE_ACCESS = "StorageAccess" + TOP_LEVEL_STORAGE_ACCESS = "TopLevelStorageAccess" + CORS_OPT_IN = "CorsOptIn" + SCHEME = "Scheme" + + def to_json(self) -> str: + return self.value + + @classmethod + def from_json(cls, json: str) -> CookieExemptionReason: + return cls(json) + + @dataclass class BlockedSetCookieWithReason: ''' @@ -1361,27 +1497,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 +1607,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 +1637,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 +1656,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 +1952,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: @@ -1899,6 +2072,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 +2554,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 +2574,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 +2598,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 +2611,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 +2622,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 +2894,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 +2936,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 +2954,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 +2983,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 +3078,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 +3097,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]: @@ -2993,6 +3203,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 +3212,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 +3257,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] @@ -3527,8 +3740,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 +3755,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, @@ -3580,9 +3793,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 +3809,32 @@ 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. + 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 +3875,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..a76c523 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 @@ -1281,6 +1311,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..0314455 100644 --- a/pycdp/cdp/page.py +++ b/pycdp/cdp/page.py @@ -168,18 +168,21 @@ class PermissionsPolicyFeature(enum.Enum): in third_party/blink/renderer/core/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" @@ -188,7 +191,7 @@ class PermissionsPolicyFeature(enum.Enum): 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" @@ -200,6 +203,8 @@ class PermissionsPolicyFeature(enum.Enum): CLIPBOARD_WRITE = "clipboard-write" COMPUTE_PRESSURE = "compute-pressure" CROSS_ORIGIN_ISOLATED = "cross-origin-isolated" + DEFERRED_FETCH = "deferred-fetch" + DIGITAL_CREDENTIALS_GET = "digital-credentials-get" DIRECT_SOCKETS = "direct-sockets" DISPLAY_CAPTURE = "display-capture" DOCUMENT_DOMAIN = "document-domain" @@ -220,6 +225,7 @@ 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" @@ -228,6 +234,7 @@ class PermissionsPolicyFeature(enum.Enum): 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 +243,17 @@ 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_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: @@ -819,7 +829,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. @@ -1233,9 +1243,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 +1731,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 +1746,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 +1766,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 +1782,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" @@ -1397,6 +1811,7 @@ 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" def to_json(self) -> str: return self.value @@ -1422,6 +1837,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 +1884,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 +1902,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, ) @@ -1722,26 +2176,39 @@ def enable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: 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 +2288,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 +2499,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 +2521,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 +2560,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 +2575,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 +2717,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 +2987,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 +3085,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 +3130,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 +3267,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() @@ -3264,7 +3711,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 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..4de6806 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 @@ -226,7 +226,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 +237,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 +248,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 +278,20 @@ 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" def to_json(self) -> str: return self.value @@ -325,7 +333,8 @@ class PrefetchStatus(enum.Enum): 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" @@ -357,6 +366,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 +438,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: @@ -487,6 +499,7 @@ class PrerenderStatusUpdated: #: 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: @@ -494,7 +507,8 @@ def from_json(cls, json: T_JSON_DICT) -> PrerenderStatusUpdated: key=PreloadingAttemptKey.from_json(json['key']), 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..2e4b42a 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 = { @@ -1375,11 +1360,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 +1384,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..824b594 100644 --- a/pycdp/cdp/storage.py +++ b/pycdp/cdp/storage.py @@ -104,6 +104,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 +129,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 +143,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 + STARTED = "started" + CONFIG_RESOLVED = "configResolved" - metadata: typing.Optional[str] = None - - 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 + BIDDER_JS = "bidderJs" + BIDDER_WASM = "bidderWasm" + SELLER_JS = "sellerJs" + BIDDER_TRUSTED_SIGNALS = "bidderTrustedSignals" + SELLER_TRUSTED_SIGNALS = "sellerTrustedSignals" - name: str - - 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 +187,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 +197,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 +238,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 +265,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 +347,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 +539,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 +601,132 @@ 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 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 +743,20 @@ 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 debug_key: typing.Optional[UnsignedInt64AsBase10] = 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,12 +765,9 @@ 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() if self.debug_key is not None: json['debugKey'] = self.debug_key.to_json() return json @@ -634,6 +776,9 @@ def to_json(self) -> T_JSON_DICT: 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,9 +787,9 @@ 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']), debug_key=UnsignedInt64AsBase10.from_json(json['debugKey']) if json.get('debugKey', None) is not None else None, ) @@ -662,6 +807,8 @@ class AttributionReportingSourceRegistrationResult(enum.Enum): DESTINATION_BOTH_LIMITS_REACHED = "destinationBothLimitsReached" REPORTING_ORIGINS_PER_SITE_LIMIT_REACHED = "reportingOriginsPerSiteLimitReached" EXCEEDS_MAX_CHANNEL_CAPACITY = "exceedsMaxChannelCapacity" + EXCEEDS_MAX_TRIGGER_STATE_CARDINALITY = "exceedsMaxTriggerStateCardinality" + DESTINATION_PER_DAY_REPORTING_LIMIT_REACHED = "destinationPerDayReportingLimitReached" def to_json(self) -> str: return self.value @@ -671,6 +818,284 @@ 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 + + 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() + 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']), + 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" + 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 +1443,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 +1451,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 +1461,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 +1483,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 +1747,38 @@ 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']] + + @event_class('Storage.cacheStorageContentUpdated') @dataclass class CacheStorageContentUpdated: @@ -1403,12 +1880,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 +1902,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 +1976,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 +2021,7 @@ class AttributionReportingSourceRegistered: ''' **EXPERIMENTAL** - TODO(crbug.com/1458532): Add other Attribution Reporting events, e.g. - trigger registration. + ''' registration: AttributionReportingSourceRegistration result: AttributionReportingSourceRegistrationResult @@ -1492,3 +2032,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..95c2446 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. @@ -256,7 +257,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. @@ -286,12 +287,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 +314,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 = { @@ -402,8 +399,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 +495,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/web_authn.py b/pycdp/cdp/web_authn.py index 2e2f5a1..964eed2 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,16 @@ 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 + def to_json(self) -> T_JSON_DICT: json: T_JSON_DICT = dict() json['credentialId'] = self.credential_id @@ -185,6 +211,10 @@ 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 return json @classmethod @@ -197,6 +227,8 @@ 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, ) @@ -435,6 +467,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: diff --git a/pycdp/gen/browser_protocol.json b/pycdp/gen/browser_protocol.json index 35ee320..4776c1c 100644 --- a/pycdp/gen/browser_protocol.json +++ b/pycdp/gen/browser_protocol.json @@ -248,7 +248,8 @@ "errormessage", "flowto", "labelledby", - "owns" + "owns", + "url" ] }, { @@ -407,7 +408,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 +504,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 +620,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 +649,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 +721,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 +966,17 @@ "$ref": "Animation" } ] + }, + { + "name": "animationUpdated", + "description": "Event for animation that has been updated.", + "parameters": [ + { + "name": "animation", + "description": "Animation that was updated.", + "$ref": "Animation" + } + ] } ] }, @@ -993,7 +1047,8 @@ "ExcludeInvalidSameParty", "ExcludeSamePartyCrossPartyContext", "ExcludeDomainNonASCII", - "ExcludeThirdPartyCookieBlockedInFirstPartySet" + "ExcludeThirdPartyCookieBlockedInFirstPartySet", + "ExcludeThirdPartyPhaseout" ] }, { @@ -1010,7 +1065,8 @@ "WarnSameSiteLaxCrossDowngradeLax", "WarnAttributeValueExceedsMaxSize", "WarnDomainNonASCII", - "WarnThirdPartyPhaseout" + "WarnThirdPartyPhaseout", + "WarnCrossSiteRedirectDowngradeChangesInclusion" ] }, { @@ -1098,6 +1154,7 @@ "Frame", "Image", "Import", + "JSON", "Manifest", "Ping", "PluginData", @@ -1107,6 +1164,7 @@ "Script", "ServiceWorker", "SharedWorker", + "SpeculationRules", "Stylesheet", "Track", "Video", @@ -1163,6 +1221,8 @@ "CoopSandboxedIFrameCannotNavigateToCoopPage", "CorpNotSameOrigin", "CorpNotSameOriginAfterDefaultedToSameOriginByCoep", + "CorpNotSameOriginAfterDefaultedToSameOriginByDip", + "CorpNotSameOriginAfterDefaultedToSameOriginByCoepAndDip", "CorpNotSameSite" ] }, @@ -1422,7 +1482,41 @@ "InvalidRegisterOsTriggerHeader", "WebAndOsHeaders", "NoWebOrOsSupport", - "NavigationRegistrationWithoutTransientUserActivation" + "NavigationRegistrationWithoutTransientUserActivation", + "InvalidInfoHeader", + "NoRegisterSourceHeader", + "NoRegisterTriggerHeader", + "NoRegisterOsSourceHeader", + "NoRegisterOsTriggerHeader" + ] + }, + { + "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" ] }, { @@ -1495,11 +1589,24 @@ } ] }, + { + "id": "SharedDictionaryIssueDetails", + "type": "object", + "properties": [ + { + "name": "sharedDictionaryError", + "$ref": "SharedDictionaryError" + }, + { + "name": "request", + "$ref": "AffectedRequest" + } + ] + }, { "id": "GenericIssueErrorType", "type": "string", "enum": [ - "CrossOriginPortalPostMessageError", "FormLabelForNameError", "FormDuplicateIdForInputError", "FormInputWithNoLabelError", @@ -1580,6 +1687,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 +1753,9 @@ "ClientMetadataNoResponse", "ClientMetadataInvalidResponse", "ClientMetadataInvalidContentType", + "IdpNotPotentiallyTrustworthy", "DisabledInSettings", + "DisabledInFlags", "ErrorFetchingSignin", "InvalidSigninResponse", "AccountsHttpNotFound", @@ -1631,13 +1766,21 @@ "IdTokenHttpNotFound", "IdTokenNoResponse", "IdTokenInvalidResponse", + "IdTokenIdpErrorResponse", + "IdTokenCrossSiteIdpErrorResponse", "IdTokenInvalidRequest", "IdTokenInvalidContentType", "ErrorIdToken", "Canceled", "RpPageNotVisible", "SilentMediationFailure", - "ThirdPartyCookiesBlocked" + "ThirdPartyCookiesBlocked", + "NotSignedInWithIdp", + "MissingTransientUserActivation", + "ReplacedByButtonMode", + "InvalidFieldsSpecified", + "RelyingPartyOriginIsOpaque", + "TypeNotMatching" ] }, { @@ -1733,6 +1876,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.", @@ -1754,8 +1930,11 @@ "ClientHintIssue", "FederatedAuthRequestIssue", "BounceTrackingIssue", + "CookieDeprecationMetadataIssue", "StylesheetLoadingIssue", - "FederatedAuthUserInfoRequestIssue" + "FederatedAuthUserInfoRequestIssue", + "PropertyRuleIssue", + "SharedDictionaryIssue" ] }, { @@ -1844,15 +2023,30 @@ "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" } ] }, @@ -1981,6 +2175,75 @@ } ] }, + { + "domain": "Extensions", + "description": "Defines commands and events for browser extensions.", + "experimental": true, + "types": [ + { + "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": "path", + "description": "Absolute file path.", + "type": "string" + } + ], + "returns": [ + { + "name": "id", + "description": "Extension id.", + "type": "string" + } + ] + }, + { + "name": "getStorageItems", + "description": "Gets data from extension storage in the given `area`. If `keys` is\nspecified, these are used to filter the result.", + "parameters": [ + { + "name": "id", + "description": "ID of extension.", + "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" + } + ] + } + ] + }, { "domain": "Autofill", "description": "Defines commands and events for Autofill.", @@ -2028,24 +2291,129 @@ }, { "name": "value", - "description": "address field name, for example Jon Doe.", + "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 +2451,14 @@ } } ] + }, + { + "name": "disable", + "description": "Disables autofill domain notifications." + }, + { + "name": "enable", + "description": "Enables autofill domain notifications." } ] }, @@ -2315,6 +2691,7 @@ "audioCapture", "backgroundSync", "backgroundFetch", + "capturedSurfaceControl", "clipboardReadWrite", "clipboardSanitizedWrite", "displayCapture", @@ -2332,6 +2709,7 @@ "protectedMediaIdentifier", "sensors", "storageAccess", + "speakerSelection", "topLevelStorageAccess", "videoCapture", "videoCapturePanTiltZoom", @@ -2352,7 +2730,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 +2757,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 +2895,6 @@ { "name": "resetPermissions", "description": "Reset all permission management for all origins.", - "experimental": true, "parameters": [ { "name": "browserContextId", @@ -2528,7 +2911,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", @@ -3043,7 +3426,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" }, { @@ -3699,6 +4082,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,29 +4216,42 @@ ] }, { - "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" - } - } - ] - }, - { - "id": "CSSKeyframesRule", - "description": "CSS keyframes 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": "style", + "description": "Associated style declaration.", + "$ref": "CSSStyle" + }, + { + "name": "active", + "type": "boolean" + } + ] + }, + { + "id": "CSSKeyframesRule", + "description": "CSS keyframes rule representation.", + "type": "object", + "properties": [ { "name": "animationName", "description": "Animation name.", @@ -3866,6 +4267,86 @@ } ] }, + { + "id": "CSSPropertyRegistration", + "description": "Representation of a custom property registration through CSS.registerProperty", + "type": "object", + "properties": [ + { + "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": "CSSKeyframeRule", "description": "CSS keyframe rule representation.", @@ -3936,6 +4417,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": [ @@ -4156,14 +4644,44 @@ } }, { - "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.", @@ -4240,6 +4758,30 @@ } ] }, + { + "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": "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 +4830,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 +5040,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": [ @@ -5021,11 +5595,14 @@ "marker", "backdrop", "selection", + "search-text", "target-text", "spelling-error", "grammar-error", "highlight", "first-line-inherited", + "scroll-marker", + "scroll-marker-group", "scrollbar", "scrollbar-thumb", "scrollbar-button", @@ -5081,6 +5658,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.", @@ -5532,7 +6118,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 +6208,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 +6694,33 @@ } ] }, + { + "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" + ] + } + ], + "returns": [ + { + "name": "nodeId", + "description": "NodeId of the element matching the queried relation.", + "$ref": "NodeId" + } + ] + }, { "name": "redo", "description": "Re-does the last undone action.", @@ -6495,6 +7107,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": [ @@ -6742,7 +7379,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 +7535,8 @@ "name": "removeInstrumentationBreakpoint", "description": "Removes breakpoint on particular native event.", "experimental": true, + "deprecated": true, + "redirect": "EventBreakpoints", "parameters": [ { "name": "eventName", @@ -6971,6 +7609,8 @@ "name": "setInstrumentationBreakpoint", "description": "Sets breakpoint on particular native event.", "experimental": true, + "deprecated": true, + "redirect": "EventBreakpoints", "parameters": [ { "name": "eventName", @@ -6994,7 +7634,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 +7658,10 @@ "type": "string" } ] + }, + { + "name": "disable", + "description": "Removes all breakpoints" } ] }, @@ -8263,6 +8907,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 +8949,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 +8965,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": [ @@ -8367,35 +9026,181 @@ ] }, { - "id": "DisabledImageType", - "description": "Enum of image types that can be disabled.", + "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": [ - "avif", - "webp" + "absolute-orientation", + "accelerometer", + "ambient-light", + "gravity", + "gyroscope", + "linear-acceleration", + "magnetometer", + "proximity", + "relative-orientation" ] - } - ], - "commands": [ + }, { - "name": "canEmulate", - "description": "Tells whether emulation is supported.", - "returns": [ + "id": "SensorMetadata", + "experimental": true, + "type": "object", + "properties": [ { - "name": "result", - "description": "True if emulation is supported.", + "name": "available", + "optional": true, "type": "boolean" + }, + { + "name": "minimumFrequency", + "optional": true, + "type": "number" + }, + { + "name": "maximumFrequency", + "optional": true, + "type": "number" } ] }, { - "name": "clearDeviceMetricsOverride", - "description": "Clears the overridden device metrics." - }, - { - "name": "clearGeolocationOverride", - "description": "Clears the overridden Geolocation Position and Error." + "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.", + "experimental": true, + "type": "string", + "enum": [ + "avif", + "webp" + ] + } + ], + "commands": [ + { + "name": "canEmulate", + "description": "Tells whether emulation is supported.", + "deprecated": true, + "returns": [ + { + "name": "result", + "description": "True if emulation is supported.", + "type": "boolean" + } + ] + }, + { + "name": "clearDeviceMetricsOverride", + "description": "Clears the overridden device metrics." + }, + { + "name": "clearGeolocationOverride", + "description": "Clears the overridden Geolocation Position and Error." }, { "name": "resetPageScaleFactor", @@ -8430,7 +9235,6 @@ { "name": "setCPUThrottlingRate", "description": "Enables CPU throttling to emulate slow CPUs.", - "experimental": true, "parameters": [ { "name": "rate", @@ -8536,9 +9340,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 +9434,6 @@ { "name": "setEmulatedVisionDeficiency", "description": "Emulates the given vision deficiency.", - "experimental": true, "parameters": [ { "name": "type", @@ -8648,10 +9475,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 +9579,7 @@ }, { "name": "clearIdleOverride", - "description": "Clears Idle state overrides.", - "experimental": true + "description": "Clears Idle state overrides." }, { "name": "setNavigatorOverrides", @@ -8775,11 +9686,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 +9739,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 +9748,7 @@ }, { "name": "acceptLanguage", - "description": "Browser langugage to emulate.", + "description": "Browser language to emulate.", "optional": true, "type": "string" }, @@ -9007,7 +9917,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" }, @@ -9058,88 +9968,190 @@ ] }, { - "domain": "IndexedDB", + "domain": "FileSystem", "experimental": true, "dependencies": [ - "Runtime", + "Network", "Storage" ], "types": [ { - "id": "DatabaseWithObjectStores", - "description": "Database with an array of object stores.", + "id": "File", "type": "object", "properties": [ { "name": "name", - "description": "Database name.", "type": "string" }, { - "name": "version", - "description": "Database version (type is not 'integer', as the standard\nrequires the version number to be 'unsigned long long')", + "name": "lastModified", + "description": "Timestamp", + "$ref": "Network.TimeSinceEpoch" + }, + { + "name": "size", + "description": "Size in bytes", "type": "number" }, { - "name": "objectStores", - "description": "Object stores in this database.", - "type": "array", - "items": { - "$ref": "ObjectStore" - } + "name": "type", + "type": "string" } ] }, { - "id": "ObjectStore", - "description": "Object store.", + "id": "Directory", "type": "object", "properties": [ { "name": "name", - "description": "Object store name.", "type": "string" }, { - "name": "keyPath", - "description": "Object store key path.", - "$ref": "KeyPath" - }, - { - "name": "autoIncrement", - "description": "If true, object store has auto increment flag set.", - "type": "boolean" + "name": "nestedDirectories", + "type": "array", + "items": { + "type": "string" + } }, { - "name": "indexes", - "description": "Indexes in this object store.", + "name": "nestedFiles", + "description": "Files that are directly nested under this directory.", "type": "array", "items": { - "$ref": "ObjectStoreIndex" + "$ref": "File" } } ] }, { - "id": "ObjectStoreIndex", - "description": "Object store index.", + "id": "BucketFileSystemLocator", "type": "object", "properties": [ { - "name": "name", - "description": "Index name.", - "type": "string" + "name": "storageKey", + "description": "Storage key", + "$ref": "Storage.SerializedStorageKey" }, { - "name": "keyPath", - "description": "Index key path.", - "$ref": "KeyPath" + "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": "unique", - "description": "If true, index is unique.", - "type": "boolean" - }, + "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, + "dependencies": [ + "Runtime", + "Storage" + ], + "types": [ + { + "id": "DatabaseWithObjectStores", + "description": "Database with an array of object stores.", + "type": "object", + "properties": [ + { + "name": "name", + "description": "Database name.", + "type": "string" + }, + { + "name": "version", + "description": "Database version (type is not 'integer', as the standard\nrequires the version number to be 'unsigned long long')", + "type": "number" + }, + { + "name": "objectStores", + "description": "Object stores in this database.", + "type": "array", + "items": { + "$ref": "ObjectStore" + } + } + ] + }, + { + "id": "ObjectStore", + "description": "Object store.", + "type": "object", + "properties": [ + { + "name": "name", + "description": "Object store name.", + "type": "string" + }, + { + "name": "keyPath", + "description": "Object store key path.", + "$ref": "KeyPath" + }, + { + "name": "autoIncrement", + "description": "If true, object store has auto increment flag set.", + "type": "boolean" + }, + { + "name": "indexes", + "description": "Indexes in this object store.", + "type": "array", + "items": { + "$ref": "ObjectStoreIndex" + } + } + ] + }, + { + "id": "ObjectStoreIndex", + "description": "Object store index.", + "type": "object", + "properties": [ + { + "name": "name", + "description": "Index name.", + "type": "string" + }, + { + "name": "keyPath", + "description": "Index key path.", + "$ref": "KeyPath" + }, + { + "name": "unique", + "description": "If true, index is unique.", + "type": "boolean" + }, { "name": "multiEntry", "description": "If true, index allows multiple entries for a key.", @@ -9624,16 +10636,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 +10903,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 +11007,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 +11775,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": { @@ -11349,6 +12357,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 +12458,8 @@ }, { "name": "postData", - "description": "HTTP POST request data.", + "description": "HTTP POST request data.\nUse postDataEntries instead.", + "deprecated": true, "optional": true, "type": "string" }, @@ -11448,7 +12471,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 +12520,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,6 +12691,8 @@ "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-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" ] }, @@ -11793,6 +12818,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 +12891,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 +12949,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.", @@ -12090,6 +13169,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 +13253,7 @@ "name": "sameParty", "description": "True if cookie is SameParty.", "experimental": true, + "deprecated": true, "type": "boolean" }, { @@ -12172,10 +13270,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 +13296,7 @@ "SameSiteUnspecifiedTreatedAsLax", "SameSiteNoneInsecure", "UserPreferences", + "ThirdPartyPhaseout", "ThirdPartyBlockedInFirstPartySet", "SyntaxError", "SchemeNotSupported", @@ -12211,7 +13310,8 @@ "SamePartyFromCrossPartyContext", "SamePartyConflictsWithOtherAttributes", "NameValuePairExceedsMaxSize", - "DisallowedCharacter" + "DisallowedCharacter", + "NoCookieContent" ] }, { @@ -12228,6 +13328,7 @@ "SameSiteUnspecifiedTreatedAsLax", "SameSiteNoneInsecure", "UserPreferences", + "ThirdPartyPhaseout", "ThirdPartyBlockedInFirstPartySet", "UnknownError", "SchemefulSameSiteStrict", @@ -12237,6 +13338,24 @@ "NameValuePairExceedsMaxSize" ] }, + { + "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", + "TPCDHeuristics", + "EnterprisePolicy", + "StorageAccess", + "TopLevelStorageAccess", + "CorsOptIn", + "Scheme" + ] + }, { "id": "BlockedSetCookieWithReason", "description": "A cookie which was not stored from a response with the corresponding reason.", @@ -12265,23 +13384,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 +13520,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 +13785,7 @@ }, { "name": "errors", - "description": "Errors occurred while handling the signed exchagne.", + "description": "Errors occurred while handling the signed exchange.", "optional": true, "type": "array", "items": { @@ -12722,7 +13870,8 @@ "RestrictProperties", "UnsafeNone", "SameOriginPlusCoep", - "RestrictPropertiesPlusCoep" + "RestrictPropertiesPlusCoep", + "NoopenerAllowPopups" ] }, { @@ -13100,7 +14249,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 +14273,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 +14316,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 +14578,6 @@ { "name": "setBypassServiceWorker", "description": "Toggles ignoring of service worker for each request.", - "experimental": true, "parameters": [ { "name": "bypass", @@ -13507,10 +14683,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 +14763,7 @@ }, { "name": "acceptLanguage", - "description": "Browser langugage to emulate.", + "description": "Browser language to emulate.", "optional": true, "type": "string" }, @@ -13606,6 +14782,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.", @@ -13691,6 +14886,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 +14948,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" }, { @@ -14247,10 +15449,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" } }, { @@ -14320,19 +15522,46 @@ { "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": "trustTokenOperationDone", + }, + { + "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.", + "$ref": "Headers" + } + ] + }, + { + "name": "trustTokenOperationDone", "description": "Fired exactly once for each Trust Token operation. Depending on\nthe type of the operation and whether the operation succeeded or\nfailed, the event is fired before the corresponding request was sent\nor after the response was received.", "experimental": true, "parameters": [ @@ -14347,7 +15576,7 @@ "FailedPrecondition", "ResourceExhausted", "AlreadyExists", - "Unavailable", + "ResourceLimited", "Unauthorized", "BadResponse", "InternalError", @@ -14383,6 +15612,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 +15763,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 +16267,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 +16471,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": [ { @@ -15567,6 +16823,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": [ @@ -15724,18 +16992,21 @@ "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", @@ -15744,7 +17015,7 @@ "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", @@ -15756,6 +17027,8 @@ "clipboard-write", "compute-pressure", "cross-origin-isolated", + "deferred-fetch", + "digital-credentials-get", "direct-sockets", "display-capture", "document-domain", @@ -15776,6 +17049,7 @@ "keyboard-map", "local-fonts", "magnetometer", + "media-playback-while-not-visible", "microphone", "midi", "otp-credentials", @@ -15784,6 +17058,7 @@ "private-aggregation", "private-state-token-issuance", "private-state-token-redemption", + "publickey-credentials-create", "publickey-credentials-get", "run-ad-auction", "screen-wake-lock", @@ -15792,14 +17067,17 @@ "shared-storage", "shared-storage-select-url", "smart-card", + "speaker-selection", "storage-access", + "sub-apps", "sync-xhr", "unload", "usb", + "usb-unrestricted", "vertical-scroll", + "web-printing", "web-share", "window-management", - "window-placement", "xr-spatial-tracking" ] }, @@ -16279,7 +17557,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" }, { @@ -16602,504 +17880,933 @@ ] }, { - "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", - "type": "string" - } - ], - "returns": [ - { - "name": "identifier", - "description": "Identifier of the added script.", - "$ref": "ScriptIdentifier" + }, + { + "name": "launchType", + "description": "Won't repeat the enums, using string for easy comparison. Same as the\nother enums below.", + "type": "string" } ] }, { - "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, + "type": "object", + "properties": [ + { + "name": "backgroundColor", + "optional": true, + "type": "string" + }, + { + "name": "description", + "description": "The extra description provided by the manifest.", + "optional": true, + "type": "string" + }, + { + "name": "dir", + "optional": true, + "type": "string" + }, + { + "name": "display", + "optional": true, + "type": "string" + }, + { + "name": "displayOverrides", + "description": "The overrided display mode controlled by the user.", + "optional": true, + "type": "array", + "items": { + "type": "string" + } + }, + { + "name": "fileHandlers", + "description": "The handlers to open files.", + "optional": true, + "type": "array", + "items": { + "$ref": "FileHandler" + } + }, + { + "name": "icons", + "optional": true, + "type": "array", + "items": { + "$ref": "ImageResource" + } + }, + { + "name": "id", + "optional": true, + "type": "string" + }, + { + "name": "lang", + "optional": true, + "type": "string" + }, + { + "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": "LaunchHandler" + }, + { + "name": "name", + "optional": true, + "type": "string" + }, + { + "name": "orientation", + "optional": true, + "type": "string" + }, + { + "name": "preferRelatedApplications", + "optional": true, + "type": "boolean" + }, + { + "name": "protocolHandlers", + "description": "The handlers to open protocols.", + "optional": true, + "type": "array", + "items": { + "$ref": "ProtocolHandler" + } + }, + { + "name": "relatedApplications", + "optional": true, + "type": "array", + "items": { + "$ref": "RelatedApplication" + } + }, + { + "name": "scope", + "optional": true, + "type": "string" + }, + { + "name": "scopeExtensions", + "description": "Non-standard, see\nhttps://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-explainer.md", + "optional": true, + "type": "array", + "items": { + "$ref": "ScopeExtension" + } + }, + { + "name": "screenshots", + "description": "The screenshots used by chromium.", + "optional": true, + "type": "array", + "items": { + "$ref": "Screenshot" + } + }, + { + "name": "shareTarget", + "optional": true, + "$ref": "ShareTarget" + }, + { + "name": "shortName", + "optional": true, + "type": "string" + }, + { + "name": "shortcuts", + "optional": true, + "type": "array", + "items": { + "$ref": "Shortcut" + } + }, + { + "name": "startUrl", + "optional": true, + "type": "string" + }, + { + "name": "themeColor", + "optional": true, + "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", + "EmbedderPopupBlockerTabHelper", + "EmbedderSafeBrowsingTriggeredPopupBlocker", + "EmbedderSafeBrowsingThreatDetails", + "EmbedderAppBannerManager", + "EmbedderDomDistillerViewerSource", + "EmbedderDomDistillerSelfDeletingRequestDelegate", + "EmbedderOomInterventionTabHelper", + "EmbedderOfflinePage", + "EmbedderChromePasswordManagerClientBindCredentialManager", + "EmbedderPermissionRequestManager", + "EmbedderModalDialog", + "EmbedderExtensions", + "EmbedderExtensionMessaging", + "EmbedderExtensionMessagingForOpenPort", + "EmbedderExtensionSentMessageToCachedFrame", + "RequestedByWebViewClient" + ] + }, + { + "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." + }, + { + "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": [ { @@ -17134,23 +18841,6 @@ } ] }, - { - "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": [ - { - "name": "cookies", - "description": "Array of cookie objects.", - "type": "array", - "items": { - "$ref": "Network.Cookie" - } - } - ] - }, { "name": "getFrameTree", "description": "Returns present frame tree structure.", @@ -17453,6 +19143,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 +19182,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 +19285,6 @@ { "name": "setBypassCSP", "description": "Enable page Content Security Policy by-passing.", - "experimental": true, "parameters": [ { "name": "enabled", @@ -17833,7 +19536,6 @@ { "name": "setLifecycleEventsEnabled", "description": "Controls whether page will emit lifecycle events.", - "experimental": true, "parameters": [ { "name": "enabled", @@ -17918,8 +19620,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 +19645,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 +19726,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", @@ -18395,7 +20095,7 @@ "parameters": [ { "name": "loaderId", - "description": "The loader id for the associated navgation.", + "description": "The loader id for the associated navigation.", "$ref": "Network.LoaderId" }, { @@ -18725,7 +20425,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 +20587,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 +20796,6 @@ { "name": "setIgnoreCertificateErrors", "description": "Enable/disable whether all certificate errors should be ignored.", - "experimental": true, "parameters": [ { "name": "ignore", @@ -19313,6 +21012,11 @@ "name": "targetId", "optional": true, "$ref": "Target.TargetID" + }, + { + "name": "routerRules", + "optional": true, + "type": "string" } ] }, @@ -19462,569 +21166,940 @@ "name": "unregister", "parameters": [ { - "name": "scopeURL", - "type": "string" + "name": "scopeURL", + "type": "string" + } + ] + }, + { + "name": "updateRegistration", + "parameters": [ + { + "name": "scopeURL", + "type": "string" + } + ] + } + ], + "events": [ + { + "name": "workerErrorReported", + "parameters": [ + { + "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": [ + "appcache", + "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" } ] }, { - "name": "updateRegistration", - "parameters": [ + "id": "SharedStorageReportingMetadata", + "description": "Pair of reporting metadata details for a candidate URL for `selectURL()`.", + "type": "object", + "properties": [ { - "name": "scopeURL", + "name": "eventType", "type": "string" - } - ] - } - ], - "events": [ - { - "name": "workerErrorReported", - "parameters": [ + }, { - "name": "errorMessage", - "$ref": "ServiceWorkerErrorMessage" + "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": "filterValues", + "type": "array", + "items": { + "$ref": "AttributionReportingFilterDataEntry" + } }, { - "name": "expirationTime", - "$ref": "Network.TimeSinceEpoch" - }, + "name": "lookbackWindow", + "description": "duration in seconds", + "optional": true, + "type": "integer" + } + ] + }, + { + "id": "AttributionReportingFilterPair", + "experimental": true, + "type": "object", + "properties": [ { - "name": "joiningOrigin", - "type": "string" + "name": "filters", + "type": "array", + "items": { + "$ref": "AttributionReportingFilterConfig" + } }, { - "name": "biddingUrl", - "optional": true, - "type": "string" - }, + "name": "notFilters", + "type": "array", + "items": { + "$ref": "AttributionReportingFilterConfig" + } + } + ] + }, + { + "id": "AttributionReportingAggregationKeysEntry", + "experimental": true, + "type": "object", + "properties": [ { - "name": "biddingWasmHelperUrl", - "optional": true, + "name": "key", "type": "string" }, { - "name": "updateUrl", - "optional": true, - "type": "string" - }, + "name": "value", + "$ref": "UnsignedInt128AsBase16" + } + ] + }, + { + "id": "AttributionReportingEventReportWindows", + "experimental": true, + "type": "object", + "properties": [ { - "name": "trustedBiddingSignalsUrl", - "optional": true, - "type": "string" + "name": "start", + "description": "duration in seconds", + "type": "integer" }, { - "name": "trustedBiddingSignalsKeys", + "name": "ends", + "description": "duration in seconds", "type": "array", "items": { - "type": "string" + "type": "integer" } - }, - { - "name": "userBiddingSignals", - "optional": true, - "type": "string" - }, + } + ] + }, + { + "id": "AttributionReportingTriggerSpec", + "experimental": true, + "type": "object", + "properties": [ { - "name": "ads", + "name": "triggerData", + "description": "number instead of integer because not all uint32 can be represented by\nint", "type": "array", "items": { - "$ref": "InterestGroupAd" + "type": "number" } }, { - "name": "adComponents", - "type": "array", - "items": { - "$ref": "InterestGroupAd" - } + "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" - } - ] - }, - { - "id": "SharedStorageReportingMetadata", - "description": "Pair of reporting metadata details for a candidate URL for `selectURL()`.", - "type": "object", - "properties": [ - { - "name": "eventType", - "type": "string" + "name": "debugData", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregatableDebugReportingData" + } }, { - "name": "reportingUrl", + "name": "aggregationCoordinatorOrigin", + "optional": true, "type": "string" } ] }, { - "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.", - "optional": true, - "type": "string" + "name": "priority", + "$ref": "SignedInt64AsBase10" }, { - "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": "filterData", + "type": "array", + "items": { + "$ref": "AttributionReportingFilterDataEntry" + } + }, + { + "name": "aggregationKeys", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregationKeysEntry" + } + }, + { + "name": "debugKey", "optional": true, - "type": "boolean" + "$ref": "UnsignedInt64AsBase10" + }, + { + "name": "triggerDataMatching", + "$ref": "AttributionReportingTriggerDataMatching" + }, + { + "name": "destinationLimitPriority", + "$ref": "SignedInt64AsBase10" + }, + { + "name": "aggregatableDebugReportingConfig", + "$ref": "AttributionReportingAggregatableDebugReportingConfig" } ] }, { - "id": "StorageBucketsDurability", + "id": "AttributionReportingSourceRegistrationResult", + "experimental": true, "type": "string", "enum": [ - "relaxed", - "strict" + "success", + "internalError", + "insufficientSourceCapacity", + "insufficientUniqueDestinationCapacity", + "excessiveReportingOrigins", + "prohibitedByBrowserPolicy", + "successNoised", + "destinationReportingLimitReached", + "destinationGlobalLimitReached", + "destinationBothLimitsReached", + "reportingOriginsPerSiteLimitReached", + "exceedsMaxChannelCapacity", + "exceedsMaxTriggerStateCardinality", + "destinationPerDayReportingLimitReached" ] }, { - "id": "StorageBucket", - "type": "object", - "properties": [ - { - "name": "storageKey", - "$ref": "SerializedStorageKey" - }, - { - "name": "name", - "description": "If not specified, it is the default bucket of the storageKey.", - "optional": true, - "type": "string" - } + "id": "AttributionReportingSourceRegistrationTimeConfig", + "experimental": true, + "type": "string", + "enum": [ + "include", + "exclude" ] }, { - "id": "StorageBucketInfo", + "id": "AttributionReportingAggregatableValueDictEntry", + "experimental": true, "type": "object", "properties": [ { - "name": "bucket", - "$ref": "StorageBucket" - }, - { - "name": "id", + "name": "key", "type": "string" }, { - "name": "expiration", - "$ref": "Network.TimeSinceEpoch" - }, - { - "name": "quota", - "description": "Storage quota (bytes).", + "name": "value", + "description": "number instead of integer because not all uint32 can be represented by\nint", "type": "number" }, { - "name": "persistent", - "type": "boolean" - }, - { - "name": "durability", - "$ref": "StorageBucketsDurability" + "name": "filteringId", + "$ref": "UnsignedInt64AsBase10" } ] }, { - "id": "AttributionReportingSourceType", + "id": "AttributionReportingAggregatableValueEntry", "experimental": true, - "type": "string", - "enum": [ - "navigation", - "event" + "type": "object", + "properties": [ + { + "name": "values", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregatableValueDictEntry" + } + }, + { + "name": "filters", + "$ref": "AttributionReportingFilterPair" + } ] }, { - "id": "UnsignedInt64AsBase10", - "experimental": true, - "type": "string" - }, - { - "id": "UnsignedInt128AsBase16", - "experimental": true, - "type": "string" - }, - { - "id": "SignedInt64AsBase10", + "id": "AttributionReportingEventTriggerData", "experimental": true, - "type": "string" + "type": "object", + "properties": [ + { + "name": "data", + "$ref": "UnsignedInt64AsBase10" + }, + { + "name": "priority", + "$ref": "SignedInt64AsBase10" + }, + { + "name": "dedupKey", + "optional": true, + "$ref": "UnsignedInt64AsBase10" + }, + { + "name": "filters", + "$ref": "AttributionReportingFilterPair" + } + ] }, { - "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": "expiry", - "description": "duration in seconds", - "optional": true, - "type": "integer" - }, - { - "name": "eventReportWindow", - "description": "duration in seconds", - "optional": true, - "type": "integer" + "name": "filters", + "$ref": "AttributionReportingFilterPair" }, { - "name": "aggregatableReportWindow", - "description": "duration in seconds", + "name": "debugKey", "optional": true, - "type": "integer" + "$ref": "UnsignedInt64AsBase10" }, { - "name": "type", - "$ref": "AttributionReportingSourceType" + "name": "aggregatableDedupKeys", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregatableDedupKey" + } }, { - "name": "sourceOrigin", - "type": "string" + "name": "eventTriggerData", + "type": "array", + "items": { + "$ref": "AttributionReportingEventTriggerData" + } }, { - "name": "reportingOrigin", - "type": "string" + "name": "aggregatableTriggerData", + "type": "array", + "items": { + "$ref": "AttributionReportingAggregatableTriggerData" + } }, { - "name": "destinationSites", + "name": "aggregatableValues", "type": "array", "items": { - "type": "string" + "$ref": "AttributionReportingAggregatableValueEntry" } }, { - "name": "eventId", - "$ref": "UnsignedInt64AsBase10" + "name": "aggregatableFilteringIdMaxBytes", + "type": "integer" }, { - "name": "priority", - "$ref": "SignedInt64AsBase10" + "name": "debugReporting", + "type": "boolean" }, { - "name": "filterData", - "type": "array", - "items": { - "$ref": "AttributionReportingFilterDataEntry" - } + "name": "aggregationCoordinatorOrigin", + "optional": true, + "type": "string" }, { - "name": "aggregationKeys", - "type": "array", - "items": { - "$ref": "AttributionReportingAggregationKeysEntry" - } + "name": "sourceRegistrationTimeConfig", + "$ref": "AttributionReportingSourceRegistrationTimeConfig" }, { - "name": "debugKey", + "name": "triggerContextId", "optional": true, - "$ref": "UnsignedInt64AsBase10" + "type": "string" + }, + { + "name": "aggregatableDebugReportingConfig", + "$ref": "AttributionReportingAggregatableDebugReportingConfig" } ] }, { - "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", + "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 +22397,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 +22413,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 +22596,32 @@ "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" + } + } + ] } ], "events": [ @@ -20613,7 +22726,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 +22743,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 +22847,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 +22872,6 @@ }, { "name": "attributionReportingSourceRegistered", - "description": "TODO(crbug.com/1458532): Add other Attribution Reporting events, e.g.\ntrigger registration.", "experimental": true, "parameters": [ { @@ -20696,6 +22883,24 @@ "$ref": "AttributionReportingSourceRegistrationResult" } ] + }, + { + "name": "attributionReportingTriggerRegistered", + "experimental": true, + "parameters": [ + { + "name": "registration", + "$ref": "AttributionReportingTriggerRegistration" + }, + { + "name": "eventLevel", + "$ref": "AttributionReportingEventLevelResult" + }, + { + "name": "aggregatable", + "$ref": "AttributionReportingAggregatableResult" + } + ] } ] }, @@ -21032,6 +23237,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 +23280,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 +23295,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" }, @@ -21192,7 +23398,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": [ { @@ -21210,29 +23416,32 @@ { "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 +23460,6 @@ { "name": "getBrowserContexts", "description": "Returns all browser contexts created with `Target.createBrowserContext` method.", - "experimental": true, "returns": [ { "name": "browserContextIds", @@ -21348,7 +23556,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 +23631,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 +23645,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 +23878,6 @@ }, { "domain": "Tracing", - "experimental": true, "dependencies": [ "IO" ], @@ -21679,6 +23885,7 @@ { "id": "MemoryDumpConfig", "description": "Configuration for memory dump. Used only when \"memory-infra\" category is enabled.", + "experimental": true, "type": "object" }, { @@ -21688,6 +23895,7 @@ { "name": "recordMode", "description": "Controls how the trace buffer stores data.", + "experimental": true, "optional": true, "type": "string", "enum": [ @@ -21700,24 +23908,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 +23954,7 @@ { "name": "syntheticDelays", "description": "Configuration to synthesize the delays in tracing.", + "experimental": true, "optional": true, "type": "array", "items": { @@ -21751,6 +23964,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 +23973,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 +23983,7 @@ { "id": "StreamCompression", "description": "Compression type to use for traces returned via streams.", + "experimental": true, "type": "string", "enum": [ "none", @@ -21777,6 +23993,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 +24004,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 +24021,7 @@ { "name": "getCategories", "description": "Gets supported tracing categories.", + "experimental": true, "returns": [ { "name": "categories", @@ -21817,6 +24036,7 @@ { "name": "recordClockSyncMarker", "description": "Record a clock sync marker in the trace.", + "experimental": true, "parameters": [ { "name": "syncId", @@ -21828,6 +24048,7 @@ { "name": "requestMemoryDump", "description": "Request a global memory dump.", + "experimental": true, "parameters": [ { "name": "deterministic", @@ -21862,6 +24083,7 @@ { "name": "categories", "description": "Category/tag filter", + "experimental": true, "deprecated": true, "optional": true, "type": "string" @@ -21869,6 +24091,7 @@ { "name": "options", "description": "Tracing options", + "experimental": true, "deprecated": true, "optional": true, "type": "string" @@ -21876,6 +24099,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 +24122,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 +24134,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 +24151,7 @@ "events": [ { "name": "bufferUsage", + "experimental": true, "parameters": [ { "name": "percentFull", @@ -21948,6 +24176,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", @@ -22999,8 +25228,20 @@ "type": "boolean" }, { - "name": "isUserVerified", - "description": "Sets whether User Verification succeeds or fails for an authenticator.\nDefaults to false.", + "name": "isUserVerified", + "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 +25286,18 @@ "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" } ] } @@ -23224,6 +25477,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": [ @@ -23666,7 +25943,7 @@ }, { "id": "PreloadingAttemptSource", - "description": "Lists sources for a preloading attempt, specifically the ids of rule sets\nthat had a speculation rule that triggered the attempt, and the\nBackendNodeIds of or elements that triggered the\nattempt (in the case of attempts triggered by a document rule). It is\npossible for mulitple rule sets and links to trigger a single attempt.", + "description": "Lists sources for a preloading attempt, specifically the ids of rule sets\nthat had a speculation rule that triggered the attempt, and the\nBackendNodeIds of or elements that triggered the\nattempt (in the case of attempts triggered by a document rule). It is\npossible for multiple rule sets and links to trigger a single attempt.", "type": "object", "properties": [ { @@ -23699,7 +25976,6 @@ "LowEndDevice", "InvalidSchemeRedirect", "InvalidSchemeNavigation", - "InProgressNavigation", "NavigationRequestBlockedByCsp", "MainFrameNavigation", "MojoBinderPolicy", @@ -23711,7 +25987,6 @@ "NavigationBadHttpStatus", "ClientCertRequested", "NavigationRequestNetworkError", - "MaxNumOfRunningPrerendersExceeded", "CancelAllHostsForTesting", "DidFailLoad", "Stop", @@ -23723,9 +25998,8 @@ "MixedContent", "TriggerBackgrounded", "MemoryLimitExceeded", - "FailToGetMemoryUsage", "DataSaverEnabled", - "HasEffectiveUrl", + "TriggerUrlHasEffectiveUrl", "ActivatedBeforeStarted", "InactivePageRestriction", "StartFailed", @@ -23754,9 +26028,20 @@ "MemoryPressureOnTrigger", "MemoryPressureAfterTriggered", "PrerenderingDisabledByDevTools", - "ResourceLoadBlockedByClient", "SpeculationRuleRemoved", - "ActivatedWithAuxiliaryBrowsingContexts" + "ActivatedWithAuxiliaryBrowsingContexts", + "MaxNumOfRunningEagerPrerendersExceeded", + "MaxNumOfRunningNonEagerPrerendersExceeded", + "MaxNumOfRunningEmbedderPrerendersExceeded", + "PrerenderingUrlHasEffectiveUrl", + "RedirectedPrerenderingUrlHasEffectiveUrl", + "ActivationUrlHasEffectiveUrl", + "JavaScriptInterfaceAdded", + "JavaScriptInterfaceRemoved", + "AllPrerenderingCanceled", + "WindowClosed", + "SlowNetwork", + "OtherPrerenderedPageActivated" ] }, { @@ -23784,7 +26069,8 @@ "PrefetchFailedNetError", "PrefetchFailedNon2XX", "PrefetchFailedPerPageLimitExceeded", - "PrefetchEvicted", + "PrefetchEvictedAfterCandidateRemoved", + "PrefetchEvictedForNewerPrefetch", "PrefetchHeldback", "PrefetchIneligibleRetryAfter", "PrefetchIsPrivacyDecoy", @@ -23808,6 +26094,27 @@ "PrefetchSuccessfulButNotUsed", "PrefetchNotUsedProbeFailed" ] + }, + { + "id": "PrerenderMismatchedHeaders", + "description": "Information of headers to be displayed when the header mismatch occurred.", + "type": "object", + "properties": [ + { + "name": "headerName", + "type": "string" + }, + { + "name": "initialValue", + "optional": true, + "type": "string" + }, + { + "name": "activationValue", + "optional": true, + "type": "string" + } + ] } ], "commands": [ @@ -23838,35 +26145,6 @@ } ] }, - { - "name": "prerenderAttemptCompleted", - "description": "Fired when a prerender attempt is completed.", - "parameters": [ - { - "name": "key", - "$ref": "PreloadingAttemptKey" - }, - { - "name": "initiatingFrameId", - "description": "The frame id of the frame initiating prerendering.", - "$ref": "Page.FrameId" - }, - { - "name": "prerenderingUrl", - "type": "string" - }, - { - "name": "finalStatus", - "$ref": "PrerenderFinalStatus" - }, - { - "name": "disallowedApiMethod", - "description": "This is used to give users more information about the name of the API call\nthat is incompatible with prerender and has caused the cancellation of the attempt", - "optional": true, - "type": "string" - } - ] - }, { "name": "preloadEnabledStateUpdated", "description": "Fired when a preload enabled state is updated.", @@ -23946,6 +26224,14 @@ "description": "This is used to give users more information about the name of Mojo interface\nthat is incompatible with prerender and has caused the cancellation of the attempt.", "optional": true, "type": "string" + }, + { + "name": "mismatchedHeaders", + "optional": true, + "type": "array", + "items": { + "$ref": "PrerenderMismatchedHeaders" + } } ] }, @@ -23984,11 +26270,32 @@ }, { "id": "DialogType", - "description": "Whether the dialog shown is an account chooser or an auto re-authentication dialog.", + "description": "The types of FedCM dialogs.", "type": "string", "enum": [ "AccountChooser", - "AutoReauthn" + "AutoReauthn", + "ConfirmIdpLogin", + "Error" + ] + }, + { + "id": "DialogButton", + "description": "The buttons on the FedCM dialog.", + "type": "string", + "enum": [ + "ConfirmIdpLoginContinue", + "ErrorGotIt", + "ErrorMoreDetails" + ] + }, + { + "id": "AccountUrlType", + "description": "The URLs that each account has", + "type": "string", + "enum": [ + "TermsOfService", + "PrivacyPolicy" ] }, { @@ -24021,7 +26328,7 @@ "type": "string" }, { - "name": "idpSigninUrl", + "name": "idpLoginUrl", "type": "string" }, { @@ -24072,6 +26379,16 @@ "type": "string" } ] + }, + { + "name": "dialogClosed", + "description": "Triggered when a dialog is closed, either by user action, JS abort,\nor a command below.", + "parameters": [ + { + "name": "dialogId", + "type": "string" + } + ] } ], "commands": [ @@ -24102,6 +26419,36 @@ } ] }, + { + "name": "clickDialogButton", + "parameters": [ + { + "name": "dialogId", + "type": "string" + }, + { + "name": "dialogButton", + "$ref": "DialogButton" + } + ] + }, + { + "name": "openUrl", + "parameters": [ + { + "name": "dialogId", + "type": "string" + }, + { + "name": "accountIndex", + "type": "integer" + }, + { + "name": "accountUrlType", + "$ref": "AccountUrlType" + } + ] + }, { "name": "dismissDialog", "parameters": [ @@ -24121,6 +26468,194 @@ "description": "Resets the cooldown time, if any, to allow the next FedCM call to show\na dialog even if one was recently dismissed by the user." } ] + }, + { + "domain": "PWA", + "description": "This domain allows interacting with the browser to control PWAs.", + "experimental": true, + "types": [ + { + "id": "FileHandlerAccept", + "description": "The following types are the replica of\nhttps://crsrc.org/c/chrome/browser/web_applications/proto/web_app_os_integration_state.proto;drc=9910d3be894c8f142c977ba1023f30a656bc13fc;l=67", + "type": "object", + "properties": [ + { + "name": "mediaType", + "description": "New name of the mimetype according to\nhttps://www.iana.org/assignments/media-types/media-types.xhtml", + "type": "string" + }, + { + "name": "fileExtensions", + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + { + "id": "FileHandler", + "type": "object", + "properties": [ + { + "name": "action", + "type": "string" + }, + { + "name": "accepts", + "type": "array", + "items": { + "$ref": "FileHandlerAccept" + } + }, + { + "name": "displayName", + "type": "string" + } + ] + }, + { + "id": "DisplayMode", + "description": "If user prefers opening the app in browser or an app window.", + "type": "string", + "enum": [ + "standalone", + "browser" + ] + } + ], + "commands": [ + { + "name": "getOsAppState", + "description": "Returns the following OS state for the given manifest id.", + "parameters": [ + { + "name": "manifestId", + "description": "The id from the webapp's manifest file, commonly it's the url of the\nsite installing the webapp. See\nhttps://web.dev/learn/pwa/web-app-manifest.", + "type": "string" + } + ], + "returns": [ + { + "name": "badgeCount", + "type": "integer" + }, + { + "name": "fileHandlers", + "type": "array", + "items": { + "$ref": "FileHandler" + } + } + ] + }, + { + "name": "install", + "description": "Installs the given manifest identity, optionally using the given install_url\nor IWA bundle location.\n\nTODO(crbug.com/337872319) Support IWA to meet the following specific\nrequirement.\nIWA-specific install description: If the manifest_id is isolated-app://,\ninstall_url_or_bundle_url is required, and can be either an http(s) URL or\nfile:// URL pointing to a signed web bundle (.swbn). The .swbn file's\nsigning key must correspond to manifest_id. If Chrome is not in IWA dev\nmode, the installation will fail, regardless of the state of the allowlist.", + "parameters": [ + { + "name": "manifestId", + "type": "string" + }, + { + "name": "installUrlOrBundleUrl", + "description": "The location of the app or bundle overriding the one derived from the\nmanifestId.", + "optional": true, + "type": "string" + } + ] + }, + { + "name": "uninstall", + "description": "Uninstalls the given manifest_id and closes any opened app windows.", + "parameters": [ + { + "name": "manifestId", + "type": "string" + } + ] + }, + { + "name": "launch", + "description": "Launches the installed web app, or an url in the same web app instead of the\ndefault start url if it is provided. Returns a page Target.TargetID which\ncan be used to attach to via Target.attachToTarget or similar APIs.", + "parameters": [ + { + "name": "manifestId", + "type": "string" + }, + { + "name": "url", + "optional": true, + "type": "string" + } + ], + "returns": [ + { + "name": "targetId", + "description": "ID of the tab target created as a result.", + "$ref": "Target.TargetID" + } + ] + }, + { + "name": "launchFilesInApp", + "description": "Opens one or more local files from an installed web app identified by its\nmanifestId. The web app needs to have file handlers registered to process\nthe files. The API returns one or more page Target.TargetIDs which can be\nused to attach to via Target.attachToTarget or similar APIs.\nIf some files in the parameters cannot be handled by the web app, they will\nbe ignored. If none of the files can be handled, this API returns an error.\nIf no files are provided as the parameter, this API also returns an error.\n\nAccording to the definition of the file handlers in the manifest file, one\nTarget.TargetID may represent a page handling one or more files. The order\nof the returned Target.TargetIDs is not guaranteed.\n\nTODO(crbug.com/339454034): Check the existences of the input files.", + "parameters": [ + { + "name": "manifestId", + "type": "string" + }, + { + "name": "files", + "type": "array", + "items": { + "type": "string" + } + } + ], + "returns": [ + { + "name": "targetIds", + "description": "IDs of the tab targets created as the result.", + "type": "array", + "items": { + "$ref": "Target.TargetID" + } + } + ] + }, + { + "name": "openCurrentPageInApp", + "description": "Opens the current page in its web app identified by the manifest id, needs\nto be called on a page target. This function returns immediately without\nwaiting for the app to finish loading.", + "parameters": [ + { + "name": "manifestId", + "type": "string" + } + ] + }, + { + "name": "changeAppUserSettings", + "description": "Changes user settings of the web app identified by its manifestId. If the\napp was not installed, this command returns an error. Unset parameters will\nbe ignored; unrecognized values will cause an error.\n\nUnlike the ones defined in the manifest files of the web apps, these\nsettings are provided by the browser and controlled by the users, they\nimpact the way the browser handling the web apps.\n\nSee the comment of each parameter.", + "parameters": [ + { + "name": "manifestId", + "type": "string" + }, + { + "name": "linkCapturing", + "description": "If user allows the links clicked on by the user in the app's scope, or\nextended scope if the manifest has scope extensions and the flags\n`DesktopPWAsLinkCapturingWithScopeExtensions` and\n`WebAppEnableScopeExtensions` are enabled.\n\nNote, the API does not support resetting the linkCapturing to the\ninitial value, uninstalling and installing the web app again will reset\nit.\n\nTODO(crbug.com/339453269): Setting this value on ChromeOS is not\nsupported yet.", + "optional": true, + "type": "boolean" + }, + { + "name": "displayMode", + "optional": true, + "$ref": "DisplayMode" + } + ] + } + ] } ] } \ No newline at end of file diff --git a/pycdp/gen/js_protocol.json b/pycdp/gen/js_protocol.json index 18587d7..d2207ea 100644 --- a/pycdp/gen/js_protocol.json +++ b/pycdp/gen/js_protocol.json @@ -2163,7 +2163,7 @@ }, { "id": "SerializationOptions", - "description": "Represents options for serialization. Overrides `generatePreview`, `returnByValue` and\n`generateWebDriverValue`.", + "description": "Represents options for serialization. Overrides `generatePreview` and `returnByValue`.", "type": "object", "properties": [ { @@ -2220,7 +2220,8 @@ "typedarray", "arraybuffer", "node", - "window" + "window", + "generator" ] }, { @@ -2322,13 +2323,6 @@ "optional": true, "type": "string" }, - { - "name": "webDriverValue", - "description": "Deprecated. Use `deepSerializedValue` instead. WebDriver BiDi representation of the value.", - "deprecated": true, - "optional": true, - "$ref": "DeepSerializedValue" - }, { "name": "deepSerializedValue", "description": "Deep serialized value.", @@ -2997,16 +2991,9 @@ "optional": true, "type": "string" }, - { - "name": "generateWebDriverValue", - "description": "Deprecated. Use `serializationOptions: {serialization:\"deep\"}` instead.\nWhether the result should contain `webDriverValue`, serialized according to\nhttps://w3c.github.io/webdriver-bidi. This is mutually exclusive with `returnByValue`, but\nresulting `objectId` is still provided.", - "deprecated": true, - "optional": true, - "type": "boolean" - }, { "name": "serializationOptions", - "description": "Specifies the result serialization. If provided, overrides\n`generatePreview`, `returnByValue` and `generateWebDriverValue`.", + "description": "Specifies the result serialization. If provided, overrides\n`generatePreview` and `returnByValue`.", "experimental": true, "optional": true, "$ref": "SerializationOptions" @@ -3179,16 +3166,9 @@ "optional": true, "type": "string" }, - { - "name": "generateWebDriverValue", - "description": "Deprecated. Use `serializationOptions: {serialization:\"deep\"}` instead.\nWhether the result should contain `webDriverValue`, serialized\naccording to\nhttps://w3c.github.io/webdriver-bidi. This is mutually exclusive with `returnByValue`, but\nresulting `objectId` is still provided.", - "deprecated": true, - "optional": true, - "type": "boolean" - }, { "name": "serializationOptions", - "description": "Specifies the result serialization. If provided, overrides\n`generatePreview`, `returnByValue` and `generateWebDriverValue`.", + "description": "Specifies the result serialization. If provided, overrides\n`generatePreview` and `returnByValue`.", "experimental": true, "optional": true, "$ref": "SerializationOptions" @@ -3486,7 +3466,6 @@ { "name": "addBinding", "description": "If executionContextId is empty, adds binding with the given name on the\nglobal objects of all inspected contexts, including those created later,\nbindings survive reloads.\nBinding function takes exactly one argument, this argument should be string,\nin case of any other input, function throws an exception.\nEach binding function call produces Runtime.bindingCalled notification.", - "experimental": true, "parameters": [ { "name": "name", @@ -3495,6 +3474,7 @@ { "name": "executionContextId", "description": "If specified, the binding would only be exposed to the specified\nexecution context. If omitted and `executionContextName` is not set,\nthe binding is exposed to all execution contexts of the target.\nThis parameter is mutually exclusive with `executionContextName`.\nDeprecated in favor of `executionContextName` due to an unclear use case\nand bugs in implementation (crbug.com/1169639). `executionContextId` will be\nremoved in the future.", + "experimental": true, "deprecated": true, "optional": true, "$ref": "ExecutionContextId" @@ -3502,7 +3482,6 @@ { "name": "executionContextName", "description": "If specified, the binding is exposed to the executionContext with\nmatching name, even for contexts created after the binding is added.\nSee also `ExecutionContext.name` and `worldName` parameter to\n`Page.addScriptToEvaluateOnNewDocument`.\nThis parameter is mutually exclusive with `executionContextId`.", - "experimental": true, "optional": true, "type": "string" } @@ -3511,7 +3490,6 @@ { "name": "removeBinding", "description": "This method does not remove binding function from global object but\nunsubscribes current runtime agent from Runtime.bindingCalled notifications.", - "experimental": true, "parameters": [ { "name": "name", From 1a1728d00f3967dc227d75a567682daf857fb429 Mon Sep 17 00:00:00 2001 From: Razvan Pricop <22615594+RazorBest@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:50:58 +0200 Subject: [PATCH 2/5] feat: update cdp protocol to r1358005 --- docs/api/bluetooth_emulation.rst | 66 +++++ docs/api/dom.rst | 12 + docs/api/extensions.rst | 6 + docs/api/memory.rst | 7 + docs/api/page.rst | 5 + docs/api/storage.rst | 5 + pycdp/cdp/__init__.py | 2 +- pycdp/cdp/audits.py | 3 + pycdp/cdp/bluetooth_emulation.py | 198 +++++++++++++++ pycdp/cdp/browser.py | 1 + pycdp/cdp/dom.py | 73 ++++++ pycdp/cdp/emulation.py | 1 - pycdp/cdp/extensions.py | 69 +++++- pycdp/cdp/memory.py | 46 +++- pycdp/cdp/network.py | 2 +- pycdp/cdp/overlay.py | 5 +- pycdp/cdp/page.py | 35 ++- pycdp/cdp/preload.py | 1 - pycdp/cdp/storage.py | 37 +++ pycdp/gen/browser_protocol.json | 399 ++++++++++++++++++++++++++++++- 20 files changed, 951 insertions(+), 22 deletions(-) create mode 100644 docs/api/bluetooth_emulation.rst create mode 100644 pycdp/cdp/bluetooth_emulation.py diff --git a/docs/api/bluetooth_emulation.rst b/docs/api/bluetooth_emulation.rst new file mode 100644 index 0000000..27bfbd2 --- /dev/null +++ b/docs/api/bluetooth_emulation.rst @@ -0,0 +1,66 @@ +BluetoothEmulation +================== + +This domain allows configuring virtual Bluetooth devices to test +the web-bluetooth API. + +*This CDP domain is experimental.* + +.. module:: cdp.bluetooth_emulation + +* 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:: CentralState + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: ManufacturerData + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: ScanRecord + :members: + :undoc-members: + :exclude-members: from_json, to_json + +.. autoclass:: ScanEntry + :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:: disable + +.. autofunction:: enable + +.. autofunction:: simulate_advertisement + +.. autofunction:: simulate_preconnected_peripheral + +Events +------ + +*There are no events in this module.* diff --git a/docs/api/dom.rst b/docs/api/dom.rst index 2b3d468..544e221 100644 --- a/docs/api/dom.rst +++ b/docs/api/dom.rst @@ -73,6 +73,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: DetachedElementInfo + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: RGBA :members: :undoc-members: @@ -139,6 +144,8 @@ to. For more information, see .. autofunction:: get_content_quads +.. autofunction:: get_detached_dom_nodes + .. autofunction:: get_document .. autofunction:: get_element_by_relation @@ -279,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/extensions.rst b/docs/api/extensions.rst index e0943bf..13572df 100644 --- a/docs/api/extensions.rst +++ b/docs/api/extensions.rst @@ -36,10 +36,16 @@ 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 + Events ------ 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/page.rst b/docs/api/page.rst index c50d044..9e9f741 100644 --- a/docs/api/page.rst +++ b/docs/api/page.rst @@ -476,6 +476,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: diff --git a/docs/api/storage.rst b/docs/api/storage.rst index 822cc06..894fd8c 100644 --- a/docs/api/storage.rst +++ b/docs/api/storage.rst @@ -167,6 +167,11 @@ arguments to other commands. :undoc-members: :exclude-members: from_json, to_json +.. autoclass:: AttributionScopesData + :members: + :undoc-members: + :exclude-members: from_json, to_json + .. autoclass:: AttributionReportingSourceRegistration :members: :undoc-members: diff --git a/pycdp/cdp/__init__.py b/pycdp/cdp/__init__.py index d0cc11a..4476c87 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, 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 +from . import (accessibility, animation, audits, autofill, background_service, bluetooth_emulation, browser, css, cache_storage, cast, console, dom, dom_debugger, dom_snapshot, dom_storage, database, 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/audits.py b/pycdp/cdp/audits.py index 83e81bd..a65d9d0 100644 --- a/pycdp/cdp/audits.py +++ b/pycdp/cdp/audits.py @@ -121,6 +121,8 @@ class CookieWarningReason(enum.Enum): 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 @@ -651,6 +653,7 @@ class AttributionReportingIssueType(enum.Enum): 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 diff --git a/pycdp/cdp/bluetooth_emulation.py b/pycdp/cdp/bluetooth_emulation.py new file mode 100644 index 0000000..9f36e41 --- /dev/null +++ b/pycdp/cdp/bluetooth_emulation.py @@ -0,0 +1,198 @@ +# 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 + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Enable the BluetoothEmulation domain. + + :param state: State of the simulated central. + ''' + params: T_JSON_DICT = dict() + params['state'] = state.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'BluetoothEmulation.enable', + '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 696d33c..8eea1cf 100644 --- a/pycdp/cdp/browser.py +++ b/pycdp/cdp/browser.py @@ -130,6 +130,7 @@ class PermissionType(enum.Enum): VIDEO_CAPTURE_PAN_TILT_ZOOM = "videoCapturePanTiltZoom" WAKE_LOCK_SCREEN = "wakeLockScreen" WAKE_LOCK_SYSTEM = "wakeLockSystem" + WEB_APP_INSTALLATION = "webAppInstallation" WINDOW_MANAGEMENT = "windowManagement" def to_json(self) -> str: diff --git a/pycdp/cdp/dom.py b/pycdp/cdp/dom.py index 7a75d93..83a0038 100644 --- a/pycdp/cdp/dom.py +++ b/pycdp/cdp/dom.py @@ -86,6 +86,7 @@ class PseudoType(enum.Enum): AFTER = "after" MARKER = "marker" BACKDROP = "backdrop" + COLUMN = "column" SELECTION = "selection" SEARCH_TEXT = "search-text" TARGET_TEXT = "target-text" @@ -95,6 +96,8 @@ class PseudoType(enum.Enum): FIRST_LINE_INHERITED = "first-line-inherited" SCROLL_MARKER = "scroll-marker" SCROLL_MARKER_GROUP = "scroll-marker-group" + SCROLL_NEXT_BUTTON = "scroll-next-button" + SCROLL_PREV_BUTTON = "scroll-prev-button" SCROLLBAR = "scrollbar" SCROLLBAR_THUMB = "scrollbar-thumb" SCROLLBAR_BUTTON = "scrollbar-button" @@ -108,6 +111,12 @@ 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" + SELECT_FALLBACK_BUTTON = "select-fallback-button" + SELECT_FALLBACK_BUTTON_TEXT = "select-fallback-button-text" + PICKER = "picker" def to_json(self) -> str: return self.value @@ -298,6 +307,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() @@ -356,6 +367,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 @@ -392,6 +405,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']], ) @@ -1548,6 +1585,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]: @@ -1965,6 +2017,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/emulation.py b/pycdp/cdp/emulation.py index 07f9e8d..00a71c1 100644 --- a/pycdp/cdp/emulation.py +++ b/pycdp/cdp/emulation.py @@ -226,7 +226,6 @@ class SensorType(enum.Enum): GYROSCOPE = "gyroscope" LINEAR_ACCELERATION = "linear-acceleration" MAGNETOMETER = "magnetometer" - PROXIMITY = "proximity" RELATIVE_ORIENTATION = "relative-orientation" def to_json(self) -> str: diff --git a/pycdp/cdp/extensions.py b/pycdp/cdp/extensions.py index 757c2fd..d526a65 100644 --- a/pycdp/cdp/extensions.py +++ b/pycdp/cdp/extensions.py @@ -58,7 +58,7 @@ def get_storage_items( keys: typing.Optional[typing.List[str]] = None ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,dict]: ''' - Gets data from extension storage in the given ``area``. If ``keys`` is + 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. @@ -77,3 +77,70 @@ def get_storage_items( } 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/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 d25e359..7c8e84d 100644 --- a/pycdp/cdp/network.py +++ b/pycdp/cdp/network.py @@ -1447,11 +1447,11 @@ class CookieExemptionReason(enum.Enum): 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" - CORS_OPT_IN = "CorsOptIn" SCHEME = "Scheme" def to_json(self) -> str: diff --git a/pycdp/cdp/overlay.py b/pycdp/cdp/overlay.py index a76c523..11cf041 100644 --- a/pycdp/cdp/overlay.py +++ b/pycdp/cdp/overlay.py @@ -1242,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: ''' diff --git a/pycdp/cdp/page.py b/pycdp/cdp/page.py index 0314455..4125058 100644 --- a/pycdp/cdp/page.py +++ b/pycdp/cdp/page.py @@ -202,10 +202,12 @@ 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" 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" @@ -231,6 +233,7 @@ class PermissionsPolicyFeature(enum.Enum): 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" @@ -251,6 +254,7 @@ class PermissionsPolicyFeature(enum.Enum): 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" @@ -1117,14 +1121,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 @@ -1796,6 +1802,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" @@ -3394,6 +3401,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: @@ -3754,12 +3780,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/preload.py b/pycdp/cdp/preload.py index 4de6806..549fb8b 100644 --- a/pycdp/cdp/preload.py +++ b/pycdp/cdp/preload.py @@ -332,7 +332,6 @@ 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_AFTER_CANDIDATE_REMOVED = "PrefetchEvictedAfterCandidateRemoved" PREFETCH_EVICTED_FOR_NEWER_PREFETCH = "PrefetchEvictedForNewerPrefetch" PREFETCH_HELDBACK = "PrefetchHeldback" diff --git a/pycdp/cdp/storage.py b/pycdp/cdp/storage.py index 824b594..b73b8a5 100644 --- a/pycdp/cdp/storage.py +++ b/pycdp/cdp/storage.py @@ -715,6 +715,32 @@ def from_json(cls, json: T_JSON_DICT) -> AttributionReportingAggregatableDebugRe ) +@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 @@ -751,6 +777,8 @@ class AttributionReportingSourceRegistration: 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() @@ -770,6 +798,8 @@ def to_json(self) -> T_JSON_DICT: json['aggregatableDebugReportingConfig'] = self.aggregatable_debug_reporting_config.to_json() 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 @@ -791,6 +821,7 @@ def from_json(cls, json: T_JSON_DICT) -> AttributionReportingSourceRegistration: destination_limit_priority=SignedInt64AsBase10.from_json(json['destinationLimitPriority']), aggregatable_debug_reporting_config=AttributionReportingAggregatableDebugReportingConfig.from_json(json['aggregatableDebugReportingConfig']), 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, ) @@ -807,7 +838,9 @@ 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: @@ -970,6 +1003,8 @@ class AttributionReportingTriggerRegistration: aggregatable_debug_reporting_config: AttributionReportingAggregatableDebugReportingConfig + scopes: typing.List[str] + debug_key: typing.Optional[UnsignedInt64AsBase10] = None aggregation_coordinator_origin: typing.Optional[str] = None @@ -987,6 +1022,7 @@ def to_json(self) -> T_JSON_DICT: 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: @@ -1007,6 +1043,7 @@ def from_json(cls, json: T_JSON_DICT) -> AttributionReportingTriggerRegistration 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, diff --git a/pycdp/gen/browser_protocol.json b/pycdp/gen/browser_protocol.json index 4776c1c..cb3c54c 100644 --- a/pycdp/gen/browser_protocol.json +++ b/pycdp/gen/browser_protocol.json @@ -1066,7 +1066,9 @@ "WarnAttributeValueExceedsMaxSize", "WarnDomainNonASCII", "WarnThirdPartyPhaseout", - "WarnCrossSiteRedirectDowngradeChangesInclusion" + "WarnCrossSiteRedirectDowngradeChangesInclusion", + "WarnDeprecationTrialMetadata", + "WarnThirdPartyCookieHeuristic" ] }, { @@ -1487,7 +1489,8 @@ "NoRegisterSourceHeader", "NoRegisterTriggerHeader", "NoRegisterOsSourceHeader", - "NoRegisterOsTriggerHeader" + "NoRegisterOsTriggerHeader", + "NavigationRegistrationUniqueScopeAlreadySet" ] }, { @@ -2213,7 +2216,7 @@ }, { "name": "getStorageItems", - "description": "Gets data from extension storage in the given `area`. If `keys` is\nspecified, these are used to filter the result.", + "description": "Gets data from extension storage in the given `storageArea`. If `keys` is\nspecified, these are used to filter the result.", "parameters": [ { "name": "id", @@ -2241,6 +2244,67 @@ "type": "object" } ] + }, + { + "name": "removeStorageItems", + "description": "Removes `keys` from 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": "keys", + "description": "Keys to remove.", + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + { + "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" + } + ] } ] }, @@ -2715,6 +2779,7 @@ "videoCapturePanTiltZoom", "wakeLockScreen", "wakeLockSystem", + "webAppInstallation", "windowManagement" ] }, @@ -5594,6 +5659,7 @@ "after", "marker", "backdrop", + "column", "selection", "search-text", "target-text", @@ -5603,6 +5669,8 @@ "first-line-inherited", "scroll-marker", "scroll-marker-group", + "scroll-next-button", + "scroll-prev-button", "scrollbar", "scrollbar-thumb", "scrollbar-button", @@ -5615,7 +5683,13 @@ "view-transition-group", "view-transition-image-pair", "view-transition-old", - "view-transition-new" + "view-transition-new", + "placeholder", + "file-selector-button", + "details-content", + "select-fallback-button", + "select-fallback-button-text", + "picker" ] }, { @@ -5865,6 +5939,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" + } } ] }, @@ -6956,6 +7054,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).", @@ -7302,6 +7415,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.", @@ -9038,7 +9168,6 @@ "gyroscope", "linear-acceleration", "magnetometer", - "proximity", "relative-orientation" ] }, @@ -12047,11 +12176,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", @@ -12068,7 +12215,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", @@ -13348,11 +13510,11 @@ "UserSetting", "TPCDMetadata", "TPCDDeprecationTrial", + "TopLevelTPCDDeprecationTrial", "TPCDHeuristics", "EnterprisePolicy", "StorageAccess", "TopLevelStorageAccess", - "CorsOptIn", "Scheme" ] }, @@ -16779,7 +16941,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", @@ -17026,10 +17189,12 @@ "clipboard-read", "clipboard-write", "compute-pressure", + "controlled-frame", "cross-origin-isolated", "deferred-fetch", "digital-credentials-get", "direct-sockets", + "direct-sockets-private", "display-capture", "document-domain", "encrypted-media", @@ -17055,6 +17220,7 @@ "otp-credentials", "payment", "picture-in-picture", + "popins", "private-aggregation", "private-state-token-issuance", "private-state-token-redemption", @@ -17075,6 +17241,7 @@ "usb", "usb-unrestricted", "vertical-scroll", + "web-app-installation", "web-printing", "web-share", "window-management", @@ -17785,14 +17952,16 @@ "experimental": true, "type": "string", "enum": [ + "anchorClick", "formSubmissionGet", "formSubmissionPost", "httpHeaderRefresh", - "scriptInitiated", + "initialFrameNavigation", "metaTagRefresh", + "other", "pageBlockInterstitial", "reload", - "anchorClick" + "scriptInitiated" ] }, { @@ -18397,6 +18566,7 @@ "ContentWebUSB", "ContentMediaSessionService", "ContentScreenReader", + "ContentDiscarded", "EmbedderPopupBlockerTabHelper", "EmbedderSafeBrowsingTriggeredPopupBlocker", "EmbedderSafeBrowsingThreatDetails", @@ -19837,6 +20007,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.", @@ -20142,6 +20324,16 @@ "name": "url", "description": "Frame's new url.", "type": "string" + }, + { + "name": "navigationType", + "description": "Navigation type", + "type": "string", + "enum": [ + "fragment", + "historyApi", + "other" + ] } ] }, @@ -21737,6 +21929,29 @@ } ] }, + { + "id": "AttributionScopesData", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "values", + "type": "array", + "items": { + "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": "AttributionReportingSourceRegistration", "experimental": true, @@ -21820,6 +22035,11 @@ { "name": "aggregatableDebugReportingConfig", "$ref": "AttributionReportingAggregatableDebugReportingConfig" + }, + { + "name": "scopesData", + "optional": true, + "$ref": "AttributionScopesData" } ] }, @@ -21840,7 +22060,9 @@ "destinationBothLimitsReached", "reportingOriginsPerSiteLimitReached", "exceedsMaxChannelCapacity", + "exceedsMaxScopesChannelCapacity", "exceedsMaxTriggerStateCardinality", + "exceedsMaxEventStatesLimit", "destinationPerDayReportingLimitReached" ] }, @@ -22020,6 +22242,13 @@ { "name": "aggregatableDebugReportingConfig", "$ref": "AttributionReportingAggregatableDebugReportingConfig" + }, + { + "name": "scopes", + "type": "array", + "items": { + "type": "string" + } } ] }, @@ -26068,7 +26297,6 @@ "PrefetchFailedMIMENotSupported", "PrefetchFailedNetError", "PrefetchFailedNon2XX", - "PrefetchFailedPerPageLimitExceeded", "PrefetchEvictedAfterCandidateRemoved", "PrefetchEvictedForNewerPrefetch", "PrefetchHeldback", @@ -26656,6 +26884,155 @@ ] } ] + }, + { + "domain": "BluetoothEmulation", + "description": "This domain allows configuring virtual Bluetooth devices to test\nthe web-bluetooth API.", + "experimental": true, + "types": [ + { + "id": "CentralState", + "description": "Indicates the various states of Central.", + "type": "string", + "enum": [ + "absent", + "powered-off", + "powered-on" + ] + }, + { + "id": "ManufacturerData", + "description": "Stores the manufacturer data", + "type": "object", + "properties": [ + { + "name": "key", + "description": "Company identifier\nhttps://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/company_identifiers/company_identifiers.yaml\nhttps://usb.org/developers", + "type": "integer" + }, + { + "name": "data", + "description": "Manufacturer-specific data (Encoded as a base64 string when passed over JSON)", + "type": "string" + } + ] + }, + { + "id": "ScanRecord", + "description": "Stores the byte data of the advertisement packet sent by a Bluetooth device.", + "type": "object", + "properties": [ + { + "name": "name", + "optional": true, + "type": "string" + }, + { + "name": "uuids", + "optional": true, + "type": "array", + "items": { + "type": "string" + } + }, + { + "name": "appearance", + "description": "Stores the external appearance description of the device.", + "optional": true, + "type": "integer" + }, + { + "name": "txPower", + "description": "Stores the transmission power of a broadcasting device.", + "optional": true, + "type": "integer" + }, + { + "name": "manufacturerData", + "description": "Key is the company identifier and the value is an array of bytes of\nmanufacturer specific data.", + "optional": true, + "type": "array", + "items": { + "$ref": "ManufacturerData" + } + } + ] + }, + { + "id": "ScanEntry", + "description": "Stores the advertisement packet information that is sent by a Bluetooth device.", + "type": "object", + "properties": [ + { + "name": "deviceAddress", + "type": "string" + }, + { + "name": "rssi", + "type": "integer" + }, + { + "name": "scanRecord", + "$ref": "ScanRecord" + } + ] + } + ], + "commands": [ + { + "name": "enable", + "description": "Enable the BluetoothEmulation domain.", + "parameters": [ + { + "name": "state", + "description": "State of the simulated central.", + "$ref": "CentralState" + } + ] + }, + { + "name": "disable", + "description": "Disable the BluetoothEmulation domain." + }, + { + "name": "simulatePreconnectedPeripheral", + "description": "Simulates a peripheral with |address|, |name| and |knownServiceUuids|\nthat has already been connected to the system.", + "parameters": [ + { + "name": "address", + "type": "string" + }, + { + "name": "name", + "type": "string" + }, + { + "name": "manufacturerData", + "type": "array", + "items": { + "$ref": "ManufacturerData" + } + }, + { + "name": "knownServiceUuids", + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + { + "name": "simulateAdvertisement", + "description": "Simulates an advertisement packet described in |entry| being received by\nthe central.", + "parameters": [ + { + "name": "entry", + "$ref": "ScanEntry" + } + ] + } + ] } ] } \ No newline at end of file From 96cea6cb2a99dd155fd94b9c522749c1a1ab2654 Mon Sep 17 00:00:00 2001 From: Serply <59339358+googio@users.noreply.github.com> Date: Sat, 8 Feb 2025 09:54:39 -0500 Subject: [PATCH 3/5] update poetry to support latest python --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 81c4147..af6acc1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ authors = [ ] [tool.poetry.dependencies] -python = "^3.8, <3.12" +python = ">=3.8,<4.0.0" deprecated = "^1.2.9" inflection = "^0.4.0" aiohttp = "^3.8.3" From 8bd3c097d4ca8d32eef182240e9e0e9f1cf7afdd Mon Sep 17 00:00:00 2001 From: Serply <59339358+googio@users.noreply.github.com> Date: Sat, 8 Feb 2025 10:59:21 -0500 Subject: [PATCH 4/5] add bluetooth_emulation --- pycdp/cdp/bluetooth_emulation.py | 198 +++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 pycdp/cdp/bluetooth_emulation.py diff --git a/pycdp/cdp/bluetooth_emulation.py b/pycdp/cdp/bluetooth_emulation.py new file mode 100644 index 0000000..a66925e --- /dev/null +++ b/pycdp/cdp/bluetooth_emulation.py @@ -0,0 +1,198 @@ +# 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 + ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]: + ''' + Enable the BluetoothEmulation domain. + + :param state: State of the simulated central. + ''' + params: T_JSON_DICT = dict() + params['state'] = state.to_json() + cmd_dict: T_JSON_DICT = { + 'method': 'BluetoothEmulation.enable', + '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 \ No newline at end of file From c59a838a31095535f8b4eb1884a94fd355096e97 Mon Sep 17 00:00:00 2001 From: Serply <59339358+googio@users.noreply.github.com> Date: Sat, 8 Feb 2025 11:36:33 -0500 Subject: [PATCH 5/5] one speaker selection --- pycdp/cdp/browser.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pycdp/cdp/browser.py b/pycdp/cdp/browser.py index 0517e99..51ab52b 100644 --- a/pycdp/cdp/browser.py +++ b/pycdp/cdp/browser.py @@ -130,7 +130,6 @@ class PermissionType(enum.Enum): SMART_CARD = "smartCard" SPEAKER_SELECTION = "speakerSelection" STORAGE_ACCESS = "storageAccess" - SPEAKER_SELECTION = "speakerSelection" TOP_LEVEL_STORAGE_ACCESS = "topLevelStorageAccess" VIDEO_CAPTURE = "videoCapture" VR = "vr"