dfindexeddb 20240417__py3-none-any.whl → 20240519__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dfindexeddb/indexeddb/chromium/blink.py +5 -0
- dfindexeddb/indexeddb/chromium/record.py +90 -7
- dfindexeddb/indexeddb/cli.py +82 -80
- dfindexeddb/indexeddb/safari/definitions.py +123 -0
- dfindexeddb/indexeddb/safari/record.py +238 -0
- dfindexeddb/indexeddb/safari/webkit.py +701 -0
- dfindexeddb/leveldb/cli.py +70 -11
- dfindexeddb/leveldb/log.py +9 -3
- dfindexeddb/leveldb/plugins/__init__.py +17 -0
- dfindexeddb/leveldb/plugins/chrome_notifications.py +135 -0
- dfindexeddb/leveldb/plugins/interface.py +36 -0
- dfindexeddb/leveldb/plugins/manager.py +75 -0
- dfindexeddb/leveldb/plugins/notification_database_data_pb2.py +38 -0
- dfindexeddb/leveldb/record.py +212 -53
- dfindexeddb/utils.py +34 -0
- dfindexeddb/version.py +1 -1
- {dfindexeddb-20240417.dist-info → dfindexeddb-20240519.dist-info}/METADATA +74 -80
- dfindexeddb-20240519.dist-info/RECORD +37 -0
- dfindexeddb-20240417.dist-info/RECORD +0 -29
- {dfindexeddb-20240417.dist-info → dfindexeddb-20240519.dist-info}/AUTHORS +0 -0
- {dfindexeddb-20240417.dist-info → dfindexeddb-20240519.dist-info}/LICENSE +0 -0
- {dfindexeddb-20240417.dist-info → dfindexeddb-20240519.dist-info}/WHEEL +0 -0
- {dfindexeddb-20240417.dist-info → dfindexeddb-20240519.dist-info}/entry_points.txt +0 -0
- {dfindexeddb-20240417.dist-info → dfindexeddb-20240519.dist-info}/top_level.txt +0 -0
dfindexeddb/leveldb/cli.py
CHANGED
|
@@ -19,11 +19,13 @@ from datetime import datetime
|
|
|
19
19
|
import json
|
|
20
20
|
import pathlib
|
|
21
21
|
|
|
22
|
+
from dfindexeddb import utils
|
|
22
23
|
from dfindexeddb import version
|
|
23
24
|
from dfindexeddb.leveldb import descriptor
|
|
24
25
|
from dfindexeddb.leveldb import ldb
|
|
25
26
|
from dfindexeddb.leveldb import log
|
|
26
27
|
from dfindexeddb.leveldb import record
|
|
28
|
+
from dfindexeddb.leveldb.plugins import manager
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
_VALID_PRINTABLE_CHARACTERS = (
|
|
@@ -37,7 +39,7 @@ class Encoder(json.JSONEncoder):
|
|
|
37
39
|
def default(self, o):
|
|
38
40
|
"""Returns a serializable object for o."""
|
|
39
41
|
if dataclasses.is_dataclass(o):
|
|
40
|
-
o_dict =
|
|
42
|
+
o_dict = utils.asdict(o)
|
|
41
43
|
return o_dict
|
|
42
44
|
if isinstance(o, bytes):
|
|
43
45
|
out = []
|
|
@@ -66,16 +68,39 @@ def _Output(structure, output):
|
|
|
66
68
|
|
|
67
69
|
def DbCommand(args):
|
|
68
70
|
"""The CLI for processing leveldb folders."""
|
|
69
|
-
if args.
|
|
70
|
-
for
|
|
71
|
-
|
|
71
|
+
if args.plugin and args.plugin == 'list':
|
|
72
|
+
for plugin, _ in manager.LeveldbPluginManager.GetPlugins():
|
|
73
|
+
print(plugin)
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
if args.plugin:
|
|
77
|
+
plugin_class = manager.LeveldbPluginManager.GetPlugin(args.plugin)
|
|
72
78
|
else:
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
plugin_class = None
|
|
80
|
+
|
|
81
|
+
for leveldb_record in record.FolderReader(
|
|
82
|
+
args.source).GetRecords(
|
|
83
|
+
use_manifest=args.use_manifest,
|
|
84
|
+
use_sequence_number=args.use_sequence_number):
|
|
85
|
+
if plugin_class:
|
|
86
|
+
plugin_record = plugin_class.FromLevelDBRecord(leveldb_record)
|
|
87
|
+
_Output(plugin_record, output=args.output)
|
|
88
|
+
else:
|
|
89
|
+
_Output(leveldb_record, output=args.output)
|
|
75
90
|
|
|
76
91
|
|
|
77
92
|
def LdbCommand(args):
|
|
78
93
|
"""The CLI for processing ldb files."""
|
|
94
|
+
if args.plugin and args.plugin == 'list':
|
|
95
|
+
for plugin, _ in manager.LeveldbPluginManager.GetPlugins():
|
|
96
|
+
print(plugin)
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
if args.plugin:
|
|
100
|
+
plugin_class = manager.LeveldbPluginManager.GetPlugin(args.plugin)
|
|
101
|
+
else:
|
|
102
|
+
plugin_class = None
|
|
103
|
+
|
|
79
104
|
ldb_file = ldb.FileReader(args.source)
|
|
80
105
|
|
|
81
106
|
if args.structure_type == 'blocks':
|
|
@@ -86,7 +111,11 @@ def LdbCommand(args):
|
|
|
86
111
|
elif args.structure_type == 'records' or not args.structure_type:
|
|
87
112
|
# Prints key value record information.
|
|
88
113
|
for key_value_record in ldb_file.GetKeyValueRecords():
|
|
89
|
-
|
|
114
|
+
if plugin_class:
|
|
115
|
+
plugin_record = plugin_class.FromKeyValueRecord(key_value_record)
|
|
116
|
+
_Output(plugin_record, output=args.output)
|
|
117
|
+
else:
|
|
118
|
+
_Output(key_value_record, output=args.output)
|
|
90
119
|
|
|
91
120
|
else:
|
|
92
121
|
print(f'{args.structure_type} is not supported for ldb files.')
|
|
@@ -94,6 +123,16 @@ def LdbCommand(args):
|
|
|
94
123
|
|
|
95
124
|
def LogCommand(args):
|
|
96
125
|
"""The CLI for processing log files."""
|
|
126
|
+
if args.plugin and args.plugin == 'list':
|
|
127
|
+
for plugin, _ in manager.LeveldbPluginManager.GetPlugins():
|
|
128
|
+
print(plugin)
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
if args.plugin:
|
|
132
|
+
plugin_class = manager.LeveldbPluginManager.GetPlugin(args.plugin)
|
|
133
|
+
else:
|
|
134
|
+
plugin_class = None
|
|
135
|
+
|
|
97
136
|
log_file = log.FileReader(args.source)
|
|
98
137
|
|
|
99
138
|
if args.structure_type == 'blocks':
|
|
@@ -115,7 +154,11 @@ def LogCommand(args):
|
|
|
115
154
|
or not args.structure_type):
|
|
116
155
|
# Prints key value record information.
|
|
117
156
|
for internal_key_record in log_file.GetParsedInternalKeys():
|
|
118
|
-
|
|
157
|
+
if plugin_class:
|
|
158
|
+
plugin_record = plugin_class.FromKeyValueRecord(internal_key_record)
|
|
159
|
+
_Output(plugin_record, output=args.output)
|
|
160
|
+
else:
|
|
161
|
+
_Output(internal_key_record, output=args.output)
|
|
119
162
|
|
|
120
163
|
else:
|
|
121
164
|
print(f'{args.structure_type} is not supported for log files.')
|
|
@@ -147,6 +190,7 @@ def DescriptorCommand(args):
|
|
|
147
190
|
else:
|
|
148
191
|
print(f'{args.structure_type} is not supported for descriptor files.')
|
|
149
192
|
|
|
193
|
+
|
|
150
194
|
def App():
|
|
151
195
|
"""The CLI app entrypoint for parsing leveldb files."""
|
|
152
196
|
parser = argparse.ArgumentParser(
|
|
@@ -163,10 +207,17 @@ def App():
|
|
|
163
207
|
required=True,
|
|
164
208
|
type=pathlib.Path,
|
|
165
209
|
help='The source leveldb directory')
|
|
166
|
-
parser_db.
|
|
210
|
+
recover_group = parser_db.add_mutually_exclusive_group()
|
|
211
|
+
recover_group.add_argument(
|
|
167
212
|
'--use_manifest',
|
|
168
213
|
action='store_true',
|
|
169
214
|
help='Use manifest file to determine active/deleted records.')
|
|
215
|
+
recover_group.add_argument(
|
|
216
|
+
'--use_sequence_number',
|
|
217
|
+
action='store_true',
|
|
218
|
+
help=(
|
|
219
|
+
'Use sequence number and file offset to determine active/deleted '
|
|
220
|
+
'records.'))
|
|
170
221
|
parser_db.add_argument(
|
|
171
222
|
'-o',
|
|
172
223
|
'--output',
|
|
@@ -176,6 +227,9 @@ def App():
|
|
|
176
227
|
'repr'],
|
|
177
228
|
default='json',
|
|
178
229
|
help='Output format. Default is json')
|
|
230
|
+
parser_db.add_argument(
|
|
231
|
+
'--plugin',
|
|
232
|
+
help='Use plugin to parse records.')
|
|
179
233
|
parser_db.set_defaults(func=DbCommand)
|
|
180
234
|
|
|
181
235
|
parser_log = subparsers.add_parser(
|
|
@@ -194,6 +248,9 @@ def App():
|
|
|
194
248
|
'repr'],
|
|
195
249
|
default='json',
|
|
196
250
|
help='Output format. Default is json')
|
|
251
|
+
parser_log.add_argument(
|
|
252
|
+
'--plugin',
|
|
253
|
+
help='Use plugin to parse records.')
|
|
197
254
|
parser_log.add_argument(
|
|
198
255
|
'-t',
|
|
199
256
|
'--structure_type',
|
|
@@ -221,6 +278,9 @@ def App():
|
|
|
221
278
|
'repr'],
|
|
222
279
|
default='json',
|
|
223
280
|
help='Output format. Default is json')
|
|
281
|
+
parser_ldb.add_argument(
|
|
282
|
+
'--plugin',
|
|
283
|
+
help='Use plugin to parse records.')
|
|
224
284
|
parser_ldb.add_argument(
|
|
225
285
|
'-t',
|
|
226
286
|
'--structure_type',
|
|
@@ -257,8 +317,7 @@ def App():
|
|
|
257
317
|
'-v',
|
|
258
318
|
'--version_history',
|
|
259
319
|
action='store_true',
|
|
260
|
-
help='Parses the leveldb version history.'
|
|
261
|
-
)
|
|
320
|
+
help='Parses the leveldb version history.')
|
|
262
321
|
parser_descriptor.set_defaults(func=DescriptorCommand)
|
|
263
322
|
|
|
264
323
|
args = parser.parse_args()
|
dfindexeddb/leveldb/log.py
CHANGED
|
@@ -152,7 +152,7 @@ class PhysicalRecord(utils.FromDecoderMixin):
|
|
|
152
152
|
@classmethod
|
|
153
153
|
def FromDecoder(
|
|
154
154
|
cls, decoder: utils.LevelDBDecoder, base_offset: int = 0
|
|
155
|
-
) -> PhysicalRecord:
|
|
155
|
+
) -> Optional[PhysicalRecord]:
|
|
156
156
|
"""Decodes a PhysicalRecord from the current position of a LevelDBDecoder.
|
|
157
157
|
|
|
158
158
|
Args:
|
|
@@ -161,11 +161,13 @@ class PhysicalRecord(utils.FromDecoderMixin):
|
|
|
161
161
|
read from.
|
|
162
162
|
|
|
163
163
|
Returns:
|
|
164
|
-
A PhysicalRecord.
|
|
164
|
+
A PhysicalRecord or None if the parsed header is 0.
|
|
165
165
|
"""
|
|
166
166
|
offset, checksum = decoder.DecodeUint32()
|
|
167
167
|
_, length = decoder.DecodeUint16()
|
|
168
168
|
_, record_type_byte = decoder.DecodeUint8()
|
|
169
|
+
if checksum == 0 or length == 0 or record_type_byte == 0:
|
|
170
|
+
return None
|
|
169
171
|
try:
|
|
170
172
|
record_type = definitions.LogFilePhysicalRecordType(record_type_byte)
|
|
171
173
|
except ValueError as error:
|
|
@@ -206,7 +208,11 @@ class Block:
|
|
|
206
208
|
buffer_length = len(self.data)
|
|
207
209
|
|
|
208
210
|
while buffer.tell() + PhysicalRecord.PHYSICAL_HEADER_LENGTH < buffer_length:
|
|
209
|
-
|
|
211
|
+
record = PhysicalRecord.FromStream(buffer, base_offset=self.offset)
|
|
212
|
+
if record:
|
|
213
|
+
yield record
|
|
214
|
+
else:
|
|
215
|
+
return
|
|
210
216
|
|
|
211
217
|
@classmethod
|
|
212
218
|
def FromStream(cls, stream: BinaryIO) -> Optional[Block]:
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright 2024 Google LLC
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Leveldb Plugin module."""
|
|
16
|
+
|
|
17
|
+
from dfindexeddb.leveldb.plugins import chrome_notifications
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright 2024 Google LLC
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Parser plugin for Chrome Notifications."""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import dataclasses
|
|
19
|
+
import logging
|
|
20
|
+
|
|
21
|
+
from typing import Optional
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
# pytype: disable=import-error
|
|
25
|
+
from dfdatetime import webkit_time
|
|
26
|
+
from dfindexeddb.leveldb.plugins import notification_database_data_pb2 as \
|
|
27
|
+
notification_pb2
|
|
28
|
+
# pytype: enable=import-error
|
|
29
|
+
_has_import_dependencies = True
|
|
30
|
+
except ImportError as err:
|
|
31
|
+
_has_import_dependencies = False
|
|
32
|
+
logging.warning((
|
|
33
|
+
'Could not import dependencies for '
|
|
34
|
+
'leveldb.plugins.chrome_notifications: %s'), err)
|
|
35
|
+
|
|
36
|
+
from dfindexeddb.indexeddb.chromium import blink
|
|
37
|
+
from dfindexeddb.leveldb.plugins import interface
|
|
38
|
+
from dfindexeddb.leveldb.plugins import manager
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclasses.dataclass
|
|
42
|
+
class ChromeNotificationRecord(interface.LeveldbPlugin):
|
|
43
|
+
"""Chrome notification record."""
|
|
44
|
+
src_file: Optional[str] = None
|
|
45
|
+
offset: Optional[int] = None
|
|
46
|
+
key: Optional[str] = None
|
|
47
|
+
sequence_number: Optional[int] = None
|
|
48
|
+
type: Optional[int] = None
|
|
49
|
+
origin: Optional[str] = None
|
|
50
|
+
service_worker_registration_id: Optional[int] = None
|
|
51
|
+
notification_title: Optional[str] = None
|
|
52
|
+
notification_direction: Optional[str] = None
|
|
53
|
+
notification_lang: Optional[str] = None
|
|
54
|
+
notification_body: Optional[str] = None
|
|
55
|
+
notification_tag: Optional[str] = None
|
|
56
|
+
notification_icon: Optional[str] = None
|
|
57
|
+
notification_silent: Optional[bool] = None
|
|
58
|
+
notification_data: Optional[str] = None
|
|
59
|
+
notification_require_interaction: Optional[bool] = None
|
|
60
|
+
notification_time: Optional[str] = None
|
|
61
|
+
notification_renotify: Optional[bool] = None
|
|
62
|
+
notification_badge: Optional[str] = None
|
|
63
|
+
notification_image: Optional[str] = None
|
|
64
|
+
notification_id: Optional[str] = None
|
|
65
|
+
replaced_existing_notification: Optional[bool] = None
|
|
66
|
+
num_clicks: Optional[int] = None
|
|
67
|
+
num_action_button_clicks: Optional[int] = None
|
|
68
|
+
creation_time: Optional[str] = None
|
|
69
|
+
closed_reason: Optional[str] = None
|
|
70
|
+
has_triggered: Optional[bool] = None
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def FromKeyValueRecord(
|
|
74
|
+
cls,
|
|
75
|
+
ldb_record
|
|
76
|
+
) -> ChromeNotificationRecord:
|
|
77
|
+
record = cls()
|
|
78
|
+
record.offset = ldb_record.offset
|
|
79
|
+
record.key = ldb_record.key.decode()
|
|
80
|
+
record.sequence_number = ldb_record.sequence_number
|
|
81
|
+
record.type = ldb_record.record_type
|
|
82
|
+
|
|
83
|
+
if not ldb_record.value:
|
|
84
|
+
return record
|
|
85
|
+
|
|
86
|
+
# pylint: disable-next=no-member,line-too-long
|
|
87
|
+
notification_proto = notification_pb2.NotificationDatabaseDataProto() # pytype: disable=module-attr
|
|
88
|
+
notification_proto.ParseFromString(ldb_record.value)
|
|
89
|
+
|
|
90
|
+
record.origin = notification_proto.origin
|
|
91
|
+
record.service_worker_registration_id = (
|
|
92
|
+
notification_proto.service_worker_registration_id)
|
|
93
|
+
record.notification_title = notification_proto.notification_data.title
|
|
94
|
+
record.notification_direction = (
|
|
95
|
+
notification_proto.notification_data.direction)
|
|
96
|
+
record.notification_lang = notification_proto.notification_data.lang
|
|
97
|
+
record.notification_body = notification_proto.notification_data.body
|
|
98
|
+
record.notification_tag = notification_proto.notification_data.tag
|
|
99
|
+
record.notification_icon = notification_proto.notification_data.icon
|
|
100
|
+
record.notification_silent = notification_proto.notification_data.silent
|
|
101
|
+
record.notification_data = notification_proto.notification_data.data
|
|
102
|
+
record.notification_require_interaction = (
|
|
103
|
+
notification_proto.notification_data.require_interaction)
|
|
104
|
+
record.notification_time = webkit_time.WebKitTime(
|
|
105
|
+
timestamp=notification_proto.notification_data.timestamp
|
|
106
|
+
).CopyToDateTimeString()
|
|
107
|
+
record.notification_renotify = notification_proto.notification_data.renotify
|
|
108
|
+
record.notification_badge = notification_proto.notification_data.badge
|
|
109
|
+
record.notification_image = notification_proto.notification_data.image
|
|
110
|
+
record.notification_id = notification_proto.notification_id
|
|
111
|
+
record.replaced_existing_notification = (
|
|
112
|
+
notification_proto.replaced_existing_notification)
|
|
113
|
+
record.num_clicks = notification_proto.num_clicks
|
|
114
|
+
record.num_action_button_clicks = (
|
|
115
|
+
notification_proto.num_action_button_clicks)
|
|
116
|
+
record.creation_time = webkit_time.WebKitTime(
|
|
117
|
+
timestamp=notification_proto.creation_time_millis
|
|
118
|
+
).CopyToDateTimeString()
|
|
119
|
+
record.closed_reason = notification_proto.closed_reason
|
|
120
|
+
record.has_triggered = notification_proto.has_triggered
|
|
121
|
+
|
|
122
|
+
if not notification_proto.notification_data.data:
|
|
123
|
+
return record
|
|
124
|
+
|
|
125
|
+
notification_data = blink.V8ScriptValueDecoder(
|
|
126
|
+
raw_data=notification_proto.notification_data.data).Deserialize()
|
|
127
|
+
record.notification_data = notification_data
|
|
128
|
+
|
|
129
|
+
return record
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# check if dependencies are in existence..
|
|
133
|
+
|
|
134
|
+
if _has_import_dependencies:
|
|
135
|
+
manager.PluginManager.RegisterPlugin(ChromeNotificationRecord)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright 2024 Google LLC
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Interface for leveldb plugins."""
|
|
16
|
+
from typing import Any, Union
|
|
17
|
+
|
|
18
|
+
from dfindexeddb.leveldb import record
|
|
19
|
+
from dfindexeddb.leveldb import ldb
|
|
20
|
+
from dfindexeddb.leveldb import log
|
|
21
|
+
|
|
22
|
+
class LeveldbPlugin:
|
|
23
|
+
"""The base leveldb plugin class."""
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def FromLevelDBRecord(cls,
|
|
27
|
+
ldb_record: record.LevelDBRecord) -> Any:
|
|
28
|
+
"""Parses a leveldb record."""
|
|
29
|
+
parsed_record = cls.FromKeyValueRecord(ldb_record.record)
|
|
30
|
+
ldb_record.record = parsed_record
|
|
31
|
+
return ldb_record
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def FromKeyValueRecord(
|
|
35
|
+
cls, ldb_record: Union[ldb.KeyValueRecord, log.ParsedInternalKey]) -> Any:
|
|
36
|
+
"""Parses a leveldb key value record."""
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright 2024 Google LLC
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Leveldb plugin manager."""
|
|
16
|
+
from typing import Type
|
|
17
|
+
|
|
18
|
+
from dfindexeddb.leveldb.plugins import interface
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class LeveldbPluginManager:
|
|
22
|
+
"""The leveldb plugin manager."""
|
|
23
|
+
|
|
24
|
+
_class_registry = {}
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def GetPlugins(cls):
|
|
28
|
+
"""Retrieves the registered leveldb plugins.
|
|
29
|
+
|
|
30
|
+
Yields:
|
|
31
|
+
tuple: containing:
|
|
32
|
+
str: the name of the leveldb plugin.
|
|
33
|
+
class: the plugin class.
|
|
34
|
+
"""
|
|
35
|
+
yield from cls._class_registry.items()
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def GetPlugin(cls, plugin_name: str) -> interface.LeveldbPlugin:
|
|
39
|
+
"""Retrieves a class object of a specific plugin.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
plugin_name: name of the plugin.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
the LeveldbPlugin class.
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
KeyError: if the plugin is not found/registered in the manager.
|
|
49
|
+
"""
|
|
50
|
+
try:
|
|
51
|
+
return cls._class_registry[plugin_name]
|
|
52
|
+
except KeyError:
|
|
53
|
+
raise KeyError(f'Plugin not found: {plugin_name}')
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def RegisterPlugin(cls, plugin_class: Type[interface.LeveldbPlugin]):
|
|
57
|
+
"""Registers a leveldb plugin.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
plugin_class (class): the plugin class to register.
|
|
61
|
+
|
|
62
|
+
Raises:
|
|
63
|
+
KeyError: if class is already set for the corresponding name.
|
|
64
|
+
"""
|
|
65
|
+
plugin_name = plugin_class.__name__
|
|
66
|
+
if plugin_name in cls._class_registry:
|
|
67
|
+
raise KeyError(f'Plugin already registered {plugin_name}')
|
|
68
|
+
cls._class_registry[plugin_name] = plugin_class
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def ClearPlugins(cls):
|
|
72
|
+
"""Clears all plugin registrations."""
|
|
73
|
+
cls._class_registry = {}
|
|
74
|
+
|
|
75
|
+
PluginManager = LeveldbPluginManager()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# source: notification_database_data.proto
|
|
4
|
+
# Protobuf Python Version: 4.25.1
|
|
5
|
+
"""Generated protocol buffer code."""
|
|
6
|
+
from google.protobuf import descriptor as _descriptor
|
|
7
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
8
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
9
|
+
from google.protobuf.internal import builder as _builder
|
|
10
|
+
# @@protoc_insertion_point(imports)
|
|
11
|
+
|
|
12
|
+
_sym_db = _symbol_database.Default()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# pylint: skip-file
|
|
17
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n notification_database_data.proto\"\xff\t\n\x1dNotificationDatabaseDataProto\x12\"\n\x1apersistent_notification_id\x18\x01 \x01(\x03\x12\x17\n\x0fnotification_id\x18\x05 \x01(\t\x12\x0e\n\x06origin\x18\x02 \x01(\t\x12&\n\x1eservice_worker_registration_id\x18\x03 \x01(\x03\x12&\n\x1ereplaced_existing_notification\x18\x06 \x01(\x08\x12\x12\n\nnum_clicks\x18\x07 \x01(\x05\x12 \n\x18num_action_button_clicks\x18\x08 \x01(\x05\x12\x1c\n\x14\x63reation_time_millis\x18\t \x01(\x03\x12%\n\x1dtime_until_first_click_millis\x18\n \x01(\x03\x12$\n\x1ctime_until_last_click_millis\x18\x0b \x01(\x03\x12\x1f\n\x17time_until_close_millis\x18\x0c \x01(\x03\x12\x42\n\rclosed_reason\x18\r \x01(\x0e\x32+.NotificationDatabaseDataProto.ClosedReason\x12J\n\x11notification_data\x18\x04 \x01(\x0b\x32/.NotificationDatabaseDataProto.NotificationData\x12\x15\n\rhas_triggered\x18\x0e \x01(\x08\x1a\xba\x01\n\x12NotificationAction\x12\x0e\n\x06\x61\x63tion\x18\x01 \x01(\t\x12\r\n\x05title\x18\x02 \x01(\t\x12\x0c\n\x04icon\x18\x03 \x01(\t\x12\x44\n\x04type\x18\x04 \x01(\x0e\x32\x36.NotificationDatabaseDataProto.NotificationAction.Type\x12\x13\n\x0bplaceholder\x18\x05 \x01(\t\"\x1c\n\x04Type\x12\n\n\x06\x42UTTON\x10\x00\x12\x08\n\x04TEXT\x10\x01\x1a\xe4\x03\n\x10NotificationData\x12\r\n\x05title\x18\x01 \x01(\t\x12L\n\tdirection\x18\x02 \x01(\x0e\x32\x39.NotificationDatabaseDataProto.NotificationData.Direction\x12\x0c\n\x04lang\x18\x03 \x01(\t\x12\x0c\n\x04\x62ody\x18\x04 \x01(\t\x12\x0b\n\x03tag\x18\x05 \x01(\t\x12\r\n\x05image\x18\x0f \x01(\t\x12\x0c\n\x04icon\x18\x06 \x01(\t\x12\r\n\x05\x62\x61\x64ge\x18\x0e \x01(\t\x12\x1d\n\x11vibration_pattern\x18\t \x03(\x05\x42\x02\x10\x01\x12\x11\n\ttimestamp\x18\x0c \x01(\x03\x12\x10\n\x08renotify\x18\r \x01(\x08\x12\x0e\n\x06silent\x18\x07 \x01(\x08\x12\x1b\n\x13require_interaction\x18\x0b \x01(\x08\x12\x0c\n\x04\x64\x61ta\x18\x08 \x01(\x0c\x12\x42\n\x07\x61\x63tions\x18\n \x03(\x0b\x32\x31.NotificationDatabaseDataProto.NotificationAction\x12\x1e\n\x16show_trigger_timestamp\x18\x10 \x01(\x03\";\n\tDirection\x12\x11\n\rLEFT_TO_RIGHT\x10\x00\x12\x11\n\rRIGHT_TO_LEFT\x10\x01\x12\x08\n\x04\x41UTO\x10\x02\"4\n\x0c\x43losedReason\x12\x08\n\x04USER\x10\x00\x12\r\n\tDEVELOPER\x10\x01\x12\x0b\n\x07UNKNOWN\x10\x02')
|
|
18
|
+
|
|
19
|
+
_globals = globals()
|
|
20
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
21
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'notification_database_data_pb2', _globals)
|
|
22
|
+
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
23
|
+
DESCRIPTOR._options = None
|
|
24
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_NOTIFICATIONDATA'].fields_by_name['vibration_pattern']._options = None
|
|
25
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_NOTIFICATIONDATA'].fields_by_name['vibration_pattern']._serialized_options = b'\020\001'
|
|
26
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO']._serialized_start=37
|
|
27
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO']._serialized_end=1316
|
|
28
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_NOTIFICATIONACTION']._serialized_start=589
|
|
29
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_NOTIFICATIONACTION']._serialized_end=775
|
|
30
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_NOTIFICATIONACTION_TYPE']._serialized_start=747
|
|
31
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_NOTIFICATIONACTION_TYPE']._serialized_end=775
|
|
32
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_NOTIFICATIONDATA']._serialized_start=778
|
|
33
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_NOTIFICATIONDATA']._serialized_end=1262
|
|
34
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_NOTIFICATIONDATA_DIRECTION']._serialized_start=1203
|
|
35
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_NOTIFICATIONDATA_DIRECTION']._serialized_end=1262
|
|
36
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_CLOSEDREASON']._serialized_start=1264
|
|
37
|
+
_globals['_NOTIFICATIONDATABASEDATAPROTO_CLOSEDREASON']._serialized_end=1316
|
|
38
|
+
# @@protoc_insertion_point(module_scope)
|