|
| 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 Any, Union |
| 22 | + |
| 23 | +try: |
| 24 | + from dfdatetime import webkit_time |
| 25 | + from google.protobuf.json_format import MessageToJson |
| 26 | + from dfindexeddb.leveldb.plugins import notification_database_data_pb2 as notification_pb2 |
| 27 | + _has_import_dependencies = True |
| 28 | +except ImportError as err: |
| 29 | + _has_import_dependencies = False |
| 30 | + logging.warning(f'Could not import dependencies for leveldb.plugins.chrome_notifications: %s', err) |
| 31 | + |
| 32 | +from dfindexeddb.indexeddb.chromium import blink |
| 33 | +from dfindexeddb.leveldb.plugins import interface |
| 34 | +from dfindexeddb.leveldb.plugins import manager |
| 35 | +from dfindexeddb.leveldb import record |
| 36 | + |
| 37 | + |
| 38 | +@dataclasses.dataclass |
| 39 | +class ChromeNotificationRecord(interface.LeveldbPlugin): |
| 40 | + src_file: str = None |
| 41 | + offset: int = None |
| 42 | + key: str = None |
| 43 | + sequence_number: int = None |
| 44 | + type: int = None |
| 45 | + origin: str = None |
| 46 | + service_worker_registration_id: int = None |
| 47 | + notification_title: str = None |
| 48 | + notification_direction: str = None |
| 49 | + notification_lang: str = None |
| 50 | + notification_body: str = None |
| 51 | + notification_tag: str = None |
| 52 | + notification_icon: str = None |
| 53 | + notification_silent: bool = None |
| 54 | + notification_data: str = None |
| 55 | + notification_require_interaction: bool = None |
| 56 | + notification_time: str = None |
| 57 | + notification_renotify: bool = None |
| 58 | + notification_badge: str = None |
| 59 | + notification_image: str = None |
| 60 | + notification_id: str = None |
| 61 | + replaced_existing_notification: bool = None |
| 62 | + num_clicks: int = None |
| 63 | + num_action_button_clicks: int = None |
| 64 | + creation_time: str = None |
| 65 | + closed_reason: str = None |
| 66 | + has_triggered: bool = None |
| 67 | + |
| 68 | + @classmethod |
| 69 | + def FromKeyValueRecord( |
| 70 | + cls, |
| 71 | + ldb_record |
| 72 | + ) -> ChromeNotificationRecord: |
| 73 | + record = cls() |
| 74 | + record.offset = ldb_record.offset |
| 75 | + record.key = ldb_record.key.decode() |
| 76 | + record.sequence_number = ldb_record.sequence_number |
| 77 | + record.type = ldb_record.record_type |
| 78 | + |
| 79 | + if not ldb_record.value: |
| 80 | + return record |
| 81 | + |
| 82 | + notification_proto = notification_pb2.NotificationDatabaseDataProto() |
| 83 | + notification_proto.ParseFromString(ldb_record.value) |
| 84 | + |
| 85 | + record.origin = notification_proto.origin |
| 86 | + record.service_worker_registration_id = ( |
| 87 | + notification_proto.service_worker_registration_id) |
| 88 | + record.notification_title = notification_proto.notification_data.title |
| 89 | + record.notification_direction = ( |
| 90 | + notification_proto.notification_data.direction) |
| 91 | + record.notification_lang = notification_proto.notification_data.lang |
| 92 | + record.notification_body = notification_proto.notification_data.body |
| 93 | + record.notification_tag = notification_proto.notification_data.tag |
| 94 | + record.notification_icon = notification_proto.notification_data.icon |
| 95 | + record.notification_silent = notification_proto.notification_data.silent |
| 96 | + record.notification_data = notification_proto.notification_data.data |
| 97 | + record.notification_require_interaction = ( |
| 98 | + notification_proto.notification_data.require_interaction) |
| 99 | + record.notification_time = webkit_time.WebKitTime( |
| 100 | + timestamp=notification_proto.notification_data.timestamp |
| 101 | + ).CopyToDateTimeString() |
| 102 | + record.notification_renotify = notification_proto.notification_data.renotify |
| 103 | + record.notification_badge = notification_proto.notification_data.badge |
| 104 | + record.notification_image = notification_proto.notification_data.image |
| 105 | + record.notification_id = notification_proto.notification_id |
| 106 | + record.replaced_existing_notification = ( |
| 107 | + notification_proto.replaced_existing_notification) |
| 108 | + record.num_clicks = notification_proto.num_clicks |
| 109 | + record.num_action_button_clicks = ( |
| 110 | + notification_proto.num_action_button_clicks) |
| 111 | + record.creation_time = webkit_time.WebKitTime( |
| 112 | + timestamp=notification_proto.creation_time_millis |
| 113 | + ).CopyToDateTimeString() |
| 114 | + record.closed_reason = notification_proto.closed_reason |
| 115 | + record.has_triggered = notification_proto.has_triggered |
| 116 | + |
| 117 | + if not notification_proto.notification_data.data: |
| 118 | + return record |
| 119 | + |
| 120 | + notification_data = blink.V8ScriptValueDecoder( |
| 121 | + raw_data=notification_proto.notification_data.data).Deserialize() |
| 122 | + record.notification_data = notification_data |
| 123 | + |
| 124 | + return record |
| 125 | + |
| 126 | + |
| 127 | +# check if dependencies are in existence.. |
| 128 | + |
| 129 | +if _has_import_dependencies: |
| 130 | + manager.PluginManager.RegisterPlugin(ChromeNotificationRecord) |
0 commit comments