From 752850b9366056a37df0e9c93dc71b0dacb38764 Mon Sep 17 00:00:00 2001 From: tzdwindows 7 <3076584115@qq.com> Date: Fri, 2 Jan 2026 17:49:28 +0800 Subject: [PATCH] =?UTF-8?q?chore(jcef):=20=E6=9B=B4=E6=96=B0=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E6=97=A5=E5=BF=97=E6=96=87=E4=BB=B6=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=88=B3=E5=92=8C=E8=BF=9B=E7=A8=8BID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新了多个JCEF缓存目录下的LOG文件时间戳 - 更新了chrome_debug.log中的时间戳和进程ID - 更新了Extension State、GCM Store、Local Storage等目录的LOG文件 - 保持了原有的缓存数据结构和功能 - 修正了Session Storage目录中的时间戳信息 - 更新了shared_proto_db和Site Characteristics Database的元数据日志 --- language/saved_language.properties | 2 +- library/jcef/cache/Default/DIPS | Bin 36864 -> 36864 bytes .../jcef/cache/Default/Extension State/LOG | 6 +- .../cache/Default/Extension State/LOG.old | 6 +- .../cache/Default/GCM Store/Encryption/LOG | 6 +- .../Default/GCM Store/Encryption/LOG.old | 6 +- library/jcef/cache/Default/History | Bin 491520 -> 491520 bytes .../cache/Default/Local Storage/leveldb/LOG | 6 +- .../Default/Local Storage/leveldb/LOG.old | 6 +- .../Default/Network/Network Persistent State | 2 +- library/jcef/cache/Default/Preferences | 2 +- .../jcef/cache/Default/Session Storage/LOG | 6 +- .../cache/Default/Session Storage/LOG.old | 6 +- .../Default/Site Characteristics Database/LOG | 6 +- .../Site Characteristics Database/LOG.old | 6 +- .../jcef/cache/Default/Sync Data/LevelDB/LOG | 6 +- .../cache/Default/Sync Data/LevelDB/LOG.old | 6 +- .../jcef/cache/Default/shared_proto_db/LOG | 6 +- .../cache/Default/shared_proto_db/LOG.old | 6 +- .../shared_proto_db/metadata/000003.log | Bin 21458 -> 21492 bytes .../Default/shared_proto_db/metadata/LOG | 6 +- .../Default/shared_proto_db/metadata/LOG.old | 6 +- library/jcef/cache/Local State | 2 +- library/jcef/cache/Variations | 2 +- library/jcef/cache/chrome_debug.log | 10 +- library/jcef/cache/first_party_sets.db | Bin 69632 -> 69632 bytes .../jcef/cache/segmentation_platform/ukm_db | Bin 94208 -> 94208 bytes .../segmentation_platform/ukm_db-journal | Bin 4616 -> 0 bytes sql_learning.lock.db | 6 +- .../innovators/box/AxisInnovatorsBox.java | 24 +- .../box/plugins/BoxClassLoader.java | 62 ++- .../box/plugins/PluginDescriptor.java | 84 ++- .../innovators/box/plugins/PluginLoader.java | 507 +++++++++++------- .../box/register/LanguageManager.java | 147 +++-- .../register/RegistrationSettingsItem.java | 2 +- .../axis/innovators/box/window/LoadIcon.java | 246 +++++---- src/main/resources/build/build.properties | 2 +- 37 files changed, 732 insertions(+), 464 deletions(-) diff --git a/language/saved_language.properties b/language/saved_language.properties index 0e7e828..0aafc99 100644 --- a/language/saved_language.properties +++ b/language/saved_language.properties @@ -1,3 +1,3 @@ #Current Loaded Language -#Fri Jan 02 17:08:53 CST 2026 +#Fri Jan 02 17:46:22 CST 2026 loadedLanguage=system\:zh_CN diff --git a/library/jcef/cache/Default/DIPS b/library/jcef/cache/Default/DIPS index 04a913185c9a6ea1abd6c8d0099ef34f26169432..d6c5e741fb20077748d79836ee6463aee3e3602c 100644 GIT binary patch delta 57 zcmZozz|^pSX@WH4;fXTNjE6TSwAjmJFzd3FWag$8#pfgzm&B)K7Nw>z=r8?se}hZd NCWrt0j2Vjp8~|oe79{`x delta 57 zcmZozz|^pSX@WH4p@}lijE6QRwAjm}GwZUIWag$8#pfgzm&B)K7Nw>z=r5g|`d&bH Nlf!?0#`Hx24ggse6(Rrt diff --git a/library/jcef/cache/Default/Extension State/LOG b/library/jcef/cache/Default/Extension State/LOG index 1bc14f0..0d7932f 100644 --- a/library/jcef/cache/Default/Extension State/LOG +++ b/library/jcef/cache/Default/Extension State/LOG @@ -1,3 +1,3 @@ -2025/12/28-14:50:54.309 d58 Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\Extension State/MANIFEST-000001 -2025/12/28-14:50:54.309 d58 Recovering log #3 -2025/12/28-14:50:54.312 d58 Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\Extension State/000003.log +2026/01/02-17:46:55.167 52c Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\Extension State/MANIFEST-000001 +2026/01/02-17:46:55.168 52c Recovering log #3 +2026/01/02-17:46:55.169 52c Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\Extension State/000003.log diff --git a/library/jcef/cache/Default/Extension State/LOG.old b/library/jcef/cache/Default/Extension State/LOG.old index aa8541e..1bc14f0 100644 --- a/library/jcef/cache/Default/Extension State/LOG.old +++ b/library/jcef/cache/Default/Extension State/LOG.old @@ -1,3 +1,3 @@ -2025/12/28-14:19:49.868 bcc Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\Extension State/MANIFEST-000001 -2025/12/28-14:19:49.869 bcc Recovering log #3 -2025/12/28-14:19:49.881 bcc Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\Extension State/000003.log +2025/12/28-14:50:54.309 d58 Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\Extension State/MANIFEST-000001 +2025/12/28-14:50:54.309 d58 Recovering log #3 +2025/12/28-14:50:54.312 d58 Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\Extension State/000003.log diff --git a/library/jcef/cache/Default/GCM Store/Encryption/LOG b/library/jcef/cache/Default/GCM Store/Encryption/LOG index 4c3f223..bc2cce7 100644 --- a/library/jcef/cache/Default/GCM Store/Encryption/LOG +++ b/library/jcef/cache/Default/GCM Store/Encryption/LOG @@ -1,3 +1,3 @@ -2025/12/28-14:50:57.787 24fc Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\GCM Store\Encryption/MANIFEST-000001 -2025/12/28-14:50:57.787 24fc Recovering log #3 -2025/12/28-14:50:57.788 24fc Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\GCM Store\Encryption/000003.log +2026/01/02-17:46:58.729 3d98 Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\GCM Store\Encryption/MANIFEST-000001 +2026/01/02-17:46:58.730 3d98 Recovering log #3 +2026/01/02-17:46:58.730 3d98 Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\GCM Store\Encryption/000003.log diff --git a/library/jcef/cache/Default/GCM Store/Encryption/LOG.old b/library/jcef/cache/Default/GCM Store/Encryption/LOG.old index 2c8e05e..4c3f223 100644 --- a/library/jcef/cache/Default/GCM Store/Encryption/LOG.old +++ b/library/jcef/cache/Default/GCM Store/Encryption/LOG.old @@ -1,3 +1,3 @@ -2025/12/28-14:19:54.454 4760 Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\GCM Store\Encryption/MANIFEST-000001 -2025/12/28-14:19:54.457 4760 Recovering log #3 -2025/12/28-14:19:54.458 4760 Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\GCM Store\Encryption/000003.log +2025/12/28-14:50:57.787 24fc Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\GCM Store\Encryption/MANIFEST-000001 +2025/12/28-14:50:57.787 24fc Recovering log #3 +2025/12/28-14:50:57.788 24fc Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\GCM Store\Encryption/000003.log diff --git a/library/jcef/cache/Default/History b/library/jcef/cache/Default/History index a6308f5fa757f79fc614a52cd7260d67f764ce9b..012663a9fa82f85dd5db13a960f319dba5d141e9 100644 GIT binary patch delta 644 zcmY*VO=uHQ5YFt|dHEs9OSYQC{_J+4CoN>V*)*xWSSz;nAQ417cxX#S8mm|k{|>rQ zF_#ouf<7-oK|NGaBS9ba(2DfZL!pQ$EmExrie9`GrHZ?4bMP|5H#6VN_l<3@Tfeox}VKFua=M|Sc z2|aRXE%Z&~CgDmD8mrMr0@Scf0cu=*@IR;x2>Jy6g3GRevBP9f8D}{*#qP0vtd*76 z4Q8`T?5sFgfiqzkbp)LXA_33`-KY%|v$G(wvyy%>#F%sC_t(_krGob)|BxX^`S@#8 z_+pmaQ53~(e!Ny#C^QZGJ%tlJd^JOQ`OO0)UR>%RVyQ#k^$v;xBiJQLf%~_X(c~8t zyeXSgko{H%f-Z~OSMIALwBheGMtO0_^}$^GGiY(uL+ z4+hy@%^tZPv}h158Nnu?wN;oiD|8D6WW7)CBX(>U*NNRl26ib5vFx`n>T{<+4Me8dS8mp*XVk{`kX&EALcUZ8&U3LBO><` zO>vrLA5Fukz^f@-%ruQx2Qse*#BC=V6zk7eefF}8(Pfw1eg^LdgV-y5xI#xPn7F)I zixCRf;t9f$fAIk5OBi3&$@i||l+eaqNgOzMN4p7(sTw~FXo3F{kH>L>p7&re22+Hi zcq>uc7)F8AF?`A3#;+>_`L4r$=2YDYwTQ2_XV$A&bR{GqctYw;M1& diff --git a/library/jcef/cache/Default/shared_proto_db/metadata/LOG b/library/jcef/cache/Default/shared_proto_db/metadata/LOG index 80d08c0..97426ce 100644 --- a/library/jcef/cache/Default/shared_proto_db/metadata/LOG +++ b/library/jcef/cache/Default/shared_proto_db/metadata/LOG @@ -1,3 +1,3 @@ -2025/12/28-14:50:54.290 22b4 Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\shared_proto_db\metadata/MANIFEST-000001 -2025/12/28-14:50:54.291 22b4 Recovering log #3 -2025/12/28-14:50:54.291 22b4 Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\shared_proto_db\metadata/000003.log +2026/01/02-17:46:55.156 109c Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\shared_proto_db\metadata/MANIFEST-000001 +2026/01/02-17:46:55.156 109c Recovering log #3 +2026/01/02-17:46:55.157 109c Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\shared_proto_db\metadata/000003.log diff --git a/library/jcef/cache/Default/shared_proto_db/metadata/LOG.old b/library/jcef/cache/Default/shared_proto_db/metadata/LOG.old index 53965fc..80d08c0 100644 --- a/library/jcef/cache/Default/shared_proto_db/metadata/LOG.old +++ b/library/jcef/cache/Default/shared_proto_db/metadata/LOG.old @@ -1,3 +1,3 @@ -2025/12/28-14:19:49.851 6ac Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\shared_proto_db\metadata/MANIFEST-000001 -2025/12/28-14:19:49.852 6ac Recovering log #3 -2025/12/28-14:19:49.854 6ac Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\shared_proto_db\metadata/000003.log +2025/12/28-14:50:54.290 22b4 Reusing MANIFEST C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\shared_proto_db\metadata/MANIFEST-000001 +2025/12/28-14:50:54.291 22b4 Recovering log #3 +2025/12/28-14:50:54.291 22b4 Reusing old log C:\Users\Administrator\MCreatorWorkspaces\AxisInnovatorsBox\library\jcef\cache\Default\shared_proto_db\metadata/000003.log diff --git a/library/jcef/cache/Local State b/library/jcef/cache/Local State index e7536a2..3846bd1 100644 --- a/library/jcef/cache/Local State +++ b/library/jcef/cache/Local State @@ -1 +1 @@ -{"accessibility":{"captions":{"soda_registered_language_packs":["en-US"]},"screen_ai":{"last_used_time":"13411376390570760"}},"autofill":{"ablation_seed":"TALAAWR3U5o=","states_data_dir":"C:\\Users\\Administrator\\MCreatorWorkspaces\\AxisInnovatorsBox\\library\\jcef\\cache\\AutofillStates\\2025.6.13.84507"},"background_tracing":{"session_state":{"privacy_filter":false,"state":0}},"breadcrumbs":{"enabled":false,"enabled_time":"13410596638238299"},"browser":{"shortcut_migration_version":"132.0.6834.83"},"chrome_labs_activation_threshold":44,"hardware_acceleration_mode_previous":true,"legacy":{"profile":{"name":{"migrated":true}}},"local":{"password_hash_data_list":[]},"management":{"platform":{"azure_active_directory":0,"enterprise_mdm_win":0}},"optimization_guide":{"model_store_metadata":{},"on_device":{"last_version":"132.0.6834.83","model_crash_count":0,"performance_class":7}},"origin_trials":{"disabled_features":["CanvasTextNg","WebAssemblyCustomDescriptors"]},"os_crypt":{"audit_enabled":true,"encrypted_key":"RFBBUEkBAAAA0Iyd3wEV0RGMegDAT8KX6wEAAADBwqsP1QzrT6MWcdZVJfu5EAAAABIAAABDAGgAcgBvAG0AaQB1AG0AAAAQZgAAAAEAACAAAACB1ryRyzwij1C09/fW7Nq6xYWNYBouyiCtBQVy/dm3CQAAAAAOgAAAAAIAACAAAADbFABSUOggpWGtdyt8gjY1U0KOsQGeTko2gmAW90ZayTAAAADFq9PcgOxeNssHaxgGBueXV4hvHQJJpmfEMZ+q1Evd16SVsDQI/5ryEswRmAd6zwNAAAAAOuqKXbFa23SsXpgg7Pl2JS8o587xUaAWaRKpBdtanJxeqCeHs86s5Xb7UUFCatlPZCByX+JyuenI90CW2C8Ncw=="},"policy":{"last_statistics_update":"13411376389687513"},"privacy_budget":{"meta_experiment_activation_salt":0.8784738491452397},"profile":{"info_cache":{"Default":{"active_time":1763794268.852173,"avatar_icon":"chrome://theme/IDR_PROFILE_AVATAR_26","background_apps":false,"force_signin_profile_locked":false,"gaia_given_name":"","gaia_id":"","gaia_name":"","hosted_domain":"","is_consented_primary_account":false,"is_ephemeral":false,"is_using_default_avatar":true,"is_using_default_name":true,"managed_user_id":"","metrics_bucket_index":1,"name":"Person 1","signin.with_credential_provider":false,"user_name":""}},"last_active_profiles":["Default"],"metrics":{"next_bucket_index":2},"profile_counts_reported":"13411376389699211","profiles_order":["Default"],"show_picker_on_startup":false},"profile_network_context_service":{"http_cache_finch_experiment_groups":"None None None None"},"session_id_generator_last_value":"1067275048","signin":{"active_accounts_last_emitted":"13411376389481478"},"subresource_filter":{"ruleset_version":{"checksum":1588750443,"content":"9.64.0","format":36}},"tab_stats":{"discards_external":0,"discards_frozen":0,"discards_proactive":0,"discards_suggested":0,"discards_urgent":0,"last_daily_sample":"13411376389632063","max_tabs_per_window":1,"reloads_external":0,"reloads_frozen":0,"reloads_proactive":0,"reloads_suggested":0,"reloads_urgent":0,"total_tab_count_max":1,"window_count_max":1},"tpcd":{"metadata":{"cohorts":{"+85uj8UpFJFs1LbZzRODD1aQ+Vs=":2,"+EvRah+wIaVJthrhxHGvfjZWQqY=":2,"+Goy06x/MCwrTV/aHU6CfXEkvHs=":2,"+OlMW5y2ANwBFsH03kShVXYVYM4=":2,"+WavPWcVf6qGVorrutx5lkDvL8g=":2,"+exM1B26jXxhR2Ux05ie/WWp0x0=":2,"+mNvpfM3JkKTeK+6ohl+LXstAC8=":2,"+qkOunaBVbv6XoaIwvMn3m6HluM=":2,"+tsbvVZgVIUs6CaBR9z7zuZH70o=":2,"+xOc8Z8Bc8iWT3jhs1SRha/IbDM=":2,"/AzXcP7UuUNwY1auU8IKM+kO+4A=":2,"/Bvm/Rrh3ZMwqH+/+4QOIcUQPPk=":2,"/FeZnUMHLubMD1MVDBjadEPAlVo=":2,"/HAmLxXpHT88v9y7xE9hHTkgIvM=":2,"/Qdp4MAUrNtjqZV9mfb20WAMugw=":2,"/QxFmTaKVmgoQI7u32pqfP+71Bc=":2,"/aGCDNLRew1LLZH+59lHCuAYNdk=":2,"/hbF3j5JOvAak7vNsAbK79bOP34=":2,"/llw2C0PMltsatGnpTHqrkbluYM=":2,"/oHhyW5YAQhdBpgYcbm1vJyiP+Q=":2,"/rtQf7RE4vMc92KjutC8LkjUZgQ=":2,"/xVDyosmqM6bfIMKyDuRAUI1Qyo=":2,"0Eq8eriICMngC2bt8vmV6V5tJCc=":2,"0OWhcqeF92w5b13FI7cuw0wYOiM=":2,"0b9gyhS7XLqmkmOe5OQuD409YLc=":2,"0gnBMXopl7lReGu+XSk/UzZakLk=":2,"0o2/D9RwYjAcr69AeW+JJDm3uHQ=":2,"0y3W2Bn1Kfxh/5CIvP2vZz5fwTE=":2,"164zkQ1BuqOVnZxlkMScGNXYC8Y=":2,"190T6zIzSL3PTH7lqquaA8KAqVg=":2,"1KHE7JEW3MsvkGFH8et2wPovDqk=":2,"1MfDQw3vHCQqaDa7CJ05y8CkuJs=":2,"1XfEZ7+2f5d1GWbkN5KoDjaQBL8=":2,"1v+25/b3OROEvLwpc+58pTQHvUQ=":2,"24O8PXrKNoFD7n9OiIn/kPM8q1E=":2,"26KadWj8dsla9qY4pbLWwc3WCQY=":2,"2EnXui3e9m8cVkso31bGopul3g0=":2,"2PGjwY0nYdnDLk59gOOl/h012PY=":2,"2W5F+NooL0WF8r0ykkHsqw75NVM=":2,"2ks61ETyiwJVBKjWdeLi+jBzvHw=":2,"2ogzRk2u3FpQekT714FkK0vkFy8=":2,"3IgtLbRDI7pm77T7imadPrRxR5E=":2,"3LIGdlgJ5Rw05ZwZulvKp0JajOw=":2,"3UWlaBDJKI5jNgpXTezvx7uZ7L8=":2,"3dFQSDfXS18fA563uc5mxhMXjLk=":2,"3iGyG3EVKY4vxn8RarUIggZVVkY=":2,"3pCe5f7oscOC94pJnWvhlszLhr0=":2,"3qs39ewgIOr/6zygzv+0ltu0SjE=":2,"3vvP54USUtSZlm/osFRbdXjCN/U=":2,"4+yW/l/2EqzM0fGVj0BcXV5TqDI=":2,"44pYIrJiSE08LkH770bq0wwoNEA=":2,"4TwK5fjrPUvueMXp4HZKGWvCJ0M=":2,"4ZC+GtEmLmHToJys2q2fbofqXeE=":2,"4eXKnzRS6ifFncgprkihsauqdGE=":2,"4qJ4K07ijGN6GmvmTNYzTJYmtRw=":2,"4rqrzEd2r2LoSpwBy3Wd1v4Drtc=":2,"4tQsYPAXpmciDFIC4nUACa9X4Wo=":2,"4vXUVM3Beyj2Rn+4lrrMuX455kY=":2,"55tALpi6iGTNuAMJkIQHrV/h8Zw=":2,"5Mo2uOqOAgDMAFR9xJxpj+Ps9vw=":2,"5Roy+ahYhL8V+JUUKT4pljRssYk=":2,"5UJk8zfVHpYxYI3tEGAQfMrks6k=":2,"6/9fhC6bkvQ+GDnCZzKV5b1uEs4=":2,"6218Tv51tHCkvM+pj15cmmrEp44=":2,"6AuvpHbKzPKvnQ5Iq4ZnJrH7VJc=":2,"6DjDzfLMbfYOmlGOJVAk9WK0yxs=":2,"6Edcp8jwSlxhClh0ZABA7VHryeY=":2,"6HE+xAlLmyPiZz4+IOE6QJR2+qU=":2,"6MJKJThHrZ77JxHeDkpqjqsJmPc=":2,"6S99zH9nPCcQM3Z3Z1tFjU0qI/8=":2,"6WtNqNcKg7znf4yFj/CmTJII+Ik=":2,"6iyZ50rVcsj89+phE3AIAQJ5Rl8=":2,"6sUp2EUK4KkR37GrEyH5Yoqc+Vg=":2,"74ScHGU1kOsGMCDn6+SMbExuJ0Y=":2,"74kVp2Qz/ClJ+826v36FnrVlEmU=":2,"7G9aQ3bdYQZRR5Xfs9AsSwsaPRs=":2,"7JjfkitOjBaGC/olVMv7P7VXegA=":2,"7Q3tTd5EeObvMV4js0wywUGWCDo=":2,"7ZvG0q9vmUTKE/kR/8lnxgr+W9g=":2,"7trRGs2suPfs2j1Fw8il8Ct2I4w=":2,"7ypMXoaWrM++zdAbjUUcvDdl6DA=":2,"84VFR/BgNC855g31gNI+lcgcvK0=":2,"8EArI4IQxFb1Jy5KKpgqxnjYqU8=":2,"8WDNGSYrBtXaSuNuCUcuENOqzbE=":2,"8jVuTrHMGXgJ62nUXx9V7cN/mzM=":2,"8nS7YyD+ru/R67lIeZKe30RKet8=":2,"8tt9aAK5Lm7Zcy9hZvUy06bgxCU=":2,"8ur3KjsVLO0lz7bfhzH5Rz06+fM=":2,"9J2Hjgd0WomJNXCVXUnnFp7HblY=":2,"9MZYN7ZW722NmXNr0I0a6xNGHw8=":2,"9PrZjFg2RssHXVdygP2FMo63tHk=":2,"9UuNM5QRWcp6mYkcu/t/I7FADLw=":2,"9V5BfQG4ZefovfNaXdHkf3YSIbM=":2,"9fj5AS7ShECezTEbos0drF7hGYo=":2,"9kQgpCCVk03s/PvG6sFZp1HUjFU=":2,"9rJ/kzjFOsSGSnyRLXimccFODIk=":2,"A24Vd0mboNwTK86qjAnL5NPT0ew=":2,"A7mJev6l+9dO4av3/tE3zj9JzLY=":2,"ANAAVt1I64nz8zJraV4+sB3bn5M=":2,"AgtaUdyyXGWAAMwjRWqwR8Ni8fk=":2,"AsgodONRHQuPbpgDwflsruAzPns=":2,"BJMwY+kVmXIH7sXwmXK/Q13fPkY=":2,"BVHoUpngEWtu0oY2qTH5s35an88=":2,"Bg6wgMZDYx0+/TxkfcfpqINBID0=":2,"BhE51h7DPwhQMQULRUIC2yvAK0Y=":2,"Bpex3OdFL9MLPykjDHF83THK4XU=":2,"Bxd9P1pUJldfaa0T/bjJ4RryaWE=":2,"C3WnzDhbWkxjLSTmT0Q4X+C5Y0g=":2,"CAPrE/fqgLuDiAW9p2hVJvKDVow=":2,"CBUdQZWRoFXyEsfV+uWNQuCMeFA=":2,"CFfzn2HEP0aH/l6Ix4YZ61KhVaM=":2,"CHJAmkWmDHuhYsu3pfxXnIh7HZQ=":2,"COZfIR9QIUwbad3hWuzoXMpnAN8=":2,"CQDGAq5GGMwFpHfW1z5j8CT63sM=":2,"Cjr9Pmookm1kE1NrmqrajTbbNGQ=":2,"CkEWJOcxrLmlVHE98ZW0fCC7cLo=":2,"CpdpCv4T0/puu4pnh4QKOoEMmAY=":2,"CvqZCPmZan5z33NXlrLvk5mzYrc=":2,"Cvywmg5xUNWlVmE1IlOnnaftKTc=":2,"Cz5dAHQlqdvtLvLtHPDUZiiiu+8=":2,"D7m1f2X1ZclMkgJz6eoxMvjV/BY=":2,"DBJzFXqFvKfiVCuXYUaENduUW+4=":2,"DK9He0ANXehmcN8YZhoASlkBlBo=":2,"DjMDHHpf+nnOnHxm/T1q8y5AoGs=":2,"DptldxPMxrOcxrsoRizh9K9nzEs=":2,"E+JAai/R1FoHjUcPV6PvZ+pFENY=":2,"E6/wFsja05ZZziyq3W/qhIfGjWM=":2,"E6h3qgjEj/9/yT6FUGw6YpUCrEU=":2,"E90biI3zHl/mrbRJIr35sUO1G2A=":2,"ECSWj1Bohkn3n1AWHIMEKlbepxQ=":2,"ELx9iaWnrWA5GpWryrvIbwgayb0=":2,"EYpM3f28E5iXkICbU1lbq13/xDs=":2,"EcH6B6F0qgOh+aDUV+DrOVR8Ag0=":2,"EdIuR7LPx1E9lRrlGHXSFSHL2zo=":2,"EkweGdn7Hj2CcJIpLShtXcn4Z5U=":2,"ErqMWkx4Pxb7qmvS+z+hDqzHXtM=":2,"Ew5jcdiDb1RN24kn4qz0nvhVBRg=":2,"Ewtt2SfL5QqYenyxIDEkC9k3tXs=":2,"F+TX3oARl/flaR0nHt5Js6PSCF0=":2,"FBC4lg/vz1H0FxdIxuTqNU4ZEB8=":2,"FJGJZYWxDCoJrYWPy2BUgtq1HM0=":2,"FRQtGBzKKPjy+HEtL7DsX3Felx0=":2,"FcelBmyYBLBRw/HaUwB9s6j5p3Q=":2,"FmvG9vz/LOjYYeU35txjwm9nZRQ=":2,"Fo02W4qlJUivZslOW61nZcCyA9I=":2,"FxMDzlEZgYp2JToAhAg+/yUllRU=":2,"G37v4qWLagnhBfOYr/ow2BEX8wQ=":2,"G3w71gAwbEQRQHACN74TIHrskus=":2,"GA+aolhIHd7aBXICZM5+0OrHfac=":2,"GBKfC442lwAxRkYbckvrizRO9s0=":2,"GVXlVv4EGFdKXDT5DPw/i710C9c=":2,"GWb9dIET7NeLkFZHxmz/DyBcwvw=":2,"GYhBRDeJahYz7i3JJ/8IyE2P5Oc=":2,"GgzZdRVruTyuSjP6N/LfEPt+Rw8=":2,"Gpss+UglPt1UUU2jy1ZlC2Haaos=":2,"GtCeVEmWQHdw3rryz0AuH5gyJxM=":2,"H3GqtTSpNlUUna7Umw0oI+0NgR4=":2,"H4j81ysGT6UYvop5kplp6lxlqXg=":2,"HABGlXq1BaOVH1Ifx+TyX6oI1c8=":2,"HKs5tNwpPQnqsBWBwrTC+hZGTTk=":2,"HM/pWnlnNgRgj3BUP0fYxxzl73Q=":2,"HPKcn8DkK6LusgLP9nDxVh2uJC8=":2,"HSh4Zm3wQfJIatvBZlrOfUeOfwk=":2,"HeMPvC/blr02FSRJtCharxgmzco=":2,"HmcCaa4SwSvvXXelNnwnv7AJeY8=":2,"Ht53X4lOUdtiGjATCg1fkJrokAU=":2,"HwkleqQc/sC85c17L6GdLZZRy14=":2,"I+7UKSXKSzGBgefFdkILZwsI9bs=":2,"I/ZGfrelShQUfRY9aoFBE2Ey1es=":2,"I5BwwRq++KWQv4ptZSLHGgVymIs=":2,"I9HlcZVHx3L832KLRSQTyyKcszM=":2,"IR5VBOOYDolqu3h+57TkJv62y4Y=":2,"IVYz/Wpt7sibxI0sN4+ORgouym4=":2,"IXYNhiWHet2dJvLpHZUkTrdX3T8=":2,"IYpFc21SFnpXN7O5VIPFH6jzdDU=":2,"IZM2fgogPf28F3qsGfathZESrto=":2,"IbS6gvfuP5iBCntJRl7/kGFWfU0=":2,"IpkxtRCHzfxeCqhGtGlgTZho5PA=":2,"Is6xz79EUUUlkrq+vTsITATIXy0=":2,"IvBIWWt8SMIZYO4zi8CNRQBdMa4=":2,"J0sdM/l3EGX6Frv/rSg7j7GL01Y=":2,"J6lcmiUnipJu3gVcoFiUbu+lbDs=":2,"JCDhMYyv6cBx12AS4NeS46EYq1U=":2,"JNVlxkqEWTvStjmY4qJmC71fnzo=":2,"JTODY14/ed4R5V5Q07Wyq1nHZCs=":2,"JWymogHaDHPgCtgoLPRcgF77J7g=":2,"JX1E7bBowYq/NXrg6uP+3EJOu1E=":2,"JgkRGWnXEHJQ70T82y1m8BrqX3Q=":2,"JslOsSCDdI34ClPlNXHA44C8BdM=":2,"K/m4A4gm9l73A6cVZkwC06VtJOU=":2,"K0pey71AM2vyu7pnYfphijaZFQQ=":2,"KCVNDq0FuwrUaqe8KovMG7Uj3F4=":2,"KCmDv40c4KHL+sZ06jr0iETCE/o=":2,"KHAia59NLQnyXDqGRHyg0ZiaTFA=":2,"KJyIq4mOXhu24VxX9gSFD3D93v4=":2,"KfKkkVLOQcHL8t9vHg9yVAoakwQ=":2,"KixfNZ8p0zlprYxunHrPzxobaq4=":2,"KmZM9Qj7kdUlBfwHt3Ha5IOIaXo=":2,"KnVtOxTqcw8Bj0cILIShIFWDZRU=":2,"Koq5VrYu1jgSuPxzC8JneftbXrY=":2,"KqtJUSyT2ifVLtE+YTa+Jwrew0k=":2,"L/1K37AEimYFLDPtWP00QHs4Y68=":2,"L2SILwi57slYAS17LPKLyjzn//M=":2,"L67fEFjVgKvKrPk8WOq+ypaV0dc=":2,"L8Sb2X7fKyM5N332D0ndTxRV6UY=":2,"LBcANp6Rge+D7JyH+lPItmNHsqw=":2,"LH6IDw2lqWicdgcu+tSQmhjaVvs=":2,"LI77XnWaUgy77p5DAeqIO7vOH14=":2,"LIcUrXtcBWBDTsYmK/hSjTpkhOQ=":2,"LK/nTUZLp4wQL8LSp6SlGXML0Xo=":2,"LLWfG5BXDbqHYtiETKDto5KENC0=":2,"LPP/dWFPHE2kpSUwpzspR7jegbE=":2,"LW/7lCwmMHUj5quQrOys8yKgpSU=":2,"LYaNdeviHa0JUthz/IPOwEOXmQQ=":2,"LZMdcjkdapf2PBM+TcQgrrw5l1Q=":2,"LadD1LUTKp90k3P8uJv25vGYSHI=":2,"LcbdMwrGmghZm+QEi615YhcnzP0=":2,"LhU39BVBhzq0HvhANd7D6dP5Qu4=":2,"LtHcu/ZmzB4KTac2VXn1G9F2+yE=":2,"LxPYBWzEULXwJn7iyMSa8QtD+kg=":2,"M+ZG7S72MQJCJe2aQVcvZoKftWA=":2,"M/Wjwu0AfUQ2o20egq9z+7bIzRE=":2,"MVHNDtRF1gJXlUK/+UZ6MIq+cMk=":2,"MXK6lMxDUXU9R5KLAL2bNOMx//A=":2,"MYnF7KiFcThaEWDO9xNzhikWzZg=":2,"McPp8MRX+uUUktsdxYDRi8o+eos=":2,"MftGgIb+TIwSyHnx7apoYs9NrDA=":2,"MpWCvxXFEf9daTeLjHcm3R/E81U=":2,"MqHL/cxomXHa8ev3atB93jJzbZI=":2,"MuDS3URWGZcyPBilzs4FXRzmboc=":2,"MuuNU16haFees5FcNMYXYToRZfY=":2,"N8NipVw4J3jV3lwC90mjPwfCHxg=":2,"NEHnjJf0uubHBmHAJBilzidYpks=":2,"NF8b22VZThqOOVOFtwz90G+TnlE=":2,"NMjxROmwGnztdYpQh/UAc4Bbnr4=":2,"NQamteBltpv0Ps+H619TiFUCf+I=":2,"NdXqc2xTrq/FN6tgl0gsTiq3F38=":2,"Ne1UYIth2fIOE+GqWmLouOzVGoM=":2,"NeSyTyiMagGROQJlNI8QSaSlBSw=":2,"NgAzcAy15WMJsY2pkT/2GxdgG04=":2,"NmMsYpAfxlJVp0FWodzxuSiHS3c=":2,"O/ynEwzhifwXixFynPqJ/W/oWh4=":2,"O0wSnPIMZPh/STNUh0vac3hUGJA=":2,"OEU7USrAsrnhG8bqMiZ26hK2CNg=":2,"OGH8Nmp74ZiT2sjux1xx41S2tNw=":2,"OJcSYTQfOFc27T/8rITzt7968R8=":2,"OQmSZcXWlR6aMwil6XEKlWcjacg=":2,"OVBSN2PMsKlMAlmaAKYB1cRcoY4=":2,"Obd7ogklY6JivNJCQIXV8d0qDuk=":2,"OjHuY9k7IqD58ta4pJplHxor6YM=":2,"OrjPTpbv6b9JNjns2OKkVTiKM+s=":2,"Ow215V5uWo11K+h3r5uqPKLzJI0=":2,"OzlQr4k8StWsbx6xo25olxpqFPo=":2,"P20wwKcWg8wwuTQl2+Brvgsvt0I=":2,"P2fxs0FUJWvTtwxgQ60U8ShnO10=":2,"PDaqV454hbqksZYGhTh5MEKnTws=":2,"PP/b+e8PPjUMQYS2OBT8GhMPS1o=":2,"PZwAWgz5MHGCT1WnkwTC53E/m9M=":2,"Pmvf6keEdJ2RdJbIEPbC6yjlB2I=":2,"Pn/ePL4HFaa4hTTOIC1z+UcbhSE=":2,"Q7VBdSOn3tXuYecIipApfUrWc0E=":2,"QANgRaF/b2zkl6ZtfzavHjFDGww=":2,"QGhV7+yJFgHnsLlp61izzFLm+8M=":2,"QKSyrWjQ6MjhtW2FNppRoKVNRCY=":2,"Qbrqdt73OY7jzL0r98xuGkILcf0=":2,"QtCZzUY6hCGEqCUTc2M5HNrrs4w=":2,"QuBiJAmt3+xnOmt838WFWkZNBII=":2,"Quz0fwq2iFeVentUcxv7EtGXBgI=":2,"Qy0HTOBuuQRuxmyN6GCjTBI+2MQ=":2,"R7CcmUEwytA73udabElrP9G8sN0=":2,"RF2lGGs4R20QEkXEifuLc5MTiy4=":2,"RIrVY4vPSyEJqz7rQNux/M6K2Uc=":2,"RNUHLVNAftYYrVsfw0XdkUFumwo=":2,"RSTkS8lWrQGjrgVquWcQVopYcRc=":2,"RUj0ztXJ7+kOsCpP9Kv3TDeFJJg=":2,"RVzwez9xPSX1AEn5pHSL/PR1Ak0=":2,"RYWzXqC3fQdwkaxnwdmOPmZixUw=":2,"RbcSJm/cbTD27QN7lN6Us62QIlE=":2,"RnwhHERLjD4kuXuJm44mHsUem+Y=":2,"RpqgmmdI4JgMujDXyfPAuYlQsNc=":2,"RqXHWd3nIsw7tt+RmTWynHdd0X4=":2,"S3CW+p7BtwcbD0fgDCiZ0RAQyjE=":2,"SAo2aVtafLNYHW7zVkEhRT9bh2Y=":2,"SY+bhxGSSGCnz1kQKI5yVUmhEfE=":2,"SYm5CVFkFOVllamvQ9D/tRM1JDw=":2,"SdL3nSP2tifv3D4axuGNQnI2bUc=":2,"Sdit/gOF9Dasz7o9sp6F7f95VxU=":2,"Sf6QB4b+AtQzltHOGfemdKTv/FI=":2,"So1TyGdA4U1tMl43UysxLdrBD+8=":2,"SvBLShco9LDUjRwg1aaiMvtvTFo=":2,"T/wIOHUG39AOmrfsXhUAzuEQY68=":2,"T2+of555wmTbJ2TrkfFXZPtJe6w=":2,"T9Qe0SNV0OBiGFU2oks1F78khLA=":2,"TMo985XELW9v74mmn50qi7dfmbc=":2,"TXp5FPH1q8BqEe/vPr2XzQNN4DQ=":2,"TYN2QA74YpLLdgx/KIWyDC7yWrs=":2,"TmrP6vdRPLfVW5N55bGHKWuqKxY=":2,"ToVZFnRaRPFc+bC+kUfL0o6oVbY=":2,"Twx+PUyhAazRa7zunJLUk7AuLcc=":2,"U/HvDF5lgUDIOvDbP9v5BmirEUs=":2,"U/MXSpdHG3Qh2p/vzyc0aFq/U94=":2,"U3KMQW6Rs95g1UJIi3OsZRqYWvQ=":2,"U7ti2JIQ2rB+nGUoJfrARNYcm/o=":2,"U9A/mkuLQvuMuaD1/0NbkxKJwsk=":2,"UDzrIJUrsqeKvuc/bTIuZnU0+5Q=":2,"UHJJhRN9z3qlaau2hbL1mfcfrI4=":2,"USKrPvDKw/JS/mQnPgXXm0PjWhI=":2,"Ucs6z5K6yxsQzCuxBg8IhFUW1uY=":2,"UyrsycnE0Y34SKsZr4aPMI19T4Q=":2,"V2W3L8FR9XTVZQtEl9UZ76GRaOk=":2,"VC/PaSikiazeBowkWU8F8s8Fbdc=":2,"VXhkGMKyQv4EGmsqXOlEmAdtX8E=":2,"Vus+nTDrUYcfuhZkTwWq8pp72Fo=":2,"W/vJPSCn52d0z02T4zSZuXmUFIo=":2,"W3JXUQpisayYUb8fvciX7mz/LUw=":2,"W79Q1UtfGoRJvjuDwvvCFd/g0g8=":2,"WGcOskzornIFeV5Wbec+z/7T8yQ=":2,"WN6w7LqpMGoL89o4ulIxTcXAttM=":2,"WirG4pLCvHATRD/XepELhtbx2z4=":2,"WybscQ6r1DfHRHCfANqlzsLEfR4=":2,"X+IBU7yum6s8R9EIK1eZ5xNXHzY=":2,"X1hwqKxZESTzs9BvFVN1cudNbU0=":2,"X3CsotjCGLmix01VOhQnaVzerc4=":2,"X3r0cKrB50GCupilXtIT0OsNmNU=":2,"X88GhHdCWKsBm24R727HFAkDr7U=":2,"XIcpBEZDocLvzctDOSolZeZZGMM=":2,"XJGnm7SMThSxDgLYX1WCQCpXIeE=":2,"XXS4Q2MvRlQ3g/5H4ppGQKiDMuc=":2,"XdRdTTf2L82I/5T7+QKhT3Pho24=":2,"XiqKy7gubyO5rqh2hQCzWLmuRP0=":2,"XkVTCFQo/kf96t12VPlUHI7Bsoo=":2,"XlU2doslDe9k2Sjyz+HoF+s4Fuk=":2,"Xmi6obAjhT4C07AkOLr1DrZOYng=":2,"Y+3yeiQnPoLWrymZUS7uiptfvWE=":2,"Y9F1acusJNtR1MKQ9sV/LUbtLcU=":2,"YCITb6CU1HEkdv0e/aMbXU15Bsc=":2,"YCrDNn1PepBzFGwS4liz7EGhd20=":2,"YQX9fwmNvbp79I5BVuG+xSFVcjM=":2,"YXSX9V1CWZmwRJWSO+196koeC7Y=":2,"YeDH3FcQ76eu+6wKfeDV3Z75z4k=":2,"Yv9p2UhdpPR9HiQAehTqepmaOtk=":2,"Z1cXRToCPBewKDIjZhu01gzNgvM=":2,"ZAqPZQWJRYyqIy1vmo7cQCQVpEU=":2,"ZCc7WSp1R56ujdXzRr1nbB6X4PY=":2,"ZIWJDsMLDNK3inlfrSMccHToQv0=":2,"ZN87pxH8AlA0PR/ktFLGAjm8JDc=":2,"ZSyVOd9TPha8GxMzhtgZiF93aZg=":2,"ZcCE53MqfEUAG0OC9vuXsgNygQA=":2,"ZnEawSbVIhbrxvLmTU/51FR3PHc=":2,"Zntf7wQ+SmweAQbnVsys7KRLiCA=":2,"ZtCtW2Sze8YbTG1fS4loW1n3F4s=":2,"ZuT1OewLis1kVKZoBEacnH8c4oQ=":2,"a/06Cc1qCMoW5/jphsMeYfBLXrA=":2,"a13zReUtyPNWrTN/Br6vION4M9k=":2,"aMpjfejGmbvrz24NGwVgyoJWmB0=":2,"aOhZbO9SzuqTcdPglSVnbInJ0HY=":2,"akhZxq2ZypH9U+g8ptVEix2Ys30=":2,"b390+KlW3do0iY5dWxyw/Nvj8y8=":2,"b64LG8t0nZIMAH4frxWe0Xe0lVc=":2,"bAfivuZXv6xQHZCq1H7RdaBGeJs=":2,"bI1Vo/T/gZu6ziJq0A76h0bkQ3A=":2,"cDMRM41OYKodBqf5yPs7PXp7Ibc=":2,"cFGuCTImI1LKaInDPxQtiun7tc4=":2,"cFmOFeeAC2RTc++FepBrbqvZJu8=":2,"cS+k6IBZ28FX5Gu5yS+3rwfash0=":2,"cU2FpWNjt8mGURI0k5QPpMUA1p0=":2,"cVRrJOXl5PBGO3dbZJV8A5XlMQY=":2,"cYEiRDkwdEht5TZ8ftQ2T12/vmI=":2,"cZnefofy4yEnFmkQ0gaP7nfgGBQ=":2,"ccdh7Hta93FtJR+qwt7DElNPqBI=":2,"chKNF84vgaJ1RtQrKV4ytLiKjlk=":2,"ciN5+j5UQseF5/8p+leZThdpwLk=":2,"cnQYSsJdyO+otNbyW42g39tQHFw=":2,"dCGPD+ybLSgoWN7NZsSKWMIMa8g=":2,"dNRX77I/GjMbKJwIPRRuZQnef5k=":2,"dSgRwJW6QXt5Gyti9tvXKOSloVI=":2,"dULO06RXKgWKOnT+2EPWFhzSOzQ=":2,"ddNzLLovIOQAjI1Fuour/azCRPs=":2,"dfVd5Cks1FFJVdNmS+sD4zItmmQ=":2,"dhvEuIu4bREe/yc3n+uWgemDH+Y=":2,"e7QR994kinvEvNi5PEREfEgRBPk=":2,"eIkv3FutAxmGf2Mh7yo0HiDjrls=":2,"ePMMAHx9Ax6ezSppn6dpqbBnLhE=":2,"ex04CvLWFikDWXjGQ4RtjbOeRNM=":2,"f/TYvHakawJF91GiVgpjciGJPc8=":2,"f8cvQ/sraTsg0bwM+aS4D6pFT6I=":2,"f9ysKU6hcNbVfpf1njOmFQ2qbZ0=":2,"fBmcT7XNbLpOQsfKdgdXEdc1P38=":1,"fLj05EfmTLEt58m3jVUhPVS04sU=":2,"fMus4OBg1K5k+k8tLnAZyRBbnLY=":1,"fa4i6qfS5+dDiDVKFZDjsFnF6Rc=":2,"fnRvo3ItSPsvU3LKSXBRXJg0FUs=":2,"foNSnwHq8ph3wPaXJ8I88LehpI4=":2,"fuy5x4yKH5LLTw4kz6c1pnFiOcQ=":2,"g0FiO0sC3nMBLvy49sLKeESA7h0=":2,"gCgo0usJBkT8uf+0XUuS3gWGdoA=":2,"gJJSwVtCLng5e1xxugIzmlnHbd4=":2,"gJK5pMWuNFrD9OGNIgKananYNSo=":2,"gMpTRAKA7Ayl+W/YVqQhr5GU6x0=":2,"gSTTNamgmAMk2//gdb5jcZMN9AQ=":2,"gqGHjniFghep8E6txoAdzX/4h3M=":2,"gr0I/I6o5WZbCX3ANuvNoagEEe8=":2,"gsU6EH/i8w1ThrqsEm6GK79feO4=":2,"gtc5hvQud0vqhMhm2fmcV4S+Agc=":2,"gxn+9RnfotKjIQsWN6Ldd6tJFwQ=":2,"hGJJ6Hh+MF5i2sXu2g4Yz8nZwHs=":2,"hJM03Qy65rIixL+QnwFnZUWdS7o=":2,"hRdDjllKxVjmSDiRpxs+uOUT9Q4=":2,"hl/Ql44a9B+9BQR34dUhENrlIJ4=":2,"hmt01LHgEU30nJb6VMA41XMWRyg=":2,"ho9bP3IJ21F4d3qP3pTJA0JkTj4=":2,"htyr9QaPXQOHGsfVmr+97oeW0UM=":2,"iBD/DGiehe+56IosGVlv3c1wJ3Q=":2,"iD9S1fFa6FpM5DcIk5pQUCSj4aw=":2,"iGzRH+UPc4Ea3ApuY49us3/XCaA=":2,"iHnWlD4n0QHbXoUv3k90wclViuU=":2,"iXvZsH9NpG0qHURLzLTudfP9aeU=":2,"ihQuIV4rmAFYvTr6lwMV4HokREI=":2,"ihRhUKLVahjKDEOmS0BbYyhgv7k=":2,"ipbKvdY2LsQlCcEkuSqe8v4By6g=":2,"ipt6XYj9NCIb0hWN8BbyXEF5DfQ=":2,"irephTXGVO+MmlZ2AS7MbB5AyLM=":2,"j+6DOgEHMZgTIWSHhf9CjmUGIK8=":2,"j+GDvmG+Am9Xd+4Q/XDAlrQrFz4=":2,"jAuqNF/yhbdqVNpoWw+2Jo6e6bs=":2,"jEtGDH1uWCTHnmHc2bGPDrpEHCg=":2,"jODdAGIb3/eRchqP2DHAiTYlP0Y=":2,"jQfCzjp4d/PizsLo5UpdD2f8www=":2,"jUoBtJ03/Xr45tg4Dqenc5cYWAU=":2,"jVgQocUsQaH7V/2UxhLVOidhP20=":2,"jYhk6dm72WAaxSdjIvOSNJ3d0sE=":2,"jaMkW1knsztb/0+GNCKx6G/SzaI=":2,"jc0TPKjiMVneKPNeY2avjLI9KVY=":2,"jq2rGPyUu7grG5FJi/I/qcKLKg0=":2,"k/v8xkMt57fg28L2fh73gxXa4Yc=":2,"k1J17FRo3myPzj+UE+LXaZ9ohSc=":2,"k3bwFkPXH/EDNGF7Npn6kwKJu6Q=":2,"k7hYQMMCyKjXIXP+LR8U+d3GIzQ=":2,"kDJnIwokySTxXp20eRGTskuMM9c=":2,"kLV2LBNc1aIFljjZItvqx2bhY1U=":2,"kMGe+97jR78zimxmtL9Ak8a0OHw=":2,"kOvgd336AvzRZ7zhd6KqxVNyMiU=":2,"kYI0w0yGJWsEW8mUvaWKX5BGN34=":2,"kYvIeNAo8XJrY0sLt9RkQb/ArLk=":2,"kbEmSJ7AT4IyCib5dANoydcLsmE=":2,"kfmukk3rEZbsice63or/akfPSU0=":2,"l1TwOsy32JiZV/bM26UQ8oCnn7k=":2,"l1l9LWMnuHXWDBSLcfQ3Zp7bVVk=":2,"l38tVXmuuGlAgD9a3eXwX/jQwgI=":2,"lHA+dhHLhlHLq/O+0+Xz7buufJ4=":2,"lJcNksg20bY6CgGPqZu5aQHbRhE=":2,"lUbDYyCRhvBzS0nDrz8rx/nq0A0=":2,"lUfzJ3y5Jzs7p4PBHh4xhm+zoG8=":2,"lV/IOzmMkT+d9gXfFgqtsErYe2M=":2,"lY3+bGoDRF7A0eSICXUJ1yfpxo8=":2,"lZpQb3elaMvd1gsI/plZxcpUVwY=":2,"lcXOtK8KVWFVeHE4WLEewHPCWWY=":2,"ldPbP2/DX6N+AldQ7AFtoht/Bvc=":2,"lhONN2tBTBA/tSnMtizicuNBPLU=":2,"lmXhk+G6r/qbCMYZcVdJbnn+93I=":2,"mEj21qtta3LLlAxWkZ8sijZvktM=":2,"mSNPvAXxob4waWjBxs3ziW6z71g=":2,"mYby0t8WAz6jV9RgYIRRGyfeWB8=":2,"mg1zJLHTYaJIMLNxa+rsYWsZJhI=":2,"mh3wxEYkuAk6sRhlr/C5G/gxYRI=":2,"miEzBOZuMem0Cj9Uxw1LjN9S9cw=":2,"mlWAbHBzQ5Td8U9HSp8fcPdPyzQ=":2,"mmci9ejkh1yqEt/tTbqbQeSaSwI=":2,"mqI5UE1zlvwODeiYkE+97gk/N38=":2,"mv8xDlT2/YhQtkLKnptz6SQB5uM=":2,"nAj3Ny++JKnx/3X/T3HRcVSVXN0=":2,"nHcOob6uJ8APh5510nMH7Ikg5XI=":2,"nNG/hSMKDgXudXzByhmJ+8Udww8=":2,"o/9SDeB9XVwuJyTLitMsvbgaQKg=":2,"o1UwUqLfJmuxKSuFfNRz/EzR9So=":2,"oHsvpBtYgeqeqVOdT/DQDeNAyp8=":2,"oIsMwEfYOTvIzVNKHP6nF5RhkVk=":2,"oNPOB+kuiVqZt91Ceva1HD2babU=":2,"oNrKGepVbapve5qoLE4s7JK926I=":2,"oVr3ZmvWmeO5V4lOW6+8gEGE5YY=":2,"oX3Jk2hkzKOTCsCjIb8aBoEQxCY=":2,"oc/SFHoD/b37HnDYvDl1S+Ln8+o=":2,"odROFyqXD/frsFAhnWAK7yW9p1E=":2,"oibx5gMRdevDCHgIZ8xHbhmCom0=":2,"pCDKhit9yDclLI07LYJ2Arec58E=":2,"pFBMDn/qQ2sU3hbTzN0XE+gPNlE=":2,"pGtFao+Eqv0xw/MJ4ne73wMtss0=":2,"pKocQQbERh0k2bBtqqHvsL6IzwY=":2,"pQbhy62y3+Jaimld0fQXsr90MPU=":2,"pSQhqungWlpbyd5qgvoDgc7AE/E=":2,"pXA8CdPQ2YBCgTcuH0u3ji94FpM=":2,"pj/VyHVWYMY781dFmsalRMjAdng=":2,"po8Y5k48QpkNI3OQK3HJSajJvIk=":2,"qGuRw9GZC5DTd5qdb/ri4A76b90=":2,"qX+92itsZYUdfyqVnkRNS1z8pEg=":2,"qhL0XSJvQoCDATRSMO6uHK6s0AE=":2,"qnTJ6qWlEO3mGlvjzZxRj1SWBSg=":2,"qpvlQsYaJOxyL6Vr9sOa7itTjWg=":2,"qtTOojYzivrM05kWyMG+4B3oavI=":2,"qxM7PjtM2REivHU89TUKjRFyX/c=":2,"r2jAg5LKs99/R7UDy7n+RVExthw=":2,"r66x+/C7gcK0ek2UGYaFgDG9W7A=":2,"r7iJmf1gYZfcG8O+Vd5YotXOO98=":2,"r7yFRxkCgT3Oeq05RWA9OtXpSI0=":2,"rBvqswHFQGNJ+GA8LqPPr3KtF+8=":2,"rEMdbHd/v8VQAKMX0knLaZEP8KI=":2,"rFDwZivZT0u0vRe8Vj180HEOHEI=":2,"rPu9e+cSQCdzkKfYpDy9vIMdrTU=":2,"rSlZi3H7e2ESXD48TLSxA+uHjp0=":2,"rVsxB7wqXgKFK40cRaUdv5100/8=":2,"rXmjfschRYJInGVNNv9jGIRrjJ4=":2,"rXtx9FDQjNrYAd+Xt+sv0IjIaJ8=":2,"rc4WJXNzddjdAyW+WERMtKMaYYI=":2,"rjWw31OACJd76/zAEVPT3BCWrpE=":2,"rp1qUhW5AwlfEo+FC5F3v84IJG4=":2,"rzbYuWFx8KRHnLGL8HtL+0dJhIo=":2,"s6btLO7QAG1u99wehXlGkxKUb0Y=":2,"sD67cLr9VrAeoarwQnBVmBOjfCs=":2,"sDK4hQp8T2RmWpWvgnHk6FQ2iwM=":2,"sIl513b2C2/QeDrHSuBpH2c6C0k=":2,"sL1dde8EjkxF+Lb89yeCnsBYBOU=":2,"sNAV48ni/e0b7Gn9jEfM3Q3dVe8=":2,"sPTnbQmrNOyx/qW0Xu4g4cu0aR4=":2,"siHaDi1iEPE3xPgGISfpfwb8h4M=":2,"skXg82RVCi6BZHNRI23RIG2DRC4=":2,"sunLW+vgbWmbUrarV07NcFmnKgE=":2,"t/DNJowu9uHR/kBc3bc1Nm7+9lo=":2,"t97bh7mYz2gwiY6nU+/w1i9dgZU=":2,"tBZZ8SUVG/FjRUpROxHXX3KaCyw=":2,"tK2lpUcycitAF1Et7B+/ZhiQ0ZM=":2,"tPPRnCQb4zC0dD4BJYFC6KAMVWw=":1,"tR2fhHtwBTc9bKHWDB/g0JFDNBY=":2,"tWRGM3CFPPslofcsSqj6vpcd7JU=":2,"uBMu4M5/0KKZY37hxUNLN39LPtA=":2,"uKsvvIzSMOyMR+4LPExkT1A8iDA=":2,"uNmw0kNAuK13LWxLuTZiaO140LY=":2,"uSACpi6t4iSWKjHFN6UHju08OB4=":2,"uf4z/h0h9ZnyOD7ycAiwgx/aHFo=":2,"unvMMzjFrurZix1N1pOtUC+RriY=":2,"utfiG74gl+SIxnKipbPl66ZNVWc=":2,"v6RXBuPtNohU+Lb6MHwV9z4lt1w=":2,"vD6n6Z9JW8prLB0rVlTt/g+4cCI=":2,"vDX9FACK55aBjFOaPdncKX2o+Bg=":2,"vW9hX9bdu7jEnh05U+zjXI+SbA8=":2,"vWbt1X54cCEDXSdUl4qpqdCohNE=":2,"vYmUY3JR7HpU6cV3sp31ubgx+YE=":2,"vqAjPDOmXZGBn833qAWFeo1PtsU=":2,"vqaClXLm/YZ8MhiUAukne10yy/o=":2,"w1vJ0NG9kDFtUNHq8zCMuDUVb8M=":2,"wAsstIPtDtjSlxUGn0gh+TfTWmQ=":2,"wJ4TJKlTMrrNezUg8dfBuOltq4U=":2,"wK4Zb71UwMahGOQFp0E3RYeMfYw=":2,"wZinPjTdOm5rrXI4u1NIKiffmp8=":2,"wib9u5YbRGJAqT5Bvh9zNZp4iTY=":2,"wqO+JoG3Un7fd2bDdvRxfAhbJ3Q=":2,"wr9Z2KN9f3Tq2jo3nTe3DpsNr54=":2,"wv3DmXgFeOrq/dbsherqtSjmrO8=":2,"x4c04qHrWNjtvJ2XgQQpd7wW1rA=":2,"xFo5PPJwZaq7i4dWLyzXeywAOEY=":2,"xUJ/eh98DaHs0DxWLA9fYYD6PzM=":2,"xgEKSqpgWJmo+flxFClV2/NiOJk=":2,"xjHJCBSoTdEQjebMV8aARzFcEkA=":2,"xm3y8sIKteMNAiUYEkt/ocEG7VI=":2,"xoxgp5Cx/yYkyO4yumq70s+D5t0=":2,"xtOFUD8jRLwrgCyGI5QnD7K+CG0=":2,"y0OlqPMUw6B8jvG1d2F9DOvkDp4=":2,"y2Kf0efsIVsF8PYgZBOV7tc5AfM=":2,"y2QRZhLYezQlVyzaDO4PEKbAmAc=":2,"yAXQT+zYHydb1uUhkuwtxm5At5k=":2,"yAyH2ZVkhzgat7fcC+nSDXQ11jw=":2,"yKtZdPSQMfJNQVKjIJ6noDw07mQ=":2,"yM5jN0VjPFKIKpUqRuN5KyRPd94=":2,"yad44gD7FAnezf8DgiIRZiDGlRY=":2,"yekkHNxtLVYK9WvooNiEKVWXabA=":2,"ykSAQyJm33Umehd0Txp/8rpum2I=":2,"yx1gN4z+x0naLVTbhc4/HO1c7cY=":2,"yzJqCQsowhulZe3Hx/xsWOvlTbw=":2,"z6CTfToXHCMt/46aowVDcKOYuL8=":2,"zAmtiHUH7ncF4kcOLIROCCAtn5Y=":2,"zTzCkN1zga1linYQP6v2AyMYW5w=":2,"zd+y/4GyfV5LQFAHFVfIKQuur+U=":2,"zejOvMNeql2wesKjXICcANkzyPM=":2,"zvV3Pm+WpZE4xD79k4mjhrJu0gw=":2,"zwzjvFMamlRnd5MSmg2F0LgPqso=":2,"zydtsLKKSp4EUItk7o34H/+dTNQ=":2}}},"ukm":{"persisted_logs":[]},"uninstall_metrics":{"installation_date2":"1746408261"},"updateclientdata":{"apps":{"eeigpngbgcognadeebkilcpcaedhellh":{"cohort":"1:w59:","cohortname":"Auto","dlrc":6935,"fp":"1.4497d8060d0e53c12b4403aa9ebe7e827d4880bae3f4139a26a4feb7ed64c4a2","installdate":6698,"max_pv":"0.0.0.0","pf":"a7c41bd0-3c83-4e42-901d-169858797d5f","pv":"2025.6.13.84507"},"efniojlnjndmcbiieegkicadnoecjjef":{"cohort":"1:18ql:","cohortname":"Auto Stage3","dlrc":6935,"fp":"1.160aa782aaa39e7b812a5e5e2c7c2f8a56e21d5ea84b92cd1f493cb384b4fdbd","installdate":6698,"max_pv":"1517","pf":"cfb54599-5524-42a6-94a9-4eb611f3e3cc","pv":"1532"},"gcmjkmgdlgnkkcocmoeiminaijmmjnii":{"cohort":"1:bm1:","cohortname":"Stable","dlrc":6935,"fp":"1.ed43e732234cc8b79a137be0a0aab8f72b37ae6ca51caf1292986edbf618c1d1","installdate":6698,"max_pv":"9.62.0","pf":"70407188-dbff-4402-b862-c453dfa9314d","pv":"9.64.0"},"ggkkehgbnfjpeggfpleeakpidbkibbmn":{"cohort":"1:ut9/1a0f:","cohortname":"M108 and Above","dlrc":6935,"fp":"1.4795b6d7d7c2e0878abbb461850eb2068971273643901fd992814b9bfaff202b","installdate":6698,"max_pv":"2025.12.11.120","pf":"1b4be169-15e2-43bc-8bf6-d1d524b6b814","pv":"2025.12.25.121"},"giekcmmlnklenlaomppkphknjmnnpneh":{"cohort":"1:j5l:","cohortname":"Auto","dlrc":6935,"fp":"1.3eb16d6c28b502ac4cfee8f4a148df05f4d93229fa36a71db8b08d06329ff18a","installdate":6698,"max_pv":"0.0.0.0","pf":"7107732a-c529-4ad6-9b5b-328d37f7e207","pv":"7"},"gonpemdgkjcecdgbnaabipppbmgfggbe":{"cohort":"1:z1x:","cohortname":"Auto","dlrc":6935,"fp":"1.56c21927faa028be6ce18c931660eec37e41da4bfbfd47cafa48350f828c0dbd","installdate":6698,"max_pv":"0.0.0.0","pf":"20cde327-dc74-409f-9beb-1f9bf7fdd0ab","pv":"2025.7.24.0"},"hfnkpimlhhgieaddgfemjhofmfblmnib":{"cohort":"1:287f:","cohortname":"Auto full","dlrc":6935,"fp":"1.b8b379861bbe9bedb44834d307c8b3c21d4f55774170c504f18d0ab36bb712ca","installdate":6698,"max_pv":"10215","pf":"687bf388-c31f-48fa-bea6-96ccb0f88c32","pv":"10244"},"jamhcnnkihinmdlkakkaopbjbbcngflc":{"cohort":"1:wvr:","cohortname":"Auto","dlrc":6935,"fp":"1.c52c62a7c50daf7d3f73ec16977cd4b0ea401710807d5dbe3850941dd1b73a70","installdate":6698,"max_pv":"0.0.0.0","pf":"ff9c160a-d447-4bc7-80ab-16f8c90cb229","pv":"120.0.6050.0"},"jflhchccmppkfebkiaminageehmchikm":{"cohort":"1:26yf:","cohortname":"Stable","dlrc":6935,"fp":"1.4a06cfbce6f26c81ec6cba52e84985c0111183e0b06a953b14992b4511bb78af","installdate":6698,"max_pv":"2025.10.5.1","pf":"175712a1-15a0-463c-90d0-04c4d321d8d4","pv":"2025.10.7.1"},"jflookgnkcckhobaglndicnbbgbonegd":{"cohort":"1:s7x:","cohortname":"Auto","dlrc":6935,"fp":"1.220f906777a5ca8a28c0d7bb742912805fb6f93b262abc897f372213fc9841ef","installdate":6698,"max_pv":"3087","pf":"d7718e53-e47c-423a-935d-ab3fcaa74607","pv":"3088"},"khaoiebndkojlmppeemjhbpbandiljpe":{"cohort":"1:cux:","cohortname":"Auto","dlrc":6935,"fp":"1.03c55f4f45c2a62c467f5bcf7e3fbee31e9ec27abeccefed06adc927cdf52968","installdate":6698,"max_pv":"67","pf":"ad1225a1-3ff5-4d2c-a148-d5509cbe32fe","pv":"144.0.7512.1"},"kiabhabjdbkjdpjbpigfodbdjmbglcoo":{"cohort":"1:v3l:","cohortname":"Auto","dlrc":6935,"fp":"1.caf22da361a099ee7f504cfd6018872cff61e16946d0a5a57fb07c529bfa8072","installdate":6698,"max_pv":"2025.8.25.1","pf":"937aa6d2-50a6-42e7-b621-e70874ad8247","pv":"2025.9.29.1"},"laoigpblnllgcgjnjnllmfolckpjlhki":{"cohort":"1:10zr:","cohortname":"Auto","dlrc":6935,"fp":"1.e444ba601ac72b669514e6788bc458ac6b4a3f4400f18ad9b297a84eb27009e5","installdate":6698,"max_pv":"0.0.0.0","pf":"a49039e1-db95-4348-87a1-81ff5be2c18a","pv":"1.0.7.1744928549"},"llkgjffcdpffmhiakmfcdcblohccpfmo":{"cohort":"1::","cohortname":"","dlrc":6935,"fp":"1.2be74d0afadd4c9b2ee33695e1f81fc5ce5dc3016cd8a13cfa0e1f0b571834ea","installdate":6698,"max_pv":"1.0.0.18","pf":"5071b6f0-b254-4497-b7cd-f8cf157ce30d","pv":"1.0.0.19"},"lmelglejhemejginpboagddgdfbepgmp":{"cohort":"1:lwl:","cohortname":"Auto","dlrc":6935,"fp":"1.c1d25adf4d9c55d12a550bfe02e87c267561e95b35079841966ba57bf10a6d9e","installdate":6698,"max_pv":"587","pf":"212b94da-4152-4f6a-b78f-27282f9e1eb4","pv":"595"},"mfhmdacoffpmifoibamicehhklffanao":{"cohort":"1:1ge3:","cohortname":"Stable","dlrc":6935,"fp":"1.a10a891103c69736b97d77dd5fa1ce1ffd77a0c8bc3aea6162df0423933e0755","installdate":6698,"max_pv":"140.10","pf":"d0a1fb9b-e723-4545-bd2e-40993a35724a","pv":"140.12"},"niikhdgajlphfehepabhhblakbdgeefj":{"cohort":"1:1uh3:","cohortname":"Auto Main Cohort.","dlrc":6935,"fp":"1.38c89b12bb20a8f2751c9c7cd2e31c173a47af08c115e1ecccc2f5151a2cf2c6","installdate":6698,"max_pv":"0.0.0.0","pf":"94565b0e-974c-4509-bb20-8c29fd335abd","pv":"2025.6.16.0"},"obedbbhbpmojnkanicioggnmelmoomoc":{"cohort":"1:s6f:3cr3@0.025","cohortname":"Auto","dlrc":6935,"fp":"1.f0fac1ffee516ccd1505ec8a51acfa6d9c4fca45d78de2059eceaf3dde376216","installdate":6698,"max_pv":"0.0.0.0","pf":"9b5ea977-cbb8-4a67-953c-f3ea4b1c4c1c","pv":"20250629.778704241.14"},"oimompecagnajdejgnnjijobebaeigek":{"cohort":"1:3cjr:","cohortname":"Auto","dlrc":6935,"fp":"1.92ac4503d850d61341c2b89b0ca25ae45a875f85e7ab7018354cef9a0b37bba7","installdate":6698,"max_pv":"4.10.2891.0","pf":"697db852-419d-4b11-97da-b1a2a3e3a498","pv":"4.10.2934.0"},"ojhpjlocmbogdgmfpkhlaaeamibhnphh":{"cohort":"1:w0x:","cohortname":"All users","dlrc":6935,"fp":"1.545666a4efd056351597bb386aea1368105ededc976ed5650d8682daab9f37ff","installdate":6698,"max_pv":"0.0.0.0","pf":"e1d81574-5b38-40e0-9816-db9a7ed09aa6","pv":"3"}}},"user_experience_metrics":{"limited_entropy_randomization_source":"347548CD8B793C0E43E5BEDEBC391338","low_entropy_source3":5052,"machine_id":5183260,"pseudo_low_entropy_source":2545,"session_id":538,"stability":{"browser_last_live_timestamp":"13411378254176799","exited_cleanly":true,"stats_buildtime":"1736279424","stats_version":"132.0.6834.83-64-devel","system_crash_count":0}},"variations_crash_streak":594,"variations_google_groups":{"Default":[]},"variations_limited_entropy_synthetic_trial_seed_v2":"48","was":{"restarted":false}} \ No newline at end of file +{"accessibility":{"captions":{"soda_registered_language_packs":["en-US"]},"screen_ai":{"last_used_time":"13411820815912680"}},"autofill":{"ablation_seed":"TALAAWR3U5o=","states_data_dir":"C:\\Users\\Administrator\\MCreatorWorkspaces\\AxisInnovatorsBox\\library\\jcef\\cache\\AutofillStates\\2025.6.13.84507"},"background_tracing":{"session_state":{"privacy_filter":false,"state":0}},"breadcrumbs":{"enabled":false,"enabled_time":"13410596638238299"},"browser":{"shortcut_migration_version":"132.0.6834.83"},"chrome_labs_activation_threshold":44,"hardware_acceleration_mode_previous":true,"legacy":{"profile":{"name":{"migrated":true}}},"local":{"password_hash_data_list":[]},"management":{"platform":{"azure_active_directory":0,"enterprise_mdm_win":0}},"optimization_guide":{"model_store_metadata":{},"on_device":{"last_version":"132.0.6834.83","model_crash_count":0,"performance_class":7}},"origin_trials":{"disabled_features":["CanvasTextNg","WebAssemblyCustomDescriptors"]},"os_crypt":{"audit_enabled":true,"encrypted_key":"RFBBUEkBAAAA0Iyd3wEV0RGMegDAT8KX6wEAAADBwqsP1QzrT6MWcdZVJfu5EAAAABIAAABDAGgAcgBvAG0AaQB1AG0AAAAQZgAAAAEAACAAAACB1ryRyzwij1C09/fW7Nq6xYWNYBouyiCtBQVy/dm3CQAAAAAOgAAAAAIAACAAAADbFABSUOggpWGtdyt8gjY1U0KOsQGeTko2gmAW90ZayTAAAADFq9PcgOxeNssHaxgGBueXV4hvHQJJpmfEMZ+q1Evd16SVsDQI/5ryEswRmAd6zwNAAAAAOuqKXbFa23SsXpgg7Pl2JS8o587xUaAWaRKpBdtanJxeqCeHs86s5Xb7UUFCatlPZCByX+JyuenI90CW2C8Ncw=="},"policy":{"last_statistics_update":"13411820814994139"},"privacy_budget":{"meta_experiment_activation_salt":0.8784738491452397},"profile":{"info_cache":{"Default":{"active_time":1763794268.852173,"avatar_icon":"chrome://theme/IDR_PROFILE_AVATAR_26","background_apps":false,"force_signin_profile_locked":false,"gaia_given_name":"","gaia_id":"","gaia_name":"","hosted_domain":"","is_consented_primary_account":false,"is_ephemeral":false,"is_using_default_avatar":true,"is_using_default_name":true,"managed_user_id":"","metrics_bucket_index":1,"name":"Person 1","signin.with_credential_provider":false,"user_name":""}},"last_active_profiles":["Default"],"metrics":{"next_bucket_index":2},"profile_counts_reported":"13411820815005226","profiles_order":["Default"],"show_picker_on_startup":false},"profile_network_context_service":{"http_cache_finch_experiment_groups":"None None None None"},"session_id_generator_last_value":"1067275100","signin":{"active_accounts_last_emitted":"13411820814826676"},"subresource_filter":{"ruleset_version":{"checksum":1588750443,"content":"9.64.0","format":36}},"tab_stats":{"discards_external":0,"discards_frozen":0,"discards_proactive":0,"discards_suggested":0,"discards_urgent":0,"last_daily_sample":"13411820814933199","max_tabs_per_window":1,"reloads_external":0,"reloads_frozen":0,"reloads_proactive":0,"reloads_suggested":0,"reloads_urgent":0,"total_tab_count_max":1,"window_count_max":1},"tpcd":{"metadata":{"cohorts":{"+85uj8UpFJFs1LbZzRODD1aQ+Vs=":2,"+EvRah+wIaVJthrhxHGvfjZWQqY=":2,"+Goy06x/MCwrTV/aHU6CfXEkvHs=":2,"+OlMW5y2ANwBFsH03kShVXYVYM4=":2,"+WavPWcVf6qGVorrutx5lkDvL8g=":2,"+exM1B26jXxhR2Ux05ie/WWp0x0=":2,"+mNvpfM3JkKTeK+6ohl+LXstAC8=":2,"+qkOunaBVbv6XoaIwvMn3m6HluM=":2,"+tsbvVZgVIUs6CaBR9z7zuZH70o=":2,"+xOc8Z8Bc8iWT3jhs1SRha/IbDM=":2,"/AzXcP7UuUNwY1auU8IKM+kO+4A=":2,"/Bvm/Rrh3ZMwqH+/+4QOIcUQPPk=":2,"/FeZnUMHLubMD1MVDBjadEPAlVo=":2,"/HAmLxXpHT88v9y7xE9hHTkgIvM=":2,"/Qdp4MAUrNtjqZV9mfb20WAMugw=":2,"/QxFmTaKVmgoQI7u32pqfP+71Bc=":2,"/aGCDNLRew1LLZH+59lHCuAYNdk=":2,"/hbF3j5JOvAak7vNsAbK79bOP34=":2,"/llw2C0PMltsatGnpTHqrkbluYM=":2,"/oHhyW5YAQhdBpgYcbm1vJyiP+Q=":2,"/rtQf7RE4vMc92KjutC8LkjUZgQ=":2,"/xVDyosmqM6bfIMKyDuRAUI1Qyo=":2,"0Eq8eriICMngC2bt8vmV6V5tJCc=":2,"0OWhcqeF92w5b13FI7cuw0wYOiM=":2,"0b9gyhS7XLqmkmOe5OQuD409YLc=":2,"0gnBMXopl7lReGu+XSk/UzZakLk=":2,"0o2/D9RwYjAcr69AeW+JJDm3uHQ=":2,"0y3W2Bn1Kfxh/5CIvP2vZz5fwTE=":2,"164zkQ1BuqOVnZxlkMScGNXYC8Y=":2,"190T6zIzSL3PTH7lqquaA8KAqVg=":2,"1KHE7JEW3MsvkGFH8et2wPovDqk=":2,"1MfDQw3vHCQqaDa7CJ05y8CkuJs=":2,"1XfEZ7+2f5d1GWbkN5KoDjaQBL8=":2,"1v+25/b3OROEvLwpc+58pTQHvUQ=":2,"24O8PXrKNoFD7n9OiIn/kPM8q1E=":2,"26KadWj8dsla9qY4pbLWwc3WCQY=":2,"2EnXui3e9m8cVkso31bGopul3g0=":2,"2PGjwY0nYdnDLk59gOOl/h012PY=":2,"2W5F+NooL0WF8r0ykkHsqw75NVM=":2,"2ks61ETyiwJVBKjWdeLi+jBzvHw=":2,"2ogzRk2u3FpQekT714FkK0vkFy8=":2,"3IgtLbRDI7pm77T7imadPrRxR5E=":2,"3LIGdlgJ5Rw05ZwZulvKp0JajOw=":2,"3UWlaBDJKI5jNgpXTezvx7uZ7L8=":2,"3dFQSDfXS18fA563uc5mxhMXjLk=":2,"3iGyG3EVKY4vxn8RarUIggZVVkY=":2,"3pCe5f7oscOC94pJnWvhlszLhr0=":2,"3qs39ewgIOr/6zygzv+0ltu0SjE=":2,"3vvP54USUtSZlm/osFRbdXjCN/U=":2,"4+yW/l/2EqzM0fGVj0BcXV5TqDI=":2,"44pYIrJiSE08LkH770bq0wwoNEA=":2,"4TwK5fjrPUvueMXp4HZKGWvCJ0M=":2,"4ZC+GtEmLmHToJys2q2fbofqXeE=":2,"4eXKnzRS6ifFncgprkihsauqdGE=":2,"4qJ4K07ijGN6GmvmTNYzTJYmtRw=":2,"4rqrzEd2r2LoSpwBy3Wd1v4Drtc=":2,"4tQsYPAXpmciDFIC4nUACa9X4Wo=":2,"4vXUVM3Beyj2Rn+4lrrMuX455kY=":2,"55tALpi6iGTNuAMJkIQHrV/h8Zw=":2,"5Mo2uOqOAgDMAFR9xJxpj+Ps9vw=":2,"5Roy+ahYhL8V+JUUKT4pljRssYk=":2,"5UJk8zfVHpYxYI3tEGAQfMrks6k=":2,"6/9fhC6bkvQ+GDnCZzKV5b1uEs4=":2,"6218Tv51tHCkvM+pj15cmmrEp44=":2,"6AuvpHbKzPKvnQ5Iq4ZnJrH7VJc=":2,"6DjDzfLMbfYOmlGOJVAk9WK0yxs=":2,"6Edcp8jwSlxhClh0ZABA7VHryeY=":2,"6HE+xAlLmyPiZz4+IOE6QJR2+qU=":2,"6MJKJThHrZ77JxHeDkpqjqsJmPc=":2,"6S99zH9nPCcQM3Z3Z1tFjU0qI/8=":2,"6WtNqNcKg7znf4yFj/CmTJII+Ik=":2,"6iyZ50rVcsj89+phE3AIAQJ5Rl8=":2,"6sUp2EUK4KkR37GrEyH5Yoqc+Vg=":2,"74ScHGU1kOsGMCDn6+SMbExuJ0Y=":2,"74kVp2Qz/ClJ+826v36FnrVlEmU=":2,"7G9aQ3bdYQZRR5Xfs9AsSwsaPRs=":2,"7JjfkitOjBaGC/olVMv7P7VXegA=":2,"7Q3tTd5EeObvMV4js0wywUGWCDo=":2,"7ZvG0q9vmUTKE/kR/8lnxgr+W9g=":2,"7trRGs2suPfs2j1Fw8il8Ct2I4w=":2,"7ypMXoaWrM++zdAbjUUcvDdl6DA=":2,"84VFR/BgNC855g31gNI+lcgcvK0=":2,"8EArI4IQxFb1Jy5KKpgqxnjYqU8=":2,"8WDNGSYrBtXaSuNuCUcuENOqzbE=":2,"8jVuTrHMGXgJ62nUXx9V7cN/mzM=":2,"8nS7YyD+ru/R67lIeZKe30RKet8=":2,"8tt9aAK5Lm7Zcy9hZvUy06bgxCU=":2,"8ur3KjsVLO0lz7bfhzH5Rz06+fM=":2,"9J2Hjgd0WomJNXCVXUnnFp7HblY=":2,"9MZYN7ZW722NmXNr0I0a6xNGHw8=":2,"9PrZjFg2RssHXVdygP2FMo63tHk=":2,"9UuNM5QRWcp6mYkcu/t/I7FADLw=":2,"9V5BfQG4ZefovfNaXdHkf3YSIbM=":2,"9fj5AS7ShECezTEbos0drF7hGYo=":2,"9kQgpCCVk03s/PvG6sFZp1HUjFU=":2,"9rJ/kzjFOsSGSnyRLXimccFODIk=":2,"A24Vd0mboNwTK86qjAnL5NPT0ew=":2,"A7mJev6l+9dO4av3/tE3zj9JzLY=":2,"ANAAVt1I64nz8zJraV4+sB3bn5M=":2,"AgtaUdyyXGWAAMwjRWqwR8Ni8fk=":2,"AsgodONRHQuPbpgDwflsruAzPns=":2,"BJMwY+kVmXIH7sXwmXK/Q13fPkY=":2,"BVHoUpngEWtu0oY2qTH5s35an88=":2,"Bg6wgMZDYx0+/TxkfcfpqINBID0=":2,"BhE51h7DPwhQMQULRUIC2yvAK0Y=":2,"Bpex3OdFL9MLPykjDHF83THK4XU=":2,"Bxd9P1pUJldfaa0T/bjJ4RryaWE=":2,"C3WnzDhbWkxjLSTmT0Q4X+C5Y0g=":2,"CAPrE/fqgLuDiAW9p2hVJvKDVow=":2,"CBUdQZWRoFXyEsfV+uWNQuCMeFA=":2,"CFfzn2HEP0aH/l6Ix4YZ61KhVaM=":2,"CHJAmkWmDHuhYsu3pfxXnIh7HZQ=":2,"COZfIR9QIUwbad3hWuzoXMpnAN8=":2,"CQDGAq5GGMwFpHfW1z5j8CT63sM=":2,"Cjr9Pmookm1kE1NrmqrajTbbNGQ=":2,"CkEWJOcxrLmlVHE98ZW0fCC7cLo=":2,"CpdpCv4T0/puu4pnh4QKOoEMmAY=":2,"CvqZCPmZan5z33NXlrLvk5mzYrc=":2,"Cvywmg5xUNWlVmE1IlOnnaftKTc=":2,"Cz5dAHQlqdvtLvLtHPDUZiiiu+8=":2,"D7m1f2X1ZclMkgJz6eoxMvjV/BY=":2,"DBJzFXqFvKfiVCuXYUaENduUW+4=":2,"DK9He0ANXehmcN8YZhoASlkBlBo=":2,"DjMDHHpf+nnOnHxm/T1q8y5AoGs=":2,"DptldxPMxrOcxrsoRizh9K9nzEs=":2,"E+JAai/R1FoHjUcPV6PvZ+pFENY=":2,"E6/wFsja05ZZziyq3W/qhIfGjWM=":2,"E6h3qgjEj/9/yT6FUGw6YpUCrEU=":2,"E90biI3zHl/mrbRJIr35sUO1G2A=":2,"ECSWj1Bohkn3n1AWHIMEKlbepxQ=":2,"ELx9iaWnrWA5GpWryrvIbwgayb0=":2,"EYpM3f28E5iXkICbU1lbq13/xDs=":2,"EcH6B6F0qgOh+aDUV+DrOVR8Ag0=":2,"EdIuR7LPx1E9lRrlGHXSFSHL2zo=":2,"EkweGdn7Hj2CcJIpLShtXcn4Z5U=":2,"ErqMWkx4Pxb7qmvS+z+hDqzHXtM=":2,"Ew5jcdiDb1RN24kn4qz0nvhVBRg=":2,"Ewtt2SfL5QqYenyxIDEkC9k3tXs=":2,"F+TX3oARl/flaR0nHt5Js6PSCF0=":2,"FBC4lg/vz1H0FxdIxuTqNU4ZEB8=":2,"FJGJZYWxDCoJrYWPy2BUgtq1HM0=":2,"FRQtGBzKKPjy+HEtL7DsX3Felx0=":2,"FcelBmyYBLBRw/HaUwB9s6j5p3Q=":2,"FmvG9vz/LOjYYeU35txjwm9nZRQ=":2,"Fo02W4qlJUivZslOW61nZcCyA9I=":2,"FxMDzlEZgYp2JToAhAg+/yUllRU=":2,"G37v4qWLagnhBfOYr/ow2BEX8wQ=":2,"G3w71gAwbEQRQHACN74TIHrskus=":2,"GA+aolhIHd7aBXICZM5+0OrHfac=":2,"GBKfC442lwAxRkYbckvrizRO9s0=":2,"GVXlVv4EGFdKXDT5DPw/i710C9c=":2,"GWb9dIET7NeLkFZHxmz/DyBcwvw=":2,"GYhBRDeJahYz7i3JJ/8IyE2P5Oc=":2,"GgzZdRVruTyuSjP6N/LfEPt+Rw8=":2,"Gpss+UglPt1UUU2jy1ZlC2Haaos=":2,"GtCeVEmWQHdw3rryz0AuH5gyJxM=":2,"H3GqtTSpNlUUna7Umw0oI+0NgR4=":2,"H4j81ysGT6UYvop5kplp6lxlqXg=":2,"HABGlXq1BaOVH1Ifx+TyX6oI1c8=":2,"HKs5tNwpPQnqsBWBwrTC+hZGTTk=":2,"HM/pWnlnNgRgj3BUP0fYxxzl73Q=":2,"HPKcn8DkK6LusgLP9nDxVh2uJC8=":2,"HSh4Zm3wQfJIatvBZlrOfUeOfwk=":2,"HeMPvC/blr02FSRJtCharxgmzco=":2,"HmcCaa4SwSvvXXelNnwnv7AJeY8=":2,"Ht53X4lOUdtiGjATCg1fkJrokAU=":2,"HwkleqQc/sC85c17L6GdLZZRy14=":2,"I+7UKSXKSzGBgefFdkILZwsI9bs=":2,"I/ZGfrelShQUfRY9aoFBE2Ey1es=":2,"I5BwwRq++KWQv4ptZSLHGgVymIs=":2,"I9HlcZVHx3L832KLRSQTyyKcszM=":2,"IR5VBOOYDolqu3h+57TkJv62y4Y=":2,"IVYz/Wpt7sibxI0sN4+ORgouym4=":2,"IXYNhiWHet2dJvLpHZUkTrdX3T8=":2,"IYpFc21SFnpXN7O5VIPFH6jzdDU=":2,"IZM2fgogPf28F3qsGfathZESrto=":2,"IbS6gvfuP5iBCntJRl7/kGFWfU0=":2,"IpkxtRCHzfxeCqhGtGlgTZho5PA=":2,"Is6xz79EUUUlkrq+vTsITATIXy0=":2,"IvBIWWt8SMIZYO4zi8CNRQBdMa4=":2,"J0sdM/l3EGX6Frv/rSg7j7GL01Y=":2,"J6lcmiUnipJu3gVcoFiUbu+lbDs=":2,"JCDhMYyv6cBx12AS4NeS46EYq1U=":2,"JNVlxkqEWTvStjmY4qJmC71fnzo=":2,"JTODY14/ed4R5V5Q07Wyq1nHZCs=":2,"JWymogHaDHPgCtgoLPRcgF77J7g=":2,"JX1E7bBowYq/NXrg6uP+3EJOu1E=":2,"JgkRGWnXEHJQ70T82y1m8BrqX3Q=":2,"JslOsSCDdI34ClPlNXHA44C8BdM=":2,"K/m4A4gm9l73A6cVZkwC06VtJOU=":2,"K0pey71AM2vyu7pnYfphijaZFQQ=":2,"KCVNDq0FuwrUaqe8KovMG7Uj3F4=":2,"KCmDv40c4KHL+sZ06jr0iETCE/o=":2,"KHAia59NLQnyXDqGRHyg0ZiaTFA=":2,"KJyIq4mOXhu24VxX9gSFD3D93v4=":2,"KfKkkVLOQcHL8t9vHg9yVAoakwQ=":2,"KixfNZ8p0zlprYxunHrPzxobaq4=":2,"KmZM9Qj7kdUlBfwHt3Ha5IOIaXo=":2,"KnVtOxTqcw8Bj0cILIShIFWDZRU=":2,"Koq5VrYu1jgSuPxzC8JneftbXrY=":2,"KqtJUSyT2ifVLtE+YTa+Jwrew0k=":2,"L/1K37AEimYFLDPtWP00QHs4Y68=":2,"L2SILwi57slYAS17LPKLyjzn//M=":2,"L67fEFjVgKvKrPk8WOq+ypaV0dc=":2,"L8Sb2X7fKyM5N332D0ndTxRV6UY=":2,"LBcANp6Rge+D7JyH+lPItmNHsqw=":2,"LH6IDw2lqWicdgcu+tSQmhjaVvs=":2,"LI77XnWaUgy77p5DAeqIO7vOH14=":2,"LIcUrXtcBWBDTsYmK/hSjTpkhOQ=":2,"LK/nTUZLp4wQL8LSp6SlGXML0Xo=":2,"LLWfG5BXDbqHYtiETKDto5KENC0=":2,"LPP/dWFPHE2kpSUwpzspR7jegbE=":2,"LW/7lCwmMHUj5quQrOys8yKgpSU=":2,"LYaNdeviHa0JUthz/IPOwEOXmQQ=":2,"LZMdcjkdapf2PBM+TcQgrrw5l1Q=":2,"LadD1LUTKp90k3P8uJv25vGYSHI=":2,"LcbdMwrGmghZm+QEi615YhcnzP0=":2,"LhU39BVBhzq0HvhANd7D6dP5Qu4=":2,"LtHcu/ZmzB4KTac2VXn1G9F2+yE=":2,"LxPYBWzEULXwJn7iyMSa8QtD+kg=":2,"M+ZG7S72MQJCJe2aQVcvZoKftWA=":2,"M/Wjwu0AfUQ2o20egq9z+7bIzRE=":2,"MVHNDtRF1gJXlUK/+UZ6MIq+cMk=":2,"MXK6lMxDUXU9R5KLAL2bNOMx//A=":2,"MYnF7KiFcThaEWDO9xNzhikWzZg=":2,"McPp8MRX+uUUktsdxYDRi8o+eos=":2,"MftGgIb+TIwSyHnx7apoYs9NrDA=":2,"MpWCvxXFEf9daTeLjHcm3R/E81U=":2,"MqHL/cxomXHa8ev3atB93jJzbZI=":2,"MuDS3URWGZcyPBilzs4FXRzmboc=":2,"MuuNU16haFees5FcNMYXYToRZfY=":2,"N8NipVw4J3jV3lwC90mjPwfCHxg=":2,"NEHnjJf0uubHBmHAJBilzidYpks=":2,"NF8b22VZThqOOVOFtwz90G+TnlE=":2,"NMjxROmwGnztdYpQh/UAc4Bbnr4=":2,"NQamteBltpv0Ps+H619TiFUCf+I=":2,"NdXqc2xTrq/FN6tgl0gsTiq3F38=":2,"Ne1UYIth2fIOE+GqWmLouOzVGoM=":2,"NeSyTyiMagGROQJlNI8QSaSlBSw=":2,"NgAzcAy15WMJsY2pkT/2GxdgG04=":2,"NmMsYpAfxlJVp0FWodzxuSiHS3c=":2,"O/ynEwzhifwXixFynPqJ/W/oWh4=":2,"O0wSnPIMZPh/STNUh0vac3hUGJA=":2,"OEU7USrAsrnhG8bqMiZ26hK2CNg=":2,"OGH8Nmp74ZiT2sjux1xx41S2tNw=":2,"OJcSYTQfOFc27T/8rITzt7968R8=":2,"OQmSZcXWlR6aMwil6XEKlWcjacg=":2,"OVBSN2PMsKlMAlmaAKYB1cRcoY4=":2,"Obd7ogklY6JivNJCQIXV8d0qDuk=":2,"OjHuY9k7IqD58ta4pJplHxor6YM=":2,"OrjPTpbv6b9JNjns2OKkVTiKM+s=":2,"Ow215V5uWo11K+h3r5uqPKLzJI0=":2,"OzlQr4k8StWsbx6xo25olxpqFPo=":2,"P20wwKcWg8wwuTQl2+Brvgsvt0I=":2,"P2fxs0FUJWvTtwxgQ60U8ShnO10=":2,"PDaqV454hbqksZYGhTh5MEKnTws=":2,"PP/b+e8PPjUMQYS2OBT8GhMPS1o=":2,"PZwAWgz5MHGCT1WnkwTC53E/m9M=":2,"Pmvf6keEdJ2RdJbIEPbC6yjlB2I=":2,"Pn/ePL4HFaa4hTTOIC1z+UcbhSE=":2,"Q7VBdSOn3tXuYecIipApfUrWc0E=":2,"QANgRaF/b2zkl6ZtfzavHjFDGww=":2,"QGhV7+yJFgHnsLlp61izzFLm+8M=":2,"QKSyrWjQ6MjhtW2FNppRoKVNRCY=":2,"Qbrqdt73OY7jzL0r98xuGkILcf0=":2,"QtCZzUY6hCGEqCUTc2M5HNrrs4w=":2,"QuBiJAmt3+xnOmt838WFWkZNBII=":2,"Quz0fwq2iFeVentUcxv7EtGXBgI=":2,"Qy0HTOBuuQRuxmyN6GCjTBI+2MQ=":2,"R7CcmUEwytA73udabElrP9G8sN0=":2,"RF2lGGs4R20QEkXEifuLc5MTiy4=":2,"RIrVY4vPSyEJqz7rQNux/M6K2Uc=":2,"RNUHLVNAftYYrVsfw0XdkUFumwo=":2,"RSTkS8lWrQGjrgVquWcQVopYcRc=":2,"RUj0ztXJ7+kOsCpP9Kv3TDeFJJg=":2,"RVzwez9xPSX1AEn5pHSL/PR1Ak0=":2,"RYWzXqC3fQdwkaxnwdmOPmZixUw=":2,"RbcSJm/cbTD27QN7lN6Us62QIlE=":2,"RnwhHERLjD4kuXuJm44mHsUem+Y=":2,"RpqgmmdI4JgMujDXyfPAuYlQsNc=":2,"RqXHWd3nIsw7tt+RmTWynHdd0X4=":2,"S3CW+p7BtwcbD0fgDCiZ0RAQyjE=":2,"SAo2aVtafLNYHW7zVkEhRT9bh2Y=":2,"SY+bhxGSSGCnz1kQKI5yVUmhEfE=":2,"SYm5CVFkFOVllamvQ9D/tRM1JDw=":2,"SdL3nSP2tifv3D4axuGNQnI2bUc=":2,"Sdit/gOF9Dasz7o9sp6F7f95VxU=":2,"Sf6QB4b+AtQzltHOGfemdKTv/FI=":2,"So1TyGdA4U1tMl43UysxLdrBD+8=":2,"SvBLShco9LDUjRwg1aaiMvtvTFo=":2,"T/wIOHUG39AOmrfsXhUAzuEQY68=":2,"T2+of555wmTbJ2TrkfFXZPtJe6w=":2,"T9Qe0SNV0OBiGFU2oks1F78khLA=":2,"TMo985XELW9v74mmn50qi7dfmbc=":2,"TXp5FPH1q8BqEe/vPr2XzQNN4DQ=":2,"TYN2QA74YpLLdgx/KIWyDC7yWrs=":2,"TmrP6vdRPLfVW5N55bGHKWuqKxY=":2,"ToVZFnRaRPFc+bC+kUfL0o6oVbY=":2,"Twx+PUyhAazRa7zunJLUk7AuLcc=":2,"U/HvDF5lgUDIOvDbP9v5BmirEUs=":2,"U/MXSpdHG3Qh2p/vzyc0aFq/U94=":2,"U3KMQW6Rs95g1UJIi3OsZRqYWvQ=":2,"U7ti2JIQ2rB+nGUoJfrARNYcm/o=":2,"U9A/mkuLQvuMuaD1/0NbkxKJwsk=":2,"UDzrIJUrsqeKvuc/bTIuZnU0+5Q=":2,"UHJJhRN9z3qlaau2hbL1mfcfrI4=":2,"USKrPvDKw/JS/mQnPgXXm0PjWhI=":2,"Ucs6z5K6yxsQzCuxBg8IhFUW1uY=":2,"UyrsycnE0Y34SKsZr4aPMI19T4Q=":2,"V2W3L8FR9XTVZQtEl9UZ76GRaOk=":2,"VC/PaSikiazeBowkWU8F8s8Fbdc=":2,"VXhkGMKyQv4EGmsqXOlEmAdtX8E=":2,"Vus+nTDrUYcfuhZkTwWq8pp72Fo=":2,"W/vJPSCn52d0z02T4zSZuXmUFIo=":2,"W3JXUQpisayYUb8fvciX7mz/LUw=":2,"W79Q1UtfGoRJvjuDwvvCFd/g0g8=":2,"WGcOskzornIFeV5Wbec+z/7T8yQ=":2,"WN6w7LqpMGoL89o4ulIxTcXAttM=":2,"WirG4pLCvHATRD/XepELhtbx2z4=":2,"WybscQ6r1DfHRHCfANqlzsLEfR4=":2,"X+IBU7yum6s8R9EIK1eZ5xNXHzY=":2,"X1hwqKxZESTzs9BvFVN1cudNbU0=":2,"X3CsotjCGLmix01VOhQnaVzerc4=":2,"X3r0cKrB50GCupilXtIT0OsNmNU=":2,"X88GhHdCWKsBm24R727HFAkDr7U=":2,"XIcpBEZDocLvzctDOSolZeZZGMM=":2,"XJGnm7SMThSxDgLYX1WCQCpXIeE=":2,"XXS4Q2MvRlQ3g/5H4ppGQKiDMuc=":2,"XdRdTTf2L82I/5T7+QKhT3Pho24=":2,"XiqKy7gubyO5rqh2hQCzWLmuRP0=":2,"XkVTCFQo/kf96t12VPlUHI7Bsoo=":2,"XlU2doslDe9k2Sjyz+HoF+s4Fuk=":2,"Xmi6obAjhT4C07AkOLr1DrZOYng=":2,"Y+3yeiQnPoLWrymZUS7uiptfvWE=":2,"Y9F1acusJNtR1MKQ9sV/LUbtLcU=":2,"YCITb6CU1HEkdv0e/aMbXU15Bsc=":2,"YCrDNn1PepBzFGwS4liz7EGhd20=":2,"YQX9fwmNvbp79I5BVuG+xSFVcjM=":2,"YXSX9V1CWZmwRJWSO+196koeC7Y=":2,"YeDH3FcQ76eu+6wKfeDV3Z75z4k=":2,"Yv9p2UhdpPR9HiQAehTqepmaOtk=":2,"Z1cXRToCPBewKDIjZhu01gzNgvM=":2,"ZAqPZQWJRYyqIy1vmo7cQCQVpEU=":2,"ZCc7WSp1R56ujdXzRr1nbB6X4PY=":2,"ZIWJDsMLDNK3inlfrSMccHToQv0=":2,"ZN87pxH8AlA0PR/ktFLGAjm8JDc=":2,"ZSyVOd9TPha8GxMzhtgZiF93aZg=":2,"ZcCE53MqfEUAG0OC9vuXsgNygQA=":2,"ZnEawSbVIhbrxvLmTU/51FR3PHc=":2,"Zntf7wQ+SmweAQbnVsys7KRLiCA=":2,"ZtCtW2Sze8YbTG1fS4loW1n3F4s=":2,"ZuT1OewLis1kVKZoBEacnH8c4oQ=":2,"a/06Cc1qCMoW5/jphsMeYfBLXrA=":2,"a13zReUtyPNWrTN/Br6vION4M9k=":2,"aMpjfejGmbvrz24NGwVgyoJWmB0=":2,"aOhZbO9SzuqTcdPglSVnbInJ0HY=":2,"akhZxq2ZypH9U+g8ptVEix2Ys30=":2,"b390+KlW3do0iY5dWxyw/Nvj8y8=":2,"b64LG8t0nZIMAH4frxWe0Xe0lVc=":2,"bAfivuZXv6xQHZCq1H7RdaBGeJs=":2,"bI1Vo/T/gZu6ziJq0A76h0bkQ3A=":2,"cDMRM41OYKodBqf5yPs7PXp7Ibc=":2,"cFGuCTImI1LKaInDPxQtiun7tc4=":2,"cFmOFeeAC2RTc++FepBrbqvZJu8=":2,"cS+k6IBZ28FX5Gu5yS+3rwfash0=":2,"cU2FpWNjt8mGURI0k5QPpMUA1p0=":2,"cVRrJOXl5PBGO3dbZJV8A5XlMQY=":2,"cYEiRDkwdEht5TZ8ftQ2T12/vmI=":2,"cZnefofy4yEnFmkQ0gaP7nfgGBQ=":2,"ccdh7Hta93FtJR+qwt7DElNPqBI=":2,"chKNF84vgaJ1RtQrKV4ytLiKjlk=":2,"ciN5+j5UQseF5/8p+leZThdpwLk=":2,"cnQYSsJdyO+otNbyW42g39tQHFw=":2,"dCGPD+ybLSgoWN7NZsSKWMIMa8g=":2,"dNRX77I/GjMbKJwIPRRuZQnef5k=":2,"dSgRwJW6QXt5Gyti9tvXKOSloVI=":2,"dULO06RXKgWKOnT+2EPWFhzSOzQ=":2,"ddNzLLovIOQAjI1Fuour/azCRPs=":2,"dfVd5Cks1FFJVdNmS+sD4zItmmQ=":2,"dhvEuIu4bREe/yc3n+uWgemDH+Y=":2,"e7QR994kinvEvNi5PEREfEgRBPk=":2,"eIkv3FutAxmGf2Mh7yo0HiDjrls=":2,"ePMMAHx9Ax6ezSppn6dpqbBnLhE=":2,"ex04CvLWFikDWXjGQ4RtjbOeRNM=":2,"f/TYvHakawJF91GiVgpjciGJPc8=":2,"f8cvQ/sraTsg0bwM+aS4D6pFT6I=":2,"f9ysKU6hcNbVfpf1njOmFQ2qbZ0=":2,"fBmcT7XNbLpOQsfKdgdXEdc1P38=":1,"fLj05EfmTLEt58m3jVUhPVS04sU=":2,"fMus4OBg1K5k+k8tLnAZyRBbnLY=":1,"fa4i6qfS5+dDiDVKFZDjsFnF6Rc=":2,"fnRvo3ItSPsvU3LKSXBRXJg0FUs=":2,"foNSnwHq8ph3wPaXJ8I88LehpI4=":2,"fuy5x4yKH5LLTw4kz6c1pnFiOcQ=":2,"g0FiO0sC3nMBLvy49sLKeESA7h0=":2,"gCgo0usJBkT8uf+0XUuS3gWGdoA=":2,"gJJSwVtCLng5e1xxugIzmlnHbd4=":2,"gJK5pMWuNFrD9OGNIgKananYNSo=":2,"gMpTRAKA7Ayl+W/YVqQhr5GU6x0=":2,"gSTTNamgmAMk2//gdb5jcZMN9AQ=":2,"gqGHjniFghep8E6txoAdzX/4h3M=":2,"gr0I/I6o5WZbCX3ANuvNoagEEe8=":2,"gsU6EH/i8w1ThrqsEm6GK79feO4=":2,"gtc5hvQud0vqhMhm2fmcV4S+Agc=":2,"gxn+9RnfotKjIQsWN6Ldd6tJFwQ=":2,"hGJJ6Hh+MF5i2sXu2g4Yz8nZwHs=":2,"hJM03Qy65rIixL+QnwFnZUWdS7o=":2,"hRdDjllKxVjmSDiRpxs+uOUT9Q4=":2,"hl/Ql44a9B+9BQR34dUhENrlIJ4=":2,"hmt01LHgEU30nJb6VMA41XMWRyg=":2,"ho9bP3IJ21F4d3qP3pTJA0JkTj4=":2,"htyr9QaPXQOHGsfVmr+97oeW0UM=":2,"iBD/DGiehe+56IosGVlv3c1wJ3Q=":2,"iD9S1fFa6FpM5DcIk5pQUCSj4aw=":2,"iGzRH+UPc4Ea3ApuY49us3/XCaA=":2,"iHnWlD4n0QHbXoUv3k90wclViuU=":2,"iXvZsH9NpG0qHURLzLTudfP9aeU=":2,"ihQuIV4rmAFYvTr6lwMV4HokREI=":2,"ihRhUKLVahjKDEOmS0BbYyhgv7k=":2,"ipbKvdY2LsQlCcEkuSqe8v4By6g=":2,"ipt6XYj9NCIb0hWN8BbyXEF5DfQ=":2,"irephTXGVO+MmlZ2AS7MbB5AyLM=":2,"j+6DOgEHMZgTIWSHhf9CjmUGIK8=":2,"j+GDvmG+Am9Xd+4Q/XDAlrQrFz4=":2,"jAuqNF/yhbdqVNpoWw+2Jo6e6bs=":2,"jEtGDH1uWCTHnmHc2bGPDrpEHCg=":2,"jODdAGIb3/eRchqP2DHAiTYlP0Y=":2,"jQfCzjp4d/PizsLo5UpdD2f8www=":2,"jUoBtJ03/Xr45tg4Dqenc5cYWAU=":2,"jVgQocUsQaH7V/2UxhLVOidhP20=":2,"jYhk6dm72WAaxSdjIvOSNJ3d0sE=":2,"jaMkW1knsztb/0+GNCKx6G/SzaI=":2,"jc0TPKjiMVneKPNeY2avjLI9KVY=":2,"jq2rGPyUu7grG5FJi/I/qcKLKg0=":2,"k/v8xkMt57fg28L2fh73gxXa4Yc=":2,"k1J17FRo3myPzj+UE+LXaZ9ohSc=":2,"k3bwFkPXH/EDNGF7Npn6kwKJu6Q=":2,"k7hYQMMCyKjXIXP+LR8U+d3GIzQ=":2,"kDJnIwokySTxXp20eRGTskuMM9c=":2,"kLV2LBNc1aIFljjZItvqx2bhY1U=":2,"kMGe+97jR78zimxmtL9Ak8a0OHw=":2,"kOvgd336AvzRZ7zhd6KqxVNyMiU=":2,"kYI0w0yGJWsEW8mUvaWKX5BGN34=":2,"kYvIeNAo8XJrY0sLt9RkQb/ArLk=":2,"kbEmSJ7AT4IyCib5dANoydcLsmE=":2,"kfmukk3rEZbsice63or/akfPSU0=":2,"l1TwOsy32JiZV/bM26UQ8oCnn7k=":2,"l1l9LWMnuHXWDBSLcfQ3Zp7bVVk=":2,"l38tVXmuuGlAgD9a3eXwX/jQwgI=":2,"lHA+dhHLhlHLq/O+0+Xz7buufJ4=":2,"lJcNksg20bY6CgGPqZu5aQHbRhE=":2,"lUbDYyCRhvBzS0nDrz8rx/nq0A0=":2,"lUfzJ3y5Jzs7p4PBHh4xhm+zoG8=":2,"lV/IOzmMkT+d9gXfFgqtsErYe2M=":2,"lY3+bGoDRF7A0eSICXUJ1yfpxo8=":2,"lZpQb3elaMvd1gsI/plZxcpUVwY=":2,"lcXOtK8KVWFVeHE4WLEewHPCWWY=":2,"ldPbP2/DX6N+AldQ7AFtoht/Bvc=":2,"lhONN2tBTBA/tSnMtizicuNBPLU=":2,"lmXhk+G6r/qbCMYZcVdJbnn+93I=":2,"mEj21qtta3LLlAxWkZ8sijZvktM=":2,"mSNPvAXxob4waWjBxs3ziW6z71g=":2,"mYby0t8WAz6jV9RgYIRRGyfeWB8=":2,"mg1zJLHTYaJIMLNxa+rsYWsZJhI=":2,"mh3wxEYkuAk6sRhlr/C5G/gxYRI=":2,"miEzBOZuMem0Cj9Uxw1LjN9S9cw=":2,"mlWAbHBzQ5Td8U9HSp8fcPdPyzQ=":2,"mmci9ejkh1yqEt/tTbqbQeSaSwI=":2,"mqI5UE1zlvwODeiYkE+97gk/N38=":2,"mv8xDlT2/YhQtkLKnptz6SQB5uM=":2,"nAj3Ny++JKnx/3X/T3HRcVSVXN0=":2,"nHcOob6uJ8APh5510nMH7Ikg5XI=":2,"nNG/hSMKDgXudXzByhmJ+8Udww8=":2,"o/9SDeB9XVwuJyTLitMsvbgaQKg=":2,"o1UwUqLfJmuxKSuFfNRz/EzR9So=":2,"oHsvpBtYgeqeqVOdT/DQDeNAyp8=":2,"oIsMwEfYOTvIzVNKHP6nF5RhkVk=":2,"oNPOB+kuiVqZt91Ceva1HD2babU=":2,"oNrKGepVbapve5qoLE4s7JK926I=":2,"oVr3ZmvWmeO5V4lOW6+8gEGE5YY=":2,"oX3Jk2hkzKOTCsCjIb8aBoEQxCY=":2,"oc/SFHoD/b37HnDYvDl1S+Ln8+o=":2,"odROFyqXD/frsFAhnWAK7yW9p1E=":2,"oibx5gMRdevDCHgIZ8xHbhmCom0=":2,"pCDKhit9yDclLI07LYJ2Arec58E=":2,"pFBMDn/qQ2sU3hbTzN0XE+gPNlE=":2,"pGtFao+Eqv0xw/MJ4ne73wMtss0=":2,"pKocQQbERh0k2bBtqqHvsL6IzwY=":2,"pQbhy62y3+Jaimld0fQXsr90MPU=":2,"pSQhqungWlpbyd5qgvoDgc7AE/E=":2,"pXA8CdPQ2YBCgTcuH0u3ji94FpM=":2,"pj/VyHVWYMY781dFmsalRMjAdng=":2,"po8Y5k48QpkNI3OQK3HJSajJvIk=":2,"qGuRw9GZC5DTd5qdb/ri4A76b90=":2,"qX+92itsZYUdfyqVnkRNS1z8pEg=":2,"qhL0XSJvQoCDATRSMO6uHK6s0AE=":2,"qnTJ6qWlEO3mGlvjzZxRj1SWBSg=":2,"qpvlQsYaJOxyL6Vr9sOa7itTjWg=":2,"qtTOojYzivrM05kWyMG+4B3oavI=":2,"qxM7PjtM2REivHU89TUKjRFyX/c=":2,"r2jAg5LKs99/R7UDy7n+RVExthw=":2,"r66x+/C7gcK0ek2UGYaFgDG9W7A=":2,"r7iJmf1gYZfcG8O+Vd5YotXOO98=":2,"r7yFRxkCgT3Oeq05RWA9OtXpSI0=":2,"rBvqswHFQGNJ+GA8LqPPr3KtF+8=":2,"rEMdbHd/v8VQAKMX0knLaZEP8KI=":2,"rFDwZivZT0u0vRe8Vj180HEOHEI=":2,"rPu9e+cSQCdzkKfYpDy9vIMdrTU=":2,"rSlZi3H7e2ESXD48TLSxA+uHjp0=":2,"rVsxB7wqXgKFK40cRaUdv5100/8=":2,"rXmjfschRYJInGVNNv9jGIRrjJ4=":2,"rXtx9FDQjNrYAd+Xt+sv0IjIaJ8=":2,"rc4WJXNzddjdAyW+WERMtKMaYYI=":2,"rjWw31OACJd76/zAEVPT3BCWrpE=":2,"rp1qUhW5AwlfEo+FC5F3v84IJG4=":2,"rzbYuWFx8KRHnLGL8HtL+0dJhIo=":2,"s6btLO7QAG1u99wehXlGkxKUb0Y=":2,"sD67cLr9VrAeoarwQnBVmBOjfCs=":2,"sDK4hQp8T2RmWpWvgnHk6FQ2iwM=":2,"sIl513b2C2/QeDrHSuBpH2c6C0k=":2,"sL1dde8EjkxF+Lb89yeCnsBYBOU=":2,"sNAV48ni/e0b7Gn9jEfM3Q3dVe8=":2,"sPTnbQmrNOyx/qW0Xu4g4cu0aR4=":2,"siHaDi1iEPE3xPgGISfpfwb8h4M=":2,"skXg82RVCi6BZHNRI23RIG2DRC4=":2,"sunLW+vgbWmbUrarV07NcFmnKgE=":2,"t/DNJowu9uHR/kBc3bc1Nm7+9lo=":2,"t97bh7mYz2gwiY6nU+/w1i9dgZU=":2,"tBZZ8SUVG/FjRUpROxHXX3KaCyw=":2,"tK2lpUcycitAF1Et7B+/ZhiQ0ZM=":2,"tPPRnCQb4zC0dD4BJYFC6KAMVWw=":1,"tR2fhHtwBTc9bKHWDB/g0JFDNBY=":2,"tWRGM3CFPPslofcsSqj6vpcd7JU=":2,"uBMu4M5/0KKZY37hxUNLN39LPtA=":2,"uKsvvIzSMOyMR+4LPExkT1A8iDA=":2,"uNmw0kNAuK13LWxLuTZiaO140LY=":2,"uSACpi6t4iSWKjHFN6UHju08OB4=":2,"uf4z/h0h9ZnyOD7ycAiwgx/aHFo=":2,"unvMMzjFrurZix1N1pOtUC+RriY=":2,"utfiG74gl+SIxnKipbPl66ZNVWc=":2,"v6RXBuPtNohU+Lb6MHwV9z4lt1w=":2,"vD6n6Z9JW8prLB0rVlTt/g+4cCI=":2,"vDX9FACK55aBjFOaPdncKX2o+Bg=":2,"vW9hX9bdu7jEnh05U+zjXI+SbA8=":2,"vWbt1X54cCEDXSdUl4qpqdCohNE=":2,"vYmUY3JR7HpU6cV3sp31ubgx+YE=":2,"vqAjPDOmXZGBn833qAWFeo1PtsU=":2,"vqaClXLm/YZ8MhiUAukne10yy/o=":2,"w1vJ0NG9kDFtUNHq8zCMuDUVb8M=":2,"wAsstIPtDtjSlxUGn0gh+TfTWmQ=":2,"wJ4TJKlTMrrNezUg8dfBuOltq4U=":2,"wK4Zb71UwMahGOQFp0E3RYeMfYw=":2,"wZinPjTdOm5rrXI4u1NIKiffmp8=":2,"wib9u5YbRGJAqT5Bvh9zNZp4iTY=":2,"wqO+JoG3Un7fd2bDdvRxfAhbJ3Q=":2,"wr9Z2KN9f3Tq2jo3nTe3DpsNr54=":2,"wv3DmXgFeOrq/dbsherqtSjmrO8=":2,"x4c04qHrWNjtvJ2XgQQpd7wW1rA=":2,"xFo5PPJwZaq7i4dWLyzXeywAOEY=":2,"xUJ/eh98DaHs0DxWLA9fYYD6PzM=":2,"xgEKSqpgWJmo+flxFClV2/NiOJk=":2,"xjHJCBSoTdEQjebMV8aARzFcEkA=":2,"xm3y8sIKteMNAiUYEkt/ocEG7VI=":2,"xoxgp5Cx/yYkyO4yumq70s+D5t0=":2,"xtOFUD8jRLwrgCyGI5QnD7K+CG0=":2,"y0OlqPMUw6B8jvG1d2F9DOvkDp4=":2,"y2Kf0efsIVsF8PYgZBOV7tc5AfM=":2,"y2QRZhLYezQlVyzaDO4PEKbAmAc=":2,"yAXQT+zYHydb1uUhkuwtxm5At5k=":2,"yAyH2ZVkhzgat7fcC+nSDXQ11jw=":2,"yKtZdPSQMfJNQVKjIJ6noDw07mQ=":2,"yM5jN0VjPFKIKpUqRuN5KyRPd94=":2,"yad44gD7FAnezf8DgiIRZiDGlRY=":2,"yekkHNxtLVYK9WvooNiEKVWXabA=":2,"ykSAQyJm33Umehd0Txp/8rpum2I=":2,"yx1gN4z+x0naLVTbhc4/HO1c7cY=":2,"yzJqCQsowhulZe3Hx/xsWOvlTbw=":2,"z6CTfToXHCMt/46aowVDcKOYuL8=":2,"zAmtiHUH7ncF4kcOLIROCCAtn5Y=":2,"zTzCkN1zga1linYQP6v2AyMYW5w=":2,"zd+y/4GyfV5LQFAHFVfIKQuur+U=":2,"zejOvMNeql2wesKjXICcANkzyPM=":2,"zvV3Pm+WpZE4xD79k4mjhrJu0gw=":2,"zwzjvFMamlRnd5MSmg2F0LgPqso=":2,"zydtsLKKSp4EUItk7o34H/+dTNQ=":2}}},"ukm":{"persisted_logs":[]},"uninstall_metrics":{"installation_date2":"1746408261"},"updateclientdata":{"apps":{"eeigpngbgcognadeebkilcpcaedhellh":{"cohort":"1:w59:","cohortname":"Auto","dlrc":6941,"fp":"1.4497d8060d0e53c12b4403aa9ebe7e827d4880bae3f4139a26a4feb7ed64c4a2","installdate":6698,"max_pv":"0.0.0.0","pf":"a18a9302-8930-4d47-8dad-ae5c037f8288","pv":"2025.6.13.84507"},"efniojlnjndmcbiieegkicadnoecjjef":{"cohort":"1:18ql:","cohortname":"Auto Stage3","dlrc":6941,"fp":"1.160aa782aaa39e7b812a5e5e2c7c2f8a56e21d5ea84b92cd1f493cb384b4fdbd","installdate":6698,"max_pv":"1517","pf":"d3608814-03d0-45fa-a937-18a328a350c8","pv":"1532"},"gcmjkmgdlgnkkcocmoeiminaijmmjnii":{"cohort":"1:bm1:","cohortname":"Stable","dlrc":6941,"fp":"1.ed43e732234cc8b79a137be0a0aab8f72b37ae6ca51caf1292986edbf618c1d1","installdate":6698,"max_pv":"9.62.0","pf":"92410523-c7cf-4845-93e0-e166f7a2caa7","pv":"9.64.0"},"ggkkehgbnfjpeggfpleeakpidbkibbmn":{"cohort":"1:ut9/1a0f:","cohortname":"M108 and Above","dlrc":6941,"fp":"1.4795b6d7d7c2e0878abbb461850eb2068971273643901fd992814b9bfaff202b","installdate":6698,"max_pv":"2025.12.11.120","pf":"017c06bb-7ef3-4a85-b46e-ee415dd73b0c","pv":"2025.12.25.121"},"giekcmmlnklenlaomppkphknjmnnpneh":{"cohort":"1:j5l:","cohortname":"Auto","dlrc":6941,"fp":"1.3eb16d6c28b502ac4cfee8f4a148df05f4d93229fa36a71db8b08d06329ff18a","installdate":6698,"max_pv":"0.0.0.0","pf":"5b85f272-0b12-40e6-a508-cb6aee6f1dd8","pv":"7"},"gonpemdgkjcecdgbnaabipppbmgfggbe":{"cohort":"1:z1x:","cohortname":"Auto","dlrc":6941,"fp":"1.56c21927faa028be6ce18c931660eec37e41da4bfbfd47cafa48350f828c0dbd","installdate":6698,"max_pv":"0.0.0.0","pf":"e0898faf-4433-43cd-a722-850bb9cc7b9f","pv":"2025.7.24.0"},"hfnkpimlhhgieaddgfemjhofmfblmnib":{"cohort":"1:287f:","cohortname":"Auto full","dlrc":6941,"fp":"1.d45446da660d25c2ffbc0689c5012ae33485ad69449cc0792b1f38bebd04da9d","installdate":6698,"max_pv":"10244","pf":"87be194c-7660-44d6-82b8-fa10f7ce138e","pv":"10255"},"jamhcnnkihinmdlkakkaopbjbbcngflc":{"cohort":"1:wvr:","cohortname":"Auto","dlrc":6941,"fp":"1.c52c62a7c50daf7d3f73ec16977cd4b0ea401710807d5dbe3850941dd1b73a70","installdate":6698,"max_pv":"0.0.0.0","pf":"74774881-7e5e-4f77-920f-83969fd395e9","pv":"120.0.6050.0"},"jflhchccmppkfebkiaminageehmchikm":{"cohort":"1:26yf:","cohortname":"Stable","dlrc":6941,"fp":"1.4a06cfbce6f26c81ec6cba52e84985c0111183e0b06a953b14992b4511bb78af","installdate":6698,"max_pv":"2025.10.5.1","pf":"5ff45e3b-8abd-4fc2-9145-4f761dd45949","pv":"2025.10.7.1"},"jflookgnkcckhobaglndicnbbgbonegd":{"cohort":"1:s7x:","cohortname":"Auto","dlrc":6941,"fp":"1.220f906777a5ca8a28c0d7bb742912805fb6f93b262abc897f372213fc9841ef","installdate":6698,"max_pv":"3087","pf":"4a5a5130-5796-4521-80d6-a91611f8d6d9","pv":"3088"},"khaoiebndkojlmppeemjhbpbandiljpe":{"cohort":"1:cux:","cohortname":"Auto","dlrc":6941,"fp":"1.03c55f4f45c2a62c467f5bcf7e3fbee31e9ec27abeccefed06adc927cdf52968","installdate":6698,"max_pv":"67","pf":"77d0eff6-4989-4f04-895c-86a49db4ca67","pv":"144.0.7512.1"},"kiabhabjdbkjdpjbpigfodbdjmbglcoo":{"cohort":"1:v3l:","cohortname":"Auto","dlrc":6941,"fp":"1.caf22da361a099ee7f504cfd6018872cff61e16946d0a5a57fb07c529bfa8072","installdate":6698,"max_pv":"2025.8.25.1","pf":"8c55dcaf-cd47-442e-80db-ae4b86a81ffe","pv":"2025.9.29.1"},"laoigpblnllgcgjnjnllmfolckpjlhki":{"cohort":"1:10zr:","cohortname":"Auto","dlrc":6941,"fp":"1.e444ba601ac72b669514e6788bc458ac6b4a3f4400f18ad9b297a84eb27009e5","installdate":6698,"max_pv":"0.0.0.0","pf":"0045fe12-9d84-4570-b32c-224956ad397e","pv":"1.0.7.1744928549"},"llkgjffcdpffmhiakmfcdcblohccpfmo":{"cohort":"1::","cohortname":"","dlrc":6941,"fp":"1.2be74d0afadd4c9b2ee33695e1f81fc5ce5dc3016cd8a13cfa0e1f0b571834ea","installdate":6698,"max_pv":"1.0.0.18","pf":"07e12423-fca7-403e-aae9-bf22a1333eef","pv":"1.0.0.19"},"lmelglejhemejginpboagddgdfbepgmp":{"cohort":"1:lwl:","cohortname":"Auto","dlrc":6941,"fp":"1.bb4ff4726d6f232b7d6976a7f467ea619b7c696aa18848229e3adb9fb191336e","installdate":6698,"max_pv":"595","pf":"5d7cde47-b231-4cdd-848f-1f2ae99b67d2","pv":"599"},"mfhmdacoffpmifoibamicehhklffanao":{"cohort":"1:1ge3:","cohortname":"Stable","dlrc":6941,"fp":"1.a10a891103c69736b97d77dd5fa1ce1ffd77a0c8bc3aea6162df0423933e0755","installdate":6698,"max_pv":"140.10","pf":"347dd84a-4c4c-4818-8765-5efce2e4a1c2","pv":"140.12"},"niikhdgajlphfehepabhhblakbdgeefj":{"cohort":"1:1uh3:","cohortname":"Auto Main Cohort.","dlrc":6941,"fp":"1.38c89b12bb20a8f2751c9c7cd2e31c173a47af08c115e1ecccc2f5151a2cf2c6","installdate":6698,"max_pv":"0.0.0.0","pf":"76d4401a-7cb4-44bd-a220-7e55e37c3a3f","pv":"2025.6.16.0"},"obedbbhbpmojnkanicioggnmelmoomoc":{"cohort":"1:s6f:3cr3@0.025","cohortname":"Auto","dlrc":6941,"fp":"1.f0fac1ffee516ccd1505ec8a51acfa6d9c4fca45d78de2059eceaf3dde376216","installdate":6698,"max_pv":"0.0.0.0","pf":"a5202619-6bf1-4cd1-99e8-409cba20935d","pv":"20250629.778704241.14"},"oimompecagnajdejgnnjijobebaeigek":{"cohort":"1:3cjr:","cohortname":"Auto","dlrc":6941,"fp":"1.92ac4503d850d61341c2b89b0ca25ae45a875f85e7ab7018354cef9a0b37bba7","installdate":6698,"max_pv":"4.10.2891.0","pf":"cae51630-5641-4c06-8c64-4e585905582b","pv":"4.10.2934.0"},"ojhpjlocmbogdgmfpkhlaaeamibhnphh":{"cohort":"1:w0x:","cohortname":"All users","dlrc":6941,"fp":"1.545666a4efd056351597bb386aea1368105ededc976ed5650d8682daab9f37ff","installdate":6698,"max_pv":"0.0.0.0","pf":"4f233212-d3a0-49f5-864a-dfa4ea09ad6a","pv":"3"}}},"user_experience_metrics":{"limited_entropy_randomization_source":"347548CD8B793C0E43E5BEDEBC391338","low_entropy_source3":5052,"machine_id":5183260,"pseudo_low_entropy_source":2545,"session_id":539,"stability":{"browser_last_live_timestamp":"13411820814764378","exited_cleanly":true,"stats_buildtime":"1736279424","stats_version":"132.0.6834.83-64-devel","system_crash_count":0}},"variations_crash_streak":595,"variations_google_groups":{"Default":[]},"variations_limited_entropy_synthetic_trial_seed_v2":"48","was":{"restarted":false}} \ No newline at end of file diff --git a/library/jcef/cache/Variations b/library/jcef/cache/Variations index 1fc8283..c46edf6 100644 --- a/library/jcef/cache/Variations +++ b/library/jcef/cache/Variations @@ -1 +1 @@ -{"user_experience_metrics.stability.exited_cleanly":false,"variations_crash_streak":594} \ No newline at end of file +{"user_experience_metrics.stability.exited_cleanly":false,"variations_crash_streak":595} \ No newline at end of file diff --git a/library/jcef/cache/chrome_debug.log b/library/jcef/cache/chrome_debug.log index cef689d..4ce7507 100644 --- a/library/jcef/cache/chrome_debug.log +++ b/library/jcef/cache/chrome_debug.log @@ -1,6 +1,4 @@ -[12284:16860:1228/145054.244:WARNING:account_consistency_mode_manager.cc(77)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. -[12284:16860:1228/145054.280:WARNING:extension_service.cc(2065)] Found external version of extension ncennffkjdiamlpmcbajkmaiiiddgioothat is older than current version. Current version is: 3.52.14. New version is: 3.52.5. Keeping current version. -[8880:16484:1228/145054.563:WARNING:viz_main_impl.cc(85)] VizNullHypothesis is disabled (not a warning) -[13676:18520:1228/145254.442:WARNING:viz_main_impl.cc(85)] VizNullHypothesis is disabled (not a warning) -[14320:9004:1228/145354.607:ERROR:gpu_blocklist.cc(71)] Unable to get gpu adapter -[12284:16860:1228/145354.607:ERROR:service_client.cc(36)] Unexpected on_device_model service disconnect: The device's GPU is not supported. +[4944:21460:0102/174655.052:WARNING:account_consistency_mode_manager.cc(77)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. +[4944:21460:0102/174655.144:WARNING:extension_service.cc(2065)] Found external version of extension ncennffkjdiamlpmcbajkmaiiiddgioothat is older than current version. Current version is: 3.52.14. New version is: 3.52.5. Keeping current version. +[5764:9508:0102/174655.913:WARNING:viz_main_impl.cc(85)] VizNullHypothesis is disabled (not a warning) +[5060:21232:0102/174855.188:WARNING:viz_main_impl.cc(85)] VizNullHypothesis is disabled (not a warning) diff --git a/library/jcef/cache/first_party_sets.db b/library/jcef/cache/first_party_sets.db index 987c09de0581305c42892263fe23d3cd5de51673..6a55f9b655baef28c9179dcfb55c333f75452b49 100644 GIT binary patch delta 75 zcmV-R0JQ&rpag)R1dtm65s@520THoaR38-+10NG|b#7l{Z*^{TH8MCG0|Pq`lg%#| hv)~`-4*?Ui$uBlw0T8l~_zwXPv-w{OAhQI({7+fl7}o#* delta 75 zcmV-R0JQ&rpag)R1dtm65Rn{10T8iZR38-*10NG|b#7l{Z*^{TH8M9F0|Pq`lg%#| hv)~`-4*?Rh$uBlw0S~f}_zwXOv-w{OAhQI({7+cS7|;L! diff --git a/library/jcef/cache/segmentation_platform/ukm_db b/library/jcef/cache/segmentation_platform/ukm_db index 28fa077af3256cca3fa382aad3111de208221685..0f3c73f6f714e716492ddd01b8b3c64f4de3f07d 100644 GIT binary patch delta 327 zcmYj}F-QVo7>56k^SA4WdlAf`B94eaBC@7vut8{TXmUy-YBQsTraUm3g6{a1oN}m! zT9gYy8ia7NNr-|XQi2vCf`Y)QFQ?uIp6z+vmUdg(8>YHHlA?MgbGjMTc0(a%f7%T^ z;mU6O!A@?C6FD>3&)wLx>-#&AajQ>-Lo{Wo>9cM-l{sR{$M`uPk7^VZ0-U3WFT9Hd zc3e4d<-lD4O>pxlKH00R0V7Ou!5iDzi+&6DN~5Z9hg($fgAcL5jwiV%xwi}&;`Yht zm}MFvT0ES)lg9ov| lPI;XZWivP^4}y}uKhK?7l&qjrTiMgy*8*={FD0om^9%o*YnlK6 delta 275 zcmXAgF-XHu6h;3diA2%d!KjF$AH>C_6?a7(9XfQ%CL+4E0e1~3&iTB>I%tOK;FOX< zibKI}aViKxP$)PGA~*;x`iLCPc1|>OqM;MdQQypOQNOd(Zu+*DD@=QzUXH@c|6v{O zaW!v=lPjpoK57gmoloBx$q(S~I4yJZ_DUs$BEIVdHjm3{T2N zSK$#4=;B)}VI9jC%NN%{OU5kn$CW!P{hRayg;zXdfFH4hbs~KteX)sB`#t}@-}n1| z-$zmB&q;jz9=yFkQBT0~?D@fR_g_}v`DY-zC$BtBU3>HDwJUdEvwW5cEEQNPuvB2F zz*2#w0{;&M#^3z$@aX4{9vr>2LcP8H6h+Vp>x7LJu#8>yS8biwYm={hRBzkd?TrIx42hL-+i&3(QCYKVtl6T_H$^-&CsE#P)XHtv%uv`#O(LY0p7U+OWQbHI za4#^sDQAheWbQGi?{R^jI-Km;n-DKdwxxR2w~3ZJIv$&P$8Yu z-R#K|ORo&20KNs)VY@CRb-#Kbg|#9V&tz5juj(VBm3D{{n>~-6uQumoHt7tJj?0!_ z_D^vG#4;nJr^E)qiPcm1uBfr5KAPg}^##47t(PT#H0MWMIy{MVg3HQ_VBTuQkQ; zPjdzwMa0-`m^BnCG3+NsPfjnvnd-2o^N<%`LY&O24LNf}EpSAfp*|D4P{-383$29$ z&uQQqA~-FyK`g%*8?Xw!RH6+{Q5!GDg?j7E9>nZJ-LSnFXIm|`7I0_!=b%Yzu!sq| z5v_^XOU`hMN2C>*y0QhFy@h|Vk|8z+&b3WgvrG8Q^X{5@jtx$^>`n)X0uTAjd4n%% z&Y72>9?%1i)LIF(z+z;Kh;o?*4FhUF*YE=F%-2PYIW1O-J`ugx;Qmpsf77{Za59EE z%sHQ7tE^U1*%tJhHeA#T<^)kPhXF5$IR<}$UxdOxbDWF0!`*nM+05%}bFYIph|$v$ zM*t7>v>5un=&igs-`|_{72-^6ht3%Mgzd4kDmA9_pzz|@>%zEIGwms4@Q~Yknt|82C4MjZh3u&oy|jvzW3JaC!bwEAGVXj!|%WN<&)3vuE4}^ gK8A_E38TB1(A_AS5Bz)Ee_em=t8)$~@%_7h13Qv>x&QzG diff --git a/sql_learning.lock.db b/sql_learning.lock.db index e5b03ab..2561941 100644 --- a/sql_learning.lock.db +++ b/sql_learning.lock.db @@ -1,6 +1,6 @@ #FileLock -#Sun Dec 28 14:52:28 CST 2025 +#Fri Jan 02 17:46:53 CST 2026 hostName=192.168.116.1 -id=19b63bad12a8483d76995f9c5100715a8b474ee84cc +id=19b7e1a4b3ed8755d1cb7723021bb5b3ae83bb80d46 method=file -server=192.168.116.1\:64976 +server=192.168.116.1\:64658 diff --git a/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java b/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java index ad98e04..d019a3a 100644 --- a/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java +++ b/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java @@ -839,7 +839,7 @@ public class AxisInnovatorsBox { UIManager.getSystemLookAndFeelClassName(), LanguageManager.getLoadedLanguages().getText("default_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("default_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:default_theme", isDarkMode ); @@ -849,7 +849,7 @@ public class AxisInnovatorsBox { "javax.swing.plaf.metal.MetalLookAndFeel", LanguageManager.getLoadedLanguages().getText("metal_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("metal_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:metal_theme", false ); @@ -859,7 +859,7 @@ public class AxisInnovatorsBox { "com.sun.java.swing.plaf.motif.MotifLookAndFeel", LanguageManager.getLoadedLanguages().getText("motif_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("motif_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:motif_theme", false ); @@ -870,7 +870,7 @@ public class AxisInnovatorsBox { new com.formdev.flatlaf.FlatLightLaf(), LanguageManager.getLoadedLanguages().getText("flatLight_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("flatLight_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:flatLight_theme", false ); @@ -880,7 +880,7 @@ public class AxisInnovatorsBox { new com.formdev.flatlaf.FlatDarkLaf(), LanguageManager.getLoadedLanguages().getText("flatDark_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("flatDark_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:flatDark_theme", true ); @@ -890,7 +890,7 @@ public class AxisInnovatorsBox { new com.formdev.flatlaf.FlatIntelliJLaf(), LanguageManager.getLoadedLanguages().getText("flatIntelliJ_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("flatIntelliJ_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:flatIntelliJ_theme", false ); @@ -900,7 +900,7 @@ public class AxisInnovatorsBox { new com.formdev.flatlaf.FlatDarculaLaf(), LanguageManager.getLoadedLanguages().getText("flatDarcula_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("flatDarcula_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:flatDarcula_theme", true ); @@ -910,7 +910,7 @@ public class AxisInnovatorsBox { new FlatMacLightLaf(), LanguageManager.getLoadedLanguages().getText("flatMacLight_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("flatMacLight_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:flatMacLight_theme", false ); @@ -920,7 +920,7 @@ public class AxisInnovatorsBox { new FlatMacDarkLaf(), LanguageManager.getLoadedLanguages().getText("flatMacDark_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("flatMacDark_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:flatMacDark_theme", true ); @@ -929,7 +929,7 @@ public class AxisInnovatorsBox { new MaterialLookAndFeel(new JMarsDarkTheme()), LanguageManager.getLoadedLanguages().getText("mars_dark_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("mars_dark_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:mars_dark_theme", true ); @@ -938,7 +938,7 @@ public class AxisInnovatorsBox { new MaterialLookAndFeel(new MaterialLiteTheme()), LanguageManager.getLoadedLanguages().getText("material_lite_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("material_lite_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:material_lite_theme", false ); @@ -947,7 +947,7 @@ public class AxisInnovatorsBox { new MaterialLookAndFeel(new MaterialOceanicTheme()), LanguageManager.getLoadedLanguages().getText("material_oceanic_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("material_oceanic_theme.default.tip"), - LoadIcon.loadIcon(MainWindow.class, "logo.png", 64), + LoadIcon.loadSystemIcon(MainWindow.class, "logo.png", 64), "system:material_oceanic_theme", true ); diff --git a/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java b/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java index 0b3f941..d75dc66 100644 --- a/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java +++ b/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java @@ -1,31 +1,35 @@ package com.axis.innovators.box.plugins; +import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** * 自定义类加载器,装载CorePlugins - * @author tzdwindows 7 + * 优化:增加缓冲读取,优化集合初始化 */ public class BoxClassLoader extends URLClassLoader { private static final List CLASS_TRANSFORMS = new CopyOnWriteArrayList<>(); - private static final List CLASS_BLACKLIST = new ArrayList<>(); - private static final List CLASS_LOADING_LIST = Collections.synchronizedList(new ArrayList<>()); + // 使用 CopyOnWriteArrayList 适合读多写少的场景 + private static final List CLASS_BLACKLIST = new CopyOnWriteArrayList<>(); + // Loading list 仅用于防止循环依赖,普通同步 List 即可 + private static final List CLASS_LOADING_LIST = Collections.synchronizedList(new java.util.ArrayList<>(50)); private static final List> CLASS_LOADING_LIST_OBJECT = new CopyOnWriteArrayList<>(); static { - Collections.addAll(CLASS_BLACKLIST, + // 批量添加,减少扩容开销 + List blacklist = java.util.Arrays.asList( "java.", "javax.", "sun.", "com.sun.", "jdk.", "org.xml.", "org.w3c.", "org.apache.", - "javax.management.", "javax.swing." - , "javafx.","org.jnativehook.","com.dustinredmond." + "javax.management.", "javax.swing.", + "javafx.", "org.jnativehook.", "com.dustinredmond." ); + CLASS_BLACKLIST.addAll(blacklist); } public BoxClassLoader(ClassLoader parent) { @@ -60,7 +64,7 @@ public class BoxClassLoader extends URLClassLoader { resolveClass(c); } return c; - } catch (ClassNotFoundException e) { + } catch (ClassNotFoundException | SecurityException e) { return super.loadClass(name, resolve); } } @@ -68,27 +72,30 @@ public class BoxClassLoader extends URLClassLoader { @Override protected Class findClass(String name) throws ClassNotFoundException { - synchronized (getClassLoadingLock(name)) { - if (CLASS_LOADING_LIST.contains(name)) { - throw new ClassCircularityError(name + " circular loading detected"); - } + // 移除 synchronized (getClassLoadingLock(name)),因为 loadClass 已经锁住了 + // 防止循环依赖 + if (CLASS_LOADING_LIST.contains(name)) { + throw new ClassCircularityError(name + " circular loading detected"); + } - CLASS_LOADING_LIST.add(name); - try { - byte[] clazzByte = getClassBytes(name); + CLASS_LOADING_LIST.add(name); + try { + byte[] clazzByte = getClassBytes(name); + // 只有当存在转换器时才遍历 + if (!CLASS_TRANSFORMS.isEmpty()) { for (IClassTransformer transformer : CLASS_TRANSFORMS) { byte[] transformed = transformer.transform(name, transformer.getClass().getName(), clazzByte); if (transformed != null) clazzByte = transformed; } - - Class clazz = defineClass(name, clazzByte, 0, clazzByte.length); - CLASS_LOADING_LIST_OBJECT.add(clazz); - return clazz; - } catch (IOException e) { - throw new ClassNotFoundException("Class byte loading failed", e); - } finally { - CLASS_LOADING_LIST.remove(name); } + + Class clazz = defineClass(name, clazzByte, 0, clazzByte.length); + CLASS_LOADING_LIST_OBJECT.add(clazz); + return clazz; + } catch (IOException e) { + throw new ClassNotFoundException("Class byte loading failed: " + name, e); + } finally { + CLASS_LOADING_LIST.remove(name); } } @@ -96,12 +103,17 @@ public class BoxClassLoader extends URLClassLoader { String path = className.replace('.', '/') + ".class"; try (InputStream is = getResourceAsStream(path)) { if (is == null) throw new ClassNotFoundException(className); - return is.readAllBytes(); + try (BufferedInputStream bis = new BufferedInputStream(is)) { + return bis.readAllBytes(); + } } } private boolean isBlacklisted(String className) { - return CLASS_BLACKLIST.stream().anyMatch(className::startsWith); + for (String s : CLASS_BLACKLIST) { + if (className.startsWith(s)) return true; + } + return false; } public static void addClassTransformer(IClassTransformer transformer) { diff --git a/src/main/java/com/axis/innovators/box/plugins/PluginDescriptor.java b/src/main/java/com/axis/innovators/box/plugins/PluginDescriptor.java index f481514..3265a3c 100644 --- a/src/main/java/com/axis/innovators/box/plugins/PluginDescriptor.java +++ b/src/main/java/com/axis/innovators/box/plugins/PluginDescriptor.java @@ -1,8 +1,10 @@ package com.axis.innovators.box.plugins; +import java.net.URL; import java.util.List; /** + * 插件描述符 * @author tzdwindows 7 */ public class PluginDescriptor { @@ -15,21 +17,93 @@ public class PluginDescriptor { private String transformers; private String registrationName; + /** + * 核心字段:插件的类加载器 + * 保存这个是为了以后调用 classLoader.getResource("images/logo.png") + * 从而准确地从该插件的 JAR 包中获取资源,互不干扰。 + */ + private ClassLoader classLoader; + + /** + * 核心字段:插件 JAR 包的物理 URL + * 格式通常为: file:/C:/path/to/plugin.jar + * 用于构建 jar:file: 协议的 URL (常用于 JavaFX Image 或 FXML 加载) + */ + private URL sourceLocation; + // Getters and Setters + public String getId() { return id; } public void setId(String id) { this.id = id; } + public String getName() { return name; } public void setName(String name) { this.name = name; } + public List getSupportedVersions() { return supportedVersions; } public void setSupportedVersions(List supportedVersions) { this.supportedVersions = supportedVersions; } + public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } + public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } + public Object getInstance() { return instance; } public void setInstance(Object instance) { this.instance = instance; } - public String getTransformers() {return transformers;} - public void setTransformers(String transformers) {this.transformers = transformers;} - public String getRegistrationName() {return registrationName;} - public void setRegistrationName(String registrationName) {this.registrationName = registrationName;} -} + + public String getTransformers() { return transformers; } + public void setTransformers(String transformers) { this.transformers = transformers; } + + public String getRegistrationName() { return registrationName; } + public void setRegistrationName(String registrationName) { this.registrationName = registrationName; } + + /** + * 获取用于加载此插件资源的 ClassLoader + */ + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + /** + * 获取插件 JAR 文件的物理路径 URL + */ + public URL getSourceLocation() { + return sourceLocation; + } + + public void setSourceLocation(URL sourceLocation) { + this.sourceLocation = sourceLocation; + } + + // --- 辅助方法:便捷加载资源 --- + + /** + * 这是一个便捷方法,用于直接从当前插件的 Resources 中获取资源 URL。 + * 哪怕多个插件有同名文件(如 config.png),使用此方法也只会加载当前插件内的那个。 + * + * @param path 资源路径,例如 "assets/icon.png" (不需要以 / 开头) + * @return 资源的完整 URL,如果找不到则返回 null + */ + public URL getResource(String path) { + if (classLoader != null) { + return classLoader.getResource(path); + } + return null; + } + + /** + * 获取资源的输入流(用于读取配置文件等) + * @param path 资源路径 + * @return 输入流 + */ + public java.io.InputStream getResourceAsStream(String path) { + if (classLoader != null) { + return classLoader.getResourceAsStream(path); + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/axis/innovators/box/plugins/PluginLoader.java b/src/main/java/com/axis/innovators/box/plugins/PluginLoader.java index 1932530..2745c46 100644 --- a/src/main/java/com/axis/innovators/box/plugins/PluginLoader.java +++ b/src/main/java/com/axis/innovators/box/plugins/PluginLoader.java @@ -6,96 +6,185 @@ import com.axis.innovators.box.tools.FolderCreator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.*; import java.lang.reflect.Field; -import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicInteger; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** - * 插件加载器 - * @author tzdwindows 7 + * 插件加载器 - 性能优化版 (修复 SystemClassLoader 启动崩溃问题) */ public class PluginLoader { - private static Logger logger; - public static final String PLUGIN_PATH = FolderCreator.getPluginFolder(); - private static final List loadedPlugins = new ArrayList<>(); - private static final List transformers = new ArrayList<>(); - private static final List corePluginMainClass = new ArrayList<>(); - private static final List pluginRegisteredName = new ArrayList<>(); - public static void loadPlugins() throws IOException, PluginLoadingError { - logger = LogManager.getLogger(PluginLoader.class); - File pluginDir = null; - if (PLUGIN_PATH != null) { - pluginDir = new File(PLUGIN_PATH); - } - File[] jars = null; - if (pluginDir != null) { - jars = pluginDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".jar")); - } + // 移除 static 初始化,防止在 SystemClassLoader 构造期间触发 Log4j 初始化 + private static volatile Logger logger; - if (jars == null) { - return; - } - for (int i = 0; i < jars.length; i++) { - processJarFile(jars[i],false); - AxisInnovatorsBox.getMain().progressBarManager.updateSubProgress( - "Loading Plugin " + i, - i, - jars.length); + public static final String PLUGIN_PATH = FolderCreator.getPluginFolder(); + + private static final List loadedPlugins = new CopyOnWriteArrayList<>(); + private static final List transformers = new CopyOnWriteArrayList<>(); + private static final List corePluginMainClass = new CopyOnWriteArrayList<>(); + private static final Set pluginRegisteredName = Collections.synchronizedSet(new HashSet<>()); + + // ========================================================= + // 安全日志相关方法 (Safe Logger) + // ========================================================= + + /** + * 获取 Logger,如果 Log4j 尚未准备好(例如在 SystemClassLoader 初始化期间),则返回 null + */ + private static Logger getLogger() { + if (logger != null) return logger; + try { + // 尝试初始化 Log4j + logger = LogManager.getLogger(PluginLoader.class); + return logger; + } catch (Throwable t) { + // 捕获 BootstrapMethodError 或 IllegalStateException + // 说明此时 SystemClassLoader 正在构造中,不能使用 Log4j + return null; } } - private static void processJarFile(File jarFile, boolean isCorePlugin) throws IOException, PluginLoadingError { + private static void logInfo(String msg, Object... args) { + Logger l = getLogger(); + if (l != null) { + l.info(msg, args); + } else { + // Fallback: 在 Log4j 准备好之前使用 System.out + System.out.println("[PluginLoader-INFO] " + formatFallback(msg, args)); + } + } + + private static void logError(String msg, Object... args) { + Logger l = getLogger(); + if (l != null) { + l.error(msg, args); + } else { + System.err.println("[PluginLoader-ERROR] " + formatFallback(msg, args)); + // 打印异常堆栈 + for (Object arg : args) { + if (arg instanceof Throwable) { + ((Throwable) arg).printStackTrace(); + } + } + } + } + + private static void logWarn(String msg, Object... args) { + Logger l = getLogger(); + if (l != null) { + l.warn(msg, args); + } else { + System.out.println("[PluginLoader-WARN] " + formatFallback(msg, args)); + } + } + + private static void logDebug(String msg, Object... args) { + Logger l = getLogger(); + if (l != null) { + l.debug(msg, args); + } else { + // Debug 级别在 fallback 模式下通常不打印,或者可以打印到 System.out + // System.out.println("[PluginLoader-DEBUG] " + formatFallback(msg, args)); + } + } + + // 简单的字符串格式化,用于 fallback 模式 + private static String formatFallback(String msg, Object... args) { + if (args == null || args.length == 0) return msg; + try { + // 简单替换 {},不完美但够用 + String result = msg; + for (Object arg : args) { + if (arg instanceof Throwable) continue; // 异常单独处理 + result = result.replaceFirst("\\{\\}", String.valueOf(arg)); + } + return result; + } catch (Exception e) { + return msg; + } + } + + // ========================================================= + // 业务逻辑 + // ========================================================= + + public static void loadPlugins() throws IOException, PluginLoadingError { + File pluginDir = (PLUGIN_PATH != null) ? new File(PLUGIN_PATH) : null; + if (pluginDir == null || !pluginDir.exists()) return; + + File[] jars = pluginDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".jar")); + if (jars == null || jars.length == 0) return; + + logInfo("Found {} jars, starting parallel loading...", jars.length); + + AtomicInteger loadedCount = new AtomicInteger(0); + int total = jars.length; + + Arrays.stream(jars).parallel().forEach(jarFile -> { + try { + processJarFile(jarFile, false); + } catch (Exception e) { + logError("Failed to load plugin jar: " + jarFile.getName(), e); + } finally { + int current = loadedCount.incrementAndGet(); + if (AxisInnovatorsBox.getMain() != null && AxisInnovatorsBox.getMain().progressBarManager != null) { + try { + AxisInnovatorsBox.getMain().progressBarManager.updateSubProgress( + "Loading Plugin " + current, current, total); + } catch (Exception ignored) {} + } + } + }); + } + + private static void processJarFile(File jarFile, boolean isCorePlugin) throws IOException { try (JarFile jar = new JarFile(jarFile)) { - // Check for CorePlugin in MANIFEST.MF if (isCorePlugin) { Attributes attributes = jar.getManifest().getMainAttributes(); String corePluginClass = attributes.getValue("CorePlugin"); if (corePluginClass != null) { processCorePlugin(jarFile, corePluginClass); } - } else { - JarEntry pluginFile = jar.getJarEntry("plug-in.box"); - if (pluginFile != null) { - processWithManifest(jar, pluginFile, jarFile); - } else { - processWithAnnotations(jar, jarFile); - } + return; } + + JarEntry pluginFile = jar.getJarEntry("plug-in.box"); + PluginDescriptor descriptor = null; + + if (pluginFile != null) { + descriptor = processWithManifest(jar, pluginFile, jarFile); + } else { + descriptor = processWithAnnotations(jar, jarFile); + } + + if (descriptor != null) { + loadPluginLanguagesInternal(jar, descriptor); + Attributes attributes = jar.getManifest().getMainAttributes(); + String corePluginClass = attributes.getValue("CorePlugin"); + descriptor.setTransformers(corePluginClass); + } + } catch (PluginLoadingError e) { + logError("Plugin logic error in {}: {}", jarFile.getName(), e.getMessage()); } } - /** - * 加载核心插件 - * @throws IOException 插件加载失败 - */ public static void loadCorePlugin() throws IOException { - File pluginDir = null; - if (PLUGIN_PATH != null) { - pluginDir = new File(PLUGIN_PATH); - } - File[] jars = null; - if (pluginDir != null) { - jars = pluginDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".jar")); - } - if (jars == null) { - return; - } + File pluginDir = (PLUGIN_PATH != null) ? new File(PLUGIN_PATH) : null; + if (pluginDir == null || !pluginDir.exists()) return; + + File[] jars = pluginDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".jar")); + if (jars == null) return; + for (File jar : jars) { - try { - processJarFile(jar, true); - } catch (PluginLoadingError e) { - throw new RuntimeException(e); - } + processJarFile(jar, true); } } @@ -110,124 +199,185 @@ public class PluginLoader { registerTransformers(corePlugin, urlClassLoader); } } catch (Exception e) { - logger.error("Failed to load core plugin: {}", corePluginClass, e); + logError("Failed to load core plugin: {}", corePluginClass, e); } } private static void registerTransformers(LoadingCorePlugin corePlugin, ClassLoader classLoader) { - //if (corePlugin.getMainClass() != null) { + if (corePlugin.getMainClass() != null) { corePluginMainClass.add(corePlugin.getMainClass()); - String[] transformerClasses = corePlugin.getASMTransformerClass(); - if (transformerClasses != null) { - for (String transformerClass : transformerClasses) { - try { - Class transformerClazz = classLoader.loadClass(transformerClass); - if (IClassTransformer.class.isAssignableFrom(transformerClazz)) { - IClassTransformer transformer = (IClassTransformer) transformerClazz.getDeclaredConstructor().newInstance(); - transformers.add(transformer); - BoxClassLoader.addClassTransformer(transformer); - } - } catch (Exception e) { - logger.error("Failed to register transformer: {}", transformerClass, e); + } + String[] transformerClasses = corePlugin.getASMTransformerClass(); + if (transformerClasses != null) { + for (String transformerClass : transformerClasses) { + try { + Class transformerClazz = classLoader.loadClass(transformerClass); + if (IClassTransformer.class.isAssignableFrom(transformerClazz)) { + IClassTransformer transformer = (IClassTransformer) transformerClazz.getDeclaredConstructor().newInstance(); + transformers.add(transformer); + BoxClassLoader.addClassTransformer(transformer); } + } catch (Exception e) { + logError("Failed to register transformer: {}", transformerClass, e); } } - //} else { - // logger.error("Failed to load core plugin: {}", corePlugin.getClass().getName()); - //} + } } - private static void processWithManifest(JarFile jar, JarEntry entry, File jarFile) + private static PluginDescriptor processWithManifest(JarFile jar, JarEntry entry, File jarFile) throws IOException, PluginLoadingError { Properties props = new Properties(); try (InputStream is = jar.getInputStream(entry)) { props.load(is); - } catch (IOException e) { - logger.error("Failed to load plugin from jar: {}", jarFile.getName(), e); - return; } PluginDescriptor descriptor = new PluginDescriptor(); + + URL jarUrl = jarFile.toURI().toURL(); + descriptor.setSourceLocation(jarUrl); + URLClassLoader pluginClassLoader = new URLClassLoader( + new URL[]{jarUrl}, + PluginLoader.class.getClassLoader() + ); + descriptor.setClassLoader(pluginClassLoader); + descriptor.setId(props.getProperty("id")); descriptor.setName(props.getProperty("name")); descriptor.setDescription(props.getProperty("description")); descriptor.setIcon(props.getProperty("icon")); - descriptor.setSupportedVersions( - Arrays.asList(props.getProperty("supportedVersions").split(",")) - ); + + String versions = props.getProperty("supportedVersions"); + if (versions != null) { + descriptor.setSupportedVersions(Arrays.asList(versions.split(","))); + } + String registrationName = props.getProperty("registrationName"); verifyRegisteredNameValid(descriptor, registrationName); - logger.info("Loaded plugin: {}", descriptor.getName()); - loadMainClass(props.getProperty("mainClass"), jarFile, descriptor); + logInfo("Loaded plugin via manifest: {}", descriptor.getName()); + loadMainClass(props.getProperty("mainClass"), descriptor); - Attributes attributes = jar.getManifest().getMainAttributes(); - String corePluginClass = attributes.getValue("CorePlugin"); - descriptor.setTransformers(corePluginClass); - loadPluginLanguages(jarFile, descriptor); + return descriptor; } private static void verifyRegisteredNameValid(PluginDescriptor descriptor, String registrationName) throws PluginLoadingError { - if (registrationName != null && !registrationName.isEmpty() - && !pluginRegisteredName.contains(registrationName)) { - pluginRegisteredName.add(registrationName); - } else { - if (registrationName == null || registrationName.isEmpty()) { - throw new PluginLoadingError("Invalid registration name"); - } - throw new PluginLoadingError("When the \" " - + descriptor.getName() - + "\" plugin is loaded, this plugin contains the same registered name as the previously loaded plugin"); + if (registrationName == null || registrationName.trim().isEmpty()) { + throw new PluginLoadingError("Invalid registration name for plugin: " + descriptor.getName()); } + synchronized (pluginRegisteredName) { + if (!pluginRegisteredName.add(registrationName)) { + throw new PluginLoadingError("Duplicate registered name '" + registrationName + "' in plugin " + descriptor.getName()); + } + } descriptor.setRegistrationName(registrationName); } - private static void processWithAnnotations(JarFile jar, File jarFile) throws PluginLoadingError { - URLClassLoader classLoader = createClassLoader(jarFile); + private static PluginDescriptor processWithAnnotations(JarFile jar, File jarFile) throws PluginLoadingError { + PluginDescriptor foundDescriptor = null; + URLClassLoader classLoader = null; + boolean keepClassLoaderOpen = false; + + try { + classLoader = new URLClassLoader( + new URL[]{jarFile.toURI().toURL()}, + PluginLoader.class.getClassLoader()); + + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (!entry.isDirectory() && entry.getName().endsWith(".class")) { + String className = entry.getName() + .replace("/", ".") + .replace(".class", ""); + + try { + if (className.equals("module-info")) continue; + + Class clazz = classLoader.loadClass(className); + PluginMeta meta = clazz.getAnnotation(PluginMeta.class); + + if (meta != null) { + PluginDescriptor descriptor = new PluginDescriptor(); + descriptor.setSourceLocation(jarFile.toURI().toURL()); + + descriptor.setClassLoader(classLoader); + keepClassLoaderOpen = true; + + descriptor.setId(meta.id()); + descriptor.setName(meta.name()); + descriptor.setDescription(meta.description()); + descriptor.setIcon(meta.icon()); + descriptor.setSupportedVersions(Arrays.asList(meta.supportedVersions())); + + verifyRegisteredNameValid(descriptor, meta.registeredName()); + + Object instance = clazz.getDeclaredConstructor().newInstance(); + descriptor.setInstance(instance); + injectInstanceField(clazz, instance, descriptor); + + loadedPlugins.add(descriptor); + logInfo("Loaded plugin via annotation: {}", descriptor.getName()); + + foundDescriptor = descriptor; + break; + } + } catch (Throwable e) { + // 忽略 + } + } + } + } catch (IOException e) { + logError("Error scanning jar for annotations: " + jarFile.getName(), e); + } finally { + if (!keepClassLoaderOpen && classLoader != null) { + try { + classLoader.close(); + } catch (IOException e) { + logWarn("Failed to close unused classloader", e); + } + } + } + return foundDescriptor; + } + + private static void loadPluginLanguagesInternal(JarFile jar, PluginDescriptor plugin) { Enumeration entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); - if (entry.getName().endsWith(".class")) { - if (classLoader != null) { - processClassEntry(entry, jar,classLoader,jarFile); + String entryName = entry.getName(); - } + if (entryName.startsWith("lang/") && entryName.endsWith(".properties")) { + processLanguageFile(jar, entry, plugin); + } + else if (entryName.startsWith("assets/lang/") && entryName.endsWith(".properties")) { + processAssetsLanguageFile(plugin, entryName); } } } - private static void loadPluginLanguages(File jarFile, PluginDescriptor plugin) { - try (JarFile jar = new JarFile(jarFile)) { - Enumeration entries = jar.entries(); - while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); - if (entry.getName().startsWith("lang/") && - entry.getName().endsWith(".properties")) { - processLanguageFile(jar, entry, plugin); - } - } - } catch (IOException e) { - logger.error("Failed to load language files for plugin: {}", plugin.getName(), e); - } + private static void processAssetsLanguageFile(PluginDescriptor plugin, String entryName) { + String fileName = entryName.substring(entryName.lastIndexOf("/") + 1); + String langCode = fileName.replace(".properties", ""); + String targetRegisteredName = "system:" + langCode; + LanguageManager.registerPluginLanguage(plugin, entryName, targetRegisteredName); } private static void processLanguageFile(JarFile jar, JarEntry entry, PluginDescriptor plugin) { String fileName = entry.getName().substring(entry.getName().lastIndexOf("/") + 1); String[] parts = fileName.split("[_.]"); - if (parts.length < 3) { - return; - } - String langCode = parts[parts.length-1].replace(".properties", ""); + if (parts.length < 3) return; + + String langCode = parts[parts.length - 1].replace(".properties", ""); String langName = plugin.getName() + " " + langCode.toUpperCase(); String registeredName = plugin.getRegistrationName() + "_" + langCode; + try (InputStream is = jar.getInputStream(entry)) { Properties properties2 = new Properties(); properties2.load(new InputStreamReader(is, StandardCharsets.UTF_8)); + LanguageManager.Language language = new LanguageManager.Language( - langName, - registeredName, - null + langName, registeredName, null ) { @Override public void loadLanguageFile(String languageFile) { @@ -235,97 +385,42 @@ public class PluginLoader { } }; LanguageManager.addLanguage(language); - logger.info("Loaded plugin language: {} ({})", langName, registeredName); + logDebug("Loaded plugin language: {} ({})", langName, registeredName); } catch (IOException e) { - logger.error("Failed to load language file: {}", entry.getName(), e); + logError("Failed to load language file: {}", entry.getName(), e); } } - private static URLClassLoader createClassLoader(File jarFile) { - try { - return new URLClassLoader( - new URL[]{jarFile.toURI().toURL()}, - PluginLoader.class.getClassLoader() - ); - } catch (MalformedURLException e) { - logger.error("Error creating URLClassLoader", e); - } - return null; - } - - private static void processClassEntry(JarEntry entry,JarFile jar, - URLClassLoader classLoader, - File jarFile) throws PluginLoadingError { - String className = entry.getName() - .replace("/", ".") - .replace(".class", ""); - - try { - Class clazz = classLoader.loadClass(className); - PluginMeta meta = clazz.getAnnotation(PluginMeta.class); - if (meta != null) { - PluginDescriptor descriptor = new PluginDescriptor(); - descriptor.setId(meta.id()); - descriptor.setName(meta.name()); - descriptor.setDescription(meta.description()); - descriptor.setIcon(meta.icon()); - descriptor.setSupportedVersions(Arrays.asList(meta.supportedVersions())); - - String registrationName = meta.registeredName(); - verifyRegisteredNameValid(descriptor, registrationName); - - try { - Object instance = clazz.getDeclaredConstructor().newInstance(); - descriptor.setInstance(instance); - - try { - Field pluginInstance = instance.getClass().getDeclaredField("INSTANCE"); - pluginInstance.setAccessible(true); - pluginInstance.set(null, descriptor); - } catch (NoSuchFieldException | IllegalArgumentException - | SecurityException | IllegalAccessException e) { - logger.warn("Failed to set plugin instance: {}", instance.getClass(), e); - } - - loadedPlugins.add(descriptor); - Attributes attributes = jar.getManifest().getMainAttributes(); - String corePluginClass = attributes.getValue("CorePlugin"); - descriptor.setTransformers(corePluginClass); - loadPluginLanguages(jarFile, descriptor); - logger.info("Loaded plugin: {}", descriptor.getName()); - } catch (Exception e) { - logger.error("Failed to instantiate plugin class: {}", className, e); - } - } - } catch (ClassNotFoundException | NoClassDefFoundError e) { - logger.error("Error loading class: {}", className, e); - } - } - - private static void loadMainClass(String mainClassName, File jarFile, PluginDescriptor descriptor) { + private static void loadMainClass(String mainClassName, PluginDescriptor descriptor) { if (mainClassName == null || mainClassName.isEmpty()) { - logger.error("Invalid main class name: {}", mainClassName); return; } - try (URLClassLoader classLoader = new URLClassLoader( - new URL[]{jarFile.toURI().toURL()}, - PluginLoader.class.getClassLoader()) - ) { + ClassLoader classLoader = descriptor.getClassLoader(); + if (classLoader == null) { + logError("Plugin ClassLoader is missing for {}", descriptor.getName()); + return; + } + + try { Class mainClass = classLoader.loadClass(mainClassName); Object instance = mainClass.getDeclaredConstructor().newInstance(); descriptor.setInstance(instance); - - try { - Field pluginInstance = mainClass.getDeclaredField("INSTANCE"); - pluginInstance.setAccessible(true); - pluginInstance.set(null, descriptor); - } catch (NoSuchFieldException | IllegalArgumentException - | SecurityException | IllegalAccessException e) { - logger.warn("Failed to set plugin instance: {}", mainClassName, e); - } + injectInstanceField(mainClass, instance, descriptor); } catch (Exception e) { - logger.error("Failed to load main class: {}", mainClassName, e); + logError("Failed to load main class: {}", mainClassName, e); + } + } + + private static void injectInstanceField(Class clazz, Object instance, PluginDescriptor descriptor) { + try { + Field pluginInstance = clazz.getDeclaredField("INSTANCE"); + pluginInstance.setAccessible(true); + pluginInstance.set(null, descriptor); + } catch (NoSuchFieldException e) { + // 忽略 + } catch (Exception e) { + logWarn("Failed to set plugin instance field for {}", clazz.getName(), e); } } diff --git a/src/main/java/com/axis/innovators/box/register/LanguageManager.java b/src/main/java/com/axis/innovators/box/register/LanguageManager.java index 38d4a2a..f88a9d6 100644 --- a/src/main/java/com/axis/innovators/box/register/LanguageManager.java +++ b/src/main/java/com/axis/innovators/box/register/LanguageManager.java @@ -1,5 +1,6 @@ package com.axis.innovators.box.register; +import com.axis.innovators.box.plugins.PluginDescriptor; import com.axis.innovators.box.plugins.PluginLoader; import com.axis.innovators.box.tools.FolderCreator; import org.apache.logging.log4j.LogManager; @@ -27,14 +28,54 @@ public class LanguageManager { LANGUAGES.add(new Language("日本語", "system:ja_JP", "sys_ja_JP")); } + /** + * 插件专用:从插件 Jar 包资源中快速注册/合并语言 + *

+ * 示例用法: + * LanguageManager.registerPluginLanguage(plugin, "assets/lang/en_US.properties", "system:en_US"); + *

+ * + * @param plugin 插件描述符(用于获取 ClassLoader) + * @param resourcePath 资源在 Jar 包中的路径 (例如 "assets/lang/zh_CN.properties") + * @param targetRegisteredName 目标语言的注册名 (例如 "system:zh_CN"),将合并到此语言中 + */ + public static void registerPluginLanguage(PluginDescriptor plugin, String resourcePath, String targetRegisteredName) { + if (plugin == null || resourcePath == null || targetRegisteredName == null) { + return; + } + + try (InputStream is = plugin.getResourceAsStream(resourcePath)) { + if (is == null) { + logger.warn("无法在插件 [{}] 中找到语言资源: {}", plugin.getName(), resourcePath); + return; + } + + // 创建一个临时的 Language 对象,重写加载逻辑以避免读取磁盘文件 + Language pluginLang = new Language( + plugin.getName() + " Resource", // 临时名称,不重要 + targetRegisteredName, // 关键:注册名必须与现有语言一致才能合并 + null + ) { + @Override + public void loadLanguageFile(String ignored) { + // 覆盖父类行为:不从磁盘加载,防止 FileNotFoundException + } + }; + + // 手动从流中加载属性 + pluginLang.loadFromInputStream(is); + + // 复用现有的合并逻辑,这样可以保持统一的日志记录 + addLanguage(pluginLang); + + } catch (IOException e) { + logger.error("加载插件语言资源失败: {} - {}", plugin.getName(), resourcePath, e); + } + } + /** * 添加/合并语言资源 * @param language 要添加的语言对象 - * 处理规则: - * 1. 注册名相同时保留原有基础信息 - * 2. 相同键值的新内容覆盖旧内容 - * 3. 详细记录新增、更新的键值数量 - * 4. 提供关键示例用于调试 */ public static void addLanguage(Language language) { for (Language existing : LANGUAGES) { @@ -61,19 +102,21 @@ public class LanguageManager { existing.properties.setProperty(key, newValue); } - String logDetail = buildMergeLogDetails(added, updated, sampleAddedKeys, sampleUpdatedKeys); - - logger.info("【语言合并报告】\n" + - "▌合并目标:{} ({})\n" + - "▌变更统计:新增 {} 条 / 更新 {} 条\n" + - "▌当前总量:{} 条\n" + - "▌关键示例:\n{}", - existing.getLanguageName(), - existing.getRegisteredName(), - added, - updated, - existing.properties.size(), - logDetail); + // 仅当有变更时才构建日志,减少刷屏(可选优化) + if (added > 0 || updated > 0) { + String logDetail = buildMergeLogDetails(added, updated, sampleAddedKeys, sampleUpdatedKeys); + logger.info("【语言合并报告】\n" + + "▌合并来源:{} -> {}\n" + + "▌变更统计:新增 {} 条 / 更新 {} 条\n" + + "▌当前总量:{} 条\n" + + "▌关键示例:\n{}", + language.getLanguageName(), + existing.getRegisteredName(), + added, + updated, + existing.properties.size(), + logDetail); + } return; } catch (Exception e) { @@ -122,54 +165,43 @@ public class LanguageManager { */ public static void loadLanguage(String languageName) { loadedLanguages = LanguageManager.getLanguage(languageName); - saveCurrentLanguageToFile(); + if (loadedLanguages != null) { + saveCurrentLanguageToFile(); + } } - /** - * 将当前加载的语言保存到配置文件中 - */ private static void saveCurrentLanguageToFile() { + if (loadedLanguages == null) return; Properties properties = new Properties(); properties.setProperty("loadedLanguage", loadedLanguages.getRegisteredName()); try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(SAVED_LANGUAGE_FILE), StandardCharsets.UTF_8)) { properties.store(writer, "Current Loaded Language"); } catch (IOException e) { - System.err.println("Failed to save current language to file: " + SAVED_LANGUAGE_FILE); - e.printStackTrace(); + logger.error("Failed to save current language to file: {}", SAVED_LANGUAGE_FILE, e); } } - /** - * 从配置文件中加载保存的语言 - */ public static void loadSavedLanguage() { + File file = new File(SAVED_LANGUAGE_FILE); + if (!file.exists()) return; + Properties properties = new Properties(); - try (InputStreamReader reader = new InputStreamReader(new FileInputStream(SAVED_LANGUAGE_FILE), StandardCharsets.UTF_8)) { + try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) { properties.load(reader); String loadedLanguageName = properties.getProperty("loadedLanguage"); if (loadedLanguageName != null) { loadedLanguages = LanguageManager.getLanguage(loadedLanguageName); } } catch (IOException e) { - System.err.println("Failed to load saved language from file: " + SAVED_LANGUAGE_FILE); - e.printStackTrace(); + logger.error("Failed to load saved language from file: {}", SAVED_LANGUAGE_FILE, e); } } - /** - * 获取已加载的语言 - * @return 已加载的语言 - */ public static Language getLoadedLanguages() { return loadedLanguages; } - /** - * 获取语言 - * @param languageName 语言注册名,或者语言名称 - * @return 语言对象 - */ public static Language getLanguage(String languageName) { for (Language language : LANGUAGES) { if (language.getRegisteredName().equals(languageName)) { @@ -185,14 +217,14 @@ public class LanguageManager { return null; } - /** - * 获取所有语言 - * @return 所有语言 - */ public static List getLanguages() { return LANGUAGES; } + // ========================================== + // Inner Class Language + // ========================================== + public static class Language { private final String languageName; private final String registeredName; @@ -210,14 +242,19 @@ public class LanguageManager { this.languageFile = LANGUAGE_PATH + "\\" + languageFileName + ".properties"; } this.properties = new Properties(); + + // 默认构造时加载文件 loadLanguageFile(languageFile); } /** - * 加载语言文件 + * 从磁盘加载语言文件 */ public void loadLanguageFile(String languageFile) { - try (InputStreamReader reader = new InputStreamReader(new FileInputStream(languageFile), + File file = new File(languageFile); + if (!file.exists()) return; // 容错处理 + + try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) { properties.load(reader); } catch (IOException e) { @@ -227,10 +264,19 @@ public class LanguageManager { } /** - * 获取指定键的文本 - * @param key 键 - * @return 对应的文本,如果键不存在则返回 null + * 新增:直接从输入流加载配置(供插件使用) + * @param inputStream 资源流 */ + public void loadFromInputStream(InputStream inputStream) { + if (inputStream == null) return; + try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { + properties.load(reader); + } catch (IOException e) { + System.err.println("Failed to load language from stream for " + registeredName); + e.printStackTrace(); + } + } + public String getText(String key) { if (!properties.containsKey(key)) { return key; @@ -238,9 +284,6 @@ public class LanguageManager { return properties.getProperty(key); } - /** - * 添加文本 - */ public void addText(String key, String value) { properties.setProperty(key, value); } @@ -257,4 +300,4 @@ public class LanguageManager { return new File(languageFile); } } -} +} \ No newline at end of file diff --git a/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java b/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java index 546980f..6d1295a 100644 --- a/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java +++ b/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java @@ -465,7 +465,7 @@ public class RegistrationSettingsItem extends WindowsJDialog { JPanel iconPanel = new JPanel(); - ImageIcon icon = LoadIcon.loadIcon(plugin.getInstance().getClass(), plugin.getIcon(), 64); + ImageIcon icon = LoadIcon.loadIcon(plugin, plugin.getIcon(), 64); JLabel iconLabel = new JLabel(icon); iconPanel.add(iconLabel); mainPanel.add(iconPanel, BorderLayout.WEST); diff --git a/src/main/java/com/axis/innovators/box/window/LoadIcon.java b/src/main/java/com/axis/innovators/box/window/LoadIcon.java index e536228..a06ecb6 100644 --- a/src/main/java/com/axis/innovators/box/window/LoadIcon.java +++ b/src/main/java/com/axis/innovators/box/window/LoadIcon.java @@ -1,5 +1,6 @@ package com.axis.innovators.box.window; +import com.axis.innovators.box.plugins.PluginDescriptor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -11,67 +12,180 @@ import java.net.URL; /** * 负责加载图片 + *

+ * 更新说明:已适配 PluginDescriptor。 + *

* @author tzdwindows 7 */ public class LoadIcon { private static final Logger logger = LogManager.getLogger(LoadIcon.class); private static final String ICON_PATH = "/icons/"; + // ========================================== + // Public API - 面向 PluginDescriptor + // ========================================== + /** - * 加载图片 + * 从插件资源中加载正方形图标 + * @param plugin 插件描述符 + * @param filename 图片文件名 (相对于插件 classpath 的 /icons/ 或根路径) + * @param size 宽高 + * @return ImageIcon + */ + public static ImageIcon loadIcon(PluginDescriptor plugin, String filename, int size) { + return loadIcon(plugin, filename, size, size); + } + + /** + * 从插件资源中加载指定宽高的图标 + * @param plugin 插件描述符 + * @param filename 图片文件名 + * @param width 宽 + * @param height 高 + * @return ImageIcon + */ + public static ImageIcon loadIcon(PluginDescriptor plugin, String filename, int width, int height) { + ClassLoader loader = plugin.getClassLoader(); + if (loader == null) { + logger.warn("Plugin {} has no ClassLoader, returning placeholder.", plugin.getName()); + return createPlaceholderIcon(width, height); + } + return loadIconInternal(loader, filename, width, height); + } + + // ========================================== + // Public API - 面向主程序 (默认使用 LoadIcon.class) + // ========================================== + + /** + * 加载主程序图标 * @param filename 图片名 * @param size 图片大小 * @return ImageIcon对象 */ public static ImageIcon loadIcon(String filename, int size) { - return loadIcon(LoadIcon.class, filename, size); + return loadIconInternal(LoadIcon.class.getClassLoader(), filename, size, size); } /** - * 加载指定宽高的图片(适用于背景图) + * 加载主程序指定宽高的图片 * @param filename 图片名 * @param width 宽度 * @param height 高度 * @return ImageIcon对象 */ public static ImageIcon loadIcon(String filename, int width, int height) { - return loadIcon(LoadIcon.class, filename, width, height); + return loadIconInternal(LoadIcon.class.getClassLoader(), filename, width, height); } /** - * 加载指定宽高的图片(核心构造体) - * @param clazz resources包所在的jar + * 加载系统包下的图片 + * @param clazz resources包所在的jar类 + * @param filename 图片名 + * @param size 图片大小 + * @return ImageIcon对象 + */ + public static ImageIcon loadSystemIcon(Class clazz, String filename, int size) { + return loadIconInternal(clazz.getClassLoader(), filename, size, size); + } + + // ========================================== + // Package-Private API - 限制访问 (不支持 PluginDescriptor 的旧方法) + // ========================================== + + /** + * 加载指定宽高的图片(仅限当前包访问) + * @param clazz resources包所在的jar类 * @param filename 图片名 * @param width 目标宽度 * @param height 目标高度 * @return ImageIcon对象 */ - public static ImageIcon loadIcon(Class clazz, String filename, int width, int height) { + static ImageIcon loadIcon(Class clazz, String filename, int width, int height) { + return loadIconInternal(clazz.getClassLoader(), filename, width, height); + } + + /** + * 加载图片(仅限当前包访问) + * @param clazz resources包所在的jar类 + * @param filename 图片名 + * @param size 图片大小 + * @return ImageIcon对象 + */ + static ImageIcon loadIcon(Class clazz, String filename, int size) { + return loadIconInternal(clazz.getClassLoader(), filename, size, size); + } + + /** + * 加载图片,另一个版本(仅限当前包访问) + * 直接加载 filename,不尝试拼接 ICON_PATH + */ + static ImageIcon loadIcon0(Class clazz, String filename, int size) { + try { + if (filename == null || filename.isEmpty()) { + return createPlaceholderIcon(size, size); + } + URL imgUrl = clazz.getClassLoader().getResource(filename); // 使用 ClassLoader 加载 + if (imgUrl == null) { + // 回退尝试 class.getResource (处理相对路径差异) + imgUrl = clazz.getResource(filename); + } + + if (imgUrl == null) { + return createPlaceholderIcon(size, size); + } + Image image = new ImageIcon(imgUrl).getImage(); + return new ImageIcon(image.getScaledInstance(size, size, Image.SCALE_SMOOTH)); + } catch (Exception e) { + logger.error("Failed to load icon0 '{}'", filename, e); + return createPlaceholderIcon(size, size); + } + } + + // ========================================== + // Internal Core Logic + // ========================================== + + /** + * 统一的核心加载逻辑 + */ + private static ImageIcon loadIconInternal(ClassLoader classLoader, String filename, int width, int height) { try { if (filename == null || filename.isEmpty()) { return createPlaceholderIcon(width, height); } - Image image; - // 1. 处理绝对路径 - if (new File(filename).isAbsolute()) { - image = new ImageIcon(filename).getImage(); - } else { - // 2. 处理资源路径 - String fullPath = ICON_PATH + filename; - URL imgUrl = clazz.getResource(fullPath); - if (imgUrl == null) { - // 尝试不带 /icons/ 路径直接加载 (兼容 loadIcon0 逻辑) - imgUrl = clazz.getResource(filename); - } - - if (imgUrl == null) { - logger.warn("Resource not found: {}", filename); - return createPlaceholderIcon(width, height); - } - image = new ImageIcon(imgUrl).getImage(); + // 1. 处理绝对路径 (不依赖 ClassLoader) + File file = new File(filename); + if (file.isAbsolute() && file.exists()) { + Image image = new ImageIcon(filename).getImage(); + return new ImageIcon(image.getScaledInstance(width, height, Image.SCALE_SMOOTH)); } + // 2. 处理资源路径 + URL imgUrl = null; + + // 尝试 A: /icons/ + filename (标准化路径) + String fullPath = ICON_PATH + filename; + // 去掉开头的 / 因为 ClassLoader.getResource 不以 / 开头 + if (fullPath.startsWith("/")) fullPath = fullPath.substring(1); + + if (classLoader != null) { + imgUrl = classLoader.getResource(fullPath); + } + + // 尝试 B: 直接使用 filename (如果不带 path 或已经在根目录下) + if (imgUrl == null && classLoader != null) { + String cleanName = filename.startsWith("/") ? filename.substring(1) : filename; + imgUrl = classLoader.getResource(cleanName); + } + + if (imgUrl == null) { + logger.warn("Resource not found: {}", filename); + return createPlaceholderIcon(width, height); + } + + Image image = new ImageIcon(imgUrl).getImage(); // 3. 执行高质量缩放 return new ImageIcon(image.getScaledInstance(width, height, Image.SCALE_SMOOTH)); @@ -88,82 +202,14 @@ public class LoadIcon { BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = img.createGraphics(); // 使用更符合现代深色主题的占位颜色 - g2d.setColor(new Color(30, 30, 30)); + g2d.setColor(new Color(30, 30, 30, 128)); // 半透明深色 g2d.fillRect(0, 0, width, height); + + // 画个边框表示丢失 + g2d.setColor(Color.RED); + g2d.drawRect(0, 0, width - 1, height - 1); + g2d.dispose(); return new ImageIcon(img); } - - /** - * 加载图片 - * @param clazz resources包所在的jar - * @param filename 图片名 - * @param size 图片大小 - * @return ImageIcon对象 - */ - public static ImageIcon loadIcon(Class clazz, String filename, int size) { - try { - if (filename.isEmpty()) { - return createPlaceholderIcon(size); - } - - if (new File(filename).isAbsolute()) { - return loadAbsolutePathIcon(filename, size); - } - - String fullPath = ICON_PATH + filename; - URL imgUrl = clazz.getResource(fullPath); - if (imgUrl == null) { - return createPlaceholderIcon(size); - } - Image image = new ImageIcon(imgUrl).getImage(); - return new ImageIcon(image.getScaledInstance(size, size, Image.SCALE_SMOOTH)); - } catch (Exception e) { - logger.error("Failed to load icon image path '{}'", filename, e); - return createPlaceholderIcon(size); - } - } - - private static ImageIcon loadAbsolutePathIcon(String absolutePath, int size) { - try { - Image image = new ImageIcon(absolutePath).getImage(); - return new ImageIcon(image.getScaledInstance(size, size, Image.SCALE_SMOOTH)); - } catch (Exception e) { - logger.error("Failed to load absolute path icon '{}'", absolutePath, e); - return createPlaceholderIcon(size); - } - } - - /** - * 加载图片,另一个版本 - * @param clazz resources包所在的jar - * @param filename 图片名 - * @param size 图片大小 - * @return ImageIcon对象 - */ - public static ImageIcon loadIcon0(Class clazz ,String filename, int size) { - try { - if (filename.isEmpty()){ - return createPlaceholderIcon(size); - } - URL imgUrl = clazz.getResource(filename); - if (imgUrl == null) { - return createPlaceholderIcon(size); - } - Image image = new ImageIcon(imgUrl).getImage(); - return new ImageIcon(image.getScaledInstance(size, size, Image.SCALE_SMOOTH)); - } catch (Exception e) { - logger.error("Failed to load icon image path '{}'", filename, e); - return createPlaceholderIcon(size); - } - } - - private static ImageIcon createPlaceholderIcon(int size) { - BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); - Graphics2D g2d = img.createGraphics(); - g2d.setColor(Color.LIGHT_GRAY); - g2d.fillRect(0, 0, size, size); - g2d.dispose(); - return new ImageIcon(img); - } -} +} \ No newline at end of file diff --git a/src/main/resources/build/build.properties b/src/main/resources/build/build.properties index 7f2ac7e..3c20b1c 100644 --- a/src/main/resources/build/build.properties +++ b/src/main/resources/build/build.properties @@ -1,4 +1,4 @@ # Auto-generated build information version=0.0.1 -buildTimestamp=2026-01-02T17:08:37.387878 +buildTimestamp=2026-01-02T17:46:06.8226378 buildSystem=WINDOWS