Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/py/selenium/webdriver/common/bidi/storage.py
1864 views
1
# Licensed to the Software Freedom Conservancy (SFC) under one
2
# or more contributor license agreements. See the NOTICE file
3
# distributed with this work for additional information
4
# regarding copyright ownership. The SFC licenses this file
5
# to you under the Apache License, Version 2.0 (the
6
# "License"); you may not use this file except in compliance
7
# with the License. You may obtain a copy of the License at
8
#
9
# http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing,
12
# software distributed under the License is distributed on an
13
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
# KIND, either express or implied. See the License for the
15
# specific language governing permissions and limitations
16
# under the License.
17
18
from typing import Any, Optional, Union
19
20
from selenium.webdriver.common.bidi.common import command_builder
21
22
23
class SameSite:
24
"""Represents the possible same site values for cookies."""
25
26
STRICT = "strict"
27
LAX = "lax"
28
NONE = "none"
29
DEFAULT = "default"
30
31
32
class BytesValue:
33
"""Represents a bytes value."""
34
35
TYPE_BASE64 = "base64"
36
TYPE_STRING = "string"
37
38
def __init__(self, type: str, value: str):
39
self.type = type
40
self.value = value
41
42
def to_dict(self) -> dict:
43
"""Converts the BytesValue to a dictionary.
44
45
Returns:
46
-------
47
Dict: A dictionary representation of the BytesValue.
48
"""
49
return {"type": self.type, "value": self.value}
50
51
52
class Cookie:
53
"""Represents a cookie."""
54
55
def __init__(
56
self,
57
name: str,
58
value: BytesValue,
59
domain: str,
60
path: Optional[str] = None,
61
size: Optional[int] = None,
62
http_only: Optional[bool] = None,
63
secure: Optional[bool] = None,
64
same_site: Optional[str] = None,
65
expiry: Optional[int] = None,
66
):
67
self.name = name
68
self.value = value
69
self.domain = domain
70
self.path = path
71
self.size = size
72
self.http_only = http_only
73
self.secure = secure
74
self.same_site = same_site
75
self.expiry = expiry
76
77
@classmethod
78
def from_dict(cls, data: dict) -> "Cookie":
79
"""Creates a Cookie instance from a dictionary.
80
81
Parameters:
82
-----------
83
data: A dictionary containing the cookie information.
84
85
Returns:
86
-------
87
Cookie: A new instance of Cookie.
88
"""
89
# Validation for empty strings
90
name = data.get("name")
91
if not name:
92
raise ValueError("name is required and cannot be empty")
93
domain = data.get("domain")
94
if not domain:
95
raise ValueError("domain is required and cannot be empty")
96
97
value = BytesValue(data.get("value", {}).get("type"), data.get("value", {}).get("value"))
98
return cls(
99
name=str(name),
100
value=value,
101
domain=str(domain),
102
path=data.get("path"),
103
size=data.get("size"),
104
http_only=data.get("httpOnly"),
105
secure=data.get("secure"),
106
same_site=data.get("sameSite"),
107
expiry=data.get("expiry"),
108
)
109
110
111
class CookieFilter:
112
"""Represents a filter for cookies."""
113
114
def __init__(
115
self,
116
name: Optional[str] = None,
117
value: Optional[BytesValue] = None,
118
domain: Optional[str] = None,
119
path: Optional[str] = None,
120
size: Optional[int] = None,
121
http_only: Optional[bool] = None,
122
secure: Optional[bool] = None,
123
same_site: Optional[str] = None,
124
expiry: Optional[int] = None,
125
):
126
self.name = name
127
self.value = value
128
self.domain = domain
129
self.path = path
130
self.size = size
131
self.http_only = http_only
132
self.secure = secure
133
self.same_site = same_site
134
self.expiry = expiry
135
136
def to_dict(self) -> dict[str, Any]:
137
"""Converts the CookieFilter to a dictionary.
138
139
Returns:
140
-------
141
Dict: A dictionary representation of the CookieFilter.
142
"""
143
result: dict[str, Any] = {}
144
if self.name is not None:
145
result["name"] = self.name
146
if self.value is not None:
147
result["value"] = self.value.to_dict()
148
if self.domain is not None:
149
result["domain"] = self.domain
150
if self.path is not None:
151
result["path"] = self.path
152
if self.size is not None:
153
result["size"] = self.size
154
if self.http_only is not None:
155
result["httpOnly"] = self.http_only
156
if self.secure is not None:
157
result["secure"] = self.secure
158
if self.same_site is not None:
159
result["sameSite"] = self.same_site
160
if self.expiry is not None:
161
result["expiry"] = self.expiry
162
return result
163
164
165
class PartitionKey:
166
"""Represents a storage partition key."""
167
168
def __init__(self, user_context: Optional[str] = None, source_origin: Optional[str] = None):
169
self.user_context = user_context
170
self.source_origin = source_origin
171
172
@classmethod
173
def from_dict(cls, data: dict) -> "PartitionKey":
174
"""Creates a PartitionKey instance from a dictionary.
175
176
Parameters:
177
-----------
178
data: A dictionary containing the partition key information.
179
180
Returns:
181
-------
182
PartitionKey: A new instance of PartitionKey.
183
"""
184
return cls(
185
user_context=data.get("userContext"),
186
source_origin=data.get("sourceOrigin"),
187
)
188
189
190
class BrowsingContextPartitionDescriptor:
191
"""Represents a browsing context partition descriptor."""
192
193
def __init__(self, context: str):
194
self.type = "context"
195
self.context = context
196
197
def to_dict(self) -> dict:
198
"""Converts the BrowsingContextPartitionDescriptor to a dictionary.
199
200
Returns:
201
-------
202
Dict: A dictionary representation of the BrowsingContextPartitionDescriptor.
203
"""
204
return {"type": self.type, "context": self.context}
205
206
207
class StorageKeyPartitionDescriptor:
208
"""Represents a storage key partition descriptor."""
209
210
def __init__(self, user_context: Optional[str] = None, source_origin: Optional[str] = None):
211
self.type = "storageKey"
212
self.user_context = user_context
213
self.source_origin = source_origin
214
215
def to_dict(self) -> dict:
216
"""Converts the StorageKeyPartitionDescriptor to a dictionary.
217
218
Returns:
219
-------
220
Dict: A dictionary representation of the StorageKeyPartitionDescriptor.
221
"""
222
result = {"type": self.type}
223
if self.user_context is not None:
224
result["userContext"] = self.user_context
225
if self.source_origin is not None:
226
result["sourceOrigin"] = self.source_origin
227
return result
228
229
230
class PartialCookie:
231
"""Represents a partial cookie for setting."""
232
233
def __init__(
234
self,
235
name: str,
236
value: BytesValue,
237
domain: str,
238
path: Optional[str] = None,
239
http_only: Optional[bool] = None,
240
secure: Optional[bool] = None,
241
same_site: Optional[str] = None,
242
expiry: Optional[int] = None,
243
):
244
self.name = name
245
self.value = value
246
self.domain = domain
247
self.path = path
248
self.http_only = http_only
249
self.secure = secure
250
self.same_site = same_site
251
self.expiry = expiry
252
253
def to_dict(self) -> dict[str, Any]:
254
"""Converts the PartialCookie to a dictionary.
255
256
Returns:
257
-------
258
Dict: A dictionary representation of the PartialCookie.
259
"""
260
result: dict[str, Any] = {
261
"name": self.name,
262
"value": self.value.to_dict(),
263
"domain": self.domain,
264
}
265
if self.path is not None:
266
result["path"] = self.path
267
if self.http_only is not None:
268
result["httpOnly"] = self.http_only
269
if self.secure is not None:
270
result["secure"] = self.secure
271
if self.same_site is not None:
272
result["sameSite"] = self.same_site
273
if self.expiry is not None:
274
result["expiry"] = self.expiry
275
return result
276
277
278
class GetCookiesResult:
279
"""Represents the result of a getCookies command."""
280
281
def __init__(self, cookies: list[Cookie], partition_key: PartitionKey):
282
self.cookies = cookies
283
self.partition_key = partition_key
284
285
@classmethod
286
def from_dict(cls, data: dict) -> "GetCookiesResult":
287
"""Creates a GetCookiesResult instance from a dictionary.
288
289
Parameters:
290
-----------
291
data: A dictionary containing the get cookies result information.
292
293
Returns:
294
-------
295
GetCookiesResult: A new instance of GetCookiesResult.
296
"""
297
cookies = [Cookie.from_dict(cookie) for cookie in data.get("cookies", [])]
298
partition_key = PartitionKey.from_dict(data.get("partitionKey", {}))
299
return cls(cookies=cookies, partition_key=partition_key)
300
301
302
class SetCookieResult:
303
"""Represents the result of a setCookie command."""
304
305
def __init__(self, partition_key: PartitionKey):
306
self.partition_key = partition_key
307
308
@classmethod
309
def from_dict(cls, data: dict) -> "SetCookieResult":
310
"""Creates a SetCookieResult instance from a dictionary.
311
312
Parameters:
313
-----------
314
data: A dictionary containing the set cookie result information.
315
316
Returns:
317
-------
318
SetCookieResult: A new instance of SetCookieResult.
319
"""
320
partition_key = PartitionKey.from_dict(data.get("partitionKey", {}))
321
return cls(partition_key=partition_key)
322
323
324
class DeleteCookiesResult:
325
"""Represents the result of a deleteCookies command."""
326
327
def __init__(self, partition_key: PartitionKey):
328
self.partition_key = partition_key
329
330
@classmethod
331
def from_dict(cls, data: dict) -> "DeleteCookiesResult":
332
"""Creates a DeleteCookiesResult instance from a dictionary.
333
334
Parameters:
335
-----------
336
data: A dictionary containing the delete cookies result information.
337
338
Returns:
339
-------
340
DeleteCookiesResult: A new instance of DeleteCookiesResult.
341
"""
342
partition_key = PartitionKey.from_dict(data.get("partitionKey", {}))
343
return cls(partition_key=partition_key)
344
345
346
class Storage:
347
"""BiDi implementation of the storage module."""
348
349
def __init__(self, conn):
350
self.conn = conn
351
352
def get_cookies(
353
self,
354
filter: Optional[CookieFilter] = None,
355
partition: Optional[Union[BrowsingContextPartitionDescriptor, StorageKeyPartitionDescriptor]] = None,
356
) -> GetCookiesResult:
357
"""Retrieves cookies that match the given parameters.
358
359
Parameters:
360
-----------
361
filter: Optional filter to match cookies.
362
partition: Optional partition descriptor.
363
364
Returns:
365
-------
366
GetCookiesResult: The result of the get cookies command.
367
"""
368
params = {}
369
if filter is not None:
370
params["filter"] = filter.to_dict()
371
if partition is not None:
372
params["partition"] = partition.to_dict()
373
374
result = self.conn.execute(command_builder("storage.getCookies", params))
375
return GetCookiesResult.from_dict(result)
376
377
def set_cookie(
378
self,
379
cookie: PartialCookie,
380
partition: Optional[Union[BrowsingContextPartitionDescriptor, StorageKeyPartitionDescriptor]] = None,
381
) -> SetCookieResult:
382
"""Sets a cookie in the browser.
383
384
Parameters:
385
-----------
386
cookie: The cookie to set.
387
partition: Optional partition descriptor.
388
389
Returns:
390
-------
391
SetCookieResult: The result of the set cookie command.
392
"""
393
params = {"cookie": cookie.to_dict()}
394
if partition is not None:
395
params["partition"] = partition.to_dict()
396
397
result = self.conn.execute(command_builder("storage.setCookie", params))
398
return SetCookieResult.from_dict(result)
399
400
def delete_cookies(
401
self,
402
filter: Optional[CookieFilter] = None,
403
partition: Optional[Union[BrowsingContextPartitionDescriptor, StorageKeyPartitionDescriptor]] = None,
404
) -> DeleteCookiesResult:
405
"""Deletes cookies that match the given parameters.
406
407
Parameters:
408
-----------
409
filter: Optional filter to match cookies to delete.
410
partition: Optional partition descriptor.
411
412
Returns:
413
-------
414
DeleteCookiesResult: The result of the delete cookies command.
415
"""
416
params = {}
417
if filter is not None:
418
params["filter"] = filter.to_dict()
419
if partition is not None:
420
params["partition"] = partition.to_dict()
421
422
result = self.conn.execute(command_builder("storage.deleteCookies", params))
423
return DeleteCookiesResult.from_dict(result)
424
425