Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cdp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@
import cdp.schema
import cdp.security
import cdp.service_worker
import cdp.smart_card_emulation
import cdp.storage
import cdp.system_info
import cdp.target
import cdp.tethering
import cdp.tracing
import cdp.web_audio
import cdp.web_authn
import cdp.web_mcp
302 changes: 227 additions & 75 deletions cdp/audits.py

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions cdp/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ class PermissionType(enum.Enum):
IDLE_DETECTION = "idleDetection"
KEYBOARD_LOCK = "keyboardLock"
LOCAL_FONTS = "localFonts"
LOCAL_NETWORK = "localNetwork"
LOCAL_NETWORK_ACCESS = "localNetworkAccess"
LOOPBACK_NETWORK = "loopbackNetwork"
MIDI = "midi"
MIDI_SYSEX = "midiSysex"
NFC = "nfc"
Expand Down
245 changes: 138 additions & 107 deletions cdp/css.py

Large diffs are not rendered by default.

68 changes: 67 additions & 1 deletion cdp/dom.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ def __repr__(self):
return 'BackendNodeId({})'.format(super().__repr__())


class StyleSheetId(str):
r'''
Unique identifier for a CSS stylesheet.
'''
def to_json(self) -> str:
return self

@classmethod
def from_json(cls, json: str) -> StyleSheetId:
return cls(json)

def __repr__(self):
return 'StyleSheetId({})'.format(super().__repr__())


@dataclass
class BackendNode:
r'''
Expand Down Expand Up @@ -120,7 +135,6 @@ class PseudoType(enum.Enum):
PICKER = "picker"
PERMISSION_ICON = "permission-icon"
OVERSCROLL_AREA_PARENT = "overscroll-area-parent"
OVERSCROLL_CLIENT_AREA = "overscroll-client-area"

def to_json(self) -> str:
return self.value
Expand Down Expand Up @@ -315,6 +329,10 @@ class Node:

affected_by_starting_styles: typing.Optional[bool] = None

adopted_style_sheets: typing.Optional[typing.List[StyleSheetId]] = None

is_ad_related: typing.Optional[bool] = None

def to_json(self) -> T_JSON_DICT:
json: T_JSON_DICT = dict()
json['nodeId'] = self.node_id.to_json()
Expand Down Expand Up @@ -377,6 +395,10 @@ def to_json(self) -> T_JSON_DICT:
json['isScrollable'] = self.is_scrollable
if self.affected_by_starting_styles is not None:
json['affectedByStartingStyles'] = self.affected_by_starting_styles
if self.adopted_style_sheets is not None:
json['adoptedStyleSheets'] = [i.to_json() for i in self.adopted_style_sheets]
if self.is_ad_related is not None:
json['isAdRelated'] = self.is_ad_related
return json

@classmethod
Expand Down Expand Up @@ -415,6 +437,8 @@ def from_json(cls, json: T_JSON_DICT) -> Node:
assigned_slot=BackendNode.from_json(json['assignedSlot']) if 'assignedSlot' in json else None,
is_scrollable=bool(json['isScrollable']) if 'isScrollable' in json else None,
affected_by_starting_styles=bool(json['affectedByStartingStyles']) if 'affectedByStartingStyles' in json else None,
adopted_style_sheets=[StyleSheetId.from_json(i) for i in json['adoptedStyleSheets']] if 'adoptedStyleSheets' in json else None,
is_ad_related=bool(json['isAdRelated']) if 'isAdRelated' in json else None,
)


Expand Down Expand Up @@ -1874,6 +1898,27 @@ def from_json(cls, json: T_JSON_DICT) -> AttributeModified:
)


@event_class('DOM.adoptedStyleSheetsModified')
@dataclass
class AdoptedStyleSheetsModified:
r'''
**EXPERIMENTAL**

Fired when ``Element``'s adoptedStyleSheets are modified.
'''
#: Id of the node that has changed.
node_id: NodeId
#: New adoptedStyleSheets array.
adopted_style_sheets: typing.List[StyleSheetId]

@classmethod
def from_json(cls, json: T_JSON_DICT) -> AdoptedStyleSheetsModified:
return cls(
node_id=NodeId.from_json(json['nodeId']),
adopted_style_sheets=[StyleSheetId.from_json(i) for i in json['adoptedStyleSheets']]
)


@event_class('DOM.attributeRemoved')
@dataclass
class AttributeRemoved:
Expand Down Expand Up @@ -2085,6 +2130,27 @@ def from_json(cls, json: T_JSON_DICT) -> ScrollableFlagUpdated:
)


@event_class('DOM.adRelatedStateUpdated')
@dataclass
class AdRelatedStateUpdated:
r'''
**EXPERIMENTAL**

Fired when a node's ad related state changes.
'''
#: The id of the node.
node_id: NodeId
#: If the node is ad related.
is_ad_related: bool

@classmethod
def from_json(cls, json: T_JSON_DICT) -> AdRelatedStateUpdated:
return cls(
node_id=NodeId.from_json(json['nodeId']),
is_ad_related=bool(json['isAdRelated'])
)


@event_class('DOM.affectedByStartingStylesFlagUpdated')
@dataclass
class AffectedByStartingStylesFlagUpdated:
Expand Down
120 changes: 118 additions & 2 deletions cdp/emulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@ class DisabledImageType(enum.Enum):
Enum of image types that can be disabled.
'''
AVIF = "avif"
JXL = "jxl"
WEBP = "webp"

def to_json(self) -> str:
Expand Down Expand Up @@ -783,7 +784,9 @@ def set_device_metrics_override(
screen_orientation: typing.Optional[ScreenOrientation] = None,
viewport: typing.Optional[page.Viewport] = None,
display_feature: typing.Optional[DisplayFeature] = None,
device_posture: typing.Optional[DevicePosture] = None
device_posture: typing.Optional[DevicePosture] = None,
scrollbar_type: typing.Optional[str] = None,
screen_orientation_lock_emulation: typing.Optional[bool] = None
) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
r'''
Overrides the values of device screen dimensions (window.screen.width, window.screen.height,
Expand All @@ -804,6 +807,8 @@ def set_device_metrics_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: **(DEPRECATED)** **(EXPERIMENTAL)** *(Optional)* If set, the display feature of a multi-segment screen. If not set, multi-segment support is turned-off. Deprecated, use Emulation.setDisplayFeaturesOverride.
: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.
:param scrollbar_type: **(EXPERIMENTAL)** *(Optional)* Scrollbar type. Default: ```default```.
:param screen_orientation_lock_emulation: **(EXPERIMENTAL)** *(Optional)* If set to true, enables screen orientation lock emulation, which intercepts screen.orientation.lock() calls from the page and reports orientation changes via screenOrientationLockChanged events. This is useful for emulating mobile device orientation lock behavior in responsive design mode.
'''
params: T_JSON_DICT = dict()
params['width'] = width
Expand All @@ -830,6 +835,10 @@ def set_device_metrics_override(
params['displayFeature'] = display_feature.to_json()
if device_posture is not None:
params['devicePosture'] = device_posture.to_json()
if scrollbar_type is not None:
params['scrollbarType'] = scrollbar_type
if screen_orientation_lock_emulation is not None:
params['screenOrientationLockEmulation'] = screen_orientation_lock_emulation
cmd_dict: T_JSON_DICT = {
'method': 'Emulation.setDeviceMetricsOverride',
'params': params,
Expand Down Expand Up @@ -1560,7 +1569,8 @@ def set_small_viewport_height_difference_override(

def get_screen_infos() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[ScreenInfo]]:
r'''
Returns device's screen configuration.
Returns device's screen configuration. In headful mode, the physical screens configuration is returned,
whereas in headless mode, a virtual headless screen configuration is provided instead.

**EXPERIMENTAL**

Expand Down Expand Up @@ -1627,6 +1637,67 @@ def add_screen(
return ScreenInfo.from_json(json['screenInfo'])


def update_screen(
screen_id: ScreenId,
left: typing.Optional[int] = None,
top: typing.Optional[int] = None,
width: typing.Optional[int] = None,
height: typing.Optional[int] = None,
work_area_insets: typing.Optional[WorkAreaInsets] = None,
device_pixel_ratio: typing.Optional[float] = None,
rotation: typing.Optional[int] = None,
color_depth: typing.Optional[int] = None,
label: typing.Optional[str] = None,
is_internal: typing.Optional[bool] = None
) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,ScreenInfo]:
r'''
Updates specified screen parameters. Only supported in headless mode.

**EXPERIMENTAL**

:param screen_id: Target screen identifier.
:param left: *(Optional)* Offset of the left edge of the screen in pixels.
:param top: *(Optional)* Offset of the top edge of the screen in pixels.
:param width: *(Optional)* The width of the screen in pixels.
:param height: *(Optional)* The height of the screen in pixels.
:param work_area_insets: *(Optional)* Specifies the screen's work area.
:param device_pixel_ratio: *(Optional)* Specifies the screen's device pixel ratio.
:param rotation: *(Optional)* Specifies the screen's rotation angle. Available values are 0, 90, 180 and 270.
:param color_depth: *(Optional)* Specifies the screen's color depth in bits.
:param label: *(Optional)* Specifies the descriptive label for the screen.
:param is_internal: *(Optional)* Indicates whether the screen is internal to the device or external, attached to the device. Default is false.
:returns:
'''
params: T_JSON_DICT = dict()
params['screenId'] = screen_id.to_json()
if left is not None:
params['left'] = left
if top is not None:
params['top'] = top
if width is not None:
params['width'] = width
if height is not None:
params['height'] = height
if work_area_insets is not None:
params['workAreaInsets'] = work_area_insets.to_json()
if device_pixel_ratio is not None:
params['devicePixelRatio'] = device_pixel_ratio
if rotation is not None:
params['rotation'] = rotation
if color_depth is not None:
params['colorDepth'] = color_depth
if label is not None:
params['label'] = label
if is_internal is not None:
params['isInternal'] = is_internal
cmd_dict: T_JSON_DICT = {
'method': 'Emulation.updateScreen',
'params': params,
}
json = yield cmd_dict
return ScreenInfo.from_json(json['screenInfo'])


def remove_screen(
screen_id: ScreenId
) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
Expand All @@ -1646,6 +1717,28 @@ def remove_screen(
json = yield cmd_dict


def set_primary_screen(
screen_id: ScreenId
) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
r'''
Set primary screen. Only supported in headless mode.
Note that this changes the coordinate system origin to the top-left
of the new primary screen, updating the bounds and work areas
of all existing screens accordingly.

**EXPERIMENTAL**

:param screen_id:
'''
params: T_JSON_DICT = dict()
params['screenId'] = screen_id.to_json()
cmd_dict: T_JSON_DICT = {
'method': 'Emulation.setPrimaryScreen',
'params': params,
}
json = yield cmd_dict


@event_class('Emulation.virtualTimeBudgetExpired')
@dataclass
class VirtualTimeBudgetExpired:
Expand All @@ -1661,3 +1754,26 @@ def from_json(cls, json: T_JSON_DICT) -> VirtualTimeBudgetExpired:
return cls(

)


@event_class('Emulation.screenOrientationLockChanged')
@dataclass
class ScreenOrientationLockChanged:
r'''
**EXPERIMENTAL**

Fired when a page calls screen.orientation.lock() or screen.orientation.unlock()
while device emulation is enabled. This allows the DevTools frontend to update the
emulated device orientation accordingly.
'''
#: Whether the screen orientation is currently locked.
locked: bool
#: The orientation lock type requested by the page. Only set when locked is true.
orientation: typing.Optional[ScreenOrientation]

@classmethod
def from_json(cls, json: T_JSON_DICT) -> ScreenOrientationLockChanged:
return cls(
locked=bool(json['locked']),
orientation=ScreenOrientation.from_json(json['orientation']) if 'orientation' in json else None
)
Loading
Loading